@planetaexo/design-system 0.52.3 → 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.cjs CHANGED
@@ -1277,16 +1277,47 @@ var VARIANT_STYLES = {
1277
1277
  success: "text-primary border-primary/30 bg-primary/10",
1278
1278
  info: "text-muted-foreground border-primary/25 bg-primary/5"
1279
1279
  };
1280
- function Alert({ variant = "info", children, className }) {
1281
- return /* @__PURE__ */ jsxRuntime.jsx(
1280
+ function Alert({
1281
+ variant = "info",
1282
+ title,
1283
+ icon,
1284
+ action,
1285
+ role = "status",
1286
+ children,
1287
+ className
1288
+ }) {
1289
+ const isBanner = Boolean(title || icon || action);
1290
+ if (!isBanner) {
1291
+ return /* @__PURE__ */ jsxRuntime.jsx(
1292
+ "div",
1293
+ {
1294
+ role,
1295
+ className: cn(
1296
+ "rounded-lg border px-3 py-2 text-sm font-sans leading-snug",
1297
+ VARIANT_STYLES[variant],
1298
+ className
1299
+ ),
1300
+ children
1301
+ }
1302
+ );
1303
+ }
1304
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1282
1305
  "div",
1283
1306
  {
1307
+ role,
1284
1308
  className: cn(
1285
- "rounded-lg border px-3 py-2 text-sm font-sans leading-snug",
1309
+ "flex items-start gap-3 rounded-lg border px-4 py-3 text-sm font-sans leading-snug",
1286
1310
  VARIANT_STYLES[variant],
1287
1311
  className
1288
1312
  ),
1289
- children
1313
+ children: [
1314
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 shrink-0 [&>svg]:size-4", "aria-hidden": "true", children: icon }),
1315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
1316
+ title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-ui font-bold text-current leading-snug", children: title }),
1317
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(title && "mt-0.5", "text-current/90"), children })
1318
+ ] }),
1319
+ action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 self-center", children: action })
1320
+ ]
1290
1321
  }
1291
1322
  );
1292
1323
  }
@@ -11042,7 +11073,12 @@ var badgeVariants = classVarianceAuthority.cva(
11042
11073
  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",
11043
11074
  outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
11044
11075
  ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
11045
- link: "text-primary underline-offset-4 hover:underline"
11076
+ link: "text-primary underline-offset-4 hover:underline",
11077
+ // ── Semantic soft tones (added for status surfaces) ────────────────
11078
+ success: "bg-success/10 text-success border-success/20 [a]:hover:bg-success/20",
11079
+ warning: "bg-warning/15 text-warning-foreground border-warning/30 dark:bg-warning/20 dark:text-warning [a]:hover:bg-warning/25",
11080
+ info: "bg-info/10 text-info border-info/20 [a]:hover:bg-info/20",
11081
+ neutral: "bg-muted text-muted-foreground border-border [a]:hover:bg-muted/70"
11046
11082
  }
11047
11083
  },
11048
11084
  defaultVariants: {
@@ -13514,7 +13550,385 @@ function TripPage({
13514
13550
  }
13515
13551
  );
13516
13552
  }
13553
+ function ArrowIcon2() {
13554
+ return /* @__PURE__ */ jsxRuntime.jsxs(
13555
+ "svg",
13556
+ {
13557
+ width: "13",
13558
+ height: "13",
13559
+ viewBox: "0 0 24 24",
13560
+ fill: "none",
13561
+ stroke: "currentColor",
13562
+ strokeWidth: "2.2",
13563
+ strokeLinecap: "round",
13564
+ strokeLinejoin: "round",
13565
+ children: [
13566
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
13567
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "12 5 19 12 12 19" })
13568
+ ]
13569
+ }
13570
+ );
13571
+ }
13517
13572
  var sizeConfig2 = {
13573
+ sm: {
13574
+ card: "h-72 w-56",
13575
+ title: "text-lg font-bold",
13576
+ meta: "text-xs",
13577
+ excerpt: "text-xs"
13578
+ },
13579
+ md: {
13580
+ card: "h-96 w-72",
13581
+ title: "text-xl font-bold",
13582
+ meta: "text-xs",
13583
+ excerpt: "text-sm"
13584
+ },
13585
+ lg: {
13586
+ card: "h-[28rem] w-96",
13587
+ title: "text-2xl font-bold",
13588
+ meta: "text-sm",
13589
+ excerpt: "text-sm"
13590
+ }
13591
+ };
13592
+ function BlogCard({
13593
+ image,
13594
+ imageAlt = "",
13595
+ category,
13596
+ readingTime,
13597
+ date,
13598
+ title,
13599
+ excerpt,
13600
+ href,
13601
+ cta,
13602
+ size = "md",
13603
+ className
13604
+ }) {
13605
+ var _a;
13606
+ const s = sizeConfig2[size];
13607
+ const meta = [date != null ? date : null, readingTime != null ? readingTime : null].filter(Boolean).join(" | ");
13608
+ const ctaLabel = (_a = cta == null ? void 0 : cta.label) != null ? _a : "Read more";
13609
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13610
+ /* @__PURE__ */ jsxRuntime.jsx(
13611
+ "img",
13612
+ {
13613
+ src: image,
13614
+ alt: imageAlt,
13615
+ loading: "lazy",
13616
+ className: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
13617
+ }
13618
+ ),
13619
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/90 via-black/40 to-black/10" }),
13620
+ category ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 p-3", children: /* @__PURE__ */ jsxRuntime.jsx(Chip, { variant: "glass", children: category }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10" }),
13621
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative z-10 flex flex-col gap-1.5 p-5", children: [
13622
+ meta && /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-white/70 font-medium font-ui", s.meta), children: meta }),
13623
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: cn("text-white leading-snug", s.title), children: title }),
13624
+ excerpt && /* @__PURE__ */ jsxRuntime.jsx(
13625
+ "p",
13626
+ {
13627
+ className: cn(
13628
+ "text-white/80 leading-relaxed -mt-1 line-clamp-2",
13629
+ s.excerpt
13630
+ ),
13631
+ children: excerpt
13632
+ }
13633
+ ),
13634
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex items-center justify-between gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs(
13635
+ "span",
13636
+ {
13637
+ className: cn(
13638
+ "group/cta inline-flex items-center gap-1.5 border-b border-white/70 pb-0.5",
13639
+ "text-sm font-semibold text-white transition-colors hover:border-white hover:text-white",
13640
+ "font-ui"
13641
+ ),
13642
+ children: [
13643
+ ctaLabel,
13644
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "transition-transform duration-150 group-hover/cta:translate-x-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(ArrowIcon2, {}) })
13645
+ ]
13646
+ }
13647
+ ) })
13648
+ ] })
13649
+ ] });
13650
+ const baseClasses = cn(
13651
+ "group relative flex flex-col justify-between overflow-hidden rounded-2xl",
13652
+ "shadow-md transition-shadow duration-300 hover:shadow-xl",
13653
+ s.card,
13654
+ className
13655
+ );
13656
+ return href ? /* @__PURE__ */ jsxRuntime.jsx(
13657
+ "a",
13658
+ {
13659
+ href,
13660
+ onClick: cta == null ? void 0 : cta.onClick,
13661
+ className: baseClasses,
13662
+ "aria-label": title,
13663
+ children: inner
13664
+ }
13665
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: baseClasses, children: inner });
13666
+ }
13667
+ function SectionHeading({
13668
+ eyebrow,
13669
+ title,
13670
+ rightSlot
13671
+ }) {
13672
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end justify-between gap-4 flex-wrap mb-6", children: [
13673
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
13674
+ eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-mono font-semibold text-primary uppercase tracking-widest mb-1", children: eyebrow }),
13675
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading leading-tight", children: title })
13676
+ ] }),
13677
+ rightSlot
13678
+ ] });
13679
+ }
13680
+ function CategoryPage2({
13681
+ title,
13682
+ intro,
13683
+ heroImage,
13684
+ trustpilotMini,
13685
+ breadcrumb,
13686
+ siteHeader,
13687
+ popularTours,
13688
+ popularToursTitle = "More adventures calling your name",
13689
+ popularToursEyebrow = "Popular tours",
13690
+ trips,
13691
+ tripsTitle,
13692
+ tripsEyebrow,
13693
+ filterGroups,
13694
+ sortOptions,
13695
+ defaultSort,
13696
+ tripsInitialCount = 15,
13697
+ trustpilot,
13698
+ reviewsTitle = "Don't just take our word for it",
13699
+ reviewsSubtitle,
13700
+ blogPosts,
13701
+ aboutTitle,
13702
+ aboutContent,
13703
+ blogIntro,
13704
+ travelGuideHref,
13705
+ travelGuideLabel = "Read our Travel Guide",
13706
+ blogPostsTitle,
13707
+ blogPostsViewAllHref,
13708
+ faqs,
13709
+ faqsTitle = "Frequently asked questions",
13710
+ faqInitialCount = 5,
13711
+ gallery,
13712
+ galleryTitle,
13713
+ className
13714
+ }) {
13715
+ var _a;
13716
+ const [faqsExpanded, setFaqsExpanded] = React28__namespace.useState(false);
13717
+ const [tripsExpanded, setTripsExpanded] = React28__namespace.useState(false);
13718
+ const [filterValue, setFilterValue] = React28__namespace.useState({});
13719
+ const [sort, setSort] = React28__namespace.useState(
13720
+ defaultSort != null ? defaultSort : (_a = sortOptions == null ? void 0 : sortOptions[0]) == null ? void 0 : _a.id
13721
+ );
13722
+ const sortedTrips = React28__namespace.useMemo(
13723
+ () => [...trips].sort((a, b) => {
13724
+ const af = a.featured ? 1 : 0;
13725
+ const bf = b.featured ? 1 : 0;
13726
+ return bf - af;
13727
+ }),
13728
+ [trips]
13729
+ );
13730
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
13731
+ /* @__PURE__ */ jsxRuntime.jsxs(
13732
+ "section",
13733
+ {
13734
+ className: cn(
13735
+ "relative w-full",
13736
+ siteHeader ? "min-h-[420px] pt-[140px]" : "min-h-[300px] pt-16",
13737
+ "pb-12 text-white",
13738
+ !heroImage && "bg-gradient-to-br from-primary-900 via-primary-800 to-primary-950"
13739
+ ),
13740
+ children: [
13741
+ heroImage && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 overflow-hidden", children: [
13742
+ /* @__PURE__ */ jsxRuntime.jsx(
13743
+ "img",
13744
+ {
13745
+ src: heroImage,
13746
+ alt: "",
13747
+ "aria-hidden": true,
13748
+ fetchPriority: "high",
13749
+ className: "absolute inset-0 h-full w-full object-cover"
13750
+ }
13751
+ ),
13752
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-black/55 via-black/40 to-black/65" })
13753
+ ] }),
13754
+ siteHeader && /* @__PURE__ */ jsxRuntime.jsx(
13755
+ SiteHeader,
13756
+ {
13757
+ links: Array.isArray(siteHeader) ? siteHeader : void 0,
13758
+ position: "overlay"
13759
+ }
13760
+ ),
13761
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mx-auto w-full max-w-6xl px-6 sm:px-8", children: [
13762
+ breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3 flex items-center gap-1.5 flex-wrap", children: breadcrumb.map((crumb, i) => /* @__PURE__ */ jsxRuntime.jsxs(React28__namespace.Fragment, { children: [
13763
+ i > 0 && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
13764
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/70 font-ui", children: crumb.label })
13765
+ ] }, i)) }),
13766
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-3xl sm:text-5xl font-bold text-white font-heading leading-tight max-w-3xl", children: title }),
13767
+ intro && /* @__PURE__ */ jsxRuntime.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 }),
13768
+ trustpilotMini && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-5 max-w-sm", children: /* @__PURE__ */ jsxRuntime.jsx(TrustpilotEmbed, { config: trustpilotMini }) })
13769
+ ] })
13770
+ ]
13771
+ }
13772
+ ),
13773
+ popularTours && popularTours.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12", children: [
13774
+ /* @__PURE__ */ jsxRuntime.jsx(
13775
+ SectionHeading,
13776
+ {
13777
+ eyebrow: popularToursEyebrow,
13778
+ title: popularToursTitle
13779
+ }
13780
+ ),
13781
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("div", { className: "inline-flex gap-5 min-w-max pb-2", children: popularTours.map((trip, i) => {
13782
+ var _b;
13783
+ const _a2 = trip, { featured: _featured, variant: _variant } = _a2, cardProps = __objRest(_a2, ["featured", "variant"]);
13784
+ return /* @__PURE__ */ jsxRuntime.jsx(
13785
+ TripCard,
13786
+ __spreadProps(__spreadValues({}, cardProps), {
13787
+ variant: "overlay",
13788
+ size: (_b = cardProps.size) != null ? _b : "md"
13789
+ }),
13790
+ i
13791
+ );
13792
+ }) }) })
13793
+ ] }),
13794
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 pt-6 sm:pt-8 pb-12", children: [
13795
+ (tripsTitle || tripsEyebrow) && /* @__PURE__ */ jsxRuntime.jsx(SectionHeading, { eyebrow: tripsEyebrow, title: tripsTitle != null ? tripsTitle : "" }),
13796
+ filterGroups && filterGroups.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6", children: /* @__PURE__ */ jsxRuntime.jsx(
13797
+ FilterPanel,
13798
+ {
13799
+ variant: "horizontal",
13800
+ groups: filterGroups,
13801
+ value: filterValue,
13802
+ onChange: setFilterValue,
13803
+ onClearAll: () => setFilterValue({}),
13804
+ sortOptions,
13805
+ sort,
13806
+ onSortChange: setSort
13807
+ }
13808
+ ) }),
13809
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground font-ui mb-5", children: [
13810
+ trips.length,
13811
+ " ",
13812
+ trips.length === 1 ? "trip" : "trips",
13813
+ " found"
13814
+ ] }),
13815
+ (() => {
13816
+ const visibleTrips = tripsExpanded ? sortedTrips : sortedTrips.slice(0, tripsInitialCount);
13817
+ const hiddenCount = sortedTrips.length - visibleTrips.length;
13818
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13819
+ /* @__PURE__ */ jsxRuntime.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) => {
13820
+ const _a2 = trip, { featured: _featured } = _a2, cardProps = __objRest(_a2, ["featured"]);
13821
+ return /* @__PURE__ */ jsxRuntime.jsx(
13822
+ TripCard,
13823
+ __spreadProps(__spreadValues({}, cardProps), {
13824
+ className: cn("w-full h-auto", cardProps.className)
13825
+ }),
13826
+ i
13827
+ );
13828
+ }) }),
13829
+ sortedTrips.length > tripsInitialCount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
13830
+ "button",
13831
+ {
13832
+ type: "button",
13833
+ onClick: () => setTripsExpanded((v) => !v),
13834
+ className: cn(
13835
+ "inline-flex items-center gap-2 rounded-full border border-border bg-background px-5 py-2.5",
13836
+ "text-sm font-semibold text-foreground shadow-sm",
13837
+ "hover:bg-muted transition-colors duration-150",
13838
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
13839
+ ),
13840
+ children: tripsExpanded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13841
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUpIcon, { className: "h-4 w-4 text-muted-foreground" }),
13842
+ "Show less"
13843
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13844
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "h-4 w-4 text-muted-foreground" }),
13845
+ "Load more (",
13846
+ hiddenCount,
13847
+ ")"
13848
+ ] })
13849
+ }
13850
+ ) })
13851
+ ] });
13852
+ })()
13853
+ ] }),
13854
+ trustpilot && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12 border-t border-border", children: [
13855
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading mb-2", children: reviewsTitle }),
13856
+ reviewsSubtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base text-muted-foreground leading-relaxed max-w-3xl mb-6 [&_a]:text-primary [&_a]:underline", children: reviewsSubtitle }),
13857
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-[400px]", children: /* @__PURE__ */ jsxRuntime.jsx(TrustpilotEmbed, { config: trustpilot }) })
13858
+ ] }),
13859
+ gallery && gallery.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pt-4", children: [
13860
+ galleryTitle && /* @__PURE__ */ jsxRuntime.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 }),
13861
+ /* @__PURE__ */ jsxRuntime.jsx(PhotoGallery, { photos: gallery, variant: "gridCompact", initialVisible: 8 })
13862
+ ] }),
13863
+ (aboutTitle || aboutContent || blogPostsTitle || blogPosts && blogPosts.length > 0) && /* @__PURE__ */ jsxRuntime.jsx("section", { className: "w-full bg-gray-100", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-14", children: [
13864
+ (aboutTitle || blogPostsTitle) && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading mb-5", children: aboutTitle != null ? aboutTitle : blogPostsTitle }),
13865
+ aboutContent && /* @__PURE__ */ jsxRuntime.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 }),
13866
+ blogPosts && blogPosts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13867
+ blogIntro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-6 text-base sm:text-lg font-semibold text-foreground font-heading", children: blogIntro }),
13868
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5", children: blogPosts.map((post, i) => /* @__PURE__ */ jsxRuntime.jsx(
13869
+ BlogCard,
13870
+ {
13871
+ href: post.href,
13872
+ image: post.image,
13873
+ imageAlt: post.imageAlt,
13874
+ title: post.title,
13875
+ excerpt: post.excerpt,
13876
+ category: post.category,
13877
+ readingTime: post.readingTime,
13878
+ className: "w-full"
13879
+ },
13880
+ i
13881
+ )) }),
13882
+ (travelGuideHref || blogPostsViewAllHref) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsxs(
13883
+ "a",
13884
+ {
13885
+ href: travelGuideHref != null ? travelGuideHref : blogPostsViewAllHref,
13886
+ className: "inline-flex items-center gap-1.5 text-sm font-semibold text-primary hover:underline",
13887
+ children: [
13888
+ travelGuideHref ? travelGuideLabel : "View all posts",
13889
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRightIcon, { className: "h-4 w-4" })
13890
+ ]
13891
+ }
13892
+ ) })
13893
+ ] })
13894
+ ] }) }),
13895
+ faqs && faqs.length > 0 && (() => {
13896
+ const visibleFaqs = faqsExpanded ? faqs : faqs.slice(0, faqInitialCount);
13897
+ const hiddenCount = faqs.length - visibleFaqs.length;
13898
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12", children: [
13899
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl sm:text-3xl font-bold text-foreground font-heading mb-6", children: faqsTitle }),
13900
+ /* @__PURE__ */ jsxRuntime.jsx(Accordion, { variant: "faq", children: visibleFaqs.map((faq, i) => /* @__PURE__ */ jsxRuntime.jsxs(AccordionItem, { value: `faq-${i}`, children: [
13901
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionTrigger, { children: faq.question }),
13902
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionContent, { children: faq.answer })
13903
+ ] }, i)) }),
13904
+ faqs.length > faqInitialCount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-5 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
13905
+ "button",
13906
+ {
13907
+ type: "button",
13908
+ onClick: () => setFaqsExpanded((v) => !v),
13909
+ className: cn(
13910
+ "inline-flex items-center gap-2 rounded-full border border-border bg-background px-5 py-2.5",
13911
+ "text-sm font-semibold text-foreground shadow-sm",
13912
+ "hover:bg-muted transition-colors duration-150",
13913
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
13914
+ ),
13915
+ children: faqsExpanded ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13916
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUpIcon, { className: "h-4 w-4 text-muted-foreground" }),
13917
+ "Show less"
13918
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13919
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "h-4 w-4 text-muted-foreground" }),
13920
+ "See more (",
13921
+ hiddenCount,
13922
+ ")"
13923
+ ] })
13924
+ }
13925
+ ) })
13926
+ ] });
13927
+ })(),
13928
+ /* @__PURE__ */ jsxRuntime.jsx(SiteFooter, {})
13929
+ ] });
13930
+ }
13931
+ var sizeConfig3 = {
13518
13932
  sm: {
13519
13933
  card: "w-56",
13520
13934
  image: "h-36",
@@ -13549,7 +13963,7 @@ function ActivityCard({
13549
13963
  size = "md",
13550
13964
  className
13551
13965
  }) {
13552
- const s = sizeConfig2[size];
13966
+ const s = sizeConfig3[size];
13553
13967
  return /* @__PURE__ */ jsxRuntime.jsxs(
13554
13968
  "div",
13555
13969
  {
@@ -14762,6 +15176,516 @@ function AskExo({
14762
15176
  )
14763
15177
  ] });
14764
15178
  }
15179
+ var STATUS_MAP = {
15180
+ "draft": { label: "Draft", variant: "neutral", dot: "bg-muted-foreground" },
15181
+ "pending-approval": { label: "Pending approval", variant: "warning", dot: "bg-warning" },
15182
+ "pending-group": { label: "Pending group", variant: "info", dot: "bg-info" },
15183
+ "confirmed": { label: "Confirmed", variant: "success", dot: "bg-success" },
15184
+ "payment-pending": { label: "Payment pending", variant: "warning", dot: "bg-warning" },
15185
+ "payment-reconciliation": { label: "Reconciliation", variant: "info", dot: "bg-info" },
15186
+ "fully-paid": { label: "Fully paid", variant: "default", dot: "bg-primary-foreground" },
15187
+ "full": { label: "Full", variant: "secondary", dot: "bg-secondary-foreground" },
15188
+ "waiting-list": { label: "Waiting list", variant: "info", dot: "bg-info" },
15189
+ "operating": { label: "Operating", variant: "default", dot: "bg-primary-foreground" },
15190
+ "cancelled": { label: "Cancelled", variant: "destructive", dot: "bg-destructive" }
15191
+ };
15192
+ function StatusBadge2({ status, dot = true, label, className }) {
15193
+ const config = STATUS_MAP[status];
15194
+ return /* @__PURE__ */ jsxRuntime.jsxs(Badge, { variant: config.variant, className: cn("gap-1.5", className), children: [
15195
+ dot && /* @__PURE__ */ jsxRuntime.jsx(
15196
+ "span",
15197
+ {
15198
+ "aria-hidden": "true",
15199
+ className: cn("size-1.5 shrink-0 rounded-full", config.dot)
15200
+ }
15201
+ ),
15202
+ label != null ? label : config.label
15203
+ ] });
15204
+ }
15205
+ function GroupStatusBanner({
15206
+ variant = "info",
15207
+ title,
15208
+ icon,
15209
+ action,
15210
+ urgent = false,
15211
+ children,
15212
+ className
15213
+ }) {
15214
+ return /* @__PURE__ */ jsxRuntime.jsx(
15215
+ Alert,
15216
+ {
15217
+ variant,
15218
+ title,
15219
+ icon,
15220
+ action,
15221
+ role: urgent ? "alert" : "status",
15222
+ className,
15223
+ children
15224
+ }
15225
+ );
15226
+ }
15227
+ function ParticipantCounter({
15228
+ current,
15229
+ max,
15230
+ label = "Travelers",
15231
+ hideIcon = false,
15232
+ className
15233
+ }) {
15234
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15235
+ "span",
15236
+ {
15237
+ className: cn(
15238
+ "inline-flex items-center gap-1.5 font-ui text-sm text-foreground",
15239
+ className
15240
+ ),
15241
+ children: [
15242
+ !hideIcon && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "size-4 text-primary", "aria-hidden": "true" }),
15243
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold tabular-nums", children: [
15244
+ current,
15245
+ " / ",
15246
+ max
15247
+ ] }),
15248
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label })
15249
+ ]
15250
+ }
15251
+ );
15252
+ }
15253
+ function GroupProgressBar({
15254
+ current,
15255
+ min,
15256
+ max,
15257
+ hideLabels = false,
15258
+ className
15259
+ }) {
15260
+ const pct = Math.max(0, Math.min(100, current / max * 100));
15261
+ const minPct = Math.max(0, Math.min(100, min / max * 100));
15262
+ const quorumMet = current >= min;
15263
+ const isFull = current >= max;
15264
+ const fillTone = isFull ? "bg-success" : quorumMet ? "bg-primary" : "bg-warning";
15265
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
15266
+ /* @__PURE__ */ jsxRuntime.jsxs(
15267
+ "div",
15268
+ {
15269
+ className: "relative h-3 w-full overflow-visible rounded-full bg-muted",
15270
+ role: "progressbar",
15271
+ "aria-valuenow": current,
15272
+ "aria-valuemin": 0,
15273
+ "aria-valuemax": max,
15274
+ "aria-label": `${current} of ${max} travelers, minimum ${min}${quorumMet ? " met" : " not yet met"}`,
15275
+ children: [
15276
+ /* @__PURE__ */ jsxRuntime.jsx(
15277
+ "div",
15278
+ {
15279
+ className: cn(
15280
+ "h-full rounded-full transition-[width,background-color] duration-500",
15281
+ fillTone
15282
+ ),
15283
+ style: { width: `${pct}%` }
15284
+ }
15285
+ ),
15286
+ /* @__PURE__ */ jsxRuntime.jsx(
15287
+ "span",
15288
+ {
15289
+ "aria-hidden": "true",
15290
+ 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",
15291
+ style: { left: `${minPct}%` }
15292
+ }
15293
+ )
15294
+ ]
15295
+ }
15296
+ ),
15297
+ !hideLabels && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between font-ui text-[11px] text-muted-foreground", children: [
15298
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(quorumMet && "text-success font-semibold"), children: quorumMet ? "Quorum reached" : `Min ${min} to confirm` }),
15299
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums", children: [
15300
+ max,
15301
+ " max"
15302
+ ] })
15303
+ ] })
15304
+ ] });
15305
+ }
15306
+ function Card(_a) {
15307
+ var _b = _a, {
15308
+ className,
15309
+ size = "default"
15310
+ } = _b, props = __objRest(_b, [
15311
+ "className",
15312
+ "size"
15313
+ ]);
15314
+ return /* @__PURE__ */ jsxRuntime.jsx(
15315
+ "div",
15316
+ __spreadValues({
15317
+ "data-slot": "card",
15318
+ "data-size": size,
15319
+ className: cn(
15320
+ "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",
15321
+ className
15322
+ )
15323
+ }, props)
15324
+ );
15325
+ }
15326
+ function CardHeader(_a) {
15327
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
15328
+ return /* @__PURE__ */ jsxRuntime.jsx(
15329
+ "div",
15330
+ __spreadValues({
15331
+ "data-slot": "card-header",
15332
+ className: cn(
15333
+ "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",
15334
+ className
15335
+ )
15336
+ }, props)
15337
+ );
15338
+ }
15339
+ function CardTitle(_a) {
15340
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
15341
+ return /* @__PURE__ */ jsxRuntime.jsx(
15342
+ "div",
15343
+ __spreadValues({
15344
+ "data-slot": "card-title",
15345
+ className: cn(
15346
+ "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
15347
+ className
15348
+ )
15349
+ }, props)
15350
+ );
15351
+ }
15352
+ function CardContent(_a) {
15353
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
15354
+ return /* @__PURE__ */ jsxRuntime.jsx(
15355
+ "div",
15356
+ __spreadValues({
15357
+ "data-slot": "card-content",
15358
+ className: cn("px-4 group-data-[size=sm]/card:px-3", className)
15359
+ }, props)
15360
+ );
15361
+ }
15362
+ function PricingMatrixCard({
15363
+ tiers,
15364
+ currentTravelers,
15365
+ title = "Group pricing",
15366
+ locked = false,
15367
+ className
15368
+ }) {
15369
+ const activeIndex = tiers.reduce(
15370
+ (acc, t, i) => currentTravelers >= t.threshold ? i : acc,
15371
+ -1
15372
+ );
15373
+ const bestIndex = tiers.length - 1;
15374
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className, children: [
15375
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "font-heading", children: title }) }),
15376
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "px-0", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-sm", children: [
15377
+ /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: "Price per person by number of travelers" }),
15378
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-y border-border text-left font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: [
15379
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2 font-semibold", children: "Travelers" }),
15380
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2 text-right font-semibold", children: "Price / person" })
15381
+ ] }) }),
15382
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: tiers.map((tier, i) => {
15383
+ const isActive = !locked && i === activeIndex;
15384
+ const isBest = i === bestIndex;
15385
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15386
+ "tr",
15387
+ {
15388
+ className: cn(
15389
+ "border-b border-border last:border-0 transition-colors",
15390
+ isActive && "bg-accent",
15391
+ locked && "opacity-60"
15392
+ ),
15393
+ "aria-current": isActive ? "true" : void 0,
15394
+ children: [
15395
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-2.5", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", children: [
15396
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-ui font-semibold text-foreground", children: tier.travelers }),
15397
+ isActive && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "success", className: "h-4 px-1.5 text-[10px]", children: "You are here" }),
15398
+ isBest && !isActive && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", className: "h-4 px-1.5 text-[10px]", children: "Best price" })
15399
+ ] }) }),
15400
+ /* @__PURE__ */ jsxRuntime.jsx(
15401
+ "td",
15402
+ {
15403
+ className: cn(
15404
+ "px-4 py-2.5 text-right font-ui tabular-nums",
15405
+ isActive ? "font-bold text-foreground" : "text-muted-foreground",
15406
+ isBest && "text-primary"
15407
+ ),
15408
+ children: tier.price
15409
+ }
15410
+ )
15411
+ ]
15412
+ },
15413
+ tier.travelers
15414
+ );
15415
+ }) })
15416
+ ] }) })
15417
+ ] });
15418
+ }
15419
+ function PriceProgress({
15420
+ currentPrice,
15421
+ lowestPrice,
15422
+ travelersToLowest,
15423
+ pct,
15424
+ className
15425
+ }) {
15426
+ const reached = travelersToLowest <= 0;
15427
+ const safePct = reached ? 100 : Math.max(0, Math.min(100, pct));
15428
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15429
+ "div",
15430
+ {
15431
+ className: cn(
15432
+ "flex flex-col gap-3 rounded-xl border border-border bg-card p-4",
15433
+ className
15434
+ ),
15435
+ "aria-live": "polite",
15436
+ children: [
15437
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end justify-between gap-4", children: [
15438
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
15439
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: "Current" }),
15440
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-heading text-xl font-bold text-foreground tabular-nums", children: currentPrice })
15441
+ ] }),
15442
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownIcon, { className: "mb-1 size-4 shrink-0 text-success", "aria-hidden": "true" }),
15443
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col text-right", children: [
15444
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: "Potential" }),
15445
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-heading text-xl font-bold text-primary tabular-nums", children: lowestPrice })
15446
+ ] })
15447
+ ] }),
15448
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(
15449
+ "div",
15450
+ {
15451
+ className: cn(
15452
+ "h-full rounded-full transition-[width] duration-500",
15453
+ reached ? "bg-success" : "bg-primary"
15454
+ ),
15455
+ style: { width: `${safePct}%` }
15456
+ }
15457
+ ) }),
15458
+ /* @__PURE__ */ jsxRuntime.jsx(
15459
+ "p",
15460
+ {
15461
+ className: cn(
15462
+ "flex items-center gap-1.5 font-ui text-sm font-semibold",
15463
+ reached ? "text-success" : "text-foreground"
15464
+ ),
15465
+ children: reached ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15466
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SparkleIcon, { className: "size-4", "aria-hidden": "true" }),
15467
+ "Best possible price unlocked"
15468
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15469
+ travelersToLowest,
15470
+ " more ",
15471
+ travelersToLowest === 1 ? "traveler" : "travelers",
15472
+ " for the lowest price"
15473
+ ] })
15474
+ }
15475
+ )
15476
+ ]
15477
+ }
15478
+ );
15479
+ }
15480
+ function ParticipantList({
15481
+ participants,
15482
+ emptySlots = 0,
15483
+ title = "Travelers",
15484
+ leaderLabel = "Leader",
15485
+ emptyMessage = "Be the first to join this adventure.",
15486
+ className
15487
+ }) {
15488
+ if (participants.length === 0 && emptySlots === 0) {
15489
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("font-sans text-sm text-muted-foreground", className), children: emptyMessage });
15490
+ }
15491
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
15492
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-heading text-sm font-bold text-foreground", children: title }),
15493
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-2", children: [
15494
+ participants.map((p, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center gap-3", children: [
15495
+ /* @__PURE__ */ jsxRuntime.jsx(
15496
+ "span",
15497
+ {
15498
+ className: "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary/10 text-primary",
15499
+ "aria-hidden": "true",
15500
+ children: p.avatarUrl ? (
15501
+ // eslint-disable-next-line @next/next/no-img-element
15502
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: p.avatarUrl, alt: "", className: "size-full object-cover" })
15503
+ ) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserIcon, { className: "size-4.5" })
15504
+ }
15505
+ ),
15506
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
15507
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-ui text-sm font-medium text-foreground", children: p.firstName }),
15508
+ p.flag && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": p.country, role: "img", className: "text-base leading-none", children: p.flag }),
15509
+ p.isLeader && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", className: "h-4 px-1.5 text-[10px]", children: leaderLabel })
15510
+ ] })
15511
+ ] }, `${p.firstName}-${i}`)),
15512
+ Array.from({ length: emptySlots }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center gap-3 opacity-60", children: [
15513
+ /* @__PURE__ */ jsxRuntime.jsx(
15514
+ "span",
15515
+ {
15516
+ "aria-hidden": "true",
15517
+ className: "flex size-9 shrink-0 items-center justify-center rounded-full border border-dashed border-border text-muted-foreground",
15518
+ children: "+"
15519
+ }
15520
+ ),
15521
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans text-sm text-muted-foreground", children: "Open spot" })
15522
+ ] }, `empty-${i}`))
15523
+ ] })
15524
+ ] });
15525
+ }
15526
+ function BrandIcon({ path }) {
15527
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "size-4", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: path }) });
15528
+ }
15529
+ 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";
15530
+ 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";
15531
+ 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";
15532
+ function ShareWidget({
15533
+ url,
15534
+ message = "Join my adventure and let's unlock a lower price together!",
15535
+ layout = "row",
15536
+ title = "Invite friends & lower the price",
15537
+ className
15538
+ }) {
15539
+ const [copied, setCopied] = React28__namespace.useState(false);
15540
+ const [showToast, setShowToast] = React28__namespace.useState(false);
15541
+ const encodedUrl = encodeURIComponent(url);
15542
+ const encodedMsg = encodeURIComponent(`${message} ${url}`);
15543
+ const channels = [
15544
+ {
15545
+ key: "whatsapp",
15546
+ label: "WhatsApp",
15547
+ href: `https://wa.me/?text=${encodedMsg}`,
15548
+ path: WHATSAPP,
15549
+ color: "hover:text-[#25D366] hover:border-[#25D366]"
15550
+ },
15551
+ {
15552
+ key: "facebook",
15553
+ label: "Facebook",
15554
+ href: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`,
15555
+ path: FACEBOOK,
15556
+ color: "hover:text-[#1877F2] hover:border-[#1877F2]"
15557
+ },
15558
+ {
15559
+ key: "x",
15560
+ label: "X",
15561
+ href: `https://twitter.com/intent/tweet?text=${encodeURIComponent(message)}&url=${encodedUrl}`,
15562
+ path: X,
15563
+ color: "hover:text-foreground hover:border-foreground"
15564
+ }
15565
+ ];
15566
+ const copyLink = async () => {
15567
+ try {
15568
+ await navigator.clipboard.writeText(url);
15569
+ } catch (e) {
15570
+ }
15571
+ setCopied(true);
15572
+ setShowToast(true);
15573
+ setTimeout(() => setCopied(false), 2e3);
15574
+ };
15575
+ const isIcons = layout === "icons";
15576
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
15577
+ title && /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "flex items-center gap-1.5 font-heading text-sm font-bold text-foreground", children: [
15578
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Share2Icon, { className: "size-4 text-primary", "aria-hidden": "true" }),
15579
+ title
15580
+ ] }),
15581
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
15582
+ channels.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
15583
+ "a",
15584
+ {
15585
+ href: c.href,
15586
+ target: "_blank",
15587
+ rel: "noopener noreferrer",
15588
+ "aria-label": `Share on ${c.label}`,
15589
+ className: cn(
15590
+ "inline-flex items-center gap-2 rounded-full border border-border px-3 py-2 font-ui text-sm text-foreground transition-colors",
15591
+ c.color
15592
+ ),
15593
+ children: [
15594
+ /* @__PURE__ */ jsxRuntime.jsx(BrandIcon, { path: c.path }),
15595
+ !isIcons && /* @__PURE__ */ jsxRuntime.jsx("span", { children: c.label })
15596
+ ]
15597
+ },
15598
+ c.key
15599
+ )),
15600
+ /* @__PURE__ */ jsxRuntime.jsxs(
15601
+ "button",
15602
+ {
15603
+ type: "button",
15604
+ onClick: copyLink,
15605
+ "aria-label": "Copy link",
15606
+ className: cn(
15607
+ "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",
15608
+ copied && "border-success text-success"
15609
+ ),
15610
+ children: [
15611
+ copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, { className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, { className: "size-4" }),
15612
+ !isIcons && /* @__PURE__ */ jsxRuntime.jsx("span", { children: copied ? "Copied!" : "Copy link" })
15613
+ ]
15614
+ }
15615
+ )
15616
+ ] }),
15617
+ showToast && /* @__PURE__ */ jsxRuntime.jsx(
15618
+ Toast,
15619
+ {
15620
+ message: "Link copied to clipboard",
15621
+ variant: "success",
15622
+ onClose: () => setShowToast(false),
15623
+ duration: 2500
15624
+ }
15625
+ )
15626
+ ] });
15627
+ }
15628
+ var MODE_COPY = {
15629
+ joinable: { cta: "Join this adventure", disabled: false },
15630
+ full: { cta: "Join waiting list", disabled: false },
15631
+ closed: { cta: "Booking closed", disabled: true },
15632
+ owner: { cta: "Share your departure", disabled: false }
15633
+ };
15634
+ function StickyBookingCard({
15635
+ currentPrice,
15636
+ deposit,
15637
+ spotsRemaining,
15638
+ mode = "joinable",
15639
+ onPrimary,
15640
+ note,
15641
+ className
15642
+ }) {
15643
+ const { cta, disabled } = MODE_COPY[mode];
15644
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15645
+ "div",
15646
+ {
15647
+ className: cn(
15648
+ "flex flex-col gap-4 rounded-2xl border border-border bg-card p-5 ring-1 ring-foreground/5",
15649
+ className
15650
+ ),
15651
+ children: [
15652
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between", children: [
15653
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
15654
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-ui text-[11px] uppercase tracking-wide text-muted-foreground", children: "Current price" }),
15655
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-heading text-2xl font-bold text-foreground tabular-nums", children: currentPrice }),
15656
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans text-xs text-muted-foreground", children: "per person" })
15657
+ ] }),
15658
+ mode !== "owner" && /* @__PURE__ */ jsxRuntime.jsx(
15659
+ "span",
15660
+ {
15661
+ className: cn(
15662
+ "font-ui text-xs font-semibold",
15663
+ spotsRemaining <= 2 && spotsRemaining > 0 ? "text-warning" : "text-muted-foreground"
15664
+ ),
15665
+ children: spotsRemaining > 0 ? `${spotsRemaining} spots left` : "Full"
15666
+ }
15667
+ )
15668
+ ] }),
15669
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between rounded-lg bg-muted/60 px-3 py-2", children: [
15670
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans text-sm text-muted-foreground", children: "Deposit today" }),
15671
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-ui text-sm font-bold text-foreground tabular-nums", children: deposit })
15672
+ ] }),
15673
+ /* @__PURE__ */ jsxRuntime.jsx(
15674
+ Button,
15675
+ {
15676
+ variant: "primary",
15677
+ size: "lg",
15678
+ className: "w-full",
15679
+ disabled,
15680
+ onClick: onPrimary,
15681
+ children: cta
15682
+ }
15683
+ ),
15684
+ /* @__PURE__ */ jsxRuntime.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." })
15685
+ ]
15686
+ }
15687
+ );
15688
+ }
14765
15689
 
14766
15690
  exports.ActivityCard = ActivityCard;
14767
15691
  exports.AgentContactCard = AgentContactCard;
@@ -14780,10 +15704,12 @@ exports.BookingShell = BookingShell;
14780
15704
  exports.BookingSummary = BookingSummary;
14781
15705
  exports.Button = Button;
14782
15706
  exports.COUNTRIES = COUNTRIES;
15707
+ exports.CategoryPage2 = CategoryPage2;
14783
15708
  exports.CounterField = CounterField;
14784
15709
  exports.CountrySearchField = CountrySearchField;
14785
15710
  exports.DEFAULT_HEADER_LINKS = DEFAULT_HEADER_LINKS;
14786
15711
  exports.DEFAULT_LANGUAGES = DEFAULT_LANGUAGES;
15712
+ exports.DEPARTURE_STATUS_MAP = STATUS_MAP;
14787
15713
  exports.DatePickerField = DatePickerField;
14788
15714
  exports.Dialog = Dialog;
14789
15715
  exports.DialogClose = DialogClose;
@@ -14796,6 +15722,8 @@ exports.ExoOrb = ExoOrb;
14796
15722
  exports.FilterPanel = FilterPanel;
14797
15723
  exports.FloatingInput = FloatingInput;
14798
15724
  exports.FloatingSelect = FloatingSelect;
15725
+ exports.GroupProgressBar = GroupProgressBar;
15726
+ exports.GroupStatusBanner = GroupStatusBanner;
14799
15727
  exports.Itinerary = Itinerary;
14800
15728
  exports.ItineraryDay = ItineraryDay;
14801
15729
  exports.LOGO_PLANETAEXO_DATA_URI = LOGO_PLANETAEXO_DATA_URI;
@@ -14804,6 +15732,8 @@ exports.MenuTrip = MenuTrip;
14804
15732
  exports.OTPCodeInput = OTPCodeInput;
14805
15733
  exports.Offer = Offer;
14806
15734
  exports.OfferAdventureCard = OfferAdventureCard;
15735
+ exports.ParticipantCounter = ParticipantCounter;
15736
+ exports.ParticipantList = ParticipantList;
14807
15737
  exports.PartnerBookingCreatedEmail = PartnerBookingCreatedEmail;
14808
15738
  exports.PartnerRegistrationCompleteEmail = PartnerRegistrationCompleteEmail;
14809
15739
  exports.PaymentAmountSelector = PaymentAmountSelector;
@@ -14815,13 +15745,18 @@ exports.PaymentReminderEmail = PaymentReminderEmail;
14815
15745
  exports.PhoneCountrySelect = PhoneCountrySelect;
14816
15746
  exports.PhotoGallery = PhotoGallery;
14817
15747
  exports.Picture = Picture;
15748
+ exports.PriceProgress = PriceProgress;
15749
+ exports.PricingMatrixCard = PricingMatrixCard;
14818
15750
  exports.PricingTrip = PricingTrip;
14819
15751
  exports.RegistrationForm = RegistrationForm;
14820
15752
  exports.RegistrationProgressBar = RegistrationProgressBar;
14821
15753
  exports.RegistrationReminderEmail = RegistrationReminderEmail;
14822
15754
  exports.RegistrationReminderIndividualEmail = RegistrationReminderIndividualEmail;
14823
15755
  exports.RegistrationSuccessCard = RegistrationSuccessCard;
15756
+ exports.ShareWidget = ShareWidget;
14824
15757
  exports.SiteHeader = SiteHeader;
15758
+ exports.StatusBadge = StatusBadge2;
15759
+ exports.StickyBookingCard = StickyBookingCard;
14825
15760
  exports.TERMS_ACCEPT_KEY = TERMS_ACCEPT_KEY;
14826
15761
  exports.TermsSection = TermsSection;
14827
15762
  exports.ThemeToggle = ThemeToggle;