@planetaexo/design-system 0.52.2 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { cva } from 'class-variance-authority';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { XIcon, ChevronDownIcon, CalendarIcon, SearchIcon, ChevronRightIcon, ArrowLeftIcon, CheckCircle2Icon, MapIcon, LogOutIcon, UsersIcon, CreditCardIcon, AlertCircleIcon, MinusIcon, PlusIcon, CircleCheckIcon, SlidersHorizontalIcon, ChevronLeftIcon, HomeIcon, SailboatIcon, CarIcon, WavesIcon, FootprintsIcon, InfoIcon, ClockIcon, CheckIcon, ChevronUpIcon, MenuIcon, UserIcon, SunIcon, MoonIcon, MapPinIcon, PackageIcon, BedDoubleIcon, UtensilsIcon, CompassIcon, BackpackIcon, CherryIcon, ReceiptIcon, Loader2Icon, SendIcon, CheckCircleIcon, Info, MailIcon, PhoneIcon, MessageCircleIcon, UserPlusIcon, ExternalLinkIcon, CopyIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, TwitterIcon, YoutubeIcon, LinkedinIcon, InstagramIcon, FacebookIcon, ArrowRightIcon, LayoutGridIcon } from 'lucide-react';
7
+ import { XIcon, ChevronDownIcon, CalendarIcon, SearchIcon, ChevronRightIcon, ArrowLeftIcon, CheckCircle2Icon, MapIcon, LogOutIcon, UsersIcon, CreditCardIcon, AlertCircleIcon, MinusIcon, PlusIcon, CircleCheckIcon, SlidersHorizontalIcon, ChevronLeftIcon, HomeIcon, SailboatIcon, CarIcon, WavesIcon, FootprintsIcon, InfoIcon, ClockIcon, CheckIcon, ChevronUpIcon, MenuIcon, UserIcon, SunIcon, MoonIcon, MapPinIcon, PackageIcon, BedDoubleIcon, UtensilsIcon, CompassIcon, BackpackIcon, CherryIcon, ReceiptIcon, ArrowRightIcon, Loader2Icon, SendIcon, CheckCircleIcon, ArrowDownIcon, SparkleIcon, Share2Icon, CopyIcon, Info, MailIcon, PhoneIcon, MessageCircleIcon, UserPlusIcon, ExternalLinkIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, TwitterIcon, YoutubeIcon, LinkedinIcon, InstagramIcon, FacebookIcon, LayoutGridIcon } from 'lucide-react';
8
8
  import { Separator as Separator$1 } from '@base-ui/react/separator';
9
9
  import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
10
10
  import { Button as Button$1 } from '@base-ui/react/button';
@@ -1256,16 +1256,47 @@ var VARIANT_STYLES = {
1256
1256
  success: "text-primary border-primary/30 bg-primary/10",
1257
1257
  info: "text-muted-foreground border-primary/25 bg-primary/5"
1258
1258
  };
1259
- function Alert({ variant = "info", children, className }) {
1260
- return /* @__PURE__ */ jsx(
1259
+ function Alert({
1260
+ variant = "info",
1261
+ title,
1262
+ icon,
1263
+ action,
1264
+ role = "status",
1265
+ children,
1266
+ className
1267
+ }) {
1268
+ const isBanner = Boolean(title || icon || action);
1269
+ if (!isBanner) {
1270
+ return /* @__PURE__ */ jsx(
1271
+ "div",
1272
+ {
1273
+ role,
1274
+ className: cn(
1275
+ "rounded-lg border px-3 py-2 text-sm font-sans leading-snug",
1276
+ VARIANT_STYLES[variant],
1277
+ className
1278
+ ),
1279
+ children
1280
+ }
1281
+ );
1282
+ }
1283
+ return /* @__PURE__ */ jsxs(
1261
1284
  "div",
1262
1285
  {
1286
+ role,
1263
1287
  className: cn(
1264
- "rounded-lg border px-3 py-2 text-sm font-sans leading-snug",
1288
+ "flex items-start gap-3 rounded-lg border px-4 py-3 text-sm font-sans leading-snug",
1265
1289
  VARIANT_STYLES[variant],
1266
1290
  className
1267
1291
  ),
1268
- children
1292
+ children: [
1293
+ icon && /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 [&>svg]:size-4", "aria-hidden": "true", children: icon }),
1294
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1295
+ title && /* @__PURE__ */ jsx("p", { className: "font-ui font-bold text-current leading-snug", children: title }),
1296
+ children && /* @__PURE__ */ jsx("div", { className: cn(title && "mt-0.5", "text-current/90"), children })
1297
+ ] }),
1298
+ action && /* @__PURE__ */ jsx("div", { className: "shrink-0 self-center", children: action })
1299
+ ]
1269
1300
  }
1270
1301
  );
1271
1302
  }
@@ -9947,6 +9978,30 @@ function TrustpilotFallback({ config }) {
9947
9978
  }
9948
9979
  );
9949
9980
  }
9981
+
9982
+ // src/lib/image-webp.ts
9983
+ var WEBP_ELIGIBLE_EXTENSION = /\.(jpe?g|png)(\?[^"'\s>]*)?$/i;
9984
+ function webpVariantUrl(src) {
9985
+ var _a;
9986
+ if (!src) return null;
9987
+ const m = src.match(WEBP_ELIGIBLE_EXTENSION);
9988
+ if (!m) return null;
9989
+ const query = (_a = m[2]) != null ? _a : "";
9990
+ const withoutQuery = query ? src.slice(0, -query.length) : src;
9991
+ return `${withoutQuery}.webp${query}`;
9992
+ }
9993
+ function Picture(_a) {
9994
+ var _b = _a, { src, extraSources } = _b, imgProps = __objRest(_b, ["src", "extraSources"]);
9995
+ const webp = webpVariantUrl(src);
9996
+ if (!webp) {
9997
+ return /* @__PURE__ */ jsx("img", __spreadValues({ src }, imgProps));
9998
+ }
9999
+ return /* @__PURE__ */ jsxs("picture", { style: { display: "contents" }, children: [
10000
+ /* @__PURE__ */ jsx("source", { srcSet: webp, type: "image/webp" }),
10001
+ extraSources,
10002
+ /* @__PURE__ */ jsx("img", __spreadValues({ src }, imgProps))
10003
+ ] });
10004
+ }
9950
10005
  function ItineraryDayCard({
9951
10006
  stop,
9952
10007
  onOpen
@@ -10300,7 +10355,7 @@ function Lightbox({
10300
10355
  }
10301
10356
  ),
10302
10357
  /* @__PURE__ */ jsx(
10303
- "img",
10358
+ Picture,
10304
10359
  {
10305
10360
  src: photo.src,
10306
10361
  alt: (_a = photo.alt) != null ? _a : `Photo ${index + 1}`,
@@ -10368,7 +10423,7 @@ function PhotoTile({
10368
10423
  "aria-label": (_a = photo.alt) != null ? _a : `Photo ${index + 1}`,
10369
10424
  children: [
10370
10425
  /* @__PURE__ */ jsx(
10371
- "img",
10426
+ Picture,
10372
10427
  {
10373
10428
  src: photo.src,
10374
10429
  alt: (_b = photo.alt) != null ? _b : `Photo ${index + 1}`,
@@ -10488,7 +10543,7 @@ function MasonryGallery({
10488
10543
  "aria-label": (_a = p.alt) != null ? _a : `Photo ${i + 1}`,
10489
10544
  children: [
10490
10545
  /* @__PURE__ */ jsx(
10491
- "img",
10546
+ Picture,
10492
10547
  {
10493
10548
  src: p.src,
10494
10549
  alt: (_b = p.alt) != null ? _b : `Photo ${i + 1}`,
@@ -10527,7 +10582,7 @@ function FilmstripGallery({
10527
10582
  "aria-label": (_a = p.alt) != null ? _a : `Photo ${i + 1}`,
10528
10583
  children: [
10529
10584
  /* @__PURE__ */ jsx(
10530
- "img",
10585
+ Picture,
10531
10586
  {
10532
10587
  src: p.src,
10533
10588
  alt: (_b = p.alt) != null ? _b : `Photo ${i + 1}`,
@@ -10592,7 +10647,7 @@ function FeaturedGallery({
10592
10647
  "aria-label": (_a = p.alt) != null ? _a : `Photo ${i + 4}`,
10593
10648
  children: [
10594
10649
  /* @__PURE__ */ jsx(
10595
- "img",
10650
+ Picture,
10596
10651
  {
10597
10652
  src: p.src,
10598
10653
  alt: (_b = p.alt) != null ? _b : `Photo ${i + 4}`,
@@ -10644,7 +10699,7 @@ function CarouselGallery({
10644
10699
  "aria-label": `Open photo ${index + 1} fullscreen`,
10645
10700
  className: "absolute inset-0 w-full h-full cursor-zoom-in focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
10646
10701
  children: /* @__PURE__ */ jsx(
10647
- "img",
10702
+ Picture,
10648
10703
  {
10649
10704
  src: photo.src,
10650
10705
  alt: (_a = photo.alt) != null ? _a : `Photo ${index + 1}`,
@@ -10997,7 +11052,12 @@ var badgeVariants = cva(
10997
11052
  destructive: "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
10998
11053
  outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
10999
11054
  ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
11000
- link: "text-primary underline-offset-4 hover:underline"
11055
+ link: "text-primary underline-offset-4 hover:underline",
11056
+ // ── Semantic soft tones (added for status surfaces) ────────────────
11057
+ success: "bg-success/10 text-success border-success/20 [a]:hover:bg-success/20",
11058
+ warning: "bg-warning/15 text-warning-foreground border-warning/30 dark:bg-warning/20 dark:text-warning [a]:hover:bg-warning/25",
11059
+ info: "bg-info/10 text-info border-info/20 [a]:hover:bg-info/20",
11060
+ neutral: "bg-muted text-muted-foreground border-border [a]:hover:bg-muted/70"
11001
11061
  }
11002
11062
  },
11003
11063
  defaultVariants: {
@@ -12016,7 +12076,7 @@ function TripCardEditorial(props) {
12016
12076
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
12017
12077
  /* @__PURE__ */ jsxs("div", { className: "relative aspect-[4/3] overflow-hidden bg-muted", children: [
12018
12078
  /* @__PURE__ */ jsx(
12019
- "img",
12079
+ Picture,
12020
12080
  {
12021
12081
  src: image,
12022
12082
  alt: imageAlt,
@@ -12107,7 +12167,7 @@ function TripCard(props) {
12107
12167
  ),
12108
12168
  children: [
12109
12169
  /* @__PURE__ */ jsx(
12110
- "img",
12170
+ Picture,
12111
12171
  {
12112
12172
  src: image,
12113
12173
  alt: imageAlt,
@@ -12254,7 +12314,7 @@ function TripHeader({
12254
12314
  ),
12255
12315
  videoUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
12256
12316
  hasHeroImage ? /* @__PURE__ */ jsx(
12257
- "img",
12317
+ Picture,
12258
12318
  {
12259
12319
  src: validImages[0],
12260
12320
  alt: "",
@@ -12291,7 +12351,7 @@ function TripHeader({
12291
12351
  }
12292
12352
  )
12293
12353
  ] }) : hasHeroImage ? /* @__PURE__ */ jsx(
12294
- "img",
12354
+ Picture,
12295
12355
  {
12296
12356
  src: currentSrc,
12297
12357
  alt: title,
@@ -12868,6 +12928,7 @@ function TripPage({
12868
12928
  optionalExtras,
12869
12929
  accommodation,
12870
12930
  accommodationGallery,
12931
+ accommodationGalleryVariant = "gridCompact",
12871
12932
  whenItOperates,
12872
12933
  food,
12873
12934
  foodGallery,
@@ -13189,7 +13250,7 @@ function TripPage({
13189
13250
  PhotoGallery,
13190
13251
  {
13191
13252
  photos: accommodationGallery,
13192
- variant: "gridCompact",
13253
+ variant: accommodationGalleryVariant,
13193
13254
  initialVisible: 6
13194
13255
  }
13195
13256
  ) })
@@ -13468,7 +13529,385 @@ function TripPage({
13468
13529
  }
13469
13530
  );
13470
13531
  }
13532
+ function ArrowIcon2() {
13533
+ return /* @__PURE__ */ jsxs(
13534
+ "svg",
13535
+ {
13536
+ width: "13",
13537
+ height: "13",
13538
+ viewBox: "0 0 24 24",
13539
+ fill: "none",
13540
+ stroke: "currentColor",
13541
+ strokeWidth: "2.2",
13542
+ strokeLinecap: "round",
13543
+ strokeLinejoin: "round",
13544
+ children: [
13545
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
13546
+ /* @__PURE__ */ jsx("polyline", { points: "12 5 19 12 12 19" })
13547
+ ]
13548
+ }
13549
+ );
13550
+ }
13471
13551
  var sizeConfig2 = {
13552
+ sm: {
13553
+ card: "h-72 w-56",
13554
+ title: "text-lg font-bold",
13555
+ meta: "text-xs",
13556
+ excerpt: "text-xs"
13557
+ },
13558
+ md: {
13559
+ card: "h-96 w-72",
13560
+ title: "text-xl font-bold",
13561
+ meta: "text-xs",
13562
+ excerpt: "text-sm"
13563
+ },
13564
+ lg: {
13565
+ card: "h-[28rem] w-96",
13566
+ title: "text-2xl font-bold",
13567
+ meta: "text-sm",
13568
+ excerpt: "text-sm"
13569
+ }
13570
+ };
13571
+ function BlogCard({
13572
+ image,
13573
+ imageAlt = "",
13574
+ category,
13575
+ readingTime,
13576
+ date,
13577
+ title,
13578
+ excerpt,
13579
+ href,
13580
+ cta,
13581
+ size = "md",
13582
+ className
13583
+ }) {
13584
+ var _a;
13585
+ const s = sizeConfig2[size];
13586
+ const meta = [date != null ? date : null, readingTime != null ? readingTime : null].filter(Boolean).join(" | ");
13587
+ const ctaLabel = (_a = cta == null ? void 0 : cta.label) != null ? _a : "Read more";
13588
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
13589
+ /* @__PURE__ */ jsx(
13590
+ "img",
13591
+ {
13592
+ src: image,
13593
+ alt: imageAlt,
13594
+ loading: "lazy",
13595
+ className: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
13596
+ }
13597
+ ),
13598
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/90 via-black/40 to-black/10" }),
13599
+ category ? /* @__PURE__ */ jsx("div", { className: "relative z-10 p-3", children: /* @__PURE__ */ jsx(Chip, { variant: "glass", children: category }) }) : /* @__PURE__ */ jsx("div", { className: "relative z-10" }),
13600
+ /* @__PURE__ */ jsxs("div", { className: "relative z-10 flex flex-col gap-1.5 p-5", children: [
13601
+ meta && /* @__PURE__ */ jsx("p", { className: cn("text-white/70 font-medium font-ui", s.meta), children: meta }),
13602
+ /* @__PURE__ */ jsx("h3", { className: cn("text-white leading-snug", s.title), children: title }),
13603
+ excerpt && /* @__PURE__ */ jsx(
13604
+ "p",
13605
+ {
13606
+ className: cn(
13607
+ "text-white/80 leading-relaxed -mt-1 line-clamp-2",
13608
+ s.excerpt
13609
+ ),
13610
+ children: excerpt
13611
+ }
13612
+ ),
13613
+ /* @__PURE__ */ jsx("div", { className: "mt-3 flex items-center justify-between gap-4", children: /* @__PURE__ */ jsxs(
13614
+ "span",
13615
+ {
13616
+ className: cn(
13617
+ "group/cta inline-flex items-center gap-1.5 border-b border-white/70 pb-0.5",
13618
+ "text-sm font-semibold text-white transition-colors hover:border-white hover:text-white",
13619
+ "font-ui"
13620
+ ),
13621
+ children: [
13622
+ ctaLabel,
13623
+ /* @__PURE__ */ jsx("span", { className: "transition-transform duration-150 group-hover/cta:translate-x-0.5", children: /* @__PURE__ */ jsx(ArrowIcon2, {}) })
13624
+ ]
13625
+ }
13626
+ ) })
13627
+ ] })
13628
+ ] });
13629
+ const baseClasses = cn(
13630
+ "group relative flex flex-col justify-between overflow-hidden rounded-2xl",
13631
+ "shadow-md transition-shadow duration-300 hover:shadow-xl",
13632
+ s.card,
13633
+ className
13634
+ );
13635
+ return href ? /* @__PURE__ */ jsx(
13636
+ "a",
13637
+ {
13638
+ href,
13639
+ onClick: cta == null ? void 0 : cta.onClick,
13640
+ className: baseClasses,
13641
+ "aria-label": title,
13642
+ children: inner
13643
+ }
13644
+ ) : /* @__PURE__ */ jsx("div", { className: baseClasses, children: inner });
13645
+ }
13646
+ function SectionHeading({
13647
+ eyebrow,
13648
+ title,
13649
+ rightSlot
13650
+ }) {
13651
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-end justify-between gap-4 flex-wrap mb-6", children: [
13652
+ /* @__PURE__ */ jsxs("div", { children: [
13653
+ eyebrow && /* @__PURE__ */ jsx("p", { className: "text-xs font-mono font-semibold text-primary uppercase tracking-widest mb-1", children: eyebrow }),
13654
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading leading-tight", children: title })
13655
+ ] }),
13656
+ rightSlot
13657
+ ] });
13658
+ }
13659
+ function CategoryPage2({
13660
+ title,
13661
+ intro,
13662
+ heroImage,
13663
+ trustpilotMini,
13664
+ breadcrumb,
13665
+ siteHeader,
13666
+ popularTours,
13667
+ popularToursTitle = "More adventures calling your name",
13668
+ popularToursEyebrow = "Popular tours",
13669
+ trips,
13670
+ tripsTitle,
13671
+ tripsEyebrow,
13672
+ filterGroups,
13673
+ sortOptions,
13674
+ defaultSort,
13675
+ tripsInitialCount = 15,
13676
+ trustpilot,
13677
+ reviewsTitle = "Don't just take our word for it",
13678
+ reviewsSubtitle,
13679
+ blogPosts,
13680
+ aboutTitle,
13681
+ aboutContent,
13682
+ blogIntro,
13683
+ travelGuideHref,
13684
+ travelGuideLabel = "Read our Travel Guide",
13685
+ blogPostsTitle,
13686
+ blogPostsViewAllHref,
13687
+ faqs,
13688
+ faqsTitle = "Frequently asked questions",
13689
+ faqInitialCount = 5,
13690
+ gallery,
13691
+ galleryTitle,
13692
+ className
13693
+ }) {
13694
+ var _a;
13695
+ const [faqsExpanded, setFaqsExpanded] = React28.useState(false);
13696
+ const [tripsExpanded, setTripsExpanded] = React28.useState(false);
13697
+ const [filterValue, setFilterValue] = React28.useState({});
13698
+ const [sort, setSort] = React28.useState(
13699
+ defaultSort != null ? defaultSort : (_a = sortOptions == null ? void 0 : sortOptions[0]) == null ? void 0 : _a.id
13700
+ );
13701
+ const sortedTrips = React28.useMemo(
13702
+ () => [...trips].sort((a, b) => {
13703
+ const af = a.featured ? 1 : 0;
13704
+ const bf = b.featured ? 1 : 0;
13705
+ return bf - af;
13706
+ }),
13707
+ [trips]
13708
+ );
13709
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
13710
+ /* @__PURE__ */ jsxs(
13711
+ "section",
13712
+ {
13713
+ className: cn(
13714
+ "relative w-full",
13715
+ siteHeader ? "min-h-[420px] pt-[140px]" : "min-h-[300px] pt-16",
13716
+ "pb-12 text-white",
13717
+ !heroImage && "bg-gradient-to-br from-primary-900 via-primary-800 to-primary-950"
13718
+ ),
13719
+ children: [
13720
+ heroImage && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 overflow-hidden", children: [
13721
+ /* @__PURE__ */ jsx(
13722
+ "img",
13723
+ {
13724
+ src: heroImage,
13725
+ alt: "",
13726
+ "aria-hidden": true,
13727
+ fetchPriority: "high",
13728
+ className: "absolute inset-0 h-full w-full object-cover"
13729
+ }
13730
+ ),
13731
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-black/55 via-black/40 to-black/65" })
13732
+ ] }),
13733
+ siteHeader && /* @__PURE__ */ jsx(
13734
+ SiteHeader,
13735
+ {
13736
+ links: Array.isArray(siteHeader) ? siteHeader : void 0,
13737
+ position: "overlay"
13738
+ }
13739
+ ),
13740
+ /* @__PURE__ */ jsxs("div", { className: "relative mx-auto w-full max-w-6xl px-6 sm:px-8", children: [
13741
+ breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-3 flex items-center gap-1.5 flex-wrap", children: breadcrumb.map((crumb, i) => /* @__PURE__ */ jsxs(React28.Fragment, { children: [
13742
+ i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
13743
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui", children: crumb.label })
13744
+ ] }, i)) }),
13745
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-5xl font-bold text-white font-heading leading-tight max-w-3xl", children: title }),
13746
+ intro && /* @__PURE__ */ jsx("div", { className: "mt-4 text-base sm:text-lg text-white/90 leading-relaxed max-w-2xl [&_strong]:font-semibold [&_a]:underline", children: intro }),
13747
+ trustpilotMini && /* @__PURE__ */ jsx("div", { className: "mt-5 max-w-sm", children: /* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilotMini }) })
13748
+ ] })
13749
+ ]
13750
+ }
13751
+ ),
13752
+ popularTours && popularTours.length > 0 && /* @__PURE__ */ jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12", children: [
13753
+ /* @__PURE__ */ jsx(
13754
+ SectionHeading,
13755
+ {
13756
+ eyebrow: popularToursEyebrow,
13757
+ title: popularToursTitle
13758
+ }
13759
+ ),
13760
+ /* @__PURE__ */ jsx("div", { className: "-mx-6 sm:-mx-8 px-6 sm:px-8 overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: /* @__PURE__ */ jsx("div", { className: "inline-flex gap-5 min-w-max pb-2", children: popularTours.map((trip, i) => {
13761
+ var _b;
13762
+ const _a2 = trip, { featured: _featured, variant: _variant } = _a2, cardProps = __objRest(_a2, ["featured", "variant"]);
13763
+ return /* @__PURE__ */ jsx(
13764
+ TripCard,
13765
+ __spreadProps(__spreadValues({}, cardProps), {
13766
+ variant: "overlay",
13767
+ size: (_b = cardProps.size) != null ? _b : "md"
13768
+ }),
13769
+ i
13770
+ );
13771
+ }) }) })
13772
+ ] }),
13773
+ /* @__PURE__ */ jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 pt-6 sm:pt-8 pb-12", children: [
13774
+ (tripsTitle || tripsEyebrow) && /* @__PURE__ */ jsx(SectionHeading, { eyebrow: tripsEyebrow, title: tripsTitle != null ? tripsTitle : "" }),
13775
+ filterGroups && filterGroups.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-6", children: /* @__PURE__ */ jsx(
13776
+ FilterPanel,
13777
+ {
13778
+ variant: "horizontal",
13779
+ groups: filterGroups,
13780
+ value: filterValue,
13781
+ onChange: setFilterValue,
13782
+ onClearAll: () => setFilterValue({}),
13783
+ sortOptions,
13784
+ sort,
13785
+ onSortChange: setSort
13786
+ }
13787
+ ) }),
13788
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground font-ui mb-5", children: [
13789
+ trips.length,
13790
+ " ",
13791
+ trips.length === 1 ? "trip" : "trips",
13792
+ " found"
13793
+ ] }),
13794
+ (() => {
13795
+ const visibleTrips = tripsExpanded ? sortedTrips : sortedTrips.slice(0, tripsInitialCount);
13796
+ const hiddenCount = sortedTrips.length - visibleTrips.length;
13797
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
13798
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-6 gap-y-8 lg:gap-x-[35px] lg:gap-y-[38px]", children: visibleTrips.map((trip, i) => {
13799
+ const _a2 = trip, { featured: _featured } = _a2, cardProps = __objRest(_a2, ["featured"]);
13800
+ return /* @__PURE__ */ jsx(
13801
+ TripCard,
13802
+ __spreadProps(__spreadValues({}, cardProps), {
13803
+ className: cn("w-full h-auto", cardProps.className)
13804
+ }),
13805
+ i
13806
+ );
13807
+ }) }),
13808
+ sortedTrips.length > tripsInitialCount && /* @__PURE__ */ jsx("div", { className: "mt-8 flex justify-center", children: /* @__PURE__ */ jsx(
13809
+ "button",
13810
+ {
13811
+ type: "button",
13812
+ onClick: () => setTripsExpanded((v) => !v),
13813
+ className: cn(
13814
+ "inline-flex items-center gap-2 rounded-full border border-border bg-background px-5 py-2.5",
13815
+ "text-sm font-semibold text-foreground shadow-sm",
13816
+ "hover:bg-muted transition-colors duration-150",
13817
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
13818
+ ),
13819
+ children: tripsExpanded ? /* @__PURE__ */ jsxs(Fragment, { children: [
13820
+ /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-4 w-4 text-muted-foreground" }),
13821
+ "Show less"
13822
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
13823
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4 text-muted-foreground" }),
13824
+ "Load more (",
13825
+ hiddenCount,
13826
+ ")"
13827
+ ] })
13828
+ }
13829
+ ) })
13830
+ ] });
13831
+ })()
13832
+ ] }),
13833
+ trustpilot && /* @__PURE__ */ jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12 border-t border-border", children: [
13834
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading mb-2", children: reviewsTitle }),
13835
+ reviewsSubtitle && /* @__PURE__ */ jsx("p", { className: "text-base text-muted-foreground leading-relaxed max-w-3xl mb-6 [&_a]:text-primary [&_a]:underline", children: reviewsSubtitle }),
13836
+ /* @__PURE__ */ jsx("div", { className: "min-h-[400px]", children: /* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilot }) })
13837
+ ] }),
13838
+ gallery && gallery.length > 0 && /* @__PURE__ */ jsxs("section", { className: "pt-4", children: [
13839
+ galleryTitle && /* @__PURE__ */ jsx("h2", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 mb-6 text-2xl sm:text-3xl font-bold text-foreground font-heading", children: galleryTitle }),
13840
+ /* @__PURE__ */ jsx(PhotoGallery, { photos: gallery, variant: "gridCompact", initialVisible: 8 })
13841
+ ] }),
13842
+ (aboutTitle || aboutContent || blogPostsTitle || blogPosts && blogPosts.length > 0) && /* @__PURE__ */ jsx("section", { className: "w-full bg-gray-100", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-14", children: [
13843
+ (aboutTitle || blogPostsTitle) && /* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading mb-5", children: aboutTitle != null ? aboutTitle : blogPostsTitle }),
13844
+ aboutContent && /* @__PURE__ */ jsx("div", { className: "text-base text-foreground/85 leading-relaxed space-y-3 max-w-3xl mb-10 [&_strong]:font-semibold [&_a]:text-primary [&_a]:font-bold [&_a]:underline", children: aboutContent }),
13845
+ blogPosts && blogPosts.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
13846
+ blogIntro && /* @__PURE__ */ jsx("p", { className: "mb-6 text-base sm:text-lg font-semibold text-foreground font-heading", children: blogIntro }),
13847
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5", children: blogPosts.map((post, i) => /* @__PURE__ */ jsx(
13848
+ BlogCard,
13849
+ {
13850
+ href: post.href,
13851
+ image: post.image,
13852
+ imageAlt: post.imageAlt,
13853
+ title: post.title,
13854
+ excerpt: post.excerpt,
13855
+ category: post.category,
13856
+ readingTime: post.readingTime,
13857
+ className: "w-full"
13858
+ },
13859
+ i
13860
+ )) }),
13861
+ (travelGuideHref || blogPostsViewAllHref) && /* @__PURE__ */ jsx("div", { className: "mt-6 flex justify-end", children: /* @__PURE__ */ jsxs(
13862
+ "a",
13863
+ {
13864
+ href: travelGuideHref != null ? travelGuideHref : blogPostsViewAllHref,
13865
+ className: "inline-flex items-center gap-1.5 text-sm font-semibold text-primary hover:underline",
13866
+ children: [
13867
+ travelGuideHref ? travelGuideLabel : "View all posts",
13868
+ /* @__PURE__ */ jsx(ArrowRightIcon, { className: "h-4 w-4" })
13869
+ ]
13870
+ }
13871
+ ) })
13872
+ ] })
13873
+ ] }) }),
13874
+ faqs && faqs.length > 0 && (() => {
13875
+ const visibleFaqs = faqsExpanded ? faqs : faqs.slice(0, faqInitialCount);
13876
+ const hiddenCount = faqs.length - visibleFaqs.length;
13877
+ return /* @__PURE__ */ jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12", children: [
13878
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading mb-6", children: faqsTitle }),
13879
+ /* @__PURE__ */ jsx(Accordion, { variant: "faq", children: visibleFaqs.map((faq, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: `faq-${i}`, children: [
13880
+ /* @__PURE__ */ jsx(AccordionTrigger, { children: faq.question }),
13881
+ /* @__PURE__ */ jsx(AccordionContent, { children: faq.answer })
13882
+ ] }, i)) }),
13883
+ faqs.length > faqInitialCount && /* @__PURE__ */ jsx("div", { className: "mt-5 flex justify-center", children: /* @__PURE__ */ jsx(
13884
+ "button",
13885
+ {
13886
+ type: "button",
13887
+ onClick: () => setFaqsExpanded((v) => !v),
13888
+ className: cn(
13889
+ "inline-flex items-center gap-2 rounded-full border border-border bg-background px-5 py-2.5",
13890
+ "text-sm font-semibold text-foreground shadow-sm",
13891
+ "hover:bg-muted transition-colors duration-150",
13892
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
13893
+ ),
13894
+ children: faqsExpanded ? /* @__PURE__ */ jsxs(Fragment, { children: [
13895
+ /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-4 w-4 text-muted-foreground" }),
13896
+ "Show less"
13897
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
13898
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4 text-muted-foreground" }),
13899
+ "See more (",
13900
+ hiddenCount,
13901
+ ")"
13902
+ ] })
13903
+ }
13904
+ ) })
13905
+ ] });
13906
+ })(),
13907
+ /* @__PURE__ */ jsx(SiteFooter, {})
13908
+ ] });
13909
+ }
13910
+ var sizeConfig3 = {
13472
13911
  sm: {
13473
13912
  card: "w-56",
13474
13913
  image: "h-36",
@@ -13503,7 +13942,7 @@ function ActivityCard({
13503
13942
  size = "md",
13504
13943
  className
13505
13944
  }) {
13506
- const s = sizeConfig2[size];
13945
+ const s = sizeConfig3[size];
13507
13946
  return /* @__PURE__ */ jsxs(
13508
13947
  "div",
13509
13948
  {
@@ -14716,7 +15155,517 @@ function AskExo({
14716
15155
  )
14717
15156
  ] });
14718
15157
  }
15158
+ var STATUS_MAP = {
15159
+ "draft": { label: "Draft", variant: "neutral", dot: "bg-muted-foreground" },
15160
+ "pending-approval": { label: "Pending approval", variant: "warning", dot: "bg-warning" },
15161
+ "pending-group": { label: "Pending group", variant: "info", dot: "bg-info" },
15162
+ "confirmed": { label: "Confirmed", variant: "success", dot: "bg-success" },
15163
+ "payment-pending": { label: "Payment pending", variant: "warning", dot: "bg-warning" },
15164
+ "payment-reconciliation": { label: "Reconciliation", variant: "info", dot: "bg-info" },
15165
+ "fully-paid": { label: "Fully paid", variant: "default", dot: "bg-primary-foreground" },
15166
+ "full": { label: "Full", variant: "secondary", dot: "bg-secondary-foreground" },
15167
+ "waiting-list": { label: "Waiting list", variant: "info", dot: "bg-info" },
15168
+ "operating": { label: "Operating", variant: "default", dot: "bg-primary-foreground" },
15169
+ "cancelled": { label: "Cancelled", variant: "destructive", dot: "bg-destructive" }
15170
+ };
15171
+ function StatusBadge2({ status, dot = true, label, className }) {
15172
+ const config = STATUS_MAP[status];
15173
+ return /* @__PURE__ */ jsxs(Badge, { variant: config.variant, className: cn("gap-1.5", className), children: [
15174
+ dot && /* @__PURE__ */ jsx(
15175
+ "span",
15176
+ {
15177
+ "aria-hidden": "true",
15178
+ className: cn("size-1.5 shrink-0 rounded-full", config.dot)
15179
+ }
15180
+ ),
15181
+ label != null ? label : config.label
15182
+ ] });
15183
+ }
15184
+ function GroupStatusBanner({
15185
+ variant = "info",
15186
+ title,
15187
+ icon,
15188
+ action,
15189
+ urgent = false,
15190
+ children,
15191
+ className
15192
+ }) {
15193
+ return /* @__PURE__ */ jsx(
15194
+ Alert,
15195
+ {
15196
+ variant,
15197
+ title,
15198
+ icon,
15199
+ action,
15200
+ role: urgent ? "alert" : "status",
15201
+ className,
15202
+ children
15203
+ }
15204
+ );
15205
+ }
15206
+ function ParticipantCounter({
15207
+ current,
15208
+ max,
15209
+ label = "Travelers",
15210
+ hideIcon = false,
15211
+ className
15212
+ }) {
15213
+ return /* @__PURE__ */ jsxs(
15214
+ "span",
15215
+ {
15216
+ className: cn(
15217
+ "inline-flex items-center gap-1.5 font-ui text-sm text-foreground",
15218
+ className
15219
+ ),
15220
+ children: [
15221
+ !hideIcon && /* @__PURE__ */ jsx(UsersIcon, { className: "size-4 text-primary", "aria-hidden": "true" }),
15222
+ /* @__PURE__ */ jsxs("span", { className: "font-bold tabular-nums", children: [
15223
+ current,
15224
+ " / ",
15225
+ max
15226
+ ] }),
15227
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label })
15228
+ ]
15229
+ }
15230
+ );
15231
+ }
15232
+ function GroupProgressBar({
15233
+ current,
15234
+ min,
15235
+ max,
15236
+ hideLabels = false,
15237
+ className
15238
+ }) {
15239
+ const pct = Math.max(0, Math.min(100, current / max * 100));
15240
+ const minPct = Math.max(0, Math.min(100, min / max * 100));
15241
+ const quorumMet = current >= min;
15242
+ const isFull = current >= max;
15243
+ const fillTone = isFull ? "bg-success" : quorumMet ? "bg-primary" : "bg-warning";
15244
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
15245
+ /* @__PURE__ */ jsxs(
15246
+ "div",
15247
+ {
15248
+ className: "relative h-3 w-full overflow-visible rounded-full bg-muted",
15249
+ role: "progressbar",
15250
+ "aria-valuenow": current,
15251
+ "aria-valuemin": 0,
15252
+ "aria-valuemax": max,
15253
+ "aria-label": `${current} of ${max} travelers, minimum ${min}${quorumMet ? " met" : " not yet met"}`,
15254
+ children: [
15255
+ /* @__PURE__ */ jsx(
15256
+ "div",
15257
+ {
15258
+ className: cn(
15259
+ "h-full rounded-full transition-[width,background-color] duration-500",
15260
+ fillTone
15261
+ ),
15262
+ style: { width: `${pct}%` }
15263
+ }
15264
+ ),
15265
+ /* @__PURE__ */ jsx(
15266
+ "span",
15267
+ {
15268
+ "aria-hidden": "true",
15269
+ className: "absolute top-1/2 z-10 h-5 w-0.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-foreground/60",
15270
+ style: { left: `${minPct}%` }
15271
+ }
15272
+ )
15273
+ ]
15274
+ }
15275
+ ),
15276
+ !hideLabels && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between font-ui text-[11px] text-muted-foreground", children: [
15277
+ /* @__PURE__ */ jsx("span", { className: cn(quorumMet && "text-success font-semibold"), children: quorumMet ? "Quorum reached" : `Min ${min} to confirm` }),
15278
+ /* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
15279
+ max,
15280
+ " max"
15281
+ ] })
15282
+ ] })
15283
+ ] });
15284
+ }
15285
+ function Card(_a) {
15286
+ var _b = _a, {
15287
+ className,
15288
+ size = "default"
15289
+ } = _b, props = __objRest(_b, [
15290
+ "className",
15291
+ "size"
15292
+ ]);
15293
+ return /* @__PURE__ */ jsx(
15294
+ "div",
15295
+ __spreadValues({
15296
+ "data-slot": "card",
15297
+ "data-size": size,
15298
+ className: cn(
15299
+ "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
15300
+ className
15301
+ )
15302
+ }, props)
15303
+ );
15304
+ }
15305
+ function CardHeader(_a) {
15306
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
15307
+ return /* @__PURE__ */ jsx(
15308
+ "div",
15309
+ __spreadValues({
15310
+ "data-slot": "card-header",
15311
+ className: cn(
15312
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
15313
+ className
15314
+ )
15315
+ }, props)
15316
+ );
15317
+ }
15318
+ function CardTitle(_a) {
15319
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
15320
+ return /* @__PURE__ */ jsx(
15321
+ "div",
15322
+ __spreadValues({
15323
+ "data-slot": "card-title",
15324
+ className: cn(
15325
+ "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
15326
+ className
15327
+ )
15328
+ }, props)
15329
+ );
15330
+ }
15331
+ function CardContent(_a) {
15332
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
15333
+ return /* @__PURE__ */ jsx(
15334
+ "div",
15335
+ __spreadValues({
15336
+ "data-slot": "card-content",
15337
+ className: cn("px-4 group-data-[size=sm]/card:px-3", className)
15338
+ }, props)
15339
+ );
15340
+ }
15341
+ function PricingMatrixCard({
15342
+ tiers,
15343
+ currentTravelers,
15344
+ title = "Group pricing",
15345
+ locked = false,
15346
+ className
15347
+ }) {
15348
+ const activeIndex = tiers.reduce(
15349
+ (acc, t, i) => currentTravelers >= t.threshold ? i : acc,
15350
+ -1
15351
+ );
15352
+ const bestIndex = tiers.length - 1;
15353
+ return /* @__PURE__ */ jsxs(Card, { className, children: [
15354
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "font-heading", children: title }) }),
15355
+ /* @__PURE__ */ jsx(CardContent, { className: "px-0", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
15356
+ /* @__PURE__ */ jsx("caption", { className: "sr-only", children: "Price per person by number of travelers" }),
15357
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-y border-border text-left font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: [
15358
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2 font-semibold", children: "Travelers" }),
15359
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2 text-right font-semibold", children: "Price / person" })
15360
+ ] }) }),
15361
+ /* @__PURE__ */ jsx("tbody", { children: tiers.map((tier, i) => {
15362
+ const isActive = !locked && i === activeIndex;
15363
+ const isBest = i === bestIndex;
15364
+ return /* @__PURE__ */ jsxs(
15365
+ "tr",
15366
+ {
15367
+ className: cn(
15368
+ "border-b border-border last:border-0 transition-colors",
15369
+ isActive && "bg-accent",
15370
+ locked && "opacity-60"
15371
+ ),
15372
+ "aria-current": isActive ? "true" : void 0,
15373
+ children: [
15374
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-2.5", children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
15375
+ /* @__PURE__ */ jsx("span", { className: "font-ui font-semibold text-foreground", children: tier.travelers }),
15376
+ isActive && /* @__PURE__ */ jsx(Badge, { variant: "success", className: "h-4 px-1.5 text-[10px]", children: "You are here" }),
15377
+ isBest && !isActive && /* @__PURE__ */ jsx(Badge, { variant: "info", className: "h-4 px-1.5 text-[10px]", children: "Best price" })
15378
+ ] }) }),
15379
+ /* @__PURE__ */ jsx(
15380
+ "td",
15381
+ {
15382
+ className: cn(
15383
+ "px-4 py-2.5 text-right font-ui tabular-nums",
15384
+ isActive ? "font-bold text-foreground" : "text-muted-foreground",
15385
+ isBest && "text-primary"
15386
+ ),
15387
+ children: tier.price
15388
+ }
15389
+ )
15390
+ ]
15391
+ },
15392
+ tier.travelers
15393
+ );
15394
+ }) })
15395
+ ] }) })
15396
+ ] });
15397
+ }
15398
+ function PriceProgress({
15399
+ currentPrice,
15400
+ lowestPrice,
15401
+ travelersToLowest,
15402
+ pct,
15403
+ className
15404
+ }) {
15405
+ const reached = travelersToLowest <= 0;
15406
+ const safePct = reached ? 100 : Math.max(0, Math.min(100, pct));
15407
+ return /* @__PURE__ */ jsxs(
15408
+ "div",
15409
+ {
15410
+ className: cn(
15411
+ "flex flex-col gap-3 rounded-xl border border-border bg-card p-4",
15412
+ className
15413
+ ),
15414
+ "aria-live": "polite",
15415
+ children: [
15416
+ /* @__PURE__ */ jsxs("div", { className: "flex items-end justify-between gap-4", children: [
15417
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
15418
+ /* @__PURE__ */ jsx("span", { className: "font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: "Current" }),
15419
+ /* @__PURE__ */ jsx("span", { className: "font-heading text-xl font-bold text-foreground tabular-nums", children: currentPrice })
15420
+ ] }),
15421
+ /* @__PURE__ */ jsx(ArrowDownIcon, { className: "mb-1 size-4 shrink-0 text-success", "aria-hidden": "true" }),
15422
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col text-right", children: [
15423
+ /* @__PURE__ */ jsx("span", { className: "font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: "Potential" }),
15424
+ /* @__PURE__ */ jsx("span", { className: "font-heading text-xl font-bold text-primary tabular-nums", children: lowestPrice })
15425
+ ] })
15426
+ ] }),
15427
+ /* @__PURE__ */ jsx("div", { className: "h-2 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx(
15428
+ "div",
15429
+ {
15430
+ className: cn(
15431
+ "h-full rounded-full transition-[width] duration-500",
15432
+ reached ? "bg-success" : "bg-primary"
15433
+ ),
15434
+ style: { width: `${safePct}%` }
15435
+ }
15436
+ ) }),
15437
+ /* @__PURE__ */ jsx(
15438
+ "p",
15439
+ {
15440
+ className: cn(
15441
+ "flex items-center gap-1.5 font-ui text-sm font-semibold",
15442
+ reached ? "text-success" : "text-foreground"
15443
+ ),
15444
+ children: reached ? /* @__PURE__ */ jsxs(Fragment, { children: [
15445
+ /* @__PURE__ */ jsx(SparkleIcon, { className: "size-4", "aria-hidden": "true" }),
15446
+ "Best possible price unlocked"
15447
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
15448
+ travelersToLowest,
15449
+ " more ",
15450
+ travelersToLowest === 1 ? "traveler" : "travelers",
15451
+ " for the lowest price"
15452
+ ] })
15453
+ }
15454
+ )
15455
+ ]
15456
+ }
15457
+ );
15458
+ }
15459
+ function ParticipantList({
15460
+ participants,
15461
+ emptySlots = 0,
15462
+ title = "Travelers",
15463
+ leaderLabel = "Leader",
15464
+ emptyMessage = "Be the first to join this adventure.",
15465
+ className
15466
+ }) {
15467
+ if (participants.length === 0 && emptySlots === 0) {
15468
+ return /* @__PURE__ */ jsx("p", { className: cn("font-sans text-sm text-muted-foreground", className), children: emptyMessage });
15469
+ }
15470
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
15471
+ title && /* @__PURE__ */ jsx("h3", { className: "font-heading text-sm font-bold text-foreground", children: title }),
15472
+ /* @__PURE__ */ jsxs("ul", { className: "flex flex-col gap-2", children: [
15473
+ participants.map((p, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-3", children: [
15474
+ /* @__PURE__ */ jsx(
15475
+ "span",
15476
+ {
15477
+ className: "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary/10 text-primary",
15478
+ "aria-hidden": "true",
15479
+ children: p.avatarUrl ? (
15480
+ // eslint-disable-next-line @next/next/no-img-element
15481
+ /* @__PURE__ */ jsx("img", { src: p.avatarUrl, alt: "", className: "size-full object-cover" })
15482
+ ) : /* @__PURE__ */ jsx(UserIcon, { className: "size-4.5" })
15483
+ }
15484
+ ),
15485
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
15486
+ /* @__PURE__ */ jsx("span", { className: "truncate font-ui text-sm font-medium text-foreground", children: p.firstName }),
15487
+ p.flag && /* @__PURE__ */ jsx("span", { "aria-label": p.country, role: "img", className: "text-base leading-none", children: p.flag }),
15488
+ p.isLeader && /* @__PURE__ */ jsx(Badge, { variant: "info", className: "h-4 px-1.5 text-[10px]", children: leaderLabel })
15489
+ ] })
15490
+ ] }, `${p.firstName}-${i}`)),
15491
+ Array.from({ length: emptySlots }).map((_, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-3 opacity-60", children: [
15492
+ /* @__PURE__ */ jsx(
15493
+ "span",
15494
+ {
15495
+ "aria-hidden": "true",
15496
+ className: "flex size-9 shrink-0 items-center justify-center rounded-full border border-dashed border-border text-muted-foreground",
15497
+ children: "+"
15498
+ }
15499
+ ),
15500
+ /* @__PURE__ */ jsx("span", { className: "font-sans text-sm text-muted-foreground", children: "Open spot" })
15501
+ ] }, `empty-${i}`))
15502
+ ] })
15503
+ ] });
15504
+ }
15505
+ function BrandIcon({ path }) {
15506
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "size-4", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: path }) });
15507
+ }
15508
+ var WHATSAPP = "M.057 24l1.687-6.163a11.867 11.867 0 01-1.587-5.945C.16 5.335 5.495 0 12.05 0a11.82 11.82 0 018.413 3.488 11.82 11.82 0 013.48 8.414c-.003 6.557-5.338 11.892-11.893 11.892a11.9 11.9 0 01-5.688-1.448L.057 24zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884a9.82 9.82 0 001.51 5.26l-.999 3.648 3.978-1.945zm5.473-6.231c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.096 3.2 5.077 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414z";
15509
+ var FACEBOOK = "M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z";
15510
+ var X = "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z";
15511
+ function ShareWidget({
15512
+ url,
15513
+ message = "Join my adventure and let's unlock a lower price together!",
15514
+ layout = "row",
15515
+ title = "Invite friends & lower the price",
15516
+ className
15517
+ }) {
15518
+ const [copied, setCopied] = React28.useState(false);
15519
+ const [showToast, setShowToast] = React28.useState(false);
15520
+ const encodedUrl = encodeURIComponent(url);
15521
+ const encodedMsg = encodeURIComponent(`${message} ${url}`);
15522
+ const channels = [
15523
+ {
15524
+ key: "whatsapp",
15525
+ label: "WhatsApp",
15526
+ href: `https://wa.me/?text=${encodedMsg}`,
15527
+ path: WHATSAPP,
15528
+ color: "hover:text-[#25D366] hover:border-[#25D366]"
15529
+ },
15530
+ {
15531
+ key: "facebook",
15532
+ label: "Facebook",
15533
+ href: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`,
15534
+ path: FACEBOOK,
15535
+ color: "hover:text-[#1877F2] hover:border-[#1877F2]"
15536
+ },
15537
+ {
15538
+ key: "x",
15539
+ label: "X",
15540
+ href: `https://twitter.com/intent/tweet?text=${encodeURIComponent(message)}&url=${encodedUrl}`,
15541
+ path: X,
15542
+ color: "hover:text-foreground hover:border-foreground"
15543
+ }
15544
+ ];
15545
+ const copyLink = async () => {
15546
+ try {
15547
+ await navigator.clipboard.writeText(url);
15548
+ } catch (e) {
15549
+ }
15550
+ setCopied(true);
15551
+ setShowToast(true);
15552
+ setTimeout(() => setCopied(false), 2e3);
15553
+ };
15554
+ const isIcons = layout === "icons";
15555
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
15556
+ title && /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-1.5 font-heading text-sm font-bold text-foreground", children: [
15557
+ /* @__PURE__ */ jsx(Share2Icon, { className: "size-4 text-primary", "aria-hidden": "true" }),
15558
+ title
15559
+ ] }),
15560
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
15561
+ channels.map((c) => /* @__PURE__ */ jsxs(
15562
+ "a",
15563
+ {
15564
+ href: c.href,
15565
+ target: "_blank",
15566
+ rel: "noopener noreferrer",
15567
+ "aria-label": `Share on ${c.label}`,
15568
+ className: cn(
15569
+ "inline-flex items-center gap-2 rounded-full border border-border px-3 py-2 font-ui text-sm text-foreground transition-colors",
15570
+ c.color
15571
+ ),
15572
+ children: [
15573
+ /* @__PURE__ */ jsx(BrandIcon, { path: c.path }),
15574
+ !isIcons && /* @__PURE__ */ jsx("span", { children: c.label })
15575
+ ]
15576
+ },
15577
+ c.key
15578
+ )),
15579
+ /* @__PURE__ */ jsxs(
15580
+ "button",
15581
+ {
15582
+ type: "button",
15583
+ onClick: copyLink,
15584
+ "aria-label": "Copy link",
15585
+ className: cn(
15586
+ "inline-flex items-center gap-2 rounded-full border border-border px-3 py-2 font-ui text-sm text-foreground transition-colors hover:border-primary hover:text-primary",
15587
+ copied && "border-success text-success"
15588
+ ),
15589
+ children: [
15590
+ copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) : /* @__PURE__ */ jsx(CopyIcon, { className: "size-4" }),
15591
+ !isIcons && /* @__PURE__ */ jsx("span", { children: copied ? "Copied!" : "Copy link" })
15592
+ ]
15593
+ }
15594
+ )
15595
+ ] }),
15596
+ showToast && /* @__PURE__ */ jsx(
15597
+ Toast,
15598
+ {
15599
+ message: "Link copied to clipboard",
15600
+ variant: "success",
15601
+ onClose: () => setShowToast(false),
15602
+ duration: 2500
15603
+ }
15604
+ )
15605
+ ] });
15606
+ }
15607
+ var MODE_COPY = {
15608
+ joinable: { cta: "Join this adventure", disabled: false },
15609
+ full: { cta: "Join waiting list", disabled: false },
15610
+ closed: { cta: "Booking closed", disabled: true },
15611
+ owner: { cta: "Share your departure", disabled: false }
15612
+ };
15613
+ function StickyBookingCard({
15614
+ currentPrice,
15615
+ deposit,
15616
+ spotsRemaining,
15617
+ mode = "joinable",
15618
+ onPrimary,
15619
+ note,
15620
+ className
15621
+ }) {
15622
+ const { cta, disabled } = MODE_COPY[mode];
15623
+ return /* @__PURE__ */ jsxs(
15624
+ "div",
15625
+ {
15626
+ className: cn(
15627
+ "flex flex-col gap-4 rounded-2xl border border-border bg-card p-5 ring-1 ring-foreground/5",
15628
+ className
15629
+ ),
15630
+ children: [
15631
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
15632
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
15633
+ /* @__PURE__ */ jsx("span", { className: "font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: "Current price" }),
15634
+ /* @__PURE__ */ jsx("span", { className: "font-heading text-2xl font-bold text-foreground tabular-nums", children: currentPrice }),
15635
+ /* @__PURE__ */ jsx("span", { className: "font-sans text-xs text-muted-foreground", children: "per person" })
15636
+ ] }),
15637
+ mode !== "owner" && /* @__PURE__ */ jsx(
15638
+ "span",
15639
+ {
15640
+ className: cn(
15641
+ "font-ui text-xs font-semibold",
15642
+ spotsRemaining <= 2 && spotsRemaining > 0 ? "text-warning" : "text-muted-foreground"
15643
+ ),
15644
+ children: spotsRemaining > 0 ? `${spotsRemaining} spots left` : "Full"
15645
+ }
15646
+ )
15647
+ ] }),
15648
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-lg bg-muted/60 px-3 py-2", children: [
15649
+ /* @__PURE__ */ jsx("span", { className: "font-sans text-sm text-muted-foreground", children: "Deposit today" }),
15650
+ /* @__PURE__ */ jsx("span", { className: "font-ui text-sm font-bold text-foreground tabular-nums", children: deposit })
15651
+ ] }),
15652
+ /* @__PURE__ */ jsx(
15653
+ Button,
15654
+ {
15655
+ variant: "primary",
15656
+ size: "lg",
15657
+ className: "w-full",
15658
+ disabled,
15659
+ onClick: onPrimary,
15660
+ children: cta
15661
+ }
15662
+ ),
15663
+ /* @__PURE__ */ jsx("p", { className: "text-center font-sans text-xs text-muted-foreground", children: note != null ? note : "A hold is placed on your card \u2014 no charge until approved." })
15664
+ ]
15665
+ }
15666
+ );
15667
+ }
14719
15668
 
14720
- export { ActivityCard, AgentContactCard, Alert, AskExo, BirthDateField, BookingAdventureCard, BookingCancellationEmail, BookingConfirmedCard, BookingCreatedEmail, BookingDetails, BookingForm, BookingOtpEmail, BookingPaymentConfirmationEmail, BookingShell, BookingSummary, Button, COUNTRIES, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, DatePickerField, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, ExoOrb, FilterPanel, FloatingInput, FloatingSelect, Itinerary, ItineraryDay, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, PartnerBookingCreatedEmail, PartnerRegistrationCompleteEmail, PaymentAmountSelector, PaymentDetailsBlock, PaymentMethodSelector, PaymentModalShell, PaymentReceiptEmail, PaymentReminderEmail, PhoneCountrySelect, PhotoGallery, PricingTrip, RegistrationForm, RegistrationProgressBar, RegistrationReminderEmail, RegistrationReminderIndividualEmail, RegistrationSuccessCard, SiteHeader, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, Toast, TransferDetailsBlock, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, TrustpilotEmbed, buttonVariants, cn, emailTokens, formatCpf, getStripeAppearance, itineraryDaySpecIcons, stripeAppearance, validateCpf, wrapEmailHtml };
15669
+ export { ActivityCard, AgentContactCard, Alert, AskExo, BirthDateField, BookingAdventureCard, BookingCancellationEmail, BookingConfirmedCard, BookingCreatedEmail, BookingDetails, BookingForm, BookingOtpEmail, BookingPaymentConfirmationEmail, BookingShell, BookingSummary, Button, COUNTRIES, CategoryPage2, CounterField, CountrySearchField, DEFAULT_HEADER_LINKS, DEFAULT_LANGUAGES, STATUS_MAP as DEPARTURE_STATUS_MAP, DatePickerField, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, ExoOrb, FilterPanel, FloatingInput, FloatingSelect, GroupProgressBar, GroupStatusBanner, Itinerary, ItineraryDay, LOGO_PLANETAEXO_DATA_URI, LeadCapturePopup, MenuTrip, OTPCodeInput, Offer, OfferAdventureCard, ParticipantCounter, ParticipantList, PartnerBookingCreatedEmail, PartnerRegistrationCompleteEmail, PaymentAmountSelector, PaymentDetailsBlock, PaymentMethodSelector, PaymentModalShell, PaymentReceiptEmail, PaymentReminderEmail, PhoneCountrySelect, PhotoGallery, Picture, PriceProgress, PricingMatrixCard, PricingTrip, RegistrationForm, RegistrationProgressBar, RegistrationReminderEmail, RegistrationReminderIndividualEmail, RegistrationSuccessCard, ShareWidget, SiteHeader, StatusBadge2 as StatusBadge, StickyBookingCard, TERMS_ACCEPT_KEY, TermsSection, ThemeToggle, Toast, TransferDetailsBlock, TravellerFormInviteEmail, TripCard, TripHeader, TripPage, TrustpilotEmbed, buttonVariants, cn, emailTokens, formatCpf, getStripeAppearance, itineraryDaySpecIcons, stripeAppearance, validateCpf, webpVariantUrl, wrapEmailHtml };
14721
15670
  //# sourceMappingURL=index.js.map
14722
15671
  //# sourceMappingURL=index.js.map