Files
demo-ayristech/components/templates/TaxiTemplate/index.tsx
T
2026-06-06 00:43:39 +03:00

1167 lines
59 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { motion, AnimatePresence } from "framer-motion";
import { useRef, useState, useEffect } from "react";
import type { DemoData } from "@/data/demos";
const fadeUp = {
hidden: { opacity: 0, y: 35 },
show: { opacity: 1, y: 0, transition: { duration: 0.75, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
};
const stagger = {
hidden: {},
show: { transition: { staggerChildren: 0.1 } },
};
const translations = {
tr: {
navBook: "Rezervasyon",
navTariffs: "Tarifeler",
navBenefits: "Ayrıcalıklar",
navApp: "Mobil Uygulama",
navReviews: "Misafir Yorumları",
callCenter: "Çağrı Merkezi",
bookNow: "Rezervasyon Yap",
badge: "NYC GÜVENİLİR PRİVATE CAB AĞI",
heroTitlePart1: "NYC'DE LÜKS",
heroTitlePart2: "BİR SEYAHAT?",
heroTitlePart3: "ÖZEL ŞOFÖRLÜ HAVAALANI TRANSFER SERVİSİ",
heroDesc: "New York genelinde 7/24 güvenli, yüksek konforlu özel araç hizmetleri. Havalimanı lounge transferlerinizi anında hesaplayın ve stressiz planlayın.",
instantBooking: "Hızlı Telefon Hattı",
getQuote: "Seyahat Hesapla",
viewTariffs: "Tarifeleri İncele",
fastFormSubtitle: "Hızlı Seyahat Formu",
fastFormTitle: "MİL HESAPLA & AYIRT",
fastFormDesc: "Konum parametrelerinizi girerek seyahat tutarınızı anında hesaplayın ve rezervasyon oluşturun.",
formName: "Ad Soyad",
formNamePlaceholder: "Adınız Soyadınız",
formPhone: "Telefon Numarası",
formPhonePlaceholder: "İletişim Numaranız",
formDate: "Tarih",
formTime: "Saat",
formPickup: "Alış Noktası",
formDropoff: "Varış Noktası",
chooseVehicle: "Araç Sınıfı Seçimi",
submitBooking: "REZERVASYONU BAŞLAT",
dispatchWarning: "Bu formu gönderdiğinizde, sürücümüz sizinle 3 dakika içinde iletişime geçecektir.",
tariffsSubtitle: "Esnek Fiyatlar",
tariffsTitle: "TARİFELERİMİZ",
tariffsDesc: "Seyahatlerinize en uygun lüks araç segmentini ve ücretlendirmelerini keşfedin.",
popular: "EN ÇOK TERCİH EDİLEN",
perMile: "/ MİL",
bookTariff: "BU TARİFEYİ SEÇ",
benefitsSubtitle: "Özel Ayrıcalıklar",
benefitsTitle: "HİZMET KALİTEMİZ",
benefitsDesc: "New York'taki iş dünyasının ve seçkin yolcuların bizi tercih etmesinin nedenleri.",
appSubtitle: "Uygulamayı İndirin",
appTitle: "MOBİL CAB UYGULAMASI",
appDesc: "CabHub mobil uygulamasını telefonunuza indirin. 7/24 GPS takibi yapın, uçuş rötar senkronizasyonu ile en özel fiyatlardan faydalanın.",
getItOn: "HEMEN İNDİRİN",
googlePlay: "Google Play Store",
appStore: "App Store",
reviewsSubtitle: "Müşteri Deneyimleri",
reviewsTitle: "MUTLU YOLCULARIMIZ",
reviewsDesc: "Sık seyahat eden iş insanlarımızın CabHub özel şoför hizmeti hakkındaki yorumları.",
callStripText: "7 GÜN 24 SAAT ÇAĞRILARINIZI CEVAPLAMAYA HAZIRIZ!",
footerRights: "Tüm hakları saklıdır.",
footerPrivacy: "Gizlilik Politikası",
footerTerms: "Kullanım Şartları",
bookingRequested: "REZERVASYON ALINDI",
nycDispatchActive: "NYC Sürücü Atama Hattı Aktif",
successDesc: "Seyahat parametrelerinizi kaydettik. En yakın CabHub lüks aracı ve sürücüsü 3 dakika içinde sizinle iletişime geçecektir. Keyifli yolculuklar dileriz!",
dismiss: "KAPAT",
conceptBanner: "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır.",
calcEstimated: "Tahmini Tutar:",
calcLoading: "Hesaplanıyor...",
min: "dk",
calculatingText: "Mesafe bazlı anlık ücretlendirme"
},
en: {
navBook: "Book Cab",
navTariffs: "Tariffs",
navBenefits: "Why Us",
navApp: "Mobile App",
navReviews: "Reviews",
callCenter: "Call Center",
bookNow: "Book Now",
badge: "NYC TRUSTED PRIVATE CAB NETWORK",
heroTitlePart1: "NEED A",
heroTitlePart2: "PREMIUM RIDE?",
heroTitlePart3: "NYC'S PREMIER PRIVATE TRANSFERS",
heroDesc: "Safe, high-fidelity premium luxury rides available 24/7 across New York City. Book instantly from our modern standard line or download our custom voucher app for secure rides.",
instantBooking: "Instant Booking Line",
getQuote: "Calculate Fare",
viewTariffs: "View Tariffs",
fastFormSubtitle: "Fast Ride Form",
fastFormTitle: "BOOK A CAB",
fastFormDesc: "Fill in your destination parameters below to calculate estimated fares and allocate a nearby premium cab.",
formName: "Name",
formNamePlaceholder: "Your full name",
formPhone: "Phone",
formPhonePlaceholder: "Contact Number",
formDate: "Date",
formTime: "Time",
formPickup: "Start Location",
formDropoff: "End Destination",
chooseVehicle: "Choose Vehicle",
submitBooking: "SUBMIT BOOKING",
dispatchWarning: "By submitting this form, you trigger immediate dispatch. A professional verified driver will contact you in under 3 minutes.",
tariffsSubtitle: "Flexible Rates",
tariffsTitle: "OUR TARIFFS",
tariffsDesc: "Choose the perfect ride category structured to fit your travel coordinates.",
popular: "POPULAR CHOICE",
perMile: "/ MILE",
bookTariff: "BOOK TARIFF",
benefitsSubtitle: "Premium Values",
benefitsTitle: "SOME BENEFITS",
benefitsDesc: "Why thousands of New Yorkers and high-profile businesses trust our private network.",
appSubtitle: "Download App",
appTitle: "BEST CAB SERVICES",
appDesc: "Download the CabHub voucher application on your phone. Book local transfers, coordinate with drivers using real-time GPS search, and access exclusive 40% member benefits dynamically.",
getItOn: "GET IT ON",
googlePlay: "Google Play",
appStore: "App Store",
reviewsSubtitle: "Testimonials",
reviewsTitle: "HAPPY CLIENTS",
reviewsDesc: "Hear what frequent business travelers say about the CabHub ride coordination.",
callStripText: "WE ARE READY TO TAKE YOUR CALL 24 HOURS, 7 DAYS!",
footerRights: "All rights reserved.",
footerPrivacy: "Privacy Policy",
footerTerms: "Terms of Service",
bookingRequested: "BOOKING REQUESTED",
nycDispatchActive: "NYC Dispatch Line Active",
successDesc: "We have registered your travel parameters. A professional verified CabHub chauffeur will reach out on your contact number in under 3 minutes. Thank you!",
dismiss: "DISMISS",
conceptBanner: "This website is a premium concept prototype designed by Ayris Tech.",
calcEstimated: "Estimated Fare:",
calcLoading: "Calculating...",
min: "min",
calculatingText: "Real-time coordinate-based pricing"
}
};
const locationsList = [
"Manhattan Midtown",
"Brooklyn Heights",
"Queens Astoria",
"JFK Airport",
"LaGuardia Airport"
];
export default function TaxiTemplate({ data }: { data: DemoData }) {
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
const [showBookingModal, setShowBookingModal] = useState(false);
const [activePlan, setActivePlan] = useState<number>(1); // Standard Class active by default
const [lang, setLang] = useState<"tr" | "en">("tr");
const [preloader, setPreloader] = useState(true);
// Fare Calculator states
const [pickupLoc, setPickupLoc] = useState("Manhattan Midtown");
const [dropoffLoc, setDropoffLoc] = useState("Brooklyn Heights");
const t = translations[lang];
const getIconSvg = (type: string) => {
switch (type) {
case "pickup":
return (
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 21v-4.875c0-.621.504-1.125 1.125-1.125h5.25c.621 0 1.125.504 1.125 1.125V21m0 0h4.5V3.545M12.75 7.5h.008v.008h-.008V7.5Zm0 2.25h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008v-.008Zm-4.5-9h.008v.008H8.25V7.5Zm0 2.25h.008v.008H8.25v-.008Zm0 2.25h.008v.008H8.25v-.008Zm0 2.25h.008v.008H8.25v-.008Zm-3.75 9H3.75V3.545m0 0A2.24 2.24 0 0 1 6 1.375c.66 0 1.272.285 1.706.777l.01.012M3.75 3.545V21h4.5M18.75 3.545V21h-4.5" />
</svg>
);
case "booking":
return (
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" />
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 13.5l10.5-11.25L12 9h8.25L9.75 20.25 12 13.5H3.75Z" />
</svg>
);
case "bonus":
return (
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M21 11.25v8.25a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5v-8.25M12 4.875A2.625 2.625 0 1 0 9.375 7.5H12m0-2.625V7.5m-9 3.75h18M12 7.5v13.5" />
</svg>
);
case "gps":
return (
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 6.75h15m-15 4.5h15m-15 4.5h15M3 6.75h.008v.008H3V6.75Zm0 4.5h.008v.008H3v-.008Zm0 4.5h.008v.008H3v-.008Z" />
<path strokeLinecap="round" strokeLinejoin="round" d="M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
<path strokeLinecap="round" strokeLinejoin="round" 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 1 1 15 0Z" />
</svg>
);
default:
return (
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
);
}
};
// 1. Lenis Smooth Scroll Setup
useEffect(() => {
let lenis: any;
import("@studio-freight/lenis").then(({ default: Lenis }) => {
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
requestAnimationFrame(raf);
});
return () => lenis?.destroy();
}, []);
// 2. Preloader timer
useEffect(() => {
const timer = setTimeout(() => {
setPreloader(false);
}, 1500);
return () => clearTimeout(timer);
}, []);
// Price estimate logic
const calculatePrice = () => {
if (pickupLoc === dropoffLoc) return "$5.00";
// JFK flat rates
if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "JFK Airport") ||
(pickupLoc === "JFK Airport" && dropoffLoc === "Manhattan Midtown")) {
return activePlan === 0 ? "$55.00" : activePlan === 1 ? "$75.00" : "$110.00";
}
// LaGuardia flat rates
if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "LaGuardia Airport") ||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "Manhattan Midtown")) {
return activePlan === 0 ? "$35.00" : activePlan === 1 ? "$48.00" : "$75.00";
}
// Mileage estimations based on distance
let miles = 8;
if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "Brooklyn Heights") ||
(pickupLoc === "Brooklyn Heights" && dropoffLoc === "Manhattan Midtown")) miles = 6;
else if ((pickupLoc === "Manhattan Midtown" && dropoffLoc === "Queens Astoria") ||
(pickupLoc === "Queens Astoria" && dropoffLoc === "Manhattan Midtown")) miles = 7;
else if ((pickupLoc === "Brooklyn Heights" && dropoffLoc === "Queens Astoria") ||
(pickupLoc === "Queens Astoria" && dropoffLoc === "Brooklyn Heights")) miles = 10;
else if ((pickupLoc === "Brooklyn Heights" && dropoffLoc === "JFK Airport") ||
(pickupLoc === "JFK Airport" && dropoffLoc === "Brooklyn Heights")) miles = 16;
else if ((pickupLoc === "Brooklyn Heights" && dropoffLoc === "LaGuardia Airport") ||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "Brooklyn Heights")) miles = 14;
else if ((pickupLoc === "Queens Astoria" && dropoffLoc === "JFK Airport") ||
(pickupLoc === "JFK Airport" && dropoffLoc === "Queens Astoria")) miles = 12;
else if ((pickupLoc === "Queens Astoria" && dropoffLoc === "LaGuardia Airport") ||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "Queens Astoria")) miles = 6;
else if ((pickupLoc === "JFK Airport" && dropoffLoc === "LaGuardia Airport") ||
(pickupLoc === "LaGuardia Airport" && dropoffLoc === "JFK Airport")) miles = 12;
const basePrice = miles * 1.6 + 5.0;
const multiplier = activePlan === 0 ? 1.0 : activePlan === 1 ? 1.5 : 2.2;
return `$${(basePrice * multiplier).toFixed(2)}`;
};
// Dynamic Localization handlers
const getLocalizedStat = (deger: string) => {
if (deger.toLowerCase().includes("economy")) {
return {
title: lang === "tr" ? "Ekonomi Sınıfı" : "Economy Class",
desc: lang === "tr" ? "Şehir içi seyahatleriniz için ideal, konforlu ve ekonomik ulaşım. Mil başı $1.50." : "Optimal zero-emission trips to any destination within boroughs. $1.5/MI"
};
}
if (deger.toLowerCase().includes("standard")) {
return {
title: lang === "tr" ? "Standart Sınıf" : "Standard Class",
desc: lang === "tr" ? "Havaalanı ve eyaletler arası transferler için premium sedanlar. Mil başı $2.25." : "Premium transfers. Verified luxury sedans covering tri-state airport hubs. $2.25/MI"
};
}
return {
title: lang === "tr" ? "Business Sınıfı" : "Business Class",
desc: lang === "tr" ? "Lüks araç filomuz ve öncelikli sürücü atama ayrıcalığı. Mil başı $3.50." : "First class executive. Top-tier luxury vehicles with priority lane dispatch. $3.50/MI"
};
};
const getLocalizedService = (baslik: string, aciklama: string) => {
if (baslik.toLowerCase().includes("pickup") || baslik.toLowerCase().includes("home")) {
return {
title: lang === "tr" ? "ADRESTEN ALIM" : "HOME PICKUP",
desc: lang === "tr" ? "Kapınızdan veya otel lobinizden bagaj desteği ve koordinatlı karşılama ile lüks seyahat başlangıcı." : "We run services to serve you more better and to your convenience."
};
}
if (baslik.toLowerCase().includes("booking") || baslik.toLowerCase().includes("fast")) {
return {
title: lang === "tr" ? "KOLAY REZERVASYON" : "FAST BOOKING",
desc: lang === "tr" ? "Sadece birkaç tıkla seyahat parametrelerinizi belirleyin, stressiz rezervasyon yapın." : "Our book method is very fast and easy. It won't stress you."
};
}
if (baslik.toLowerCase().includes("bonus") || baslik.toLowerCase().includes("member")) {
return {
title: lang === "tr" ? "MİL & ÜYELİK AVANTAJLARI" : "BONUSES FOR RIDE",
desc: lang === "tr" ? "Bizimle yaptığınız her yolculukta mil puanları toplayın, sonraki rezervasyonlarda %40'a varan indirim kazanın." : "When you run services frequently we give you different bonuses that can put a smile on your face."
};
}
return {
title: lang === "tr" ? "7/24 AKTİF GPS TAKİBİ" : "GPS SEARCHING",
desc: lang === "tr" ? "Uçuş rötar senkronizasyonu ve 7/24 anlık uydu üzerinden konum takibi ile mutlak güvendesiniz." : "We run services incase you aren't sure of your destination. So you don't have to worry."
};
};
const getLocalizedTestimonial = (yazar: string) => {
if (yazar.toLowerCase().includes("john")) {
return lang === "tr"
? "CabHub NYC iş seyahatlerimde en güvendiğim ulaşım ortağım oldu. Standart sınıf araçları pırıl pırıldı ve sürücü tüm kestirmeleri biliyordu."
: "CabHub NYC provided the most reliable ride during my business trip. The standard class vehicle was pristine and the driver knew all the shortcuts.";
}
return lang === "tr"
? "Hızlı rezervasyon sistemi tek kelimeyle kusursuz çalışıyor. Adresten alım tam dakikasında gerçekleşti ve GPS takibi kendimi inanılmaz güvende hissettirdi."
: "The fast booking system works like a charm. Home pickup was exactly on time and the GPS tracking made me feel incredibly secure.";
};
const css = `
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;700;900&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Syne:wght@700;800&display=swap');
:root {
--color-taxi-yellow: #F5C518;
--color-taxi-yellow-rgb: 245, 197, 24;
--color-coal-dark: #07080A;
--color-coal-card: #121418;
--color-coal-card-hover: #181C22;
--color-text-white: #FFFFFF;
--color-text-gray: rgba(255, 255, 255, 0.6);
}
.font-industrial {
font-family: 'Syne', 'Oswald', sans-serif;
}
.font-sans-premium {
font-family: 'Plus Jakarta Sans', sans-serif;
}
.spinning-badge {
animation: spin 25s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.bg-mesh-grid {
background-image:
linear-gradient(rgba(245, 197, 24, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(245, 197, 24, 0.03) 1px, transparent 1px);
background-size: 40px 40px;
}
.glowing-bar {
box-shadow: 0 0 15px rgba(245, 197, 24, 0.4);
}
.pulse-glow {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(245, 197, 24, 0.5); }
70% { box-shadow: 0 0 0 15px rgba(245, 197, 24, 0); }
100% { box-shadow: 0 0 0 0 rgba(245, 197, 24, 0); }
}
.hero-title-clamp {
font-size: clamp(34px, 5.8vw, 84px);
letter-spacing: -0.01em;
line-height: 0.95;
}
`;
return (
<>
<style>{css}</style>
{/* ── IMZA AN: HIGH-TECH PRELOADER ── */}
<AnimatePresence>
{preloader && (
<motion.div
className="fixed inset-0 z-50 bg-[#07080A] flex flex-col items-center justify-center p-6"
exit={{
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
}}
>
<div className="max-w-md text-center space-y-6">
<motion.span
className="text-[9px] font-black tracking-[4px] uppercase text-[#F5C518] block font-sans-premium"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
CABHUB DISPATCH SYSTEM
</motion.span>
<div className="h-[2px] w-48 bg-white/10 mx-auto relative overflow-hidden">
<motion.div
className="absolute inset-y-0 left-0 bg-[#F5C518] glowing-bar"
initial={{ width: "0%" }}
animate={{ width: "100%" }}
transition={{ duration: 1.2, ease: "easeInOut" }}
/>
</div>
<motion.h2
className="font-industrial text-white text-base font-black tracking-widest uppercase"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4, duration: 0.5 }}
>
connecting...
</motion.h2>
</div>
</motion.div>
)}
</AnimatePresence>
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
<div className="fixed bottom-4 left-4 z-40 bg-[#121418]/95 backdrop-blur-md border border-[#F5C518]/20 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
<div className="w-1.5 h-1.5 rounded-full bg-[#F5C518] animate-pulse" />
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90 font-sans-premium">
{t.conceptBanner}
</span>
</div>
{/* ── MAIN CONTENT CONTAINER (Sleek Obsidian Theme) ── */}
<div className="bg-[#07080A] text-white min-h-screen font-sans-premium selection:bg-[#F5C518] selection:text-black overflow-hidden relative">
{/* Decorative Mesh Background */}
<div className="absolute inset-0 bg-mesh-grid pointer-events-none z-0" />
{/* Floating Ambient Yellow Glow Orbs */}
<div className="absolute top-[20%] left-[-10%] w-[500px] h-[500px] bg-[#F5C518]/5 blur-[120px] rounded-full pointer-events-none z-0" />
<div className="absolute bottom-[20%] right-[-10%] w-[500px] h-[500px] bg-[#F5C518]/3 blur-[140px] rounded-full pointer-events-none z-0" />
{/* ── FLOATING NAVBAR ── */}
<motion.header
className="fixed top-4 left-4 right-4 z-50 px-4"
initial={{ y: -80, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.7, ease: "easeOut" }}
>
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-[#121418]/80 backdrop-blur-xl border border-white/5 rounded-2xl shadow-[0_15px_30px_rgba(0,0,0,0.5)]">
{/* Logo */}
<a href="#" className="flex items-center gap-2 group">
<div className="w-10 h-10 rounded-xl bg-[#F5C518] flex items-center justify-center shadow-[0_0_15px_rgba(245,197,24,0.3)] transition-transform group-hover:scale-105">
<svg className="w-6 h-6 fill-black" viewBox="0 0 24 24">
<path d="M22 10.07V6c0-.55-.45-1-1-1h-2v-.07c0-.9-.72-1.63-1.61-1.68C17.15 3.12 17 3.32 17 3.5V5h-2V3.5c0-.18-.15-.38-.39-.25-.89.05-1.61.78-1.61 1.68V5H5c-.55 0-1 .45-1 1v4.07c-1.19.43-2 1.56-2 2.93v3c0 .55.45 1 1 1h1v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h10v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h1c.55 0 1-.45 1-1v-3c0-1.37-.81-2.5-2-2.93z" />
</svg>
</div>
<span className="text-xl font-black tracking-wider text-white font-industrial uppercase">
CAB<span className="text-[#F5C518]">HUB</span>
</span>
</a>
{/* Navigation Links */}
<nav className="hidden lg:flex items-center gap-8">
{[
{ label: t.navBook, href: "#booking-flow" },
{ label: t.navTariffs, href: "#tariffs" },
{ label: t.navBenefits, href: "#benefits" },
{ label: t.navApp, href: "#app-showcase" },
{ label: t.navReviews, href: "#testimonials" }
].map(item => (
<a
key={item.label}
href={item.href}
className="text-[11px] font-bold tracking-[1.5px] uppercase text-white/70 hover:text-[#F5C518] transition-colors relative py-1 cursor-pointer group"
>
{item.label}
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#F5C518] transition-all group-hover:w-full" />
</a>
))}
</nav>
{/* Quick Contact & Action */}
<div className="flex items-center gap-6">
{/* Language Switcher */}
<div className="flex items-center gap-1 bg-white/5 border border-white/10 rounded-xl p-1 shrink-0">
<button
onClick={() => setLang("tr")}
className={`text-[9px] font-black px-2.5 py-1.5 rounded-lg transition-all cursor-pointer font-sans-premium ${
lang === "tr" ? "bg-[#F5C518] text-black shadow-sm" : "text-white/60 hover:text-white"
}`}
>
TR
</button>
<button
onClick={() => setLang("en")}
className={`text-[9px] font-black px-2.5 py-1.5 rounded-lg transition-all cursor-pointer font-sans-premium ${
lang === "en" ? "bg-[#F5C518] text-black shadow-sm" : "text-white/60 hover:text-white"
}`}
>
EN
</button>
</div>
<motion.button
onClick={() => setShowBookingModal(true)}
className="text-[11px] font-black tracking-[2px] uppercase text-black bg-[#F5C518] hover:bg-white px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_5px_15px_rgba(245,197,24,0.2)] hidden sm:block"
whileHover={{ scale: 1.03 }}
whileTap={{ scale: 0.98 }}
>
{t.bookNow}
</motion.button>
</div>
</div>
</motion.header>
{/* ── HERO & BOOKING SECTION ── */}
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
<div className="max-w-7xl mx-auto w-full">
<div className="grid lg:grid-cols-12 gap-12 items-center">
{/* Left Column: Heading and Badge */}
<motion.div
className="lg:col-span-7 z-20"
variants={stagger}
initial="hidden"
animate="show"
>
{/* Yellow Accent Badge */}
<motion.div
variants={fadeUp}
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#F5C518] mb-6 bg-[#F5C518]/10 border border-[#F5C518]/20 px-4 py-2 rounded-full"
>
<span className="w-1.5 h-1.5 rounded-full bg-[#F5C518] animate-pulse" />
{t.badge}
</motion.div>
<motion.h1
variants={fadeUp}
className="font-industrial font-black text-white mb-6 uppercase hero-title-clamp"
>
{t.heroTitlePart1}
<br />
<span className="text-[#F5C518]">{t.heroTitlePart2}</span>
</motion.h1>
<motion.p
variants={fadeUp}
className="text-white/60 text-sm lg:text-base leading-relaxed max-w-xl mb-10 font-medium"
>
{t.heroDesc}
</motion.p>
{/* Call Booking Center */}
<motion.div
variants={fadeUp}
className="flex items-center gap-6 mb-12"
>
<div className="w-14 h-14 rounded-2xl bg-[#121418] border border-[#F5C518]/20 flex items-center justify-center shrink-0">
<svg className="w-6 h-6 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.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.802-5.12-4.098-6.922-6.922l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H3.75A2.25 2.25 0 0 0 2.25 4.5v2.25Z" />
</svg>
</div>
<div>
<div className="text-[11px] uppercase tracking-widest text-white/40 font-bold">{t.instantBooking}</div>
<a href={`tel:${firma.telefon}`} className="text-3xl font-black text-white hover:text-[#F5C518] transition-colors font-industrial tracking-wide">
{firma.telefon}
</a>
</div>
</motion.div>
{/* CTA Buttons */}
<motion.div variants={fadeUp} className="flex gap-4">
<a
href="#booking-flow"
className="px-8 py-4 rounded-xl bg-[#F5C518] hover:bg-white text-black font-black text-xs uppercase tracking-wider transition-all shadow-[0_5px_20px_rgba(245,197,24,0.3)] cursor-pointer"
>
{t.getQuote}
</a>
<a
href="#tariffs"
className="px-8 py-4 rounded-xl border border-white/10 bg-white/5 hover:bg-white/10 text-white font-black text-xs uppercase tracking-wider transition-all cursor-pointer"
>
{t.viewTariffs}
</a>
</motion.div>
</motion.div>
{/* Right Column: Hero Car & Parallax Plate */}
<div className="lg:col-span-5 relative flex justify-center lg:justify-end">
<motion.div
className="relative w-full max-w-md lg:max-w-lg h-[400px] lg:h-[480px] flex items-center justify-center"
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.85, ease: "easeOut" }}
>
{/* Outer circle overlay */}
<div className="absolute inset-0 rounded-full border-2 border-dashed border-[#F5C518]/10 animate-[spin_60s_linear_infinite]" />
{/* High fidelity Yellow cab image */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/cab_hero_yellow.png"
alt="CabHub Yellow Sedan Premium NYC Cab"
className="w-full h-full object-contain relative z-10 drop-shadow-[0_20px_50px_rgba(245,197,24,0.15)]"
/>
{/* Floating badge rotating around */}
<div className="absolute bottom-0 right-0 z-20 w-32 h-32 flex items-center justify-center">
<svg className="absolute w-full h-full spinning-badge" viewBox="0 0 100 100">
<path id="badgePath" d="M 50, 50 m -35, 0 a 35,35 0 1,1 70,0 a 35,35 0 1,1 -70,0" fill="none" />
<text className="font-industrial font-bold text-[8.5px] fill-[#F5C518] tracking-[1.8px]">
<textPath xlinkHref="#badgePath">
BOOK A RIDE PREMIUM CAR SERVICE 24/7
</textPath>
</text>
</svg>
<div className="w-12 h-12 rounded-full bg-[#121418] border border-[#F5C518]/30 flex items-center justify-center z-10 shadow-lg">
<svg className="w-5 h-5 fill-[#F5C518]" viewBox="0 0 24 24">
<path d="M22 10.07V6c0-.55-.45-1-1-1h-2v-.07c0-.9-.72-1.63-1.61-1.68C17.15 3.12 17 3.32 17 3.5V5h-2V3.5c0-.18-.15-.38-.39-.25-.89.05-1.61.78-1.61 1.68V5H5c-.55 0-1 .45-1 1v4.07c-1.19.43-2 1.56-2 2.93v3c0 .55.45 1 1 1h1v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h10v1.5c0 .83.67 1.5 1.5 1.5h1c.83 0 1.5-.67 1.5-1.5V18h1c.55 0 1-.45 1-1v-3c0-1.37-.81-2.5-2-2.93z" />
</svg>
</div>
</div>
</motion.div>
</div>
</div>
</div>
</section>
{/* ── INTERACTIVE TARIFF CALCULATOR WIDGET ── */}
<section id="booking-flow" className="py-24 relative z-10 px-6 border-t border-[#F5C518]/10 bg-[#0B0C0E]">
<div className="max-w-7xl mx-auto">
<div className="bg-[#121418] rounded-3xl border border-white/5 p-8 md:p-12 shadow-2xl relative">
{/* Glow border header indicator */}
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#F5C518] to-transparent glowing-bar" />
<div className="text-center max-w-xl mx-auto mb-12">
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.fastFormSubtitle}</span>
<h2 className="font-industrial text-3xl md:text-4xl font-black uppercase text-white">
{t.fastFormTitle}
</h2>
<p className="text-white/40 text-xs mt-2 font-medium">
{t.fastFormDesc}
</p>
</div>
{/* Form Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{[
{ label: t.formName, placeholder: t.formNamePlaceholder, type: "text" },
{ label: t.formPhone, placeholder: t.formPhonePlaceholder, type: "tel" },
{ label: t.formDate, placeholder: "", type: "date" },
{ label: t.formTime, placeholder: "", type: "time" },
].map((field, idx) => (
<div key={idx} className="flex flex-col">
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{field.label}</label>
<input
type={field.type}
placeholder={field.placeholder}
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#0B0C0E] text-sm text-white placeholder-white/20 focus:outline-none focus:border-[#F5C518] focus:ring-1 focus:ring-[#F5C518] transition-all font-sans-clean font-medium"
/>
</div>
))}
{/* Interactive Pickup Location */}
<div className="flex flex-col">
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{t.formPickup}</label>
<select
value={pickupLoc}
onChange={(e) => setPickupLoc(e.target.value)}
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#0B0C0E] text-sm text-white focus:outline-none focus:border-[#F5C518] transition-all font-sans-clean font-medium cursor-pointer"
>
{locationsList.map(loc => <option key={loc} value={loc} className="bg-[#121418] text-white">{loc}</option>)}
</select>
</div>
{/* Interactive Dropoff Location */}
<div className="flex flex-col">
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{t.formDropoff}</label>
<select
value={dropoffLoc}
onChange={(e) => setDropoffLoc(e.target.value)}
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#0B0C0E] text-sm text-white focus:outline-none focus:border-[#F5C518] transition-all font-sans-clean font-medium cursor-pointer"
>
{locationsList.map(loc => <option key={loc} value={loc} className="bg-[#121418] text-white">{loc}</option>)}
</select>
</div>
{/* Choose Vehicle */}
<div className="flex flex-col md:col-span-2">
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{t.chooseVehicle}</label>
<div className="grid grid-cols-3 gap-2 h-full">
{["Economy", "Standard", "Business"].map((option, oIdx) => (
<button
key={option}
onClick={() => setActivePlan(oIdx)}
className={`py-3.5 px-3 rounded-xl border text-xs font-bold transition-all cursor-pointer flex items-center justify-center gap-1.5 ${
activePlan === oIdx
? "bg-[#F5C518] text-black border-[#F5C518]"
: "bg-[#0B0C0E] text-white/60 border-white/5 hover:border-white/20"
}`}
>
<span className="w-1.5 h-1.5 rounded-full" style={{ backgroundColor: activePlan === oIdx ? "black" : "#F5C518" }} />
{option}
</button>
))}
</div>
</div>
</div>
{/* ESTIMATED FARE BANNER */}
<div className="mt-8 p-6 bg-[#0B0C0E] border border-white/5 rounded-2xl flex flex-col sm:flex-row justify-between items-center gap-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-[#F5C518]/10 border border-[#F5C518]/20 flex items-center justify-center shrink-0">
<span className="text-[#F5C518] text-lg font-black font-industrial">$</span>
</div>
<div>
<span className="text-white/40 text-[9px] uppercase tracking-widest font-black block">{t.calculatingText}</span>
<span className="font-industrial text-white text-sm font-bold uppercase tracking-wider">{t.calcEstimated} <span className="text-[#F5C518] text-base">{calculatePrice()}</span></span>
</div>
</div>
<div className="text-[10px] font-bold text-white/40 leading-relaxed font-sans-clean text-center sm:text-right">
Flat-rate airport vouchers apply dynamically between JFK / LaGuardia and Manhattan.
</div>
</div>
{/* Submit Action */}
<div className="mt-8 pt-4 flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-white/40 text-xs font-medium max-w-md text-center md:text-left">
{t.dispatchWarning}
</p>
<motion.button
onClick={() => setShowBookingModal(true)}
className="w-full md:w-auto px-10 py-4.5 rounded-xl bg-[#F5C518] hover:bg-white text-black font-black text-xs uppercase tracking-widest transition-all cursor-pointer shadow-[0_5px_15px_rgba(245,197,24,0.3)] shrink-0"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{t.submitBooking}
</motion.button>
</div>
</div>
</div>
</section>
{/* ── OUR TARIFFS (Subscription Cards) ── */}
<section id="tariffs" className="py-32 relative z-10 px-6 bg-[#07080A]">
<div className="max-w-7xl mx-auto">
<div className="text-center max-w-xl mx-auto mb-20">
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.tariffsSubtitle}</span>
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
{t.tariffsTitle}
</h2>
<p className="text-white/40 text-xs mt-2 font-medium">
{t.tariffsDesc}
</p>
</div>
{/* Three Tariff Cards Grid */}
<div className="grid lg:grid-cols-3 gap-8">
{istatistikler.map((stat, sIdx) => {
const locStat = getLocalizedStat(stat.deger);
const isPopular = stat.deger === "Standard Class";
return (
<motion.div
key={sIdx}
className={`relative rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 group ${
isPopular
? "bg-[#121418] border-2 border-[#F5C518] shadow-[0_15px_40px_rgba(245,197,24,0.08)]"
: "bg-[#121418]/60 border border-white/5 hover:border-white/15"
}`}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: sIdx * 0.1 }}
whileHover={{ y: -6 }}
>
{isPopular && (
<div className="absolute -top-3.5 left-1/2 -translate-x-1/2 px-4 py-1 bg-[#F5C518] text-black text-[9px] font-black uppercase tracking-widest rounded-full z-10">
{t.popular}
</div>
)}
<div>
{/* Car vector silhouette placeholder */}
<div className="h-28 flex items-center justify-center border-b border-white/5 mb-8 relative">
<svg className={`w-32 h-16 ${isPopular ? "fill-[#F5C518]" : "fill-white/30 group-hover:fill-[#F5C518]"} transition-colors`} viewBox="0 0 24 24">
<path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z" />
</svg>
</div>
<h3 className="font-industrial font-black text-2xl uppercase tracking-wider text-white mb-2">
{locStat.title}
</h3>
<p className="text-white/60 text-xs leading-relaxed mb-8 font-medium">
{locStat.desc}
</p>
</div>
<div>
{/* Price Display */}
<div className="flex items-baseline gap-1.5 mb-8">
<span className="text-3xl font-black text-[#F5C518] font-industrial">
{sIdx === 0 ? "$1.50" : sIdx === 1 ? "$2.20" : "$3.50"}
</span>
<span className="text-white/40 text-xs uppercase tracking-widest font-bold">{t.perMile}</span>
</div>
<motion.button
onClick={() => {
setActivePlan(sIdx);
const el = document.getElementById("booking-flow");
el?.scrollIntoView({ behavior: "smooth" });
}}
className={`w-full py-4.5 rounded-xl font-black text-xs uppercase tracking-widest transition-all cursor-pointer ${
isPopular
? "bg-[#F5C518] hover:bg-white text-black shadow-lg"
: "bg-[#0B0C0E] hover:bg-white/5 text-white/70 border border-white/5 hover:border-white/10"
}`}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{t.bookTariff}
</motion.button>
</div>
</motion.div>
);
})}
</div>
</div>
</section>
{/* ── OUR BENEFITS ── */}
<section id="benefits" className="py-28 relative z-10 px-6 bg-[#0B0C0E] border-t border-[#F5C518]/5">
<div className="max-w-7xl mx-auto">
<div className="text-center max-w-xl mx-auto mb-20">
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.benefitsSubtitle}</span>
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
{t.benefitsTitle}
</h2>
<p className="text-white/40 text-xs mt-2 font-medium">
{t.benefitsDesc}
</p>
</div>
{/* Grid display of benefits */}
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
{hizmetler.map((benefit, bIdx) => {
const locBenefit = getLocalizedService(benefit.baslik, benefit.aciklama);
return (
<motion.div
key={bIdx}
className="bg-[#121418] rounded-2xl p-8 border border-white/5 hover:border-[#F5C518]/30 transition-all duration-300 flex flex-col items-center text-center group cursor-default shadow-sm"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: bIdx * 0.1 }}
whileHover={{ y: -4 }}
>
<div className="w-16 h-16 rounded-2xl bg-[#0B0C0E] border border-white/5 flex items-center justify-center mb-6 transition-transform group-hover:scale-105 group-hover:border-[#F5C518]/30">
{getIconSvg(benefit.ikon)}
</div>
<h3 className="font-industrial font-black text-lg text-white mb-3 tracking-wider uppercase">
{locBenefit.title}
</h3>
<p className="text-white/50 text-[11px] leading-relaxed font-medium">
{locBenefit.desc}
</p>
</motion.div>
);
})}
</div>
</div>
</section>
{/* ── APP DOWNLOAD SHOWCASE ── */}
<section id="app-showcase" className="py-32 relative z-10 px-6 bg-[#07080A] border-t border-[#F5C518]/5">
<div className="max-w-7xl mx-auto">
<div className="grid lg:grid-cols-12 gap-16 items-center">
{/* Left Column: Heading and action badges */}
<motion.div
className="lg:col-span-6 z-20"
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.2 }}
variants={stagger}
>
<motion.span
variants={fadeUp}
className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial"
>
{t.appSubtitle}
</motion.span>
<motion.h2
variants={fadeUp}
className="font-industrial text-4xl lg:text-5xl font-black tracking-tight text-white uppercase mb-6"
>
{t.appTitle}
</motion.h2>
<motion.p
variants={fadeUp}
className="text-white/60 text-sm leading-relaxed mb-10 max-w-md font-medium"
>
{t.appDesc}
</motion.p>
{/* Badges buttons */}
<motion.div
variants={fadeUp}
className="flex items-center gap-4 flex-wrap"
>
{/* Google Play */}
<a href="#" className="flex items-center gap-3 px-6 py-3 rounded-xl bg-[#121418] hover:bg-[#181C22] border border-white/5 hover:border-white/10 transition-colors shadow-lg cursor-pointer group">
<svg className="w-6 h-6 fill-[#F5C518]" viewBox="0 0 24 24">
<path d="M5 2c-.37 0-.71.18-.91.49l10.96 10.96 3.1-3.1L5.6 3.12C5.41 3.04 5.21 2 5 2zm10.75 11.21L4.69 22.42c.19-.07.38-.17.51-.29l12.65-7.3a1.5 1.5 0 0 0 .15-.15l-2.25-1.47zM3.19 3.81C3.07 4.17 3 4.58 3 5v14c0 .42.07.83.19 1.19l9.31-9.31-9.31-9.07z" />
</svg>
<div className="text-left">
<div className="text-[8px] text-white/40 uppercase tracking-wider font-bold">{t.getItOn}</div>
<div className="text-xs font-black text-white font-industrial tracking-wide">{t.googlePlay}</div>
</div>
</a>
{/* App Store */}
<a href="#" className="flex items-center gap-3 px-6 py-3 rounded-xl bg-[#121418] hover:bg-[#181C22] border border-white/5 hover:border-white/10 transition-colors shadow-lg cursor-pointer group">
<svg className="w-6 h-6 fill-[#F5C518]" viewBox="0 0 24 24">
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M15.97 4.17c.66-.81 1.11-1.93.99-3.06-1 .04-2.21.67-2.93 1.49-.62.69-1.16 1.84-1.01 2.96 1.12.09 2.27-.57 2.95-1.39z" />
</svg>
<div className="text-left">
<div className="text-[8px] text-white/40 uppercase tracking-wider font-bold">{t.getItOn}</div>
<div className="text-xs font-black text-white font-industrial tracking-wide">{t.appStore}</div>
</div>
</a>
</motion.div>
</motion.div>
{/* Right Column: Hand holding smartphone flatlay mockup */}
<div className="lg:col-span-6 relative flex justify-center lg:justify-end">
<motion.div
className="relative w-full max-w-md lg:max-w-lg h-[450px] lg:h-[520px] rounded-[36px] overflow-hidden shadow-2xl border border-white/10 group"
initial={{ opacity: 0, x: 40 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.7 }}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/cab_app_mockup.png"
alt="CabHub Booking Digital Phone Interface Map"
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms]"
/>
</motion.div>
</div>
</div>
</div>
</section>
{/* ── TESTIMONIAL GRID ── */}
<section id="testimonials" className="py-28 relative z-10 px-6 bg-[#0B0C0E] border-t border-[#F5C518]/5">
<div className="max-w-7xl mx-auto">
<div className="text-center max-w-xl mx-auto mb-20">
<span className="text-[#F5C518] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.reviewsSubtitle}</span>
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
{t.reviewsTitle}
</h2>
<p className="text-white/40 text-xs mt-2 font-medium">
{t.reviewsDesc}
</p>
</div>
{/* Testimonials 2-Column Layout */}
<div className="grid md:grid-cols-2 gap-8">
{yorumlar.map((y, yIdx) => {
const locTestimonial = getLocalizedTestimonial(y.yazar);
return (
<motion.div
key={yIdx}
className="bg-[#121418] border border-white/5 rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 hover:border-[#F5C518]/30 group"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: yIdx * 0.1 }}
whileHover={{ y: -4 }}
>
{/* Rating Stars SVG */}
<div className="flex gap-1 mb-6">
{[...Array(5)].map((_, starIdx) => (
<svg key={starIdx} className="w-4.5 h-4.5 fill-[#F5C518]" viewBox="0 0 24 24">
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
</svg>
))}
</div>
<p className="text-white/70 text-xs leading-relaxed italic mb-8 font-medium">
&ldquo;{locTestimonial}&rdquo;
</p>
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full border border-white/10 flex items-center justify-center text-xs font-sans-premium font-black bg-[#0B0C0E] select-none text-[#F5C518]">
{y.yazar.charAt(0)}
</div>
<div>
<h4 className="font-industrial text-white text-xs font-black uppercase tracking-wider">
{y.yazar}
</h4>
<span className="text-[9px] text-white/40 uppercase tracking-widest font-bold">
{y.tarih}
</span>
</div>
</div>
</motion.div>
);
})}
</div>
</div>
</section>
{/* ── BOTTOM CALL RESERVATION DIRECT STRIP ── */}
<section className="relative z-10 bg-[#F5C518] text-black py-8 px-6 text-center pulse-glow overflow-hidden">
<div className="max-w-7xl mx-auto relative z-10 flex flex-col md:flex-row justify-between items-center gap-4">
<h3 className="font-industrial font-black text-base md:text-xl uppercase tracking-wider text-black text-center md:text-left">
{t.callStripText}
</h3>
<a href={`tel:${firma.telefon}`} className="inline-flex items-center gap-3 px-8 py-3.5 bg-black hover:bg-white text-white hover:text-black rounded-xl font-industrial font-black tracking-widest uppercase transition-all shadow-[0_5px_15px_rgba(0,0,0,0.3)] text-sm cursor-pointer">
📞 {firma.telefon}
</a>
</div>
{/* subtle moving abstract banner lines */}
<div className="absolute inset-0 bg-white/5 mix-blend-overlay opacity-30 pointer-events-none" />
</section>
{/* ── FOOTER ── */}
<footer className="bg-[#0B0C0E] border-t border-white/5 pt-24 pb-8 px-6 relative z-10">
<div className="max-w-7xl mx-auto">
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
{/* About Column */}
<div className="md:col-span-2">
<span className="font-industrial text-2xl font-black text-white tracking-wider uppercase mb-4 block">
CAB<span className="text-[#F5C518]">HUB</span>
</span>
<p className="text-white/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
{firma.slogan} Safe, verified, high-fidelity premium luxury sedan cab rides across New York City and global destinations.
</p>
<div className="text-white/60 text-xs font-medium space-y-2">
<p className="flex items-center gap-2">📍 <span className="text-white/80">{firma.adres}</span></p>
<p className="flex items-center gap-2">📧 <span className="text-white/80">{firma.email}</span></p>
</div>
</div>
{/* Download links */}
<div>
<h4 className="font-industrial text-[#F5C518] text-xs font-black uppercase tracking-wider mb-6">
DOWNLOAD APP
</h4>
<div className="space-y-4">
<a href="#" className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium">
Google Play Store App
</a>
<a href="#" className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium">
Apple iOS App Store
</a>
<a href="#" className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium">
Direct Web Voucher Portal
</a>
</div>
</div>
{/* Navigation links */}
<div>
<h4 className="font-industrial text-[#F5C518] text-xs font-black uppercase tracking-wider mb-6">
USEFUL LINKS
</h4>
<div className="space-y-4">
{["Book a Cab", "Economy & Business Tariffs", "Our Core Benefits", "Happy Reviews", "Terms & Regulations"].map(item => (
<a
key={item}
href="#"
className="block text-white/50 hover:text-[#F5C518] text-xs transition-colors font-medium"
>
{item}
</a>
))}
</div>
</div>
</div>
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-medium font-sans-premium">
<p>© 2026 {firma.adi}. {t.footerRights}</p>
<div className="flex gap-4">
<a href="#" className="hover:text-white transition-colors">{t.footerPrivacy}</a>
<span>·</span>
<a href="#" className="hover:text-white transition-colors">{t.footerTerms}</a>
</div>
</div>
</div>
</footer>
{/* ── FAST BOOKING SUCCESS MODAL ── */}
<AnimatePresence>
{showBookingModal && (
<motion.div
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/85 backdrop-blur-sm"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<motion.div
className="bg-[#121418] rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-[#F5C518]/20"
initial={{ scale: 0.95, y: 20 }}
animate={{ scale: 1, y: 0 }}
exit={{ scale: 0.95, y: 20 }}
>
{/* Close Button */}
<button
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#0B0C0E] border border-white/5 flex items-center justify-center text-white/40 hover:text-[#F5C518] hover:border-[#F5C518]/20 transition-all cursor-pointer"
onClick={() => setShowBookingModal(false)}
>
</button>
{/* Visual success indicator */}
<div className="w-16 h-16 rounded-2xl bg-[#F5C518]/10 border border-[#F5C518]/20 flex items-center justify-center mb-6">
<svg className="w-8 h-8 stroke-[#F5C518] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</div>
<h3 className="font-industrial font-black text-white text-2xl mb-1 uppercase tracking-wider">
{t.bookingRequested}
</h3>
<p className="text-[#F5C518] font-mono text-[10px] mb-6 uppercase tracking-widest font-bold">
{t.nycDispatchActive}
</p>
<p className="text-white/60 text-xs leading-relaxed mb-8 font-medium">
{t.successDesc}
</p>
<motion.button
className="w-full py-4.5 rounded-xl bg-[#F5C518] hover:bg-white text-black font-black text-xs uppercase tracking-widest cursor-pointer shadow-[0_5px_15px_rgba(245,197,24,0.3)]"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
onClick={() => setShowBookingModal(false)}
>
{t.dismiss}
</motion.button>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</div>
</>
);
}