+page.svelte 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <script>
  2. import { onMount } from 'svelte';
  3. let scrollY = $state(0);
  4. let mobileMenuOpen = $state(false);
  5. let lightboxOpen = $state(false);
  6. let lightboxIndex = $state(0);
  7. let galleryExpanded = $state(false);
  8. const WHATSAPP = 'https://wa.me/50689630901?text=Hi!%20I%27d%20like%20to%20book%20a%20fishing%20trip';
  9. const PHONE = 'tel:+50689630901';
  10. const navLinks = [
  11. { label: 'About', href: '#about' },
  12. { label: 'Fleet', href: '#fleet' },
  13. { label: 'Trips', href: '#trips' },
  14. { label: 'Gallery', href: '#gallery' },
  15. { label: 'Contact', href: '#contact' }
  16. ];
  17. const fleet = [
  18. {
  19. name: 'Gunslinger',
  20. brand: "Clear Water 25'",
  21. year: '2007 (Restored 2025)',
  22. engine: 'Suzuki 200 HP',
  23. capacity: '4–5 passengers',
  24. features: ['Outriggers', 'Rod holders', 'Toilet', 'Live well'],
  25. image: '/boats/gunslinger-marina-side.jpg',
  26. desc: 'Fully restored in 2025 with all new equipment. Agile and versatile — perfect for chasing roosterfish and snook inshore, and just as ready to run offshore for sailfish, mahi-mahi and more.'
  27. },
  28. {
  29. name: 'Gunslinger II',
  30. brand: "Grady-White 25.3'",
  31. year: '2022',
  32. engine: '2× Suzuki 200 HP (44 kts)',
  33. capacity: 'Up to 8 passengers',
  34. features: ['Radar', '3 Navigators', '2 Fishfinders', 'VHF Radio', 'Toilet', 'Fresh water', 'Live well'],
  35. image: '/boats/gradywhite-gunslinger2-sunset.jpg',
  36. desc: 'Our premium offshore machine. Twin engines, full electronics suite, and room for the whole crew. Built for comfort on long offshore runs.'
  37. }
  38. ];
  39. const species = [
  40. { name: 'Roosterfish', tag: 'Signature Catch' },
  41. { name: 'Sailfish', tag: 'Catch & Release' },
  42. { name: 'Snook', tag: 'Inshore Trophy' },
  43. { name: 'Red Snapper', tag: 'Year-Round' },
  44. { name: 'Mahi-Mahi', tag: 'Offshore Classic' },
  45. { name: 'Tripletail', tag: 'Unique Catch' },
  46. { name: 'Spanish Mackerel', tag: 'Fast & Fun' },
  47. { name: 'Jack Crevalle', tag: 'Hard Fighter' },
  48. { name: 'Grouper', tag: 'Deep Reef' },
  49. { name: 'Corvina', tag: 'Inshore Staple' },
  50. { name: 'Hammerhead Shark', tag: 'Rare Encounter' },
  51. { name: 'Tuna', tag: 'Offshore Power' },
  52. { name: 'Marlin', tag: 'Ultimate Trophy' }
  53. ];
  54. const techniques = ['Inshore', 'Offshore', 'Light Tackle', 'Casting', 'Trolling', 'Fly Fishing', 'Deep Fishing', 'Bottom Fishing'];
  55. let selectedBoat = $state(0);
  56. const boats = [
  57. {
  58. name: 'Gunslinger',
  59. inshore: [
  60. { name: 'Snorkeling & Dolphins', price: 350, desc: 'Dolphin encounters and snorkeling in crystal-clear waters' },
  61. { name: '4 Hours Fishing', price: 500, desc: 'Extended inshore session with more action' },
  62. { name: 'Half Day', price: 650, desc: 'Our most popular — plenty of time for variety' },
  63. { name: '¾ Day', price: 750, desc: 'Explore multiple spots for the best bites' },
  64. { name: 'Full Day', price: 850, desc: 'The ultimate inshore experience, dawn to dusk' }
  65. ],
  66. offshore: [
  67. { name: '¾ Day', price: 850, desc: 'Extended time on the open Pacific' },
  68. { name: 'Full Day', price: 1050, desc: 'All day offshore — maximize your chances' }
  69. ]
  70. },
  71. {
  72. name: 'Gunslinger II',
  73. inshore: [
  74. { name: 'Recreational', price: 350, desc: 'Quick taste of Costa Rica fishing — perfect for beginners' },
  75. { name: '4 Hours Tour', price: 500, desc: 'Extended inshore session with more action' },
  76. { name: 'Half Day', price: 750, desc: 'Our most popular — plenty of time for variety' },
  77. { name: '¾ Day', price: 850, desc: 'Explore multiple spots for the best bites' },
  78. { name: 'Full Day', price: 950, desc: 'The ultimate inshore experience, dawn to dusk' }
  79. ],
  80. offshore: [
  81. { name: 'Half Day', price: 800, desc: 'Chase sailfish, mahi-mahi and more offshore' },
  82. { name: '¾ Day', price: 950, desc: 'Extended time on the open Pacific' },
  83. { name: 'Full Day', price: 1150, desc: 'All day offshore — maximize your chances' }
  84. ]
  85. }
  86. ];
  87. const gallery = [
  88. { src: '/fishing/roosterfish-group-4men.jpg', type: 'image', caption: 'Group Roosterfish Catch' },
  89. { src: '/fishing/redsnapper-couple-boat.jpg', type: 'image', caption: 'Red Snapper Doubles' },
  90. { src: '/fishing/mahimahi-solo-bite.jpg', type: 'image', caption: 'Offshore Mahi-Mahi' },
  91. { src: '/fishing/sailfish-release-closeup-42s.mp4', type: 'video', caption: 'Sailfish Release' },
  92. { src: '/fishing/roosterfish-trio-huge.jpg', type: 'image', caption: 'Monster Roosterfish' },
  93. { src: '/fishing/redsnapper-solo-huk-cap.jpg', type: 'image', caption: 'Red Snapper' },
  94. { src: '/fishing/roosterfish-solo-huk-cap.jpg', type: 'image', caption: 'Trophy Roosterfish' },
  95. { src: '/fishing/mahimahi-kid-guide.jpg', type: 'image', caption: 'Family Mahi-Mahi' },
  96. { src: '/fishing/snook-solo-hoodie-mountains.jpg', type: 'image', caption: 'Snook — Mountain Backdrop' },
  97. { src: '/fishing/sailfish-release-boatside.jpg', type: 'image', caption: 'Sailfish Release' },
  98. { src: '/fishing/roosterfish-couple.jpg', type: 'image', caption: 'Couples Fishing' },
  99. { src: '/fishing/roosterfish-couple-1.jpg', type: 'image', caption: 'Roosterfish Catch' },
  100. { src: '/fishing/roosterfish-couple-2.jpg', type: 'image', caption: 'Roosterfish Couple' },
  101. { src: '/fishing/hammerhead-shark-solo.jpg', type: 'image', caption: 'Hammerhead Shark' },
  102. { src: '/fishing/tripletail-solo-blue-clouds.jpg', type: 'image', caption: 'Tripletail' },
  103. { src: '/fishing/roosterfish-duo-huge-pair.jpg', type: 'image', caption: 'Double Roosterfish' },
  104. { src: '/fishing/snook-woman-flyrod.jpg', type: 'image', caption: 'Snook Catch' },
  105. { src: '/fishing/corvina-trio-islands.jpg', type: 'image', caption: 'Triple Corvina' },
  106. { src: '/fishing/sailfish-release-dark.jpg', type: 'image', caption: 'Sailfish Action' },
  107. { src: '/fishing/redsnapper-woman-blue-shades.jpg', type: 'image', caption: 'Red Snapper' },
  108. { src: '/fishing/roosterfish-solo-hoodie-beach.jpg', type: 'image', caption: 'Beach Roosterfish' },
  109. { src: '/fishing/spanish-mackerel-solo.jpg', type: 'image', caption: 'Spanish Mackerel' },
  110. { src: '/fishing/group-4-marina-catch.jpg', type: 'image', caption: 'Marina Catch Day' },
  111. { src: '/fishing/roosterfish-solo-green-shirt.jpg', type: 'image', caption: 'Roosterfish' },
  112. { src: '/fishing/redsnapper-duo-boat.jpg', type: 'image', caption: 'Red Snapper Catch' }
  113. ];
  114. const imageGallery = $derived(gallery.filter((g) => g.type === 'image'));
  115. function openLightbox(src) {
  116. const idx = imageGallery.findIndex((g) => g.src === src);
  117. if (idx >= 0) {
  118. lightboxIndex = idx;
  119. lightboxOpen = true;
  120. }
  121. }
  122. function closeLightbox() {
  123. lightboxOpen = false;
  124. }
  125. function prevImage() {
  126. lightboxIndex = (lightboxIndex - 1 + imageGallery.length) % imageGallery.length;
  127. }
  128. function nextImage() {
  129. lightboxIndex = (lightboxIndex + 1) % imageGallery.length;
  130. }
  131. function handleKeydown(e) {
  132. if (!lightboxOpen) return;
  133. if (e.key === 'Escape') closeLightbox();
  134. if (e.key === 'ArrowLeft') prevImage();
  135. if (e.key === 'ArrowRight') nextImage();
  136. }
  137. $effect(() => {
  138. if (lightboxOpen) {
  139. document.body.style.overflow = 'hidden';
  140. } else {
  141. document.body.style.overflow = '';
  142. }
  143. });
  144. onMount(() => {
  145. const observer = new IntersectionObserver(
  146. (entries) => {
  147. entries.forEach((entry) => {
  148. if (entry.isIntersecting) entry.target.classList.add('visible');
  149. });
  150. },
  151. { threshold: 0.1 }
  152. );
  153. document.querySelectorAll('.reveal').forEach((el) => observer.observe(el));
  154. return () => observer.disconnect();
  155. });
  156. </script>
  157. <svelte:window bind:scrollY={scrollY} onkeydown={handleKeydown} />
  158. <!-- NAV -->
  159. <nav class="fixed top-0 left-0 right-0 z-50 transition-all duration-300 {scrollY > 50 ? 'bg-deep/95 backdrop-blur-md shadow-lg shadow-black/20' : ''}">
  160. <div class="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:h-20 sm:px-6">
  161. <a href="#" class="flex items-center gap-2">
  162. <img src="/logos/logo-black-sailfish.png" alt="Gunslinger" class="h-14 sm:h-16" style="filter: {scrollY > 50 ? 'invert(73%) sepia(40%) saturate(700%) hue-rotate(157deg) brightness(102%)' : 'invert(1)'}; transition: filter 0.3s;" />
  163. </a>
  164. <div class="hidden items-center gap-6 md:flex">
  165. {#each navLinks as link}
  166. <a href={link.href} class="text-sm font-medium uppercase tracking-wider text-slate-300 transition-colors hover:text-cyan-400">{link.label}</a>
  167. {/each}
  168. <a href={WHATSAPP} target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-2 rounded-lg bg-cyan-600 px-5 py-2.5 text-sm font-semibold text-white transition-all hover:bg-cyan-500 hover:shadow-lg hover:shadow-cyan-500/25">
  169. Book Now
  170. </a>
  171. </div>
  172. <button class="p-2 text-white md:hidden" onclick={() => (mobileMenuOpen = !mobileMenuOpen)} aria-label="Menu">
  173. <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
  174. {#if mobileMenuOpen}
  175. <path d="M6 18L18 6M6 6l12 12" />
  176. {:else}
  177. <path d="M4 6h16M4 12h16M4 18h16" />
  178. {/if}
  179. </svg>
  180. </button>
  181. </div>
  182. {#if mobileMenuOpen}
  183. <div class="border-t border-white/10 bg-deep/98 px-4 pb-4 backdrop-blur-md md:hidden">
  184. {#each navLinks as link}
  185. <a href={link.href} class="block py-3 text-sm font-medium uppercase tracking-wider text-slate-300 hover:text-cyan-400" onclick={() => (mobileMenuOpen = false)}>{link.label}</a>
  186. {/each}
  187. <a href={WHATSAPP} target="_blank" rel="noopener noreferrer" class="mt-3 flex w-full items-center justify-center gap-2 rounded-lg bg-cyan-600 px-5 py-2.5 text-sm font-semibold text-white">Book Now</a>
  188. </div>
  189. {/if}
  190. </nav>
  191. <!-- HERO -->
  192. <section class="relative min-h-screen-ios overflow-hidden">
  193. <!-- Mobile: video background -->
  194. <video class="absolute inset-0 h-full w-full object-cover md:hidden" autoplay muted loop playsinline poster="/fishing/sailfish-release-blue-dorsal.jpg">
  195. <source src="/hero-mobile.mp4" type="video/mp4" />
  196. </video>
  197. <!-- Desktop: image background -->
  198. <img src="/fishing/roosterfish-trio-huge.jpg" alt="" class="absolute inset-0 hidden h-full w-full object-cover md:block" style="object-position: center 35%" />
  199. <!-- Overlay -->
  200. <div class="absolute inset-0 bg-gradient-to-b from-deep/70 via-deep/30 to-deep"></div>
  201. <!-- Content -->
  202. <div class="relative z-10 flex min-h-screen-ios flex-col items-center justify-center px-4 text-center">
  203. <h1 class="hero-fade hero-fade-1 font-heading mb-2 text-[2.75rem] font-bold tracking-wider text-white sm:text-7xl lg:text-8xl">GUNSLINGER</h1>
  204. <p class="hero-fade hero-fade-2 font-heading mb-6 text-lg uppercase tracking-widest text-cyan-400 sm:text-2xl lg:text-3xl">Sportfishing CR</p>
  205. <p class="hero-fade hero-fade-3 mb-10 max-w-xl text-base text-slate-300 sm:text-lg">Premier fishing charters from Quepos, Costa Rica. Sailfish, roosterfish, snook — your next trophy awaits.</p>
  206. <div class="hero-fade hero-fade-4 flex flex-col gap-3 sm:flex-row">
  207. <a href={WHATSAPP} target="_blank" rel="noopener noreferrer" class="inline-flex items-center justify-center gap-2 rounded-lg bg-cyan-600 px-8 py-3.5 font-semibold text-white transition-all hover:bg-cyan-500 hover:shadow-lg hover:shadow-cyan-500/25">
  208. <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z" /><path d="M12 0C5.373 0 0 5.373 0 12c0 2.625.846 5.059 2.284 7.034L.789 23.492a.5.5 0 00.612.638l4.67-1.388A11.94 11.94 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 22c-2.24 0-4.31-.726-5.993-1.957l-.418-.31-2.79.83.746-2.723-.34-.54A9.96 9.96 0 012 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10z" /></svg>
  209. Book on WhatsApp
  210. </a>
  211. <a href="#trips" class="inline-flex items-center justify-center gap-2 rounded-lg border-2 border-cyan-500/50 px-8 py-3.5 font-semibold text-cyan-300 transition-all hover:border-cyan-400 hover:bg-cyan-500/10">
  212. View Trips
  213. <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M19 9l-7 7-7-7" /></svg>
  214. </a>
  215. </div>
  216. </div>
  217. <div class="absolute bottom-6 left-1/2 -translate-x-1/2 animate-bounce">
  218. <svg class="h-6 w-6 text-white/40" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M19 14l-7 7m0 0l-7-7m7 7V3" /></svg>
  219. </div>
  220. </section>
  221. <!-- TECHNIQUES MARQUEE -->
  222. <div class="relative overflow-hidden border-y border-white/5 bg-navy/80 py-3 sm:py-4">
  223. <div class="marquee-track flex w-max items-center gap-6 sm:gap-10">
  224. {#each [0, 1] as _set}
  225. {#each techniques as tech}
  226. <span class="flex items-center gap-2 whitespace-nowrap sm:gap-3">
  227. <span class="h-1.5 w-1.5 rounded-full bg-cyan-400"></span>
  228. <span class="font-heading text-xs font-semibold uppercase tracking-[0.2em] text-slate-300 sm:text-sm">{tech}</span>
  229. </span>
  230. {/each}
  231. {/each}
  232. </div>
  233. </div>
  234. <!-- ABOUT -->
  235. <section id="about" class="py-14 sm:py-24">
  236. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  237. <div class="reveal grid items-center gap-8 md:grid-cols-2 lg:gap-16">
  238. <div>
  239. <p class="font-heading mb-3 text-sm uppercase tracking-widest text-cyan-400">Quepos, Costa Rica</p>
  240. <h2 class="font-heading mb-6 text-3xl font-bold uppercase tracking-wide text-white sm:text-4xl lg:text-5xl">Where the Big Ones Bite</h2>
  241. <p class="mb-4 leading-relaxed text-slate-300">
  242. Based at Marina Pez Vela in Quepos — the sportfishing capital of Costa Rica's Central Pacific — Gunslinger Sportfishing offers world-class charters for anglers of all levels.
  243. </p>
  244. <p class="mb-4 leading-relaxed text-slate-300">
  245. Whether you're chasing trophy roosterfish along the inshore reefs, releasing sailfish offshore, or hunting snook in the open sea, our experienced crew and top-tier equipment make every trip one to remember.
  246. </p>
  247. <p class="text-sm leading-relaxed text-slate-400">
  248. Live bait, light tackle, casting, trolling, deep fishing, and bottom fishing — we match the technique to your target species.
  249. </p>
  250. </div>
  251. <div class="overflow-hidden rounded-xl">
  252. <img src="/boats/about-section.jpg" alt="Gunslinger Sportfishing in Quepos" class="w-full rounded-xl" loading="lazy" />
  253. </div>
  254. </div>
  255. <div class="reveal mt-12 grid grid-cols-3 gap-4 sm:mt-16">
  256. <div class="rounded-xl border border-white/5 bg-navy/50 p-4 text-center sm:p-6">
  257. <p class="font-heading text-3xl font-bold text-cyan-400 sm:text-4xl">2</p>
  258. <p class="mt-1 text-sm text-slate-400">Boats</p>
  259. </div>
  260. <div class="rounded-xl border border-white/5 bg-navy/50 p-4 text-center sm:p-6">
  261. <p class="font-heading text-3xl font-bold text-cyan-400 sm:text-4xl">15+</p>
  262. <p class="mt-1 text-sm text-slate-400">Species</p>
  263. </div>
  264. <div class="rounded-xl border border-white/5 bg-navy/50 p-4 text-center sm:p-6">
  265. <p class="font-heading text-3xl font-bold text-cyan-400 sm:text-4xl">365</p>
  266. <p class="mt-1 text-sm text-slate-400">Days / Year</p>
  267. </div>
  268. </div>
  269. </div>
  270. </section>
  271. <!-- FLEET -->
  272. <section id="fleet" class="bg-navy py-14 sm:py-24">
  273. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  274. <div class="reveal mb-10 text-center sm:mb-16">
  275. <p class="font-heading mb-3 text-sm uppercase tracking-widest text-cyan-400">Our Boats</p>
  276. <h2 class="font-heading text-3xl font-bold uppercase tracking-wide text-white sm:text-4xl lg:text-5xl">The Fleet</h2>
  277. </div>
  278. <div class="space-y-8 lg:space-y-12">
  279. {#each fleet as boat, i}
  280. <div class="reveal group grid overflow-hidden rounded-xl border border-white/5 bg-deep/80 transition-all hover:border-cyan-500/30 md:grid-cols-2">
  281. <div class="overflow-hidden {i % 2 === 1 ? 'md:order-2' : ''}">
  282. <img src={boat.image} alt={boat.name} class="aspect-[4/3] h-full w-full object-cover transition-transform duration-700 group-hover:scale-105 sm:aspect-[3/2] md:aspect-auto" loading="lazy" />
  283. </div>
  284. <div class="flex flex-col justify-center p-6 sm:p-8 lg:p-10 {i % 2 === 1 ? 'md:order-1' : ''}">
  285. <h3 class="font-heading text-3xl font-bold uppercase text-white sm:text-4xl">{boat.name}</h3>
  286. <p class="mt-1 text-sm font-medium text-cyan-400">{boat.brand} · {boat.year}</p>
  287. <p class="mt-4 text-base leading-relaxed text-slate-300">{boat.desc}</p>
  288. <div class="mt-5 flex flex-wrap gap-2 text-xs">
  289. <span class="rounded-full border border-cyan-500/20 bg-cyan-500/10 px-3 py-1 text-cyan-300">{boat.engine}</span>
  290. <span class="rounded-full border border-cyan-500/20 bg-cyan-500/10 px-3 py-1 text-cyan-300">{boat.capacity}</span>
  291. </div>
  292. <div class="mt-3 flex flex-wrap gap-1.5 text-xs text-slate-400">
  293. {#each boat.features as feature}
  294. <span class="rounded bg-white/5 px-2 py-0.5">{feature}</span>
  295. {/each}
  296. </div>
  297. </div>
  298. </div>
  299. {/each}
  300. </div>
  301. </div>
  302. </section>
  303. <!-- SPECIES -->
  304. <section class="py-14 sm:py-24">
  305. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  306. <div class="reveal mb-10 text-center sm:mb-16">
  307. <p class="font-heading mb-3 text-sm uppercase tracking-widest text-cyan-400">Target Species</p>
  308. <h2 class="font-heading text-3xl font-bold uppercase tracking-wide text-white sm:text-4xl lg:text-5xl">What You'll Catch</h2>
  309. </div>
  310. <div class="reveal flex flex-wrap justify-center gap-3 sm:gap-4">
  311. {#each species as s}
  312. <div class="rounded-full border border-white/5 bg-navy/60 px-4 py-2 transition-all hover:border-cyan-500/30 sm:px-5 sm:py-3">
  313. <span class="text-sm font-medium text-white">{s.name}</span>
  314. <span class="ml-1.5 hidden text-xs text-cyan-400/70 sm:inline">· {s.tag}</span>
  315. </div>
  316. {/each}
  317. </div>
  318. </div>
  319. </section>
  320. <!-- TRIPS & RATES -->
  321. <section id="trips" class="bg-navy py-14 sm:py-24">
  322. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  323. <div class="reveal mb-10 text-center sm:mb-16">
  324. <p class="font-heading mb-3 text-sm uppercase tracking-widest text-cyan-400">Trips & Rates</p>
  325. <h2 class="font-heading text-3xl font-bold uppercase tracking-wide text-white sm:text-4xl lg:text-5xl">Choose Your Adventure</h2>
  326. </div>
  327. <!-- Boat tabs -->
  328. <div class="reveal mb-8 flex justify-center">
  329. <div class="inline-flex rounded-lg border border-white/10 bg-deep/60 p-1">
  330. {#each boats as boat, i}
  331. <button
  332. onclick={() => (selectedBoat = i)}
  333. class="font-heading rounded-md px-6 py-2.5 text-sm uppercase tracking-wider transition-all {selectedBoat === i ? 'bg-cyan-600 text-white shadow-lg shadow-cyan-500/20' : 'text-slate-400 hover:text-white'}"
  334. >
  335. {boat.name}
  336. </button>
  337. {/each}
  338. </div>
  339. </div>
  340. <div class="grid gap-8 lg:grid-cols-2 lg:gap-12">
  341. <!-- Inshore -->
  342. <div class="reveal">
  343. <h3 class="font-heading mb-4 flex items-center gap-2 text-xl uppercase tracking-wider text-cyan-400">
  344. <span class="h-px w-8 bg-cyan-400/50"></span> Inshore
  345. </h3>
  346. <div class="space-y-3">
  347. {#each boats[selectedBoat].inshore as trip}
  348. <div class="rounded-lg border border-white/5 bg-deep/60 p-4 transition-all hover:border-cyan-500/30">
  349. <div class="mb-1 flex items-center justify-between">
  350. <h4 class="font-heading text-lg text-white">{trip.name}</h4>
  351. <span class="font-heading text-xl text-cyan-400">${trip.price.toLocaleString()}</span>
  352. </div>
  353. <p class="text-sm text-slate-400">{trip.desc}</p>
  354. </div>
  355. {/each}
  356. </div>
  357. </div>
  358. <!-- Offshore -->
  359. <div class="reveal">
  360. <h3 class="font-heading mb-4 flex items-center gap-2 text-xl uppercase tracking-wider text-cyan-400">
  361. <span class="h-px w-8 bg-cyan-400/50"></span> Offshore
  362. </h3>
  363. <div class="space-y-3">
  364. {#each boats[selectedBoat].offshore as trip}
  365. <div class="rounded-lg border border-white/5 bg-deep/60 p-4 transition-all hover:border-cyan-500/30">
  366. <div class="mb-1 flex items-center justify-between">
  367. <h4 class="font-heading text-lg text-white">{trip.name}</h4>
  368. <span class="font-heading text-xl text-cyan-400">${trip.price.toLocaleString()}</span>
  369. </div>
  370. <p class="text-sm text-slate-400">{trip.desc}</p>
  371. </div>
  372. {/each}
  373. </div>
  374. </div>
  375. </div>
  376. <div class="reveal mt-10 text-center">
  377. <p class="text-sm text-slate-400">All trips include captain, crew, fishing tackle, bait, ice, drinks & fruit. Catch & release for all billfish. Custom trips available on request.</p>
  378. <a href={WHATSAPP} target="_blank" rel="noopener noreferrer" class="mt-6 inline-flex items-center gap-2 rounded-lg bg-cyan-600 px-8 py-3.5 font-semibold text-white transition-all hover:bg-cyan-500 hover:shadow-lg hover:shadow-cyan-500/25">
  379. <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z" /><path d="M12 0C5.373 0 0 5.373 0 12c0 2.625.846 5.059 2.284 7.034L.789 23.492a.5.5 0 00.612.638l4.67-1.388A11.94 11.94 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 22c-2.24 0-4.31-.726-5.993-1.957l-.418-.31-2.79.83.746-2.723-.34-.54A9.96 9.96 0 012 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10z" /></svg>
  380. Book Your Trip
  381. </a>
  382. </div>
  383. </div>
  384. </section>
  385. <!-- GALLERY -->
  386. <section id="gallery" class="py-14 sm:py-24">
  387. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  388. <div class="reveal mb-10 text-center sm:mb-16">
  389. <p class="font-heading mb-3 text-sm uppercase tracking-widest text-cyan-400">Photo Gallery</p>
  390. <h2 class="font-heading text-3xl font-bold uppercase tracking-wide text-white sm:text-4xl lg:text-5xl">The Catches</h2>
  391. </div>
  392. <!-- Mobile: 2-col grid with show more -->
  393. <div class="md:hidden">
  394. <div class="grid grid-cols-2 gap-2">
  395. {#each galleryExpanded ? gallery : gallery.slice(0, 8) as item}
  396. <div class="overflow-hidden rounded-lg">
  397. {#if item.type === 'video'}
  398. <video src={item.src} class="h-full w-full rounded-lg object-cover" preload="metadata" controls playsinline></video>
  399. {:else}
  400. <button class="w-full" onclick={() => openLightbox(item.src)}>
  401. <img src={item.src} alt={item.caption} class="w-full rounded-lg" loading="lazy" />
  402. </button>
  403. {/if}
  404. </div>
  405. {/each}
  406. </div>
  407. {#if !galleryExpanded}
  408. <div class="mt-4 text-center">
  409. <button onclick={() => (galleryExpanded = true)} class="inline-flex items-center gap-2 rounded-lg border border-cyan-500/40 px-6 py-2.5 text-sm font-medium text-cyan-300 transition-all hover:border-cyan-400 hover:bg-cyan-500/10">
  410. Show More
  411. <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M19 9l-7 7-7-7" /></svg>
  412. </button>
  413. </div>
  414. {/if}
  415. </div>
  416. <!-- Desktop: masonry grid -->
  417. <div class="hidden gap-3 md:block md:columns-3 lg:columns-4">
  418. {#each gallery as item}
  419. <div class="gallery-item mb-3">
  420. {#if item.type === 'video'}
  421. <video
  422. src={item.src}
  423. class="w-full rounded-lg"
  424. preload="metadata"
  425. muted
  426. loop
  427. playsinline
  428. onmouseenter={(e) => e.currentTarget.play()}
  429. onmouseleave={(e) => {
  430. e.currentTarget.pause();
  431. e.currentTarget.currentTime = 0;
  432. }}
  433. ></video>
  434. {:else}
  435. <button class="w-full" onclick={() => openLightbox(item.src)}>
  436. <img src={item.src} alt={item.caption} class="w-full" loading="lazy" />
  437. </button>
  438. {/if}
  439. </div>
  440. {/each}
  441. </div>
  442. </div>
  443. </section>
  444. <!-- CONTACT -->
  445. <section id="contact" class="bg-navy py-14 sm:py-24">
  446. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  447. <div class="reveal mb-10 text-center sm:mb-16">
  448. <p class="font-heading mb-3 text-sm uppercase tracking-widest text-cyan-400">Get in Touch</p>
  449. <h2 class="font-heading text-3xl font-bold uppercase tracking-wide text-white sm:text-4xl lg:text-5xl">Book Your Trip</h2>
  450. <p class="mx-auto mt-4 max-w-lg text-slate-400">Ready for the fishing trip of a lifetime? Reach out on WhatsApp for the fastest response — we'll get you on the water.</p>
  451. </div>
  452. <div class="reveal mb-10 grid gap-4 sm:grid-cols-3">
  453. <!-- WhatsApp -->
  454. <a href={WHATSAPP} target="_blank" rel="noopener noreferrer" class="group flex flex-col items-center gap-3 rounded-xl border border-white/5 bg-deep/60 p-6 transition-all hover:border-green-500/30">
  455. <div class="flex h-14 w-14 items-center justify-center rounded-full bg-green-500/10 transition-colors group-hover:bg-green-500/20">
  456. <svg class="h-7 w-7 text-green-400" fill="currentColor" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z" /><path d="M12 0C5.373 0 0 5.373 0 12c0 2.625.846 5.059 2.284 7.034L.789 23.492a.5.5 0 00.612.638l4.67-1.388A11.94 11.94 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 22c-2.24 0-4.31-.726-5.993-1.957l-.418-.31-2.79.83.746-2.723-.34-.54A9.96 9.96 0 012 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10z" /></svg>
  457. </div>
  458. <span class="font-medium text-white">WhatsApp</span>
  459. <span class="text-sm text-slate-400">+506 8963-0901</span>
  460. </a>
  461. <!-- Phone -->
  462. <a href={PHONE} class="group flex flex-col items-center gap-3 rounded-xl border border-white/5 bg-deep/60 p-6 transition-all hover:border-cyan-500/30">
  463. <div class="flex h-14 w-14 items-center justify-center rounded-full bg-cyan-500/10 transition-colors group-hover:bg-cyan-500/20">
  464. <svg class="h-7 w-7 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" /></svg>
  465. </div>
  466. <span class="font-medium text-white">Call Us</span>
  467. <span class="text-sm text-slate-400">+506 8963-0901</span>
  468. </a>
  469. <!-- Location -->
  470. <a href="https://maps.google.com/?q=Marina+Pez+Vela+Quepos+Costa+Rica" target="_blank" rel="noopener noreferrer" class="group flex flex-col items-center gap-3 rounded-xl border border-white/5 bg-deep/60 p-6 transition-all hover:border-cyan-500/30">
  471. <div class="flex h-14 w-14 items-center justify-center rounded-full bg-cyan-500/10 transition-colors group-hover:bg-cyan-500/20">
  472. <svg class="h-7 w-7 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /></svg>
  473. </div>
  474. <span class="font-medium text-white">Location</span>
  475. <span class="text-center text-sm text-slate-400">Marina Pez Vela, Quepos</span>
  476. </a>
  477. </div>
  478. <!-- Map -->
  479. <div class="reveal overflow-hidden rounded-xl border border-white/5">
  480. <iframe
  481. src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3932.8!2d-84.16579!3d9.40833!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8fa17c8e66e5e3e7%3A0x4077b0e5e9d55b15!2sMarina%20Pez%20Vela!5e0!3m2!1sen!2scr!4v1711584000000"
  482. width="100%"
  483. height="350"
  484. style="border:0"
  485. allowfullscreen=""
  486. loading="lazy"
  487. referrerpolicy="no-referrer-when-downgrade"
  488. title="Marina Pez Vela, Quepos"
  489. ></iframe>
  490. </div>
  491. </div>
  492. </section>
  493. <!-- FOOTER -->
  494. <footer class="border-t border-white/5 bg-[#050d1a] py-10">
  495. <div class="mx-auto max-w-7xl px-4 sm:px-6">
  496. <div class="flex flex-col items-center justify-between gap-6 text-center sm:flex-row sm:text-left">
  497. <div>
  498. <p class="font-heading text-2xl font-bold tracking-wider text-white">GUNSLINGER</p>
  499. <p class="mt-1 text-sm text-slate-500">Sportfishing CR · Quepos, Costa Rica</p>
  500. </div>
  501. <div class="flex items-center gap-4">
  502. <a href={WHATSAPP} target="_blank" rel="noopener noreferrer" class="text-slate-400 transition-colors hover:text-green-400" aria-label="WhatsApp">
  503. <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z" /><path d="M12 0C5.373 0 0 5.373 0 12c0 2.625.846 5.059 2.284 7.034L.789 23.492a.5.5 0 00.612.638l4.67-1.388A11.94 11.94 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 22c-2.24 0-4.31-.726-5.993-1.957l-.418-.31-2.79.83.746-2.723-.34-.54A9.96 9.96 0 012 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10z" /></svg>
  504. </a>
  505. <a href={PHONE} class="text-slate-400 transition-colors hover:text-cyan-400" aria-label="Phone">
  506. <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" /></svg>
  507. </a>
  508. </div>
  509. </div>
  510. <div class="mt-8 flex flex-col items-center justify-between gap-2 border-t border-white/5 pt-6 text-xs text-slate-600 sm:flex-row">
  511. <p>&copy; {new Date().getFullYear()} Gunslinger Sportfishing CR. All rights reserved.</p>
  512. <a href="https://digitalmar.dev" target="_blank" rel="noopener noreferrer" class="text-slate-600 transition-colors hover:text-slate-400">Made by digitalmar.dev</a>
  513. </div>
  514. </div>
  515. </footer>
  516. <!-- WhatsApp FAB -->
  517. <a
  518. href={WHATSAPP}
  519. target="_blank"
  520. rel="noopener noreferrer"
  521. class="fixed bottom-6 right-6 z-40 flex h-14 w-14 items-center justify-center rounded-full bg-green-500 shadow-lg shadow-green-500/30 transition-all hover:scale-110 hover:bg-green-400"
  522. aria-label="WhatsApp"
  523. >
  524. <svg class="h-7 w-7 text-white" fill="currentColor" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347z" /><path d="M12 0C5.373 0 0 5.373 0 12c0 2.625.846 5.059 2.284 7.034L.789 23.492a.5.5 0 00.612.638l4.67-1.388A11.94 11.94 0 0012 24c6.627 0 12-5.373 12-12S18.627 0 12 0zm0 22c-2.24 0-4.31-.726-5.993-1.957l-.418-.31-2.79.83.746-2.723-.34-.54A9.96 9.96 0 012 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10z" /></svg>
  525. </a>
  526. <!-- LIGHTBOX -->
  527. {#if lightboxOpen}
  528. <!-- svelte-ignore a11y_no_static_element_interactions -->
  529. <div class="fixed inset-0 z-50 flex items-center justify-center bg-black/95" onclick={closeLightbox} onkeydown={() => {}}>
  530. <button class="absolute right-4 top-4 p-2 text-white/70 hover:text-white" onclick={closeLightbox}>
  531. <svg class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M6 18L18 6M6 6l12 12" /></svg>
  532. </button>
  533. <button
  534. class="absolute left-2 top-1/2 -translate-y-1/2 p-2 text-white/70 hover:text-white sm:left-4"
  535. onclick={(e) => {
  536. e.stopPropagation();
  537. prevImage();
  538. }}
  539. >
  540. <svg class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M15 19l-7-7 7-7" /></svg>
  541. </button>
  542. <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
  543. <img
  544. src={imageGallery[lightboxIndex].src}
  545. alt={imageGallery[lightboxIndex].caption}
  546. class="max-h-[85vh] max-w-[90vw] rounded-lg object-contain"
  547. onclick={(e) => e.stopPropagation()}
  548. onkeydown={() => {}}
  549. />
  550. <button
  551. class="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-white/70 hover:text-white sm:right-4"
  552. onclick={(e) => {
  553. e.stopPropagation();
  554. nextImage();
  555. }}
  556. >
  557. <svg class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M9 5l7 7-7 7" /></svg>
  558. </button>
  559. <p class="absolute bottom-4 left-1/2 -translate-x-1/2 text-sm text-white/50">{lightboxIndex + 1} / {imageGallery.length}</p>
  560. </div>
  561. {/if}