PageSourceSearch

https://pacepakistan.com/contact.html

html pacepakistan.com collected 2026-10-02 22:57:55 UTC 41,190 bytes, 952 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en" class="min-h-screen">
3
4<head>
5  <meta charset="UTF-8">
6  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7  <title>Contact Us | PACE - Building The Future Building Pakistan</title>
8  <meta name="description"
9    content="Get in touch with PACE. Reach our investment advisors for retail, financial services, and landmark real estate inquiries.">
10
11  <!-- SEO & Icons -->
12  <link rel="icon" type="image/webp" href="assets/image/pace-logo-rBG.webp">
13  <link rel="apple-touch-icon" href="assets/image/pace-logo-rBG.webp">
14
15  <!-- Google Fonts -->
16  <link rel="preconnect" href="https://fonts.googleapis.com">
17  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
18  <link
19    href="https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,100..900;1,100..900&family=Playfair+Display:ital,wght@1,400&display=swap"
20    rel="stylesheet">
21
22  <!-- Tailwind CSS Play CDN -->
23  
23<script src="https://cdn.tailwindcss.com"></script>
23
24  
24<script src="tailwind.config.js"></script>
24
25
26  <!-- Custom Styles for Cosmic Visuals & Premium Aesthetics -->
27  <link rel="stylesheet" href="style.css">
28
29  <!-- GSAP, ScrollTrigger, and Lenis Smooth Scroll -->
30  
30<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
30
31  
31<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
31
32  
32<script src="https://unpkg.com/[email protected]/dist/lenis.min.js"></script>
32
33  <!-- Global Components Declarations -->
34  
34<script src="global-components.js"></script>
34
35
36  <style>
37    /* Custom style overrides for premium contact page visual flow */
38    body {
39      background-color: #0a0a0a;
40      font-family: 'Jost', sans-serif;
41    }
42
43    /* Cosmic Ambient Glow Particles */
44    .glow-container {
45      position: fixed;
46      inset: 0;
47      z-index: 0;
48      pointer-events: none;
49      overflow: hidden;
50    }
51
52    .glow-ball-center {
53      position: absolute;
54      top: 8%;
55      left: 50%;
56      transform: translate(-50%, 0);
57      width: 750px;
58      height: 480px;
59      border-radius: 50%;
60      background: radial-gradient(circle, rgba(6, 138, 214, 0.65) 0%, rgba(66, 171, 235, 0.25) 35%, rgba(6, 138, 214, 0.05) 60%, transparent 80%);
61      filter: blur(80px);
62      animation: floatGlowCenter 10s ease-in-out infinite alternate;
63      pointer-events: none;
64      z-index: 0;
65    }
66
67    .glow-ball-1 {
68      position: absolute;
69      top: 15%;
70      left: 5%;
71      width: 450px;
72      height: 450px;
73      border-radius: 50%;
74      background: radial-gradient(circle, rgba(6, 138, 214, 0.2) 0%, rgba(66, 171, 235, 0.03) 50%, transparent 100%);
75      filter: blur(80px);
76      animation: floatGlow1 18s ease-in-out infinite alternate;
77    }
78
79    .glow-ball-2 {
80      position: absolute;
81      bottom: 15%;
82      right: 5%;
83      width: 500px;
84      height: 500px;
85      border-radius: 50%;
86      background: radial-gradient(circle, rgba(66, 171, 235, 0.18) 0%, rgba(6, 138, 214, 0.02) 50%, transparent 100%);
87      filter: blur(90px);
88      animation: floatGlow2 22s ease-in-out infinite alternate;
89    }
90
91    @keyframes floatGlowCenter {
92      0% {
93        transform: translate(-50%, -15px) scale(0.95);
94        opacity: 0.8;
95      }
96
97      50% {
98        transform: translate(-50%, 15px) scale(1.05);
99        opacity: 1;
100      }
101
102      100% {
103        transform: translate(-50%, -15px) scale(0.95);
104        opacity: 0.8;
105      }
106    }
107
108    @keyframes floatGlow1 {
109      0% {
110        transform: translate(0px, 0px) scale(1);
111      }
112
113      50% {
114        transform: translate(60px, -40px) scale(1.1);
115      }
116
117      100% {
118        transform: translate(0px, 0px) scale(1);
119      }
120    }
121
122    @keyframes floatGlow2 {
123      0% {
124        transform: translate(0px, 0px) scale(1.05);
125      }
126
127      50% {
128        transform: translate(-50px, 50px) scale(0.95);
129      }
130
131      100% {
132        transform: translate(0px, 0px) scale(1.05);
133      }
134    }
135
136    /* Subtle Grid overlay for Apple Tech feel */
137    .dot-grid-bg {
138      position: fixed;
139      inset: 0;
140      z-index: 1;
141      pointer-events: none;
142      background-image: radial-gradient(rgba(255, 255, 255, 0.015) 1px, transparent 1px);
143      background-size: 32px 32px;
144    }
145
146    /* Giant Background Outlined Text */
147    .outline-text {
148      font-size: 15vw;
149      font-weight: 900;
150      letter-spacing: 0.06em;
151      color: rgba(255, 255, 255, 0.015);
152      -webkit-text-stroke: 1.5px rgba(255, 255, 255, 0.06);
153      text-shadow: 0 0 60px rgba(6, 138, 214, 0.05);
154      font-family: 'Futura', 'Jost', sans-serif;
155      line-height: 1;
156      opacity: 0;
157      transform: scale(0.95);
158    }
159
160    /* Glare Sweep Shimmer for Submit Button */
161    .hover-shine-effect {
162      position: absolute;
163      top: 0;
164      width: 50%;
165      height: 100%;
166      background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.75) 50%, rgba(255, 255, 255, 0) 100%);
167      transform: skewX(-25deg);
168      pointer-events: none;
169    }
170
171    /* Glassmorphic input styles */
172    input:-webkit-autofill,
173    input:-webkit-autofill:hover,
174    input:-webkit-autofill:focus,
175    textarea:-webkit-autofill,
176    textarea:-webkit-autofill:hover,
177    textarea:-webkit-autofill:focus {
178      -webkit-text-fill-color: #ffffff;
179      -webkit-box-shadow: 0 0 0px 1000px rgba(20, 20, 20, 0.95) inset;
180      transition: background-color 5000s ease-in-out 0s;
181    }
182
183    /* Professional form validation error states */
184    .form-input.is-invalid {
185      border-color: rgba(244, 63, 94, 0.7) !important;
186      background-color: rgba(244, 63, 94, 0.04) !important;
187      box-shadow: 0 0 25px rgba(244, 63, 94, 0.22) !important;
188    }
189    .form-input.is-invalid:focus {
190      border-color: rgba(244, 63, 94, 0.95) !important;
191      box-shadow: 0 0 30px rgba(244, 63, 94, 0.35) !important;
192    }
193
194    @keyframes fieldShake {
195      0%, 100% { transform: translateX(0); }
196      20%, 60% { transform: translateX(-5px); }
197      40%, 80% { transform: translateX(5px); }
198    }
199    .shake-anim {
200      animation: fieldShake 0.35s ease-in-out;
201    }
202
203    /* Scrollable sections setup */
204    .contact-content-wrapper {
205      min-height: calc(100vh - 120px);
206    }
207  </style>
208</head>
209
210<body class="min-h-screen select-none text-white antialiased relative">
211
212  <!-- Capture start time for the preloader -->
213  
213<script type="text/javascript">
214    window.preloaderStartTime = Date.now();
215  </script>
215
216
217  <!-- ==================== PREMIUM PRELOADER ==================== -->
218  <div id="preloader">
219    <div class="preloader-glow"></div>
220    <div class="preloader-noise bg-noise-overlay absolute inset-0 opacity-[0.035] pointer-events-none"></div>
221    <div class="preloader-wrapper">
222      <img src="assets/image/pace-logo-rBG.webp" alt="PACE Logo Symbol" class="preloader-logo">
223      <span class="preloader-text">PACE</span>
224    </div>
225  </div>
226
227  <!-- ==================== BACKGROUND & COSMIC GLOWS ==================== -->
228  <div class="fixed inset-0 bg-[#0a0a0a] z-0 pointer-events-none"></div>
229  <div class="glow-container">
230    <div class="glow-ball-center"></div>
231    <div class="glow-ball-1"></div>
232    <div class="glow-ball-2"></div>
233  </div>
234  <div class="dot-grid-bg"></div>
235
236  <!-- Giant Outline Header Behind Grid Content -->
237  <div
238    class="absolute top-28 sm:top-36 lg:top-44 left-0 right-0 flex justify-center pointer-events-none select-none overflow-hidden z-0">
239    <div class="outline-text uppercase font-space font-black tracking-widest">CONTACT</div>
240  </div>
241
242  <!-- ==================== HEADER & NAVIGATION ==================== -->
243  <div id="global-header"></div>
244  
244<script>
245    document.getElementById('global-header').innerHTML = window.GLOBAL_HEADER_HTML;
246  </script>
246
247
248  <!-- ==================== MAIN CONTACT PAGE CONTENT ==================== -->
249  <main
250    class="relative z-10 w-full pt-56 sm:pt-68 lg:pt-80 pb-20 xs:pb-24 px-5 sm:px-10 lg:px-16 max-w-[1536px] mx-auto contact-content-wrapper flex flex-col justify-center">
251
252    <div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-start w-full">
253
254      <!-- LEFT COLUMN: Heading & Staggered Cards (Spans 5 columns) -->
255      <div class="lg:col-span-5 flex flex-col items-start text-left left-section-anim z-10">
256
257        <!-- Outlined capsule badge -->
258        <div
259          class="flex items-center gap-2 px-4 py-1.5 rounded-full bg-white/[0.03] border border-white/10 text-[10px] sm:text-xs font-semibold tracking-widest uppercase text-[#42abeb] w-fit mb-6 shadow-[0_4px_12px_rgba(6,138,214,0.15)]">
260          <svg class="w-3.5 h-3.5 animate-pulse-slow text-[#42abeb]" fill="none" stroke="currentColor"
261            stroke-width="2.5" viewBox="0 0 24 24">
262            <path stroke-linecap="round" stroke-linejoin="round"
263              d="M9.813 15.904L9 21l-.813-5.096L3 15l5.096-.813L9 9l.813 5.096L15 15l-5.096.813zM18.666 5.666L18 9l-.666-3.334L14 5l3.334-.666L18 1l.666 3.334L22 5l-3.334.666z" />
264          </svg>
265          <span>Contact Us</span>
266        </div>
267
268        <!-- Title -->
269        <h1
270          class="font-space font-light text-4xl sm:text-5xl lg:text-6xl tracking-tight leading-[1.05] mb-5 text-white">
271          Get in <span
272            class="font-bold bg-gradient-to-r from-[#068ad6] to-[#42abeb] bg-clip-text text-transparent filter drop-shadow-[0_0_25px_rgba(6,138,214,0.35)]">touch</span>
273        </h1>
274
275        <!-- Subtitle -->
276        <p class="font-outfit font-light text-white/50 text-base sm:text-lg leading-relaxed mb-10 max-w-md">
277          Have questions or ready to explore premium investment opportunities with Pakistan's leading conglomerate?
278          Reach out directly.
279        </p>
280
281        <!-- Staggered Contact Cards -->
282        <div class="flex flex-col gap-4 w-full max-w-md">
283
284          <!-- Email Info Card -->
285          <a href="mailto:[email protected]"
286            class="info-card flex items-center gap-5 p-5 bg-white/[0.015] border border-white/10 rounded-[2rem] hover:border-[#42abeb]/40 hover:bg-white/[0.04] transition-all duration-500 hover:-translate-y-1 hover:shadow-[0_20px_50px_rgba(6,138,214,0.18)] group">
287            <div
288              class="w-12 h-12 rounded-2xl flex items-center justify-center bg-[#068ad6]/10 border border-[#068ad6]/20 text-[#42abeb] shadow-[0_0_15px_rgba(6,138,214,0.15)] transition-all duration-500 group-hover:scale-110 group-hover:bg-[#068ad6]/25 group-hover:border-[#42abeb]/45 group-hover:text-white">
289              <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
290                <path stroke-linecap="round" stroke-linejoin="round"
291                  d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" />
292              </svg>
293            </div>
294            <div class="flex flex-col text-left">
295              <span class="text-white/40 text-[10px] font-bold tracking-widest uppercase mb-0.5">Email us</span>
296              <span
297                class="text-white/80 group-hover:text-[#42abeb] text-sm sm:text-base font-semibold transition-colors duration-300">[email protected]</span>
298            </div>
299          </a>
300
301          <!-- Phone Info Card -->
302          <a href="tel:+924235778217"
303            class="info-card flex items-center gap-5 p-5 bg-white/[0.015] border border-white/10 rounded-[2rem] hover:border-[#42abeb]/40 hover:bg-white/[0.04] transition-all duration-500 hover:-translate-y-1 hover:shadow-[0_20px_50px_rgba(6,138,214,0.18)] group">
304            <div
305              class="w-12 h-12 rounded-2xl flex items-center justify-center bg-[#068ad6]/10 border border-[#068ad6]/20 text-[#42abeb] shadow-[0_0_15px_rgba(6,138,214,0.15)] transition-all duration-500 group-hover:scale-110 group-hover:bg-[#068ad6]
305/25 group-hover:border-[#42abeb]/45 group-hover:text-white">
306              <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
307                <path stroke-linecap="round" stroke-linejoin="round"
308                  d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-2.824-1.806-5.122-4.106-6.928-6.927l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z" />
309              </svg>
310            </div>
311            <div class="flex flex-col text-left">
312              <span class="text-white/40 text-[10px] font-bold tracking-widest uppercase mb-0.5">Call us</span>
313              <span
314                class="text-white/80 group-hover:text-[#42abeb] text-sm sm:text-base font-semibold transition-colors duration-300">+92
315                (42) 3577 8217</span>
316            </div>
317          </a>
318
319          <!-- Location Info Card -->
320          <div
321            class="info-card flex items-center gap-5 p-5 bg-white/[0.015] border border-white/10 rounded-[2rem] hover:border-[#42abeb]/40 hover:bg-white/[0.04] transition-all duration-500 hover:-translate-y-1 hover:shadow-[0_20px_50px_rgba(6,138,214,0.18)] group">
322            <div
323              class="w-12 h-12 rounded-2xl flex items-center justify-center bg-[#068ad6]/10 border border-[#068ad6]/20 text-[#42abeb] shadow-[0_0_15px_rgba(6,138,214,0.15)] transition-all duration-500 group-hover:scale-110 group-hover:bg-[#068ad6]/25 group-hover:border-[#42abeb]/45 group-hover:text-white">
324              <svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
325                <path stroke-linecap="round" stroke-linejoin="round" d="M15 10.5a3 3 0 11-6 0 3 3 0 016 0z" />
326                <path stroke-linecap="round" stroke-linejoin="round"
327                  d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25s-7.5-4.108-7.5-11.25a7.5 7.5 0 1115 0z" />
328              </svg>
329            </div>
330            <div class="flex flex-col text-left">
331              <span class="text-white/40 text-[10px] font-bold tracking-widest uppercase mb-0.5">Our location</span>
332              <span class="text-white/80 text-sm sm:text-base font-semibold">First Capital Tower, Gulberg II, Lahore</span>
333            </div>
334          </div>
335
336        </div>
337
338      </div>
339
340      <!-- RIGHT COLUMN: Premium Contact Form (Spans 7 columns) -->
341      <div class="lg:col-span-7 z-10" id="contactFormCard">
342
343        <div
344          class="bg-white/[0.01] border border-white/10 backdrop-blur-xl rounded-[2.5rem] p-6 xs:p-8 sm:p-10 lg:p-12 shadow-[0_30px_100px_rgba(0,0,0,0.85),inset_0_1.5px_0_rgba(255,255,255,0.08)] relative overflow-hidden">
345
346          <!-- Subtle inner glow element inside the card -->
347          <div class="absolute -right-24 -top-24 w-52 h-52 rounded-full bg-[#068ad6]/10 blur-3xl pointer-events-none">
348          </div>
349          <div class="absolute -left-24 -bottom-24 w-52 h-52 rounded-full bg-[#42abeb]/5 blur-3xl pointer-events-none">
350          </div>
351
352          <form id="contactForm" method="POST" action="contact-process.php" novalidate class="relative z-10 flex flex-col gap-5">
353
354            <!-- Anti-spam Honeypot field (hidden from real users) -->
355            <div class="hidden" aria-hidden="true" style="display: none !important;">
356              <input type="text" name="_gotcha" tabindex="-1" autocomplete="off">
357            </div>
358
359            <!-- Full Name input container -->
360            <div class="flex flex-col gap-1.5 group/input" id="field-wrap-name">
361              <div class="flex justify-between items-center px-1">
362                <label for="name"
363                  class="text-white/40 text-xs font-semibold tracking-wider uppercase transition-all duration-300 group-focus-within/input:text-[#42abeb]">Full Name <span class="text-rose-400">*</span></label>
364                <span id="name-error" class="field-error text-rose-400 text-[11px] font-medium hidden"></span>
365              </div>
366              <input type="text" id="name" name="name" required minlength="2" maxlength="80" autocomplete="name" placeholder="John Doe"
367                class="form-input bg-white/[0.015] border border-white/10 focus:border-[#42abeb]/50 focus:ring-1 focus:ring-[#068ad6]
367/50 text-white rounded-2xl py-4 px-5 outline-none transition-all duration-300 font-outfit font-light placeholder-white/20 focus:bg-white/[0.03] focus:shadow-[0_0_30px_rgba(6,138,214,0.15)] w-full">
368            </div>
369
370            <!-- Email Address input container -->
371            <div class="flex flex-col gap-1.5 group/input" id="field-wrap-email">
372              <div class="flex justify-between items-center px-1">
373                <label for="email"
374                  class="text-white/40 text-xs font-semibold tracking-wider uppercase transition-all duration-300 group-focus-within/input:text-[#42abeb]">Email Address <span class="text-rose-400">*</span></label>
375                <span id="email-error" class="field-error text-rose-400 text-[11px] font-medium hidden"></span>
376              </div>
377              <input type="email" id="email" name="email" required maxlength="100" autocomplete="email" placeholder="[email protected]"
378                class="form-input bg-white/[0.015] border border-white/10 focus:border-[#42abeb]/50 focus:ring-1 focus:ring-[#068ad6]/50 text-white rounded-2xl py-4 px-5 outline-none transition-all duration-300 font-outfit font-light placeholder-white/20 focus:bg-white/[0.03] focus:shadow-[0_0_30px_rgba(6,138,214,0.15)] w-full">
379            </div>
380
381            <!-- Contact Number input container -->
382            <div class="flex flex-col gap-1.5 group/input" id="field-wrap-phone">
383              <div class="flex justify-between items-center px-1">
384                <label for="phone"
385                  class="text-white/40 text-xs font-semibold tracking-wider uppercase transition-all duration-300 group-focus-within/input:text-[#42abeb]">Contact Number <span class="text-rose-400">*</span></label>
386                <span id="phone-error" class="field-error text-rose-400 text-[11px] font-medium hidden"></span>
387              </div>
388              <input type="tel" id="phone" name="phone" required minlength="7" maxlength="20" autocomplete="tel" placeholder="+92 300 1234567"
389                class="form-input bg-white/[0.015] border border-white/10 focus:border-[#42abeb]/50 focus:ring-1 focus:ring-[#068ad6]/50 text-white rounded-2xl py-4 px-5 outline-none transition-all duration-300 font-outfit font-light placeholder-white/20 focus:bg-white/[0.03] focus:shadow-[0_0_30px_rgba(6,138,214,0.15)] w-full">
390            </div>
391
392            <!-- Message textarea container -->
393            <div class="flex flex-col gap-1.5 group/input" id="field-wrap-message">
394              <div class="flex justify-between items-center px-1">
395                <label for="message"
396                  class="text-white/40 text-xs font-semibold tracking-wider uppercase transition-all duration-300 group-focus-within/input:text-[#42abeb]">Message <span class="text-rose-400">*</span></label>
397                <span id="message-error" class="field-error text-rose-400 text-[11px] font-medium hidden"></span>
398              </div>
399              <textarea id="message" name="message" required minlength="10" maxlength="3000" rows="5" placeholder="Let us know how we can assist you (minimum 10 characters)..."
400                class="form-input bg-white/[0.015] border border-white/10 focus:border-[#42abeb]/50 focus:ring-1 focus:ring-[#068ad6]/50 text-white rounded-2xl py-4 px-5 outline-none transition-all duration-300 font-outfit font-light placeholder-white/20 resize-none focus:bg-white/[0.03] focus:shadow-[0_0_30px_rgba(6,138,214,0.15)] w-full"></textarea>
401            </div>
402
403            <!-- Submit Button: solid white, black bold, hover sweep shimmer -->
404            <button type="submit" id="submitBtn"
405              class="w-full bg-white hover:bg-white/95 text-black font-semibold text-xs tracking-widest uppercase py-4 sm:py-5 rounded-2xl transition-all duration-300 shadow-[0_4px_25px_rgba(255,255,255,0.06)] hover:shadow-[0_0_30px_rgba(255,255,255,0.3)] active:scale-[0.98] relative overflow-hidden flex items-center justify-center gap-2.5 cursor-pointer font-space hover-shine-target">
406              <span id="submitBtnText" class="relative z-10">Send Message</span>
407
408              <!-- Skewed shimmer glare -->
409              <span class="hover-shine-effect"></span>
410
411              <svg id="submitBtnIcon" class="w-4 h-4 relative z-10 transition-transform duration-300 group-hover:translate-x-1" fill="none"
412                stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
413                <path stroke-linecap="round" stroke-linejoin="round"
414                  d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" />
415              </svg>
416            </button>
417
418            <!-- Inline Ajax feedback container -->
419            <div id="formFeedback"
420              class="hidden text-center text-xs font-semibold uppercase tracking-wider py-3.5 rounded-2xl transition-all duration-300">
421            </div>
422
423          </form>
424
425        </div>
426
427      </div>
428
429    </div>
430
431  </main>
432
433  <!-- ==================== FOOTER ==================== -->
434  <div id="global-footer"></div>
435  
435<script>
436    document.getElementById('global-footer').innerHTML = window.GLOBAL_FOOTER_HTML;
437  </script>
437
438
439  <!-- ==================== GLASSMORPHIC SUCCESS MODAL OVERLAY ==================== -->
440  <div id="successModal"
441    class="fixed inset-0 z-[100] flex items-center justify-center px-4 opacity-0 pointer-events-none transition-all duration-500"
442    style="background: rgba(10, 10, 10, 0.45); backdrop-filter: blur(25px); -webkit-backdrop-filter: blur(25px);">
443
444    <div
445      class="relative bg-white/[0.015] border border-white/10 rounded-[3rem] p-8 sm:p-12 max-w-md w-full text-center shadow-[0_50px_100px_rgba(0,0,0,0.9),inset_0_1.5px_0_rgba(255,255,255,0.08)] transform scale-95 transition-all duration-500 overflow-hidden">
446
447      <!-- Rotating ambient glow inside success modal -->
448      <div
449        class="absolute -inset-10 bg-gradient-to-r from-[#068ad6]/15 to-[#42abeb]/15 blur-3xl pointer-events-none opacity-60">
450      </div>
451
452      <!-- Success Badge circle -->
453      <div
454        class="mx-auto w-16 h-16 rounded-full flex items-center justify-center bg-gradient-to-r from-[#068ad6] to-[#42abeb] text-white shadow-[0_0_30px_rgba(6,138,214,0.35)] mb-6 transform scale-90"
455        id="successIcon">
456        <svg class="w-8 h-8" fill="none" stroke="currentColor" stroke-width="3" viewBox="0 0 24 24">
457          <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" />
458        </svg>
459      </div>
460
461      <!-- Modal Title -->
462      <h3 class="font-space font-light text-2xl sm:text-3xl text-white mb-3 tracking-tight">Message Sent</h3>
463
464      <!-- Modal Text -->
465      <p class="font-outfit font-light text-white/50 text-sm leading-relaxed mb-8" id="successMsg">
466        Thank you! Your message has been sent successfully. We will get back to you shortly!
467      </p>
468
469      <!-- Back button -->
470      <div class="flex justify-center w-full">
471        <button id="closeModalBtn" class="premium-flow-btn">
472          <span class="premium-flow-inner px-8 py-3 text-xs font-semibold tracking-widest uppercase">Return to
473            Home</span>
474        </button>
475      </div>
476
477    </div>
478  </div>
479
480  <!-- ==================== FRONT-END INTERACTION LOGIC ==================== -->
481  
481<script>
482    document.addEventListener('DOMContentLoaded', () => {
483      // Initialize GSAP
484      gsap.registerPlugin(ScrollTrigger);
485
486      // 1. Initialize Lenis Smooth Scroll
487      const lenis = new Lenis({
488        duration: 1.2,
489        easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
490        orientation: 'vertical',
491        smoothWheel: true,
492        wheelMultiplier: 1,
493        touchMultiplier: 2,
494        infinite: false,
495      });
496
497      // Stop scrolling during preloading phase
498      lenis.stop();
499
500      // Preloader controller (minimum 2 seconds)
501      window.addEventListener('load', () => {
502        const preloader = document.getElementById('preloader');
503        const minTime = 2000;
504        const startTime = window.preloaderStartTime || Date.now();
505        const elapsedTime = Date.now() - startTime;
506        const remainingTime = Math.max(0, minTime - elapsedTime);
507
508        setTimeout(() => {
509          if (preloader) {
510            preloader.classList.add('fade-out');
511
512            // Resume scroll
513            lenis.start();
514
515            // Trigger animations
516            triggerEntranceAnimations();
517
518            setTimeout(() => {
519              preloader.remove();
520            }, 800);
521          }
522        }, remainingTime);
523      });
524
525      // Connect Lenis with GSAP ScrollTrigger
526      lenis.on('scroll', ScrollTrigger.update);
527      gsap.ticker.add((time) => {
528        lenis.raf(time * 1000);
529      });
530      gsap.ticker.lagSmoothing(0);
531
532      // 2. Entrance Animation Sequences
533      function triggerEntranceAnimations() {
534        const tl = gsap.timeline();
535
536        // 1. Fade outline CONTACT text back
537        tl.to(".outline-text", {
538          opacity: 1,
539          scale: 1,
540          duration: 1.8,
541          ease: "power3.out"
542        }, "+=0.2");
543
544        // 2. Animate left column contents
545        tl.fromTo(".left-section-anim > *",
546          { opacity: 0, y: 30, filter: "blur(5px)" },
547          { opacity: 1, y: 0, filter: "blur(0px)", stagger: 0.15, duration: 1.2, ease: "power4.out" },
548          "-=1.6"
549        );
550
551        // 3. Stagger info cards
552        tl.fromTo(".info-card",
553          { opacity: 0, y: 20 },
554          { opacity: 1, y: 0, stagger: 0.12, duration: 1.0, ease: "power3.out" },
555          "-=1.1"
556        );
557
558        // 4. Stagger form card container
559        tl.fromTo("#contactFormCard",
560          { opacity: 0, y: 40, scale: 0.97 },
561          { opacity: 1, y: 0, scale: 1, duration: 1.4, ease: "power4.out" },
562          "-=1.3"
563        );
564      }
565
566      // 3. Header & Hamburger Slide Drawer Navigation Controls
567      const hamburgerBtn = document.getElementById('hamburgerBtn');
568      const mobileDrawer = document.getElementById('mobileDrawer');
569      const drawerBackdrop = document.getElementById('drawerBackdrop');
570      const mobileNavLinks = document.querySelectorAll('.mobile-nav-link');
571      const mobileSubLinks = document.querySelectorAll('.mobile-sub-link');
572
573      const toggleMenu = () => {
574        hamburgerBtn.classList.toggle('active');
575        mobileDrawer.classList.toggle('active');
576        drawerBackdrop.classList.toggle('active');
577        if (mobileDrawer.classList.contains('active')) {
578          lenis.stop();
579        } else {
580          lenis.start();
581          resetAccordions();
582        }
583      };
584
585      const resetAccordions = () => {
586        const accordionBtns = document.querySelectorAll('.mobile-accordion-btn');
587        const accordionContents = document.querySelectorAll('.mobile-accordion-content');
588        accordionBtns.forEach(btn => btn.classList.remove('active'));
589        accordionContents.forEach(content => {
590          content.classList.remove('active');
591          content.style.maxHeight = '0px';
592        });
593      };
594
595      if (hamburgerBtn && mobileDrawer && drawerBackdrop) {
596        hamburgerBtn.addEventListener('click', toggleMenu);
597        drawerBackdrop.addEventListener('click', toggleMenu);
598
599        mobileNavLinks.forEach(link => {
600          link.addEventListener('click', () => {
601            if (link.classList.contains('mobile-accordion-btn')) return;
602            if (mobileDrawer.classList.contains('active')) {
603              toggleMenu();
604            }
605          });
606        });
607
608        mobileSubLinks.forEach(link => {
609          link.addEventListener('click', () => {
610            if (mobileDrawer.classList.contains('active')) {
611              toggleMenu();
612            }
613          });
614        });
615      }
616
617      // Accordions trigger in mobile drawer
618      const accordionBtns = document.querySelectorAll('.mobile-accordion-btn');
619      accordionBtns.forEach(btn => {
620        btn.addEventListener('click', (e) => {
621          e.preventDefault();
622          const targetId = btn.getAttribute('data-accordion');
623          const content = document.getElementById(targetId);
624
625          if (content) {
626            const isActive = content.classList.toggle('active');
627            btn.classList.toggle('active');
628
629            if (isActive) {
630              content.style.maxHeight = content.scrollHeight + 'px';
631            } else {
632              content.style.maxHeight = '0px';
633            }
634          }
635        });
636      });
637
638      // Desktop Touch/Click Dropdowns logic
639      const dropdownWrappers = document.querySelectorAll('.glass-dropdown-wrapper');
640      dropdownWrappers.forEach(wrapper => {
641        const trigger = wrapper.querySelector('button');
642
643        trigger.addEventListener('click', (e) => {
644          e.stopPropagation();
645
646          dropdownWrappers.forEach(otherWrapper => {
647            if (otherWrapper !== wrapper) {
648              otherWrapper.classList.remove('active');
649              otherWrapper.querySelector('button').setAttribute('aria-expanded', 'false');
650            }
651          });
652
653          const isActive = wrapper.classList.toggle('active');
654          trigger.setAttribute('aria-expanded', isActive ? 'true' : 'false');
655        });
656      });
657
658      document.addEventListener('click', () => {
659        dropdownWrappers.forEach(wrapper => {
660          wrapper.classList.remove('active');
661          wrapper.querySelector('button').setAttribute('aria-expanded', 'false');
662        });
663      });
664
665      // 4. Form Validation & AJAX POST processing
666      const contactForm = document.getElementById('contactForm');
667      const formFeedback = document.getElementById('formFeedback');
668      const submitBtn = document.getElementById('submitBtn');
669      const submitBtnText = document.getElementById('submitBtnText');
670      const submitBtnIcon = document.getElementById('submitBtnIcon');
671      const successModal = document.getElementById('successModal');
672      const successMsg = document.getElementById('successMsg');
673      const closeModalBtn = document.getElementById('closeModalBtn');
674
675      // Input elements
676      const nameInput = document.getElementById('name');
677      const emailInput = document.getElementById('email');
678      const phoneInput = document.getElementById('phone');
679      const messageInput = document.getElementById('message');
680
681      // Error label elements
682      const nameError = document.getElementById('name-error');
683      const emailError = document.getElementById('email-error');
684      const phoneError = document.getElementById('phone-error');
685      const messageError = document.getElementById('message-error');
686
687      // Helper: set field error
688      const setFieldError = (input, errorEl, message) => {
689        input.classList.add('is-invalid');
690        errorEl.textContent = message;
691        errorEl.classList.remove('hidden');
692      };
693
694      // Helper: clear field error
695      const clearFieldError = (input, errorEl) => {
696        input.classList.remove('is-invalid', 'shake-anim');
697        errorEl.textContent = '';
698        errorEl.classList.add('hidden');
699      };
700
701      // Validator: Name (letters, spaces, punctuation, 2-80 chars)
702      const validateName = () => {
703        const val = nameInput.value.trim();
704        if (!val) {
705          return { isValid: false, message: 'Full name is required.' };
706        }
707        if (val.length < 2) {
708          return { isValid: false, message: 'Name must be at least 2 characters.' };
709        }
710        if (val.length > 80) {
711          return { isValid: false, message: 'Name cannot exceed 80 characters.' };
712        }
713        if (!/^[a-zA-Z\u00C0-\u024F\s\.\'\-]{2,80}$/.test(val)) {
714          return { isValid: false, message: 'Name can only contain letters and standard punctuation.' };
715        }
716        return { isValid: true };
717      };
718
719      // Validator: Email (RFC-compliant regex)
720      const validateEmail = () => {
721        const val = emailInput.value.trim();
722        if (!val) {
723          return { isValid: false, message: 'Email address is required.' };
724        }
725        if (val.length > 100) {
726          return { isValid: false, message: 'Email address is too long.' };
727        }
728        const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
729        if (!emailRegex.test(val)) {
730          return { isValid: false, message: 'Please enter a valid email address.' };
731        }
732        return { isValid: true };
733      };
734
735      // Validator: Phone (ITU-T E.164: 7 to 15 digits, allows +, space
735s, dashes, parens)
736      const validatePhone = () => {
737        const val = phoneInput.value.trim();
738        if (!val) {
739          return { isValid: false, message: 'Contact number is required.' };
740        }
741        if (!/^(\+?[0-9\s\-\(\)\.]+)$/.test(val)) {
742          return { isValid: false, message: 'Contact number contains invalid characters.' };
743        }
744        const digits = val.replace(/\D/g, '');
745        if (digits.length < 7 || digits.length > 15) {
746          return { isValid: false, message: 'Enter a valid phone number (7 to 15 digits).' };
747        }
748        return { isValid: true };
749      };
750
751      // Validator: Message (minimum 10 chars, max 3000 chars)
752      const validateMessage = () => {
753        const val = messageInput.value.trim();
754        if (!val) {
755          return { isValid: false, message: 'Message is required.' };
756        }
757        if (val.length < 10) {
758          return { isValid: false, message: 'Message must be at least 10 characters.' };
759        }
760        if (val.length > 3000) {
761          return { isValid: false, message: 'Message cannot exceed 3000 characters.' };
762        }
763        return { isValid: true };
764      };
765
766      // Real-time validation listeners
767      const setupFieldValidation = (input, errorEl, validator) => {
768        input.addEventListener('input', () => {
769          if (input.classList.contains('is-invalid')) {
770            const result = validator();
771            if (result.isValid) {
772              clearFieldError(input, errorEl);
773            }
774          }
775        });
776
777        input.addEventListener('blur', () => {
778          if (input.value.trim() !== '') {
779            const result = validator();
780            if (!result.isValid) {
781              setFieldError(input, errorEl, result.message);
782            } else {
783              clearFieldError(input, errorEl);
784            }
785          }
786        });
787      };
788
789      setupFieldValidation(nameInput, nameError, validateName);
790      setupFieldValidation(emailInput, emailError, validateEmail);
791      setupFieldValidation(phoneInput, phoneError, validatePhone);
792      setupFieldValidation(messageInput, messageError, validateMessage);
793
794      contactForm.addEventListener('submit', (e) => {
795        e.preventDefault();
796
797        // Validate all fields
798        const nameRes = validateName();
799        const emailRes = validateEmail();
800        const phoneRes = validatePhone();
801        const messageRes = validateMessage();
802
803        let firstInvalid = null;
804
805        if (!nameRes.isValid) {
806          setFieldError(nameInput, nameError, nameRes.message);
807          firstInvalid = firstInvalid || nameInput;
808        } else {
809          clearFieldError(nameInput, nameError);
810        }
811
812        if (!emailRes.isValid) {
813          setFieldError(emailInput, emailError, emailRes.message);
814          firstInvalid = firstInvalid || emailInput;
815        } else {
816          clearFieldError(emailInput, emailError);
817        }
818
819        if (!phoneRes.isValid) {
820          setFieldError(phoneInput, phoneError, phoneRes.message);
821          firstInvalid = firstInvalid || phoneInput;
822        } else {
823          clearFieldError(phoneInput, phoneError);
824        }
825
826        if (!messageRes.isValid) {
827          setFieldError(messageInput, messageError, messageRes.message);
828          firstInvalid = firstInvalid || messageInput;
829        } else {
830          clearFieldError(messageInput, messageError);
831        }
832
833        if (firstInvalid) {
834          firstInvalid.classList.remove('shake-anim');
835          void firstInvalid.offsetWidth; // force CSS reflow
836          firstInvalid.classList.add('shake-anim');
837          firstInvalid.focus();
838          return;
839        }
840
841        // Show processing state
842        submitBtn.disabled = true;
843        submitBtn.style.opacity = '0.7';
844        if (submitBtnText) submitBtnText.textContent = 'Sending...';
845        formFeedback.classList.add('hidden');
846        formFeedback.className = "text-center text-xs font-semibold uppercase tracking-wider py-3.5 rounded-2xl transition-all duration-300";
847
848        const formData = new FormData(contactForm);
849
850        fetch('contact-process.php', {
851          method: 'POST',
852          body: formData
853        })
854          .then(async response => {
855            const data = await response.json().catch(() => null);
856            if (!data) {
857              throw new Error('Invalid response from server');
858            }
859            return data;
860          })
861          .then(data => {
862            submitBtn.disabled = false;
863            submitBtn.style.opacity = '1';
864            if (submitBtnText) submitBtnText.textContent = 'Send Message';
865
866            if (data.status === 'success') {
867              // TEMPORARY: Log server diagnostics to console
868              if (data.debug) console.log('📧 Mail Debug:', JSON.stringify(data.debug, null, 2));
869              // Trigger Success Modal ONLY after confirmed backend success
870              successMsg.textContent = data.message || 'Your message has been sent successfully. We will get back to you shortly.';
871              successModal.classList.remove('pointer-events-none');
872
873              // GSAP slide & scale entrance
874              lenis.stop();
875              gsap.to(successModal, {
876                opacity: 1,
877                duration: 0.5,
878                ease: "power3.out"
879              });
880              gsap.fromTo("#successModal > div",
881                { scale: 0.9, y: 20 },
882                { scale: 1, y: 0, duration: 0.6, ease: "back.out(1.5)" }
883              );
884              gsap.fromTo("#successIcon",
885                { scale: 0.7, rotation: -45 },
886                { scale: 1, rotation: 0, duration: 0.8, delay: 0.1, ease: "back.out(2)" }
887              );
888
889              // Reset form only on success
890              contactForm.reset();
891              clearFieldError(nameInput, nameError);
892              clearFieldError(emailInput, emailError);
893              clearFieldError(phoneInput, phoneError);
894              clearFieldError(messageInput, messageError);
895            } else {
896              // Server returned validation/processing error
897              if (data.field === 'name') setFieldError(nameInput, nameError, data.message);
898              else if (data.field === 'email') setFieldError(emailInput, emailError, data.message);
899              else if (data.field === 'phone') setFieldError(phoneInput, phoneError, data.message);
900              else if (data.field === 'message') setFieldError(messageInput, messageError, data.message);
901
902              formFeedback.textContent = data.debug ? (data.message + ' (' + data.debug + ')') : (data.message || 'Unable to send your message right now. Please try again later.');
903              formFeedback.classList.remove('hidden');
904              formFeedback.className = "text-center text-xs font-semibold uppercase tracking-wider py-3.5 rounded-2xl transition-all duration-300 text-rose-500 bg-rose-500/10 border border-rose-500/20";
905              gsap.fromTo(formFeedback,
906                { y: -10, opacity: 0 },
907                { y: 0, opacity: 1, duration: 0.3 }
908              );
909            }
910          })
911          .catch(err => {
912            submitBtn.disabled = false;
913            submitBtn.style.opacity = '1';
914            if (submitBtnText) submitBtnText.textContent = 'Send Message';
915
916            formFeedback.textContent = 'Unable to send your message right now. Please try again later.';
917            formFeedback.classList.remove('hidden');
918            formFeedback.className = "text-center text-xs font-semibold uppercase tracking-wider py-3.5 rounded-2xl transition-all duration-300 text-rose-500 bg-rose-500/10 border border-rose-500/20";
919            gsap.fromTo(formFeedback,
920              { y: -10, opacity: 0 },
921              { y: 0, opacity: 1, duration: 0.3 }
922            );
923            console.error(err);
924          });
925      });
926
927      // Dismiss modal returning to index
928      closeModalBtn.addEventListener('click', () => {
929        gsap.to("#successModal > div", {
930          scale: 0.95,
931          y: 15,
932          opacity: 0,
933          duration: 0.3,
934          ease: "power2.in"
935        });
936        gsap.to(successModal, {
937          opacity: 0,
938          duration: 0.4,
939          ease: "power2.in",
940          onComplete: () => {
941            successModal.classList.add('pointer-events-none');
942            lenis.start();
943            window.location.href = 'index.html';
944          }
945        });
946      });
947
948    });
949  </script>
949
950</body>
951
952</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.