@planetaexo/design-system 0.37.3 → 0.37.4

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
@@ -1,10 +1,10 @@
1
- import * as React8 from 'react';
1
+ import * as React28 from 'react';
2
2
  import { useState, useRef, useCallback, useEffect } from 'react';
3
3
  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, ChevronLeftIcon, HomeIcon, SailboatIcon, CarIcon, WavesIcon, FootprintsIcon, InfoIcon, ClockIcon, CheckIcon, ChevronUpIcon, UserIcon, MenuIcon, SunIcon, MoonIcon, MapPinIcon, PackageIcon, SparklesIcon, BackpackIcon, BedDoubleIcon, UtensilsIcon, ReceiptIcon, Loader2Icon, SendIcon, CheckCircleIcon, MailIcon, PhoneIcon, MessageCircleIcon, CompassIcon, UserPlusIcon, ExternalLinkIcon, CopyIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, 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, Loader2Icon, SendIcon, CheckCircleIcon, MailIcon, PhoneIcon, MessageCircleIcon, UserPlusIcon, ExternalLinkIcon, CopyIcon, PencilIcon, Trash2Icon, UserMinusIcon, AlertTriangleIcon, ZoomInIcon, StarIcon, TwitterIcon, YoutubeIcon, LinkedinIcon, InstagramIcon, FacebookIcon, ArrowRightIcon, 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';
@@ -81,7 +81,7 @@ var buttonVariants = cva(
81
81
  }
82
82
  }
83
83
  );
84
- var Button = React8.forwardRef(
84
+ var Button = React28.forwardRef(
85
85
  (_a, ref) => {
86
86
  var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
87
87
  return /* @__PURE__ */ jsx(
@@ -165,6 +165,10 @@ function Dialog(_a) {
165
165
  var props = __objRest(_a, []);
166
166
  return /* @__PURE__ */ jsx(Dialog$1.Root, __spreadValues({ "data-slot": "dialog" }, props));
167
167
  }
168
+ function DialogTrigger(_a) {
169
+ var props = __objRest(_a, []);
170
+ return /* @__PURE__ */ jsx(Dialog$1.Trigger, __spreadValues({ "data-slot": "dialog-trigger" }, props));
171
+ }
168
172
  function DialogPortal(_a) {
169
173
  var props = __objRest(_a, []);
170
174
  return /* @__PURE__ */ jsx(Dialog$1.Portal, __spreadValues({ "data-slot": "dialog-portal" }, props));
@@ -302,10 +306,10 @@ function DialogDescription(_a) {
302
306
  }, props)
303
307
  );
304
308
  }
305
- var FloatingInput = React8.forwardRef(
309
+ var FloatingInput = React28.forwardRef(
306
310
  (_a, ref) => {
307
311
  var _b = _a, { label, error, id, className, required } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required"]);
308
- const inputId = id != null ? id : React8.useId();
312
+ const inputId = id != null ? id : React28.useId();
309
313
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
310
314
  /* @__PURE__ */ jsx(
311
315
  "input",
@@ -345,10 +349,10 @@ var FloatingInput = React8.forwardRef(
345
349
  }
346
350
  );
347
351
  FloatingInput.displayName = "FloatingInput";
348
- var FloatingSelect = React8.forwardRef(
352
+ var FloatingSelect = React28.forwardRef(
349
353
  (_a, ref) => {
350
354
  var _b = _a, { label, error, id, className, required, children, value } = _b, props = __objRest(_b, ["label", "error", "id", "className", "required", "children", "value"]);
351
- const inputId = id != null ? id : React8.useId();
355
+ const inputId = id != null ? id : React28.useId();
352
356
  const hasValue = typeof value === "string" ? value !== "" : value !== void 0 && value !== null;
353
357
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
354
358
  /* @__PURE__ */ jsx(
@@ -612,11 +616,11 @@ function PhoneCountrySelect({
612
616
  disabled
613
617
  }) {
614
618
  var _a;
615
- const [open, setOpen] = React8.useState(false);
616
- const containerRef = React8.useRef(null);
617
- const listRef = React8.useRef(null);
619
+ const [open, setOpen] = React28.useState(false);
620
+ const containerRef = React28.useRef(null);
621
+ const listRef = React28.useRef(null);
618
622
  const selected = (_a = PHONE_COUNTRIES.find((c) => c.code === value)) != null ? _a : PHONE_COUNTRIES[0];
619
- React8.useEffect(() => {
623
+ React28.useEffect(() => {
620
624
  if (!open) return;
621
625
  const handler = (e) => {
622
626
  var _a2;
@@ -627,7 +631,7 @@ function PhoneCountrySelect({
627
631
  document.addEventListener("mousedown", handler);
628
632
  return () => document.removeEventListener("mousedown", handler);
629
633
  }, [open]);
630
- React8.useEffect(() => {
634
+ React28.useEffect(() => {
631
635
  if (!open || !listRef.current) return;
632
636
  const activeEl = listRef.current.querySelector("[data-selected=true]");
633
637
  activeEl == null ? void 0 : activeEl.scrollIntoView({ block: "nearest" });
@@ -897,8 +901,8 @@ function CalendarDayButton(_a) {
897
901
  "locale"
898
902
  ]);
899
903
  const defaultClassNames = getDefaultClassNames();
900
- const ref = React8.useRef(null);
901
- React8.useEffect(() => {
904
+ const ref = React28.useRef(null);
905
+ React28.useEffect(() => {
902
906
  var _a2;
903
907
  if (modifiers.focused) (_a2 = ref.current) == null ? void 0 : _a2.focus();
904
908
  }, [modifiers.focused]);
@@ -929,16 +933,16 @@ function BirthDateField({
929
933
  className,
930
934
  disabled
931
935
  }) {
932
- const [open, setOpen] = React8.useState(false);
933
- const [text, setText] = React8.useState(
936
+ const [open, setOpen] = React28.useState(false);
937
+ const [text, setText] = React28.useState(
934
938
  value ? format(value, "dd/MM/yyyy") : ""
935
939
  );
936
- const containerRef = React8.useRef(null);
937
- const inputId = React8.useId();
938
- React8.useEffect(() => {
940
+ const containerRef = React28.useRef(null);
941
+ const inputId = React28.useId();
942
+ React28.useEffect(() => {
939
943
  setText(value ? format(value, "dd/MM/yyyy") : "");
940
944
  }, [value]);
941
- React8.useEffect(() => {
945
+ React28.useEffect(() => {
942
946
  if (!open) return;
943
947
  const handler = (e) => {
944
948
  var _a;
@@ -1147,14 +1151,14 @@ function CountrySearchField({
1147
1151
  }) {
1148
1152
  var _a;
1149
1153
  const list = countries != null ? countries : COUNTRIES;
1150
- const [query, setQuery] = React8.useState("");
1151
- const [open, setOpen] = React8.useState(false);
1152
- const containerRef = React8.useRef(null);
1153
- const searchRef = React8.useRef(null);
1154
+ const [query, setQuery] = React28.useState("");
1155
+ const [open, setOpen] = React28.useState(false);
1156
+ const containerRef = React28.useRef(null);
1157
+ const searchRef = React28.useRef(null);
1154
1158
  const selected = list.find((c) => c.code === value);
1155
1159
  const isFloated = open || !!selected;
1156
1160
  const filtered = query.trim() ? list.filter((c) => c.name.toLowerCase().includes(query.toLowerCase())) : list;
1157
- React8.useEffect(() => {
1161
+ React28.useEffect(() => {
1158
1162
  if (!open) return;
1159
1163
  const handler = (e) => {
1160
1164
  var _a2;
@@ -1268,7 +1272,7 @@ function AdventureCard({
1268
1272
  }) {
1269
1273
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1270
1274
  const isControlled = (_b = (_a = adventure.optionals) == null ? void 0 : _a.some((o) => o.onCheckedChange !== void 0)) != null ? _b : false;
1271
- const [checkedInternal, setCheckedInternal] = React8.useState(
1275
+ const [checkedInternal, setCheckedInternal] = React28.useState(
1272
1276
  new Set((_d = (_c = adventure.optionals) == null ? void 0 : _c.filter((o) => o.defaultChecked).map((o) => o.id)) != null ? _d : [])
1273
1277
  );
1274
1278
  const isChecked = (opt) => {
@@ -1666,7 +1670,7 @@ function BookingShell({
1666
1670
  return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border bg-card overflow-hidden", children: [
1667
1671
  /* @__PURE__ */ jsxs("div", { className: "border-b border-border px-5 py-4 bg-muted/20", children: [
1668
1672
  /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-heading mb-2", children: title }),
1669
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React8.Fragment, { children: [
1673
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: steps.map((label, i) => /* @__PURE__ */ jsxs(React28.Fragment, { children: [
1670
1674
  /* @__PURE__ */ jsx(
1671
1675
  "span",
1672
1676
  {
@@ -1865,7 +1869,7 @@ function TermsSection({
1865
1869
  termsContent
1866
1870
  }) {
1867
1871
  var _a;
1868
- const [modalOpen, setModalOpen] = React8.useState(false);
1872
+ const [modalOpen, setModalOpen] = React28.useState(false);
1869
1873
  const i18n = (_a = TERMS_I18N[locale]) != null ? _a : TERMS_I18N.en;
1870
1874
  return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border p-4 flex flex-col gap-3", children: [
1871
1875
  /* @__PURE__ */ jsx("p", { className: "text-xs font-bold text-muted-foreground font-heading uppercase tracking-widest", children: title }),
@@ -2003,9 +2007,9 @@ function BookingWizard({
2003
2007
  }) {
2004
2008
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T;
2005
2009
  const wizardSteps = WIZARD_STEPS_FN(labels);
2006
- const [step, setStep] = React8.useState("responsible");
2007
- const [error, setError] = React8.useState(null);
2008
- const [responsible, setResponsible] = React8.useState({
2010
+ const [step, setStep] = React28.useState("responsible");
2011
+ const [error, setError] = React28.useState(null);
2012
+ const [responsible, setResponsible] = React28.useState({
2009
2013
  firstName: "",
2010
2014
  lastName: "",
2011
2015
  email: "",
@@ -2024,7 +2028,7 @@ function BookingWizard({
2024
2028
  return s + ((_b2 = (_a2 = a.slots) == null ? void 0 : _a2.children) != null ? _b2 : 0);
2025
2029
  }, 0);
2026
2030
  const totalPax = totalAdults + totalChildren;
2027
- const [travellers, setTravellers] = React8.useState(
2031
+ const [travellers, setTravellers] = React28.useState(
2028
2032
  Array.from({ length: Math.max(totalPax, 1) }, () => ({
2029
2033
  firstName: "",
2030
2034
  lastName: "",
@@ -2032,9 +2036,9 @@ function BookingWizard({
2032
2036
  email: ""
2033
2037
  }))
2034
2038
  );
2035
- const [payAmount, setPayAmount] = React8.useState("full");
2036
- const [payMethod, setPayMethod] = React8.useState("stripe");
2037
- const [termsAccepted, setTermsAccepted] = React8.useState(false);
2039
+ const [payAmount, setPayAmount] = React28.useState("full");
2040
+ const [payMethod, setPayMethod] = React28.useState("stripe");
2041
+ const [termsAccepted, setTermsAccepted] = React28.useState(false);
2038
2042
  const setR = (k, v) => setResponsible((p) => __spreadProps(__spreadValues({}, p), { [k]: v }));
2039
2043
  const setT = (i, k, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { [k]: v }) : t));
2040
2044
  const setTDob = (i, v) => setTravellers((prev) => prev.map((t, idx) => idx === i ? __spreadProps(__spreadValues({}, t), { dateOfBirth: v }) : t));
@@ -2262,7 +2266,7 @@ function Offer({
2262
2266
  className
2263
2267
  }) {
2264
2268
  var _a, _b, _c;
2265
- const [showBooking, setShowBooking] = React8.useState(false);
2269
+ const [showBooking, setShowBooking] = React28.useState(false);
2266
2270
  const isShowingCheckout = !confirmedState && (!!checkoutSlot || internalDemoCheckout && showBooking);
2267
2271
  const handleBook = () => {
2268
2272
  if (!checkoutSlot && !externalBookingFlow && internalDemoCheckout) {
@@ -2629,7 +2633,7 @@ function AdventureSection({
2629
2633
  labels
2630
2634
  }) {
2631
2635
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
2632
- const [detailsOpen, setDetailsOpen] = React8.useState(false);
2636
+ const [detailsOpen, setDetailsOpen] = React28.useState(false);
2633
2637
  const handleCopyUrl = (url) => {
2634
2638
  if (onCopyFormLink) {
2635
2639
  onCopyFormLink(url);
@@ -3141,8 +3145,8 @@ function AddTravellerDialog({
3141
3145
  errorMessage
3142
3146
  }) {
3143
3147
  var _a, _b, _c, _d, _e;
3144
- const [form, setForm] = React8.useState(() => createInitialAddFormData(config));
3145
- React8.useEffect(() => {
3148
+ const [form, setForm] = React28.useState(() => createInitialAddFormData(config));
3149
+ React28.useEffect(() => {
3146
3150
  if (open) {
3147
3151
  setForm(createInitialAddFormData(config));
3148
3152
  }
@@ -3202,7 +3206,7 @@ function EditTravellerDialog({
3202
3206
  errorMessage
3203
3207
  }) {
3204
3208
  var _a, _b, _c, _d, _e;
3205
- const [form, setForm] = React8.useState(() => ({
3209
+ const [form, setForm] = React28.useState(() => ({
3206
3210
  firstName: "",
3207
3211
  lastName: "",
3208
3212
  email: "",
@@ -3211,7 +3215,7 @@ function EditTravellerDialog({
3211
3215
  birthDate: "",
3212
3216
  personType: "ADULT"
3213
3217
  }));
3214
- React8.useEffect(() => {
3218
+ React28.useEffect(() => {
3215
3219
  var _a2, _b2, _c2, _d2, _e2, _f;
3216
3220
  if (open && traveller) {
3217
3221
  setForm({
@@ -3546,48 +3550,48 @@ function BookingDetails({
3546
3550
  const hasSubmitAddTraveller = !!onSubmitAddTraveller;
3547
3551
  const hasSubmitEditTraveller = !!onSubmitEditTraveller;
3548
3552
  const hasConfirmRemoveTraveller = !!onConfirmRemoveTraveller;
3549
- const [addModalState, setAddModalState] = React8.useState({
3553
+ const [addModalState, setAddModalState] = React28.useState({
3550
3554
  open: false,
3551
3555
  adventureId: null
3552
3556
  });
3553
- const [editModalState, setEditModalState] = React8.useState({ open: false, adventureId: null, traveller: null });
3554
- const [deleteModalState, setDeleteModalState] = React8.useState({ open: false, adventureId: null, traveller: null });
3555
- const [resendInviteDialogState, setResendInviteDialogState] = React8.useState({ open: false, traveller: null });
3556
- const handleRequestOpenAddModal = React8.useCallback((adventureId) => {
3557
+ const [editModalState, setEditModalState] = React28.useState({ open: false, adventureId: null, traveller: null });
3558
+ const [deleteModalState, setDeleteModalState] = React28.useState({ open: false, adventureId: null, traveller: null });
3559
+ const [resendInviteDialogState, setResendInviteDialogState] = React28.useState({ open: false, traveller: null });
3560
+ const handleRequestOpenAddModal = React28.useCallback((adventureId) => {
3557
3561
  setAddModalState({ open: true, adventureId });
3558
3562
  }, []);
3559
- const handleRequestOpenEditModal = React8.useCallback(
3563
+ const handleRequestOpenEditModal = React28.useCallback(
3560
3564
  (adventureId, traveller) => {
3561
3565
  setEditModalState({ open: true, adventureId, traveller });
3562
3566
  },
3563
3567
  []
3564
3568
  );
3565
- const handleRequestOpenDeleteModal = React8.useCallback(
3569
+ const handleRequestOpenDeleteModal = React28.useCallback(
3566
3570
  (adventureId, traveller) => {
3567
3571
  setDeleteModalState({ open: true, adventureId, traveller });
3568
3572
  },
3569
3573
  []
3570
3574
  );
3571
- const handleRequestOpenResendInviteDialog = React8.useCallback(
3575
+ const handleRequestOpenResendInviteDialog = React28.useCallback(
3572
3576
  (traveller) => {
3573
3577
  setResendInviteDialogState({ open: true, traveller });
3574
3578
  },
3575
3579
  []
3576
3580
  );
3577
- const closeAddModal = React8.useCallback(() => {
3581
+ const closeAddModal = React28.useCallback(() => {
3578
3582
  setAddModalState({ open: false, adventureId: null });
3579
3583
  }, []);
3580
- const closeEditModal = React8.useCallback(() => {
3584
+ const closeEditModal = React28.useCallback(() => {
3581
3585
  setEditModalState({ open: false, adventureId: null, traveller: null });
3582
3586
  }, []);
3583
- const closeDeleteModal = React8.useCallback(() => {
3587
+ const closeDeleteModal = React28.useCallback(() => {
3584
3588
  setDeleteModalState({ open: false, adventureId: null, traveller: null });
3585
3589
  }, []);
3586
- const closeResendInviteDialog = React8.useCallback(() => {
3590
+ const closeResendInviteDialog = React28.useCallback(() => {
3587
3591
  setResendInviteDialogState({ open: false, traveller: null });
3588
3592
  }, []);
3589
- const submitInFlightRef = React8.useRef(false);
3590
- const handleAddSubmit = React8.useCallback(
3593
+ const submitInFlightRef = React28.useRef(false);
3594
+ const handleAddSubmit = React28.useCallback(
3591
3595
  async (adventureId, data) => {
3592
3596
  if (!onSubmitAddTraveller) return;
3593
3597
  if (submitInFlightRef.current) return;
@@ -3602,7 +3606,7 @@ function BookingDetails({
3602
3606
  },
3603
3607
  [onSubmitAddTraveller, closeAddModal]
3604
3608
  );
3605
- const handleEditSubmit = React8.useCallback(
3609
+ const handleEditSubmit = React28.useCallback(
3606
3610
  async (adventureId, travellerId, data) => {
3607
3611
  if (!onSubmitEditTraveller) return;
3608
3612
  if (submitInFlightRef.current) return;
@@ -3617,7 +3621,7 @@ function BookingDetails({
3617
3621
  },
3618
3622
  [onSubmitEditTraveller, closeEditModal]
3619
3623
  );
3620
- const handleDeleteConfirm = React8.useCallback(
3624
+ const handleDeleteConfirm = React28.useCallback(
3621
3625
  async (adventureId, travellerId) => {
3622
3626
  if (!onConfirmRemoveTraveller) return;
3623
3627
  if (submitInFlightRef.current) return;
@@ -5091,7 +5095,7 @@ function BookingCreatedEmail({
5091
5095
  }, children: i + 1 }) }),
5092
5096
  /* @__PURE__ */ jsx("td", { style: { verticalAlign: "top" }, children: /* @__PURE__ */ jsx("p", { style: { fontSize: "14px", color: emailTokens.bodyText, lineHeight: "1.6", margin: 0 }, children: step }) })
5093
5097
  ] }) }) }, i)) }),
5094
- nextStepsImportant && nextStepsImportant.trim().length > 0 && /* @__PURE__ */ jsx("p", { style: { marginBottom: "32px", fontSize: "14px", color: emailTokens.foreground, lineHeight: "1.6" }, children: nextStepsImportant.split("\n").map((line, idx, arr) => /* @__PURE__ */ jsxs(React8.Fragment, { children: [
5098
+ nextStepsImportant && nextStepsImportant.trim().length > 0 && /* @__PURE__ */ jsx("p", { style: { marginBottom: "32px", fontSize: "14px", color: emailTokens.foreground, lineHeight: "1.6" }, children: nextStepsImportant.split("\n").map((line, idx, arr) => /* @__PURE__ */ jsxs(React28.Fragment, { children: [
5095
5099
  idx === 0 ? /* @__PURE__ */ jsx("strong", { children: line }) : line,
5096
5100
  idx < arr.length - 1 ? /* @__PURE__ */ jsx("br", {}) : null
5097
5101
  ] }, idx)) })
@@ -6460,11 +6464,11 @@ function DatePickerField({
6460
6464
  fromDate,
6461
6465
  className
6462
6466
  }) {
6463
- const [open, setOpen] = React8.useState(false);
6464
- const containerRef = React8.useRef(null);
6465
- const [calendarWidth, setCalendarWidth] = React8.useState();
6467
+ const [open, setOpen] = React28.useState(false);
6468
+ const containerRef = React28.useRef(null);
6469
+ const [calendarWidth, setCalendarWidth] = React28.useState();
6466
6470
  const hasValue = !!value;
6467
- React8.useEffect(() => {
6471
+ React28.useEffect(() => {
6468
6472
  if (!containerRef.current) return;
6469
6473
  const observer = new ResizeObserver(([entry]) => {
6470
6474
  setCalendarWidth(entry.contentRect.width);
@@ -6573,7 +6577,7 @@ function BookingForm({
6573
6577
  subtitle = "Free enquiry \u2013 no commitment",
6574
6578
  className
6575
6579
  }) {
6576
- const [values, setValues] = React8.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
6580
+ const [values, setValues] = React28.useState(__spreadValues(__spreadValues({}, defaultInitial), defaultValues));
6577
6581
  const set = (key, value) => setValues((prev) => __spreadProps(__spreadValues({}, prev), { [key]: value }));
6578
6582
  const handleSubmit = (e) => {
6579
6583
  e.preventDefault();
@@ -7110,11 +7114,11 @@ function FloatingTextarea({
7110
7114
  }
7111
7115
  function SelectField({ field, value, onChange, error, disabled }) {
7112
7116
  var _a, _b, _c;
7113
- const [open, setOpen] = React8.useState(false);
7114
- const containerRef = React8.useRef(null);
7117
+ const [open, setOpen] = React28.useState(false);
7118
+ const containerRef = React28.useRef(null);
7115
7119
  const options = (_a = field.options) != null ? _a : [];
7116
7120
  const selectedOpt = (_b = options.find((o) => o.value === value)) != null ? _b : null;
7117
- React8.useEffect(() => {
7121
+ React28.useEffect(() => {
7118
7122
  if (!open) return;
7119
7123
  const handleOutside = (e) => {
7120
7124
  if (containerRef.current && !containerRef.current.contains(e.target)) {
@@ -7503,11 +7507,11 @@ function RegistrationForm({
7503
7507
  readOnly = false
7504
7508
  }) {
7505
7509
  var _a;
7506
- const L = React8.useMemo(
7510
+ const L = React28.useMemo(
7507
7511
  () => __spreadValues(__spreadValues({}, DEFAULT_LABELS9), labels != null ? labels : {}),
7508
7512
  [labels]
7509
7513
  );
7510
- const sortedFields = React8.useMemo(
7514
+ const sortedFields = React28.useMemo(
7511
7515
  () => [...fields].sort((a, b) => {
7512
7516
  var _a2, _b;
7513
7517
  return ((_a2 = a.order) != null ? _a2 : 0) - ((_b = b.order) != null ? _b : 0);
@@ -7515,7 +7519,7 @@ function RegistrationForm({
7515
7519
  [fields]
7516
7520
  );
7517
7521
  const isControlled = values !== void 0;
7518
- const [internal, setInternal] = React8.useState(
7522
+ const [internal, setInternal] = React28.useState(
7519
7523
  () => initializeValues(
7520
7524
  sortedFields,
7521
7525
  defaultValues != null ? defaultValues : {},
@@ -7523,9 +7527,9 @@ function RegistrationForm({
7523
7527
  includeTerms
7524
7528
  )
7525
7529
  );
7526
- const [submitAttempted, setSubmitAttempted] = React8.useState(false);
7527
- const [validationErrors, setValidationErrors] = React8.useState({});
7528
- React8.useEffect(() => {
7530
+ const [submitAttempted, setSubmitAttempted] = React28.useState(false);
7531
+ const [validationErrors, setValidationErrors] = React28.useState({});
7532
+ React28.useEffect(() => {
7529
7533
  if (isControlled) return;
7530
7534
  setInternal((prev) => {
7531
7535
  const next = initializeValues(
@@ -7582,7 +7586,7 @@ function RegistrationForm({
7582
7586
  const termsError = submitAttempted && termsEnabled && !termsAccepted;
7583
7587
  const firstErrorFieldId = Object.keys(fieldErrors)[0];
7584
7588
  const scrollTargetId = firstErrorFieldId ? `rf-${firstErrorFieldId}` : termsError ? "rf-terms" : null;
7585
- React8.useEffect(() => {
7589
+ React28.useEffect(() => {
7586
7590
  if (!submitAttempted || !scrollTargetId) return;
7587
7591
  const timer = setTimeout(() => {
7588
7592
  const elem = document.getElementById(scrollTargetId);
@@ -8044,10 +8048,10 @@ var OTPCodeInput = ({
8044
8048
  id,
8045
8049
  required
8046
8050
  }) => {
8047
- const baseId = id != null ? id : React8.useId();
8048
- const inputRef = React8.useRef(null);
8049
- const [focused, setFocused] = React8.useState(false);
8050
- const digits = React8.useMemo(() => {
8051
+ const baseId = id != null ? id : React28.useId();
8052
+ const inputRef = React28.useRef(null);
8053
+ const [focused, setFocused] = React28.useState(false);
8054
+ const digits = React28.useMemo(() => {
8051
8055
  const arr = value.split("").slice(0, length);
8052
8056
  while (arr.length < length) arr.push("");
8053
8057
  return arr;
@@ -8145,7 +8149,7 @@ function Checkbox(_a) {
8145
8149
  __spreadProps(__spreadValues({
8146
8150
  "data-slot": "checkbox",
8147
8151
  className: cn(
8148
- "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
8152
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground data-indeterminate:border-primary data-indeterminate:bg-primary data-indeterminate:text-primary-foreground dark:data-checked:bg-primary",
8149
8153
  className
8150
8154
  )
8151
8155
  }, props), {
@@ -8154,16 +8158,13 @@ function Checkbox(_a) {
8154
8158
  {
8155
8159
  "data-slot": "checkbox-indicator",
8156
8160
  className: "grid place-content-center text-current transition-none [&>svg]:size-3.5",
8157
- children: /* @__PURE__ */ jsx(
8158
- CheckIcon,
8159
- {}
8160
- )
8161
+ children: props.indeterminate ? /* @__PURE__ */ jsx(MinusIcon, {}) : /* @__PURE__ */ jsx(CheckIcon, {})
8161
8162
  }
8162
8163
  )
8163
8164
  })
8164
8165
  );
8165
8166
  }
8166
- var AccordionVariantContext = React8.createContext("default");
8167
+ var AccordionVariantContext = React28.createContext("default");
8167
8168
  function Accordion(_a) {
8168
8169
  var _b = _a, { className, variant = "default" } = _b, props = __objRest(_b, ["className", "variant"]);
8169
8170
  return /* @__PURE__ */ jsx(AccordionVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx(
@@ -8181,7 +8182,7 @@ function Accordion(_a) {
8181
8182
  }
8182
8183
  function AccordionItem(_a) {
8183
8184
  var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
8184
- const variant = React8.useContext(AccordionVariantContext);
8185
+ const variant = React28.useContext(AccordionVariantContext);
8185
8186
  return /* @__PURE__ */ jsx(
8186
8187
  Accordion$1.Item,
8187
8188
  __spreadValues({
@@ -8202,7 +8203,7 @@ function AccordionTrigger(_a) {
8202
8203
  "className",
8203
8204
  "children"
8204
8205
  ]);
8205
- const variant = React8.useContext(AccordionVariantContext);
8206
+ const variant = React28.useContext(AccordionVariantContext);
8206
8207
  return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
8207
8208
  Accordion$1.Trigger,
8208
8209
  __spreadProps(__spreadValues({
@@ -8256,7 +8257,7 @@ function AccordionContent(_a) {
8256
8257
  "className",
8257
8258
  "children"
8258
8259
  ]);
8259
- const variant = React8.useContext(AccordionVariantContext);
8260
+ const variant = React28.useContext(AccordionVariantContext);
8260
8261
  return /* @__PURE__ */ jsx(
8261
8262
  Accordion$1.Panel,
8262
8263
  __spreadProps(__spreadValues({
@@ -8279,6 +8280,187 @@ function AccordionContent(_a) {
8279
8280
  })
8280
8281
  );
8281
8282
  }
8283
+ function getLeafIds(item) {
8284
+ var _a;
8285
+ if (!((_a = item.children) == null ? void 0 : _a.length)) return [item.id];
8286
+ return item.children.flatMap(getLeafIds);
8287
+ }
8288
+ function getDefaultExpandedIds(items) {
8289
+ const out = [];
8290
+ const walk = (list) => {
8291
+ var _a;
8292
+ for (const i of list) {
8293
+ if ((_a = i.children) == null ? void 0 : _a.length) {
8294
+ if (i.defaultExpanded) out.push(i.id);
8295
+ walk(i.children);
8296
+ }
8297
+ }
8298
+ };
8299
+ walk(items);
8300
+ return out;
8301
+ }
8302
+ function getAllItemIds(items) {
8303
+ return items.flatMap(
8304
+ (i) => {
8305
+ var _a;
8306
+ return ((_a = i.children) == null ? void 0 : _a.length) ? [i.id, ...getAllItemIds(i.children)] : [i.id];
8307
+ }
8308
+ );
8309
+ }
8310
+ function findItemById(items, id) {
8311
+ var _a;
8312
+ for (const item of items) {
8313
+ if (item.id === id) return item;
8314
+ if ((_a = item.children) == null ? void 0 : _a.length) {
8315
+ const found = findItemById(item.children, id);
8316
+ if (found) return found;
8317
+ }
8318
+ }
8319
+ return void 0;
8320
+ }
8321
+ function resolveGroups(groups) {
8322
+ return groups.map((g) => {
8323
+ var _a;
8324
+ if (!g.scopeItemId) return g;
8325
+ const node = findItemById(g.items, g.scopeItemId);
8326
+ return __spreadProps(__spreadValues({}, g), { items: (_a = node == null ? void 0 : node.children) != null ? _a : [] });
8327
+ }).filter((g) => g.items.length > 0);
8328
+ }
8329
+ function FilterItemsList({
8330
+ items,
8331
+ groupId,
8332
+ groupSelected,
8333
+ onToggle,
8334
+ onBulkToggle,
8335
+ idPrefix,
8336
+ depth = 0,
8337
+ parentAsHeader = false,
8338
+ expandedItems,
8339
+ onToggleExpanded
8340
+ }) {
8341
+ return /* @__PURE__ */ jsx(
8342
+ "ul",
8343
+ {
8344
+ className: cn(
8345
+ "flex flex-col gap-0.5",
8346
+ !parentAsHeader && depth > 0 && "mt-0.5 ml-6 border-l border-border pl-3"
8347
+ ),
8348
+ children: items.map((item) => {
8349
+ var _a, _b;
8350
+ const isParent = !!((_a = item.children) == null ? void 0 : _a.length);
8351
+ const checkboxId = `${idPrefix}-${groupId}-${item.id}`;
8352
+ if (!isParent) {
8353
+ const checked = groupSelected.includes(item.id);
8354
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
8355
+ "label",
8356
+ {
8357
+ htmlFor: checkboxId,
8358
+ className: "flex cursor-pointer items-center gap-3 rounded-md px-1 py-2 transition-colors hover:bg-muted/50",
8359
+ children: [
8360
+ /* @__PURE__ */ jsx(
8361
+ Checkbox,
8362
+ {
8363
+ id: checkboxId,
8364
+ checked,
8365
+ onCheckedChange: () => onToggle(item.id),
8366
+ className: "shrink-0"
8367
+ }
8368
+ ),
8369
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm text-foreground font-ui", children: item.label }),
8370
+ item.count !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-primary font-ui", children: [
8371
+ "(",
8372
+ item.count,
8373
+ ")"
8374
+ ] })
8375
+ ]
8376
+ }
8377
+ ) }, item.id);
8378
+ }
8379
+ if (parentAsHeader) {
8380
+ return /* @__PURE__ */ jsxs("li", { className: cn(depth > 0 && "mt-1"), children: [
8381
+ /* @__PURE__ */ jsx("p", { className: "px-1 pt-2 pb-1 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", children: item.label }),
8382
+ /* @__PURE__ */ jsx(
8383
+ FilterItemsList,
8384
+ {
8385
+ items: item.children,
8386
+ groupId,
8387
+ groupSelected,
8388
+ onToggle,
8389
+ onBulkToggle,
8390
+ idPrefix,
8391
+ depth: depth + 1,
8392
+ parentAsHeader: true,
8393
+ expandedItems,
8394
+ onToggleExpanded
8395
+ }
8396
+ )
8397
+ ] }, item.id);
8398
+ }
8399
+ const leafIds = item.children.flatMap(getLeafIds);
8400
+ const selectedLeaves = leafIds.filter((id) => groupSelected.includes(id));
8401
+ const allSelected = leafIds.length > 0 && selectedLeaves.length === leafIds.length;
8402
+ const someSelected = selectedLeaves.length > 0 && !allSelected;
8403
+ const isExpanded = (_b = expandedItems == null ? void 0 : expandedItems.has(item.id)) != null ? _b : false;
8404
+ const panelId = `${checkboxId}-children`;
8405
+ return /* @__PURE__ */ jsxs("li", { children: [
8406
+ /* @__PURE__ */ jsxs("div", { className: "group/parent flex items-center gap-3 rounded-md px-1 py-2 transition-colors hover:bg-muted/50", children: [
8407
+ /* @__PURE__ */ jsx(
8408
+ Checkbox,
8409
+ {
8410
+ id: checkboxId,
8411
+ checked: allSelected,
8412
+ indeterminate: someSelected,
8413
+ onCheckedChange: () => onBulkToggle(leafIds, !allSelected),
8414
+ className: "shrink-0"
8415
+ }
8416
+ ),
8417
+ /* @__PURE__ */ jsxs(
8418
+ "button",
8419
+ {
8420
+ type: "button",
8421
+ onClick: () => onToggleExpanded == null ? void 0 : onToggleExpanded(item.id),
8422
+ "aria-expanded": isExpanded,
8423
+ "aria-controls": panelId,
8424
+ className: "flex flex-1 items-center gap-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-sm cursor-pointer",
8425
+ children: [
8426
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm font-bold text-foreground font-ui", children: item.label }),
8427
+ item.count !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-primary font-ui", children: [
8428
+ "(",
8429
+ item.count,
8430
+ ")"
8431
+ ] }),
8432
+ /* @__PURE__ */ jsx(
8433
+ ChevronDownIcon,
8434
+ {
8435
+ className: cn(
8436
+ "h-4 w-4 text-muted-foreground transition-transform",
8437
+ isExpanded && "rotate-180"
8438
+ )
8439
+ }
8440
+ )
8441
+ ]
8442
+ }
8443
+ )
8444
+ ] }),
8445
+ isExpanded && /* @__PURE__ */ jsx("div", { id: panelId, children: /* @__PURE__ */ jsx(
8446
+ FilterItemsList,
8447
+ {
8448
+ items: item.children,
8449
+ groupId,
8450
+ groupSelected,
8451
+ onToggle,
8452
+ onBulkToggle,
8453
+ idPrefix,
8454
+ depth: depth + 1,
8455
+ expandedItems,
8456
+ onToggleExpanded
8457
+ }
8458
+ ) })
8459
+ ] }, item.id);
8460
+ })
8461
+ }
8462
+ );
8463
+ }
8282
8464
  function FilterPanel({
8283
8465
  groups,
8284
8466
  value,
@@ -8286,15 +8468,32 @@ function FilterPanel({
8286
8468
  onClearAll,
8287
8469
  alwaysShowClear = false,
8288
8470
  title = "Filters",
8289
- className
8471
+ className,
8472
+ variant = "sidebar",
8473
+ sortOptions,
8474
+ sort,
8475
+ onSortChange
8290
8476
  }) {
8291
- const [internalValue, setInternalValue] = React8.useState(
8477
+ var _a, _b;
8478
+ const resolvedGroups = React28.useMemo(() => resolveGroups(groups), [groups]);
8479
+ const [internalValue, setInternalValue] = React28.useState(
8292
8480
  () => Object.fromEntries(groups.map((g) => [g.id, []]))
8293
8481
  );
8294
8482
  const selected = value != null ? value : internalValue;
8483
+ const [expandedItems, setExpandedItems] = React28.useState(
8484
+ () => new Set(groups.flatMap((g) => getDefaultExpandedIds(g.items)))
8485
+ );
8486
+ const toggleExpanded = React28.useCallback((id) => {
8487
+ setExpandedItems((prev) => {
8488
+ const next = new Set(prev);
8489
+ if (next.has(id)) next.delete(id);
8490
+ else next.add(id);
8491
+ return next;
8492
+ });
8493
+ }, []);
8295
8494
  const handleToggle = (groupId, itemId) => {
8296
- var _a;
8297
- const current = (_a = selected[groupId]) != null ? _a : [];
8495
+ var _a2;
8496
+ const current = (_a2 = selected[groupId]) != null ? _a2 : [];
8298
8497
  const next = current.includes(itemId) ? current.filter((id) => id !== itemId) : [...current, itemId];
8299
8498
  const nextValue = __spreadProps(__spreadValues({}, selected), { [groupId]: next });
8300
8499
  if (onChange) {
@@ -8303,8 +8502,24 @@ function FilterPanel({
8303
8502
  setInternalValue(nextValue);
8304
8503
  }
8305
8504
  };
8505
+ const handleBulkToggle = (groupId, itemIds, select) => {
8506
+ var _a2;
8507
+ const current = (_a2 = selected[groupId]) != null ? _a2 : [];
8508
+ const next = select ? Array.from(/* @__PURE__ */ new Set([...current, ...itemIds])) : current.filter((id) => !itemIds.includes(id));
8509
+ const nextValue = __spreadProps(__spreadValues({}, selected), { [groupId]: next });
8510
+ if (onChange) {
8511
+ onChange(nextValue);
8512
+ } else {
8513
+ setInternalValue(nextValue);
8514
+ }
8515
+ };
8306
8516
  const handleClearAll = () => {
8307
- const cleared = Object.fromEntries(groups.map((g) => [g.id, []]));
8517
+ var _a2;
8518
+ const cleared = __spreadValues({}, selected);
8519
+ for (const g of resolvedGroups) {
8520
+ const visible = new Set(getAllItemIds(g.items));
8521
+ cleared[g.id] = ((_a2 = selected[g.id]) != null ? _a2 : []).filter((id) => !visible.has(id));
8522
+ }
8308
8523
  if (onChange) {
8309
8524
  onChange(cleared);
8310
8525
  } else {
@@ -8312,9 +8527,289 @@ function FilterPanel({
8312
8527
  }
8313
8528
  onClearAll == null ? void 0 : onClearAll();
8314
8529
  };
8315
- const totalSelected = Object.values(selected).flat().length;
8530
+ const totalSelected = resolvedGroups.reduce((sum, g) => {
8531
+ var _a2;
8532
+ const visible = new Set(getAllItemIds(g.items));
8533
+ return sum + ((_a2 = selected[g.id]) != null ? _a2 : []).filter((id) => visible.has(id)).length;
8534
+ }, 0);
8316
8535
  const showClear = alwaysShowClear || totalSelected > 0;
8317
- const defaultOpenValues = groups.filter((g) => g.defaultOpen).map((g) => g.id);
8536
+ const defaultOpenValues = resolvedGroups.filter((g) => g.defaultOpen).map((g) => g.id);
8537
+ if (resolvedGroups.length === 0) return null;
8538
+ if (variant === "horizontal") {
8539
+ const activeSort = (_a = sortOptions == null ? void 0 : sortOptions.find((o) => o.id === sort)) != null ? _a : sortOptions == null ? void 0 : sortOptions[0];
8540
+ const drawerGroups = /* @__PURE__ */ jsx(Accordion, { defaultValue: defaultOpenValues, className: "flex flex-col gap-2", children: resolvedGroups.map((group) => {
8541
+ var _a2;
8542
+ const groupSelected = (_a2 = selected[group.id]) != null ? _a2 : [];
8543
+ return /* @__PURE__ */ jsxs(
8544
+ AccordionItem,
8545
+ {
8546
+ value: group.id,
8547
+ className: "border-0 border-b border-border last:border-b-0",
8548
+ children: [
8549
+ /* @__PURE__ */ jsx(AccordionTrigger, { className: "px-0 py-3.5 hover:no-underline transition-colors", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2.5", children: [
8550
+ group.icon && /* @__PURE__ */ jsx("span", { className: "text-primary shrink-0", children: group.icon }),
8551
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-foreground font-ui", children: group.label }),
8552
+ groupSelected.length > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-primary text-[9px] font-bold text-primary-foreground", children: groupSelected.length })
8553
+ ] }) }),
8554
+ /* @__PURE__ */ jsx(AccordionContent, { className: "px-4 pb-3 pt-1", children: /* @__PURE__ */ jsx(
8555
+ FilterItemsList,
8556
+ {
8557
+ items: group.items,
8558
+ groupId: group.id,
8559
+ groupSelected,
8560
+ onToggle: (id) => handleToggle(group.id, id),
8561
+ onBulkToggle: (ids, select) => handleBulkToggle(group.id, ids, select),
8562
+ idPrefix: "mobile-filter",
8563
+ expandedItems,
8564
+ onToggleExpanded: toggleExpanded
8565
+ }
8566
+ ) })
8567
+ ]
8568
+ },
8569
+ group.id
8570
+ );
8571
+ }) });
8572
+ return /* @__PURE__ */ jsxs("div", { className: cn("contents", className), children: [
8573
+ /* @__PURE__ */ jsxs("div", { className: "flex sm:hidden items-center gap-2", children: [
8574
+ /* @__PURE__ */ jsxs(Dialog, { children: [
8575
+ /* @__PURE__ */ jsxs(
8576
+ DialogTrigger,
8577
+ {
8578
+ render: /* @__PURE__ */ jsx(
8579
+ "button",
8580
+ {
8581
+ type: "button",
8582
+ className: cn(
8583
+ "flex-1 inline-flex items-center justify-between gap-2 rounded-xl border-2 border-foreground bg-background px-4 py-3",
8584
+ "text-sm font-ui font-bold text-foreground transition-colors hover:bg-muted",
8585
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
8586
+ )
8587
+ }
8588
+ ),
8589
+ children: [
8590
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
8591
+ title,
8592
+ totalSelected > 0 && /* @__PURE__ */ jsx("span", { className: "inline-flex h-5 min-w-[20px] items-center justify-center rounded-full bg-primary px-1.5 text-[10px] font-bold text-primary-foreground", children: totalSelected })
8593
+ ] }),
8594
+ /* @__PURE__ */ jsx(SlidersHorizontalIcon, { className: "h-4 w-4 text-foreground" })
8595
+ ]
8596
+ }
8597
+ ),
8598
+ /* @__PURE__ */ jsx(
8599
+ DialogContent,
8600
+ {
8601
+ className: cn(
8602
+ "p-0 sm:max-w-md",
8603
+ "max-w-none w-screen h-screen sm:h-auto sm:max-h-[90vh] rounded-none sm:rounded-2xl"
8604
+ ),
8605
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full max-h-[90vh]", children: [
8606
+ /* @__PURE__ */ jsx(DialogTitle, { className: "px-5 py-4 text-lg font-bold font-heading border-b border-border", children: title }),
8607
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-5 py-3", children: drawerGroups }),
8608
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-5 py-4 border-t border-border", children: [
8609
+ /* @__PURE__ */ jsx(
8610
+ "button",
8611
+ {
8612
+ type: "button",
8613
+ onClick: handleClearAll,
8614
+ className: "text-sm font-ui font-semibold text-muted-foreground underline underline-offset-2 hover:text-foreground",
8615
+ children: "Clear all"
8616
+ }
8617
+ ),
8618
+ /* @__PURE__ */ jsxs(
8619
+ DialogClose,
8620
+ {
8621
+ render: /* @__PURE__ */ jsx(
8622
+ "button",
8623
+ {
8624
+ type: "button",
8625
+ className: "inline-flex items-center justify-center rounded-full bg-foreground text-background px-6 py-2.5 text-sm font-ui font-bold hover:bg-foreground/90 transition-colors"
8626
+ }
8627
+ ),
8628
+ children: [
8629
+ "Show ",
8630
+ totalSelected > 0 ? `(${totalSelected})` : "",
8631
+ " results"
8632
+ ]
8633
+ }
8634
+ )
8635
+ ] })
8636
+ ] })
8637
+ }
8638
+ )
8639
+ ] }),
8640
+ sortOptions && sortOptions.length > 0 && /* @__PURE__ */ jsxs(Popover, { children: [
8641
+ /* @__PURE__ */ jsxs(
8642
+ PopoverTrigger,
8643
+ {
8644
+ render: /* @__PURE__ */ jsx(
8645
+ "button",
8646
+ {
8647
+ type: "button",
8648
+ className: cn(
8649
+ "inline-flex items-center gap-1.5 rounded-xl border border-border bg-background px-4 py-3",
8650
+ "text-sm font-ui font-bold text-foreground transition-colors hover:bg-muted",
8651
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
8652
+ )
8653
+ }
8654
+ ),
8655
+ children: [
8656
+ "Sort",
8657
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4 text-muted-foreground" })
8658
+ ]
8659
+ }
8660
+ ),
8661
+ /* @__PURE__ */ jsx(PopoverContent, { align: "end", sideOffset: 6, className: "w-52", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5 p-0.5", children: sortOptions.map((opt) => /* @__PURE__ */ jsx(
8662
+ "button",
8663
+ {
8664
+ type: "button",
8665
+ onClick: () => onSortChange == null ? void 0 : onSortChange(opt.id),
8666
+ className: cn(
8667
+ "flex items-center px-2 py-1.5 rounded-md text-sm text-left",
8668
+ opt.id === (activeSort == null ? void 0 : activeSort.id) ? "bg-muted text-foreground font-semibold" : "text-foreground/80 hover:bg-muted"
8669
+ ),
8670
+ children: opt.label
8671
+ },
8672
+ opt.id
8673
+ )) }) })
8674
+ ] })
8675
+ ] }),
8676
+ /* @__PURE__ */ jsxs("div", { className: "hidden sm:flex items-center gap-2 flex-wrap", children: [
8677
+ resolvedGroups.map((group) => {
8678
+ var _a2, _b2;
8679
+ const selectedCount = ((_a2 = selected[group.id]) != null ? _a2 : []).length;
8680
+ const isActive = selectedCount > 0;
8681
+ return /* @__PURE__ */ jsxs(Popover, { children: [
8682
+ /* @__PURE__ */ jsxs(
8683
+ PopoverTrigger,
8684
+ {
8685
+ render: /* @__PURE__ */ jsx(
8686
+ "button",
8687
+ {
8688
+ type: "button",
8689
+ className: cn(
8690
+ "inline-flex items-center gap-1.5 rounded-full border px-3.5 py-1.5",
8691
+ "text-sm font-ui font-semibold transition-colors",
8692
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
8693
+ isActive ? "border-foreground bg-foreground text-background" : "border-border bg-background text-foreground hover:bg-muted"
8694
+ )
8695
+ }
8696
+ ),
8697
+ children: [
8698
+ group.icon && /* @__PURE__ */ jsx(
8699
+ "span",
8700
+ {
8701
+ className: cn(
8702
+ "[&>svg]:h-3.5 [&>svg]:w-3.5",
8703
+ isActive ? "" : "text-muted-foreground"
8704
+ ),
8705
+ children: group.icon
8706
+ }
8707
+ ),
8708
+ group.label,
8709
+ selectedCount > 0 && /* @__PURE__ */ jsx(
8710
+ "span",
8711
+ {
8712
+ className: cn(
8713
+ "inline-flex items-center justify-center rounded-full text-[10px] font-bold px-1.5 min-w-[18px] h-[18px]",
8714
+ isActive ? "bg-background text-foreground" : "bg-foreground text-background"
8715
+ ),
8716
+ children: selectedCount
8717
+ }
8718
+ ),
8719
+ /* @__PURE__ */ jsx(
8720
+ ChevronDownIcon,
8721
+ {
8722
+ className: cn(
8723
+ "h-3.5 w-3.5",
8724
+ isActive ? "text-background/70" : "text-muted-foreground"
8725
+ )
8726
+ }
8727
+ )
8728
+ ]
8729
+ }
8730
+ ),
8731
+ /* @__PURE__ */ jsx(
8732
+ PopoverContent,
8733
+ {
8734
+ align: "start",
8735
+ sideOffset: 6,
8736
+ className: "w-72 max-h-[60vh] overflow-y-auto",
8737
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 p-2", children: [
8738
+ /* @__PURE__ */ jsx("p", { className: "px-1 py-1 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", children: group.label }),
8739
+ /* @__PURE__ */ jsx(
8740
+ FilterItemsList,
8741
+ {
8742
+ items: group.items,
8743
+ groupId: group.id,
8744
+ groupSelected: (_b2 = selected[group.id]) != null ? _b2 : [],
8745
+ onToggle: (id) => handleToggle(group.id, id),
8746
+ onBulkToggle: (ids, select) => handleBulkToggle(group.id, ids, select),
8747
+ idPrefix: "popover-filter",
8748
+ parentAsHeader: true,
8749
+ expandedItems,
8750
+ onToggleExpanded: toggleExpanded
8751
+ }
8752
+ )
8753
+ ] })
8754
+ }
8755
+ )
8756
+ ] }, group.id);
8757
+ }),
8758
+ totalSelected > 0 && /* @__PURE__ */ jsxs(
8759
+ "button",
8760
+ {
8761
+ type: "button",
8762
+ onClick: handleClearAll,
8763
+ className: "inline-flex items-center gap-1 rounded-full px-3 py-1.5 text-xs font-ui font-semibold text-muted-foreground hover:text-foreground transition-colors",
8764
+ children: [
8765
+ /* @__PURE__ */ jsx(XIcon, { className: "h-3 w-3" }),
8766
+ "Clear all (",
8767
+ totalSelected,
8768
+ ")"
8769
+ ]
8770
+ }
8771
+ ),
8772
+ sortOptions && sortOptions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
8773
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground font-ui hidden sm:inline", children: "Sort by" }),
8774
+ /* @__PURE__ */ jsxs(Popover, { children: [
8775
+ /* @__PURE__ */ jsxs(
8776
+ PopoverTrigger,
8777
+ {
8778
+ render: /* @__PURE__ */ jsx(
8779
+ "button",
8780
+ {
8781
+ type: "button",
8782
+ className: cn(
8783
+ "inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-3.5 py-1.5",
8784
+ "text-sm font-ui font-semibold text-foreground hover:bg-muted transition-colors",
8785
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
8786
+ )
8787
+ }
8788
+ ),
8789
+ children: [
8790
+ (_b = activeSort == null ? void 0 : activeSort.label) != null ? _b : "Default",
8791
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3.5 w-3.5 text-muted-foreground" })
8792
+ ]
8793
+ }
8794
+ ),
8795
+ /* @__PURE__ */ jsx(PopoverContent, { align: "end", sideOffset: 6, className: "w-52", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5 p-0.5", children: sortOptions.map((opt) => /* @__PURE__ */ jsx(
8796
+ "button",
8797
+ {
8798
+ type: "button",
8799
+ onClick: () => onSortChange == null ? void 0 : onSortChange(opt.id),
8800
+ className: cn(
8801
+ "flex items-center px-2 py-1.5 rounded-md text-sm text-left",
8802
+ opt.id === (activeSort == null ? void 0 : activeSort.id) ? "bg-muted text-foreground font-semibold" : "text-foreground/80 hover:bg-muted"
8803
+ ),
8804
+ children: opt.label
8805
+ },
8806
+ opt.id
8807
+ )) }) })
8808
+ ] })
8809
+ ] })
8810
+ ] })
8811
+ ] });
8812
+ }
8318
8813
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", className), children: [
8319
8814
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
8320
8815
  /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-ui", children: title }),
@@ -8325,9 +8820,9 @@ function FilterPanel({
8325
8820
  {
8326
8821
  defaultValue: defaultOpenValues,
8327
8822
  className: "flex flex-col gap-2",
8328
- children: groups.map((group) => {
8329
- var _a;
8330
- const groupSelected = (_a = selected[group.id]) != null ? _a : [];
8823
+ children: resolvedGroups.map((group) => {
8824
+ var _a2;
8825
+ const groupSelected = (_a2 = selected[group.id]) != null ? _a2 : [];
8331
8826
  return /* @__PURE__ */ jsxs(
8332
8827
  AccordionItem,
8333
8828
  {
@@ -8339,34 +8834,19 @@ function FilterPanel({
8339
8834
  /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-foreground font-ui", children: group.label }),
8340
8835
  groupSelected.length > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-primary text-[9px] font-bold text-primary-foreground", children: groupSelected.length })
8341
8836
  ] }) }),
8342
- /* @__PURE__ */ jsx(AccordionContent, { className: "px-4 pb-3 pt-1", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5", children: group.items.map((item) => {
8343
- const checked = groupSelected.includes(item.id);
8344
- const checkboxId = `filter-${group.id}-${item.id}`;
8345
- return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
8346
- "label",
8347
- {
8348
- htmlFor: checkboxId,
8349
- className: "flex cursor-pointer items-center gap-3 rounded-md px-1 py-2 transition-colors hover:bg-muted/50",
8350
- children: [
8351
- /* @__PURE__ */ jsx(
8352
- Checkbox,
8353
- {
8354
- id: checkboxId,
8355
- checked,
8356
- onCheckedChange: () => handleToggle(group.id, item.id),
8357
- className: "shrink-0"
8358
- }
8359
- ),
8360
- /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm text-foreground font-ui", children: item.label }),
8361
- item.count !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-primary font-ui", children: [
8362
- "(",
8363
- item.count,
8364
- ")"
8365
- ] })
8366
- ]
8367
- }
8368
- ) }, item.id);
8369
- }) }) })
8837
+ /* @__PURE__ */ jsx(AccordionContent, { className: "px-4 pb-3 pt-1", children: /* @__PURE__ */ jsx(
8838
+ FilterItemsList,
8839
+ {
8840
+ items: group.items,
8841
+ groupId: group.id,
8842
+ groupSelected,
8843
+ onToggle: (id) => handleToggle(group.id, id),
8844
+ onBulkToggle: (ids, select) => handleBulkToggle(group.id, ids, select),
8845
+ idPrefix: "filter",
8846
+ expandedItems,
8847
+ onToggleExpanded: toggleExpanded
8848
+ }
8849
+ ) })
8370
8850
  ]
8371
8851
  },
8372
8852
  group.id
@@ -8387,70 +8867,182 @@ function FilterPanel({
8387
8867
  var TRUSTPILOT_SCRIPT_SRC = "https://widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js";
8388
8868
  function TrustpilotEmbed({ config }) {
8389
8869
  var _a, _b, _c, _d, _e, _f;
8390
- const ref = React8.useRef(null);
8391
- React8.useEffect(() => {
8870
+ const ref = React28.useRef(null);
8871
+ const [widgetReady, setWidgetReady] = React28.useState(false);
8872
+ const [delayPassed, setDelayPassed] = React28.useState(false);
8873
+ const showFallback = delayPassed && !widgetReady;
8874
+ React28.useEffect(() => {
8875
+ var _a2;
8392
8876
  if (typeof document === "undefined" || !ref.current) return;
8877
+ const node = ref.current;
8393
8878
  let cancelled = false;
8879
+ const checkRendered = () => {
8880
+ if (!node) return false;
8881
+ if (node.querySelector("iframe")) return true;
8882
+ if (node.innerHTML.length > 200) return true;
8883
+ return false;
8884
+ };
8885
+ const observer = new MutationObserver(() => {
8886
+ if (cancelled) return;
8887
+ if (checkRendered()) setWidgetReady(true);
8888
+ });
8889
+ observer.observe(node, { childList: true, subtree: true });
8890
+ if (checkRendered()) setWidgetReady(true);
8394
8891
  const initWidget = () => {
8395
- if (cancelled || !ref.current) return;
8892
+ if (cancelled || !node) return;
8396
8893
  const tp = window.Trustpilot;
8397
8894
  if (tp == null ? void 0 : tp.loadFromElement) {
8398
- tp.loadFromElement(ref.current, true);
8895
+ tp.loadFromElement(node, true);
8399
8896
  }
8400
8897
  };
8401
8898
  const existing = document.querySelector(
8402
8899
  `script[src="${TRUSTPILOT_SCRIPT_SRC}"]`
8403
8900
  );
8901
+ let cleanupScriptListener;
8404
8902
  if (existing) {
8405
8903
  const tp = window.Trustpilot;
8406
8904
  if (tp == null ? void 0 : tp.loadFromElement) {
8407
8905
  initWidget();
8408
8906
  } else {
8409
8907
  existing.addEventListener("load", initWidget, { once: true });
8908
+ cleanupScriptListener = () => existing.removeEventListener("load", initWidget);
8410
8909
  }
8411
- return () => {
8412
- cancelled = true;
8413
- existing.removeEventListener("load", initWidget);
8414
- };
8910
+ } else {
8911
+ const s = document.createElement("script");
8912
+ s.src = TRUSTPILOT_SCRIPT_SRC;
8913
+ s.async = true;
8914
+ s.addEventListener("load", initWidget, { once: true });
8915
+ document.body.appendChild(s);
8916
+ cleanupScriptListener = () => s.removeEventListener("load", initWidget);
8415
8917
  }
8416
- const s = document.createElement("script");
8417
- s.src = TRUSTPILOT_SCRIPT_SRC;
8418
- s.async = true;
8419
- s.addEventListener("load", initWidget, { once: true });
8420
- document.body.appendChild(s);
8918
+ const delay = (_a2 = config.fallbackDelayMs) != null ? _a2 : 3e3;
8919
+ const timeout = setTimeout(() => {
8920
+ if (!cancelled) setDelayPassed(true);
8921
+ }, delay);
8421
8922
  return () => {
8422
8923
  cancelled = true;
8423
- s.removeEventListener("load", initWidget);
8924
+ clearTimeout(timeout);
8925
+ observer.disconnect();
8926
+ cleanupScriptListener == null ? void 0 : cleanupScriptListener();
8424
8927
  };
8425
8928
  }, [config]);
8426
8929
  const sku = Array.isArray(config.sku) ? config.sku.join(",") : config.sku;
8427
- return /* @__PURE__ */ jsx(
8428
- "div",
8930
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
8931
+ /* @__PURE__ */ jsx(
8932
+ "div",
8933
+ {
8934
+ ref,
8935
+ className: "trustpilot-widget",
8936
+ "data-locale": (_a = config.locale) != null ? _a : "en-US",
8937
+ "data-template-id": (_b = config.templateId) != null ? _b : "5763bccae0a06d08e809ecbb",
8938
+ "data-businessunit-id": config.businessUnitId,
8939
+ "data-style-height": (_c = config.styleHeight) != null ? _c : "700px",
8940
+ "data-style-width": (_d = config.styleWidth) != null ? _d : "100%",
8941
+ "data-sku": sku,
8942
+ "data-no-reviews": (_e = config.noReviews) != null ? _e : "hide",
8943
+ "data-fullwidth": "true",
8944
+ "data-theme": config.theme,
8945
+ "data-token": config.token,
8946
+ "data-scroll-to-list": config.scrollToList ? "true" : void 0,
8947
+ "data-style-alignment": config.styleAlignment,
8948
+ "data-star-color": config.starColor,
8949
+ children: /* @__PURE__ */ jsx(
8950
+ "a",
8951
+ {
8952
+ href: (_f = config.fallbackHref) != null ? _f : "https://www.trustpilot.com/",
8953
+ target: "_blank",
8954
+ rel: "noopener noreferrer",
8955
+ children: "Trustpilot"
8956
+ }
8957
+ )
8958
+ }
8959
+ ),
8960
+ showFallback && /* @__PURE__ */ jsx(TrustpilotFallback, { config })
8961
+ ] });
8962
+ }
8963
+ function FallbackStar({ filled, className }) {
8964
+ return /* @__PURE__ */ jsx(
8965
+ "span",
8429
8966
  {
8430
- ref,
8431
- className: "trustpilot-widget",
8432
- "data-locale": (_a = config.locale) != null ? _a : "en-US",
8433
- "data-template-id": (_b = config.templateId) != null ? _b : "5763bccae0a06d08e809ecbb",
8434
- "data-businessunit-id": config.businessUnitId,
8435
- "data-style-height": (_c = config.styleHeight) != null ? _c : "700px",
8436
- "data-style-width": (_d = config.styleWidth) != null ? _d : "100%",
8437
- "data-sku": sku,
8438
- "data-no-reviews": (_e = config.noReviews) != null ? _e : "hide",
8439
- "data-fullwidth": "true",
8440
- "data-theme": config.theme,
8441
- "data-token": config.token,
8442
- "data-scroll-to-list": config.scrollToList ? "true" : void 0,
8443
- "data-style-alignment": config.styleAlignment,
8444
- "data-star-color": config.starColor,
8445
- children: /* @__PURE__ */ jsx(
8446
- "a",
8447
- {
8448
- href: (_f = config.fallbackHref) != null ? _f : "https://www.trustpilot.com/",
8449
- target: "_blank",
8450
- rel: "noopener noreferrer",
8451
- children: "Trustpilot"
8452
- }
8453
- )
8967
+ "aria-hidden": true,
8968
+ className: cn(
8969
+ "inline-flex items-center justify-center",
8970
+ filled ? "bg-[#00b67a] text-white" : "bg-muted text-muted-foreground",
8971
+ className
8972
+ ),
8973
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-[60%] w-[60%]", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) })
8974
+ }
8975
+ );
8976
+ }
8977
+ function TrustpilotFallback({ config }) {
8978
+ var _a, _b, _c, _d, _e, _f;
8979
+ const score = (_a = config.fallbackScore) != null ? _a : 4.8;
8980
+ const count = (_b = config.fallbackCount) != null ? _b : 0;
8981
+ const label = (_c = config.fallbackLabel) != null ? _c : "Excellent";
8982
+ const href = (_d = config.fallbackHref) != null ? _d : "https://www.trustpilot.com/";
8983
+ const isDark = config.theme === "dark";
8984
+ const styleHeightPx = parseInt((_e = config.styleHeight) != null ? _e : "", 10);
8985
+ const autoVariant = Number.isFinite(styleHeightPx) && styleHeightPx > 0 && styleHeightPx < 120 ? "mini" : "card";
8986
+ const variant = (_f = config.fallbackVariant) != null ? _f : autoVariant;
8987
+ const filledStars = Math.round(score);
8988
+ if (variant === "mini") {
8989
+ return /* @__PURE__ */ jsxs(
8990
+ "a",
8991
+ {
8992
+ href,
8993
+ target: "_blank",
8994
+ rel: "noopener noreferrer",
8995
+ className: cn(
8996
+ "inline-flex items-center gap-2 text-sm font-ui no-underline hover:opacity-80 transition-opacity",
8997
+ isDark ? "text-white" : "text-foreground"
8998
+ ),
8999
+ children: [
9000
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(FallbackStar, { filled: i < filledStars, className: "h-4 w-4 rounded-[2px]" }, i)) }),
9001
+ /* @__PURE__ */ jsx("span", { className: "font-bold", children: score.toFixed(1) }),
9002
+ count > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
9003
+ /* @__PURE__ */ jsx("span", { className: cn(isDark ? "text-white/60" : "text-muted-foreground"), children: "\xB7" }),
9004
+ /* @__PURE__ */ jsxs("span", { className: cn("text-xs", isDark ? "text-white/80" : "text-muted-foreground"), children: [
9005
+ count.toLocaleString(),
9006
+ " reviews"
9007
+ ] })
9008
+ ] }),
9009
+ /* @__PURE__ */ jsx("span", { className: cn("text-xs", isDark ? "text-white/60" : "text-muted-foreground"), children: "on Trustpilot" })
9010
+ ]
9011
+ }
9012
+ );
9013
+ }
9014
+ return /* @__PURE__ */ jsxs(
9015
+ "a",
9016
+ {
9017
+ href,
9018
+ target: "_blank",
9019
+ rel: "noopener noreferrer",
9020
+ className: "block max-w-md mx-auto rounded-2xl border border-border bg-card p-8 text-center no-underline shadow-sm hover:shadow-md transition-shadow",
9021
+ children: [
9022
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-1 mb-3", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(FallbackStar, { filled: i < filledStars, className: "h-7 w-7 rounded-[3px]" }, i)) }),
9023
+ /* @__PURE__ */ jsxs("p", { className: "text-2xl font-bold text-foreground font-heading", children: [
9024
+ label,
9025
+ " ",
9026
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground font-normal", children: [
9027
+ "\xB7 ",
9028
+ score.toFixed(1),
9029
+ " / 5"
9030
+ ] })
9031
+ ] }),
9032
+ count > 0 && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-2", children: [
9033
+ "Based on ",
9034
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: count.toLocaleString() }),
9035
+ " reviews"
9036
+ ] }),
9037
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-4", children: "Reviews powered by Trustpilot" }),
9038
+ /* @__PURE__ */ jsxs("span", { className: "mt-5 inline-flex items-center gap-1.5 text-sm font-semibold text-primary border-b border-primary/40 pb-0.5", children: [
9039
+ "Read all reviews on Trustpilot",
9040
+ /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
9041
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
9042
+ /* @__PURE__ */ jsx("polyline", { points: "12 5 19 12 12 19" })
9043
+ ] })
9044
+ ] })
9045
+ ]
8454
9046
  }
8455
9047
  );
8456
9048
  }
@@ -8520,11 +9112,11 @@ function ItineraryModal({
8520
9112
  onNext
8521
9113
  }) {
8522
9114
  var _a, _b, _c;
8523
- const [imgIndex, setImgIndex] = React8.useState(0);
9115
+ const [imgIndex, setImgIndex] = React28.useState(0);
8524
9116
  const images = stop ? [stop.coverImage, ...(_a = stop.images) != null ? _a : []] : [];
8525
9117
  const isFirst = (stop == null ? void 0 : stop.dayNumber) === ((_b = allStops[0]) == null ? void 0 : _b.dayNumber);
8526
9118
  const isLast = (stop == null ? void 0 : stop.dayNumber) === ((_c = allStops[allStops.length - 1]) == null ? void 0 : _c.dayNumber);
8527
- React8.useEffect(() => {
9119
+ React28.useEffect(() => {
8528
9120
  setImgIndex(0);
8529
9121
  }, [stop == null ? void 0 : stop.dayNumber]);
8530
9122
  if (!stop) return null;
@@ -8651,8 +9243,8 @@ function ItineraryModal({
8651
9243
  ) });
8652
9244
  }
8653
9245
  function Itinerary({ title, subtitle, stops, className }) {
8654
- const [activeIndex, setActiveIndex] = React8.useState(null);
8655
- const scrollRef = React8.useRef(null);
9246
+ const [activeIndex, setActiveIndex] = React28.useState(null);
9247
+ const scrollRef = React28.useRef(null);
8656
9248
  const activeStop = activeIndex !== null ? stops[activeIndex] : null;
8657
9249
  const scrollBy = (dir) => {
8658
9250
  if (!scrollRef.current) return;
@@ -8744,18 +9336,18 @@ function Lightbox({
8744
9336
  onClose
8745
9337
  }) {
8746
9338
  var _a;
8747
- const [index, setIndex] = React8.useState(initialIndex);
9339
+ const [index, setIndex] = React28.useState(initialIndex);
8748
9340
  const total = photos.length;
8749
9341
  const photo = photos[index];
8750
- const prev = React8.useCallback(
9342
+ const prev = React28.useCallback(
8751
9343
  () => setIndex((i) => (i - 1 + total) % total),
8752
9344
  [total]
8753
9345
  );
8754
- const next = React8.useCallback(
9346
+ const next = React28.useCallback(
8755
9347
  () => setIndex((i) => (i + 1) % total),
8756
9348
  [total]
8757
9349
  );
8758
- React8.useEffect(() => {
9350
+ React28.useEffect(() => {
8759
9351
  const onKey = (e) => {
8760
9352
  if (e.key === "Escape") onClose();
8761
9353
  if (e.key === "ArrowLeft") prev();
@@ -8921,7 +9513,7 @@ function GridGallery({
8921
9513
  initialVisible,
8922
9514
  onOpen
8923
9515
  }) {
8924
- const [expanded, setExpanded] = React8.useState(false);
9516
+ const [expanded, setExpanded] = React28.useState(false);
8925
9517
  const cols = gridCols(photos.length);
8926
9518
  const hasMore = photos.length > initialVisible;
8927
9519
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
@@ -8946,12 +9538,41 @@ function GridGallery({
8946
9538
  )
8947
9539
  ] });
8948
9540
  }
9541
+ function CompactGridGallery({
9542
+ photos,
9543
+ initialVisible,
9544
+ onOpen
9545
+ }) {
9546
+ const [expanded, setExpanded] = React28.useState(false);
9547
+ const hasMore = photos.length > initialVisible;
9548
+ const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
9549
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
9550
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4", children: visible.map((p, i) => /* @__PURE__ */ jsx(
9551
+ PhotoTile,
9552
+ {
9553
+ photo: p,
9554
+ index: i,
9555
+ className: "aspect-[4/3]",
9556
+ onClick: () => onOpen(i)
9557
+ },
9558
+ i
9559
+ )) }),
9560
+ hasMore && /* @__PURE__ */ jsx(
9561
+ ShowMoreButton,
9562
+ {
9563
+ count: photos.length - initialVisible,
9564
+ expanded,
9565
+ onClick: () => setExpanded((v) => !v)
9566
+ }
9567
+ )
9568
+ ] });
9569
+ }
8949
9570
  function MasonryGallery({
8950
9571
  photos,
8951
9572
  initialVisible,
8952
9573
  onOpen
8953
9574
  }) {
8954
- const [expanded, setExpanded] = React8.useState(false);
9575
+ const [expanded, setExpanded] = React28.useState(false);
8955
9576
  const hasMore = photos.length > initialVisible;
8956
9577
  const visible = expanded || !hasMore ? photos : photos.slice(0, initialVisible);
8957
9578
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -9024,7 +9645,7 @@ function FeaturedGallery({
9024
9645
  photos,
9025
9646
  onOpen
9026
9647
  }) {
9027
- const [expanded, setExpanded] = React8.useState(false);
9648
+ const [expanded, setExpanded] = React28.useState(false);
9028
9649
  const featured = photos.slice(0, 3);
9029
9650
  const extra = photos.slice(3);
9030
9651
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -9191,9 +9812,9 @@ function PhotoGallery({
9191
9812
  onPhotoClick,
9192
9813
  className
9193
9814
  }) {
9194
- const [lightboxIndex, setLightboxIndex] = React8.useState(null);
9195
- const [carouselIndex, setCarouselIndex] = React8.useState(0);
9196
- const normalised = React8.useMemo(() => photos.map(normalise), [photos]);
9815
+ const [lightboxIndex, setLightboxIndex] = React28.useState(null);
9816
+ const [carouselIndex, setCarouselIndex] = React28.useState(0);
9817
+ const normalised = React28.useMemo(() => photos.map(normalise), [photos]);
9197
9818
  const handleOpen = (index) => {
9198
9819
  setLightboxIndex(index);
9199
9820
  onPhotoClick == null ? void 0 : onPhotoClick(normalised[index].src, index);
@@ -9235,6 +9856,14 @@ function PhotoGallery({
9235
9856
  onOpen: handleOpen
9236
9857
  }
9237
9858
  ),
9859
+ variant === "gridCompact" && /* @__PURE__ */ jsx(
9860
+ CompactGridGallery,
9861
+ {
9862
+ photos: normalised,
9863
+ initialVisible,
9864
+ onOpen: handleOpen
9865
+ }
9866
+ ),
9238
9867
  variant === "masonry" && /* @__PURE__ */ jsx(
9239
9868
  MasonryGallery,
9240
9869
  {
@@ -9269,7 +9898,7 @@ function ItineraryDay({
9269
9898
  photoLayout = "rounded",
9270
9899
  className
9271
9900
  }) {
9272
- const photoList = React8.useMemo(() => normalisePhotos(photos), [photos]);
9901
+ const photoList = React28.useMemo(() => normalisePhotos(photos), [photos]);
9273
9902
  const isFullBleed = photoLayout === "fullBleed" || photoLayout === "fullBleedBottom";
9274
9903
  const photoPosition = photoLayout === "fullBleedBottom" ? "bottom" : "top";
9275
9904
  const gallery = photoList.length > 0 && /* @__PURE__ */ jsx(
@@ -9288,13 +9917,16 @@ function ItineraryDay({
9288
9917
  specs && specs.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-3 sm:gap-2.5", children: specs.map((spec, i) => /* @__PURE__ */ jsxs(
9289
9918
  "li",
9290
9919
  {
9291
- className: "flex flex-col text-base text-foreground font-ui",
9920
+ className: "flex items-start gap-3 text-base text-foreground font-ui",
9292
9921
  children: [
9293
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2", children: [
9294
- /* @__PURE__ */ jsx("span", { className: "font-semibold", children: spec.label }),
9295
- spec.detail && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: spec.detail })
9296
- ] }),
9297
- spec.subdetail && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: spec.subdetail })
9922
+ /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true, children: spec.icon }),
9923
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
9924
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2", children: [
9925
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: spec.label }),
9926
+ spec.detail && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: spec.detail })
9927
+ ] }),
9928
+ spec.subdetail && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: spec.subdetail })
9929
+ ] })
9298
9930
  ]
9299
9931
  },
9300
9932
  i
@@ -9321,8 +9953,8 @@ function MenuTrip({
9321
9953
  bold = true,
9322
9954
  className
9323
9955
  }) {
9324
- const scrollRef = React8.useRef(null);
9325
- React8.useEffect(() => {
9956
+ const scrollRef = React28.useRef(null);
9957
+ React28.useEffect(() => {
9326
9958
  if (!scrollRef.current || !activeSection) return;
9327
9959
  const container = scrollRef.current;
9328
9960
  const btn = container.querySelector(
@@ -9513,8 +10145,8 @@ function PricingTrip({
9513
10145
  className
9514
10146
  }) {
9515
10147
  const rOuter = sharp ? "rounded-none" : "rounded-2xl";
9516
- const [showEstimates, setShowEstimates] = React8.useState(false);
9517
- const [showPriceInfo, setShowPriceInfo] = React8.useState(false);
10148
+ const [showEstimates, setShowEstimates] = React28.useState(false);
10149
+ const [showPriceInfo, setShowPriceInfo] = React28.useState(false);
9518
10150
  if (variant === "compact") {
9519
10151
  const showOverlay = showPriceInfo && (!!priceInfo || !!currencyEstimates && currencyEstimates.length > 0);
9520
10152
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
@@ -9798,8 +10430,7 @@ var VARIANT = {
9798
10430
  mobileLink: "text-white hover:text-primary-400 border-b border-white/10",
9799
10431
  mobileSub: "text-white/70 font-bold hover:text-primary-400 border-b border-white/8",
9800
10432
  mobileLangActive: "text-primary-400 font-semibold",
9801
- mobileLangIdle: "text-white/40 hover:text-primary-400",
9802
- logoBlend: "mix-blend-screen"
10433
+ mobileLangIdle: "text-white/40 hover:text-primary-400"
9803
10434
  },
9804
10435
  white: {
9805
10436
  header: "bg-white border-b border-border shadow-sm",
@@ -9815,8 +10446,7 @@ var VARIANT = {
9815
10446
  mobileLink: "text-foreground/80 hover:text-foreground border-b border-border",
9816
10447
  mobileSub: "text-foreground/50 font-bold hover:text-foreground border-b border-border/40",
9817
10448
  mobileLangActive: "text-primary font-semibold",
9818
- mobileLangIdle: "text-muted-foreground hover:text-foreground",
9819
- logoBlend: "invert mix-blend-multiply"
10449
+ mobileLangIdle: "text-muted-foreground hover:text-foreground"
9820
10450
  },
9821
10451
  dark: {
9822
10452
  header: "bg-neutral-950 border-b border-white/10",
@@ -9832,8 +10462,7 @@ var VARIANT = {
9832
10462
  mobileLink: "text-white/80 hover:text-white border-b border-white/8",
9833
10463
  mobileSub: "text-white/45 font-bold hover:text-white border-b border-white/5",
9834
10464
  mobileLangActive: "text-white font-semibold",
9835
- mobileLangIdle: "text-white/35 hover:text-white/60",
9836
- logoBlend: "mix-blend-screen"
10465
+ mobileLangIdle: "text-white/35 hover:text-white/60"
9837
10466
  }
9838
10467
  };
9839
10468
  var DEFAULT_HEADER_LINKS = [
@@ -9943,7 +10572,9 @@ function LangDropdown({
9943
10572
  function SiteHeader({
9944
10573
  variant = "transparent",
9945
10574
  links = DEFAULT_HEADER_LINKS,
9946
- logoSrc = "/logo-planetaexo.png",
10575
+ logoSrcLight = "/logo-planetaexo-white.png",
10576
+ logoSrcDark = "/logo-planetaexo-green.png",
10577
+ logoSrc,
9947
10578
  logoAlt = "Planeta Exo",
9948
10579
  languages = DEFAULT_LANGUAGES,
9949
10580
  currentLanguage = "EN",
@@ -9954,14 +10585,15 @@ function SiteHeader({
9954
10585
  className
9955
10586
  }) {
9956
10587
  const t = VARIANT[variant];
9957
- const [openMenu, setOpenMenu] = React8.useState(null);
9958
- const [langOpen, setLangOpen] = React8.useState(false);
9959
- const [mobileOpen, setMobileOpen] = React8.useState(false);
9960
- const [openMobileSection, setOpenMobileSection] = React8.useState(null);
9961
- const [activeLang, setActiveLang] = React8.useState(currentLanguage);
10588
+ const resolvedLogo = logoSrc != null ? logoSrc : variant === "white" ? logoSrcDark : logoSrcLight;
10589
+ const [openMenu, setOpenMenu] = React28.useState(null);
10590
+ const [langOpen, setLangOpen] = React28.useState(false);
10591
+ const [mobileOpen, setMobileOpen] = React28.useState(false);
10592
+ const [openMobileSection, setOpenMobileSection] = React28.useState(null);
10593
+ const [activeLang, setActiveLang] = React28.useState(currentLanguage);
9962
10594
  const toggleMobileSection = (label) => setOpenMobileSection((prev) => prev === label ? null : label);
9963
- const menuCloseTimer = React8.useRef(void 0);
9964
- const langCloseTimer = React8.useRef(void 0);
10595
+ const menuCloseTimer = React28.useRef(void 0);
10596
+ const langCloseTimer = React28.useRef(void 0);
9965
10597
  const handleMenuEnter = (label) => {
9966
10598
  clearTimeout(menuCloseTimer.current);
9967
10599
  setOpenMenu(label);
@@ -9982,7 +10614,7 @@ function SiteHeader({
9982
10614
  setOpenMenu(null);
9983
10615
  setLangOpen(false);
9984
10616
  };
9985
- React8.useEffect(() => () => {
10617
+ React28.useEffect(() => () => {
9986
10618
  clearTimeout(menuCloseTimer.current);
9987
10619
  clearTimeout(langCloseTimer.current);
9988
10620
  }, []);
@@ -10002,17 +10634,41 @@ function SiteHeader({
10002
10634
  className
10003
10635
  ),
10004
10636
  children: [
10005
- variant === "transparent" && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-0 h-52 bg-gradient-to-b from-black/55 via-black/20 to-transparent pointer-events-none" }),
10637
+ variant === "transparent" && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-0 h-52 bg-gradient-to-b from-black/70 via-black/30 to-transparent pointer-events-none" }),
10006
10638
  /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-2 px-6 sm:px-10 h-[72px]", children: [
10007
- /* @__PURE__ */ jsx("a", { href: "#", className: "shrink-0 flex items-center mr-4", children: /* @__PURE__ */ jsx(
10008
- "img",
10639
+ /* @__PURE__ */ jsx(
10640
+ "button",
10009
10641
  {
10010
- src: logoSrc,
10011
- alt: logoAlt,
10012
- className: cn("h-11 w-auto select-none", t.logoBlend),
10013
- draggable: false
10642
+ type: "button",
10643
+ onClick: () => setMobileOpen(true),
10644
+ "aria-label": "Open menu",
10645
+ className: cn(
10646
+ "flex lg:hidden h-9 w-9 items-center justify-center rounded-full transition-colors -ml-1.5",
10647
+ t.mobileTrigger
10648
+ ),
10649
+ children: /* @__PURE__ */ jsx(MenuIcon, { className: "h-[18px] w-[18px]" })
10014
10650
  }
10015
- ) }),
10651
+ ),
10652
+ /* @__PURE__ */ jsx(
10653
+ "a",
10654
+ {
10655
+ href: "#",
10656
+ className: cn(
10657
+ "shrink-0 flex items-center",
10658
+ "absolute left-1/2 -translate-x-1/2",
10659
+ "lg:static lg:translate-x-0 lg:mr-4"
10660
+ ),
10661
+ children: /* @__PURE__ */ jsx(
10662
+ "img",
10663
+ {
10664
+ src: resolvedLogo,
10665
+ alt: logoAlt,
10666
+ className: "h-14 w-auto select-none",
10667
+ draggable: false
10668
+ }
10669
+ )
10670
+ }
10671
+ ),
10016
10672
  /* @__PURE__ */ jsx("nav", { className: "hidden lg:flex items-center gap-0.5 mx-auto", children: links.map((link) => {
10017
10673
  var _a, _b;
10018
10674
  const hasDropdown = !!((_a = link.items) == null ? void 0 : _a.length);
@@ -10136,19 +10792,6 @@ function SiteHeader({
10136
10792
  ),
10137
10793
  children: /* @__PURE__ */ jsx(UserIcon, { className: "h-[18px] w-[18px]" })
10138
10794
  }
10139
- ),
10140
- /* @__PURE__ */ jsx(
10141
- "button",
10142
- {
10143
- type: "button",
10144
- onClick: () => setMobileOpen(true),
10145
- "aria-label": "Open menu",
10146
- className: cn(
10147
- "flex lg:hidden h-9 w-9 items-center justify-center rounded-full transition-colors ml-0.5",
10148
- t.mobileTrigger
10149
- ),
10150
- children: /* @__PURE__ */ jsx(MenuIcon, { className: "h-[18px] w-[18px]" })
10151
- }
10152
10795
  )
10153
10796
  ] })
10154
10797
  ] }),
@@ -10164,9 +10807,9 @@ function SiteHeader({
10164
10807
  /* @__PURE__ */ jsx("a", { href: "#", className: "shrink-0 flex items-center", onClick: () => setMobileOpen(false), children: /* @__PURE__ */ jsx(
10165
10808
  "img",
10166
10809
  {
10167
- src: logoSrc,
10810
+ src: resolvedLogo,
10168
10811
  alt: logoAlt,
10169
- className: cn("h-11 w-auto select-none", t.logoBlend),
10812
+ className: "h-14 w-auto select-none",
10170
10813
  draggable: false
10171
10814
  }
10172
10815
  ) }),
@@ -10247,7 +10890,7 @@ function SiteHeader({
10247
10890
  ), children: [
10248
10891
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 flex-wrap", children: languages.map((lang, i) => {
10249
10892
  const isActive = lang.code === activeLang;
10250
- return /* @__PURE__ */ jsxs(React8.Fragment, { children: [
10893
+ return /* @__PURE__ */ jsxs(React28.Fragment, { children: [
10251
10894
  i > 0 && /* @__PURE__ */ jsx("span", { className: cn(
10252
10895
  "text-xs select-none",
10253
10896
  variant === "white" ? "text-border" : "text-white/15"
@@ -10309,8 +10952,8 @@ function SiteHeader({
10309
10952
  );
10310
10953
  }
10311
10954
  function ThemeToggle({ className }) {
10312
- const [dark, setDark] = React8.useState(false);
10313
- React8.useEffect(() => {
10955
+ const [dark, setDark] = React28.useState(false);
10956
+ React28.useEffect(() => {
10314
10957
  const saved = localStorage.getItem("theme");
10315
10958
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
10316
10959
  const isDark = saved === "dark" || !saved && prefersDark;
@@ -10339,6 +10982,44 @@ function ThemeToggle({ className }) {
10339
10982
  }
10340
10983
  );
10341
10984
  }
10985
+ var chipVariants = cva(
10986
+ "inline-flex items-center rounded-full font-ui font-medium transition-colors whitespace-nowrap",
10987
+ {
10988
+ variants: {
10989
+ variant: {
10990
+ glass: "border border-white/15 bg-black/30 text-white/85 backdrop-blur-sm hover:bg-white/10 hover:border-white/50 hover:text-white",
10991
+ solid: "bg-muted text-foreground/80 hover:bg-primary hover:text-primary-foreground",
10992
+ outline: "border border-border text-foreground/80 hover:bg-primary hover:border-primary hover:text-primary-foreground"
10993
+ },
10994
+ size: {
10995
+ sm: "px-2.5 py-0.5 text-[11px] leading-5",
10996
+ md: "px-3 py-1 text-xs leading-5",
10997
+ lg: "px-4 py-1.5 text-sm leading-5"
10998
+ }
10999
+ },
11000
+ defaultVariants: {
11001
+ variant: "glass",
11002
+ size: "sm"
11003
+ }
11004
+ }
11005
+ );
11006
+ var Chip = React28.forwardRef(function Chip2(_a, ref) {
11007
+ var _b = _a, { className, variant, size, href, children } = _b, props = __objRest(_b, ["className", "variant", "size", "href", "children"]);
11008
+ const classes = cn(chipVariants({ variant, size }), className);
11009
+ if (href) {
11010
+ return /* @__PURE__ */ jsx(
11011
+ "a",
11012
+ __spreadProps(__spreadValues({
11013
+ ref,
11014
+ href,
11015
+ className: classes
11016
+ }, props), {
11017
+ children
11018
+ })
11019
+ );
11020
+ }
11021
+ return /* @__PURE__ */ jsx("span", __spreadProps(__spreadValues({ ref, className: classes }, props), { children }));
11022
+ });
10342
11023
  function CalendarIcon6() {
10343
11024
  return /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
10344
11025
  /* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
@@ -10389,19 +11070,125 @@ var statusConfig = {
10389
11070
  icon: /* @__PURE__ */ jsx(TrendingIcon, {})
10390
11071
  }
10391
11072
  };
10392
- function TripCard({
10393
- image,
10394
- imageAlt = "",
10395
- status,
10396
- nights,
10397
- period,
10398
- title,
10399
- description,
10400
- cta,
10401
- price,
10402
- size = "md",
10403
- className
10404
- }) {
11073
+ function HeartIcon({ filled = false }) {
11074
+ return /* @__PURE__ */ jsx(
11075
+ "svg",
11076
+ {
11077
+ width: "16",
11078
+ height: "16",
11079
+ viewBox: "0 0 24 24",
11080
+ fill: filled ? "currentColor" : "none",
11081
+ stroke: "currentColor",
11082
+ strokeWidth: "2",
11083
+ strokeLinecap: "round",
11084
+ strokeLinejoin: "round",
11085
+ children: /* @__PURE__ */ jsx("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" })
11086
+ }
11087
+ );
11088
+ }
11089
+ function TripCardEditorial(props) {
11090
+ const {
11091
+ image,
11092
+ imageAlt = "",
11093
+ title,
11094
+ description,
11095
+ nights,
11096
+ price,
11097
+ href,
11098
+ className,
11099
+ favoritable,
11100
+ favorited: favoritedProp,
11101
+ onFavoriteToggle,
11102
+ location,
11103
+ difficulty,
11104
+ tag
11105
+ } = props;
11106
+ const [internalFav, setInternalFav] = React28.useState(false);
11107
+ const favorited = favoritedProp != null ? favoritedProp : internalFav;
11108
+ const handleFav = (e) => {
11109
+ e.preventDefault();
11110
+ e.stopPropagation();
11111
+ const next = !favorited;
11112
+ if (favoritedProp === void 0) setInternalFav(next);
11113
+ onFavoriteToggle == null ? void 0 : onFavoriteToggle(next);
11114
+ };
11115
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
11116
+ /* @__PURE__ */ jsxs("div", { className: "relative aspect-[4/3] overflow-hidden bg-muted", children: [
11117
+ /* @__PURE__ */ jsx(
11118
+ "img",
11119
+ {
11120
+ src: image,
11121
+ alt: imageAlt,
11122
+ loading: "lazy",
11123
+ className: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
11124
+ }
11125
+ ),
11126
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/85 via-black/20 to-transparent" }),
11127
+ tag && /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 max-w-[calc(100%-4.5rem)]", children: /* @__PURE__ */ jsx(Chip, { variant: "glass", size: "sm", children: tag }) }),
11128
+ favoritable && /* @__PURE__ */ jsx(
11129
+ "button",
11130
+ {
11131
+ type: "button",
11132
+ "aria-label": favorited ? "Remove from favorites" : "Add to favorites",
11133
+ "aria-pressed": favorited,
11134
+ onClick: handleFav,
11135
+ className: cn(
11136
+ "absolute top-3 right-3 flex h-9 w-9 items-center justify-center rounded-full",
11137
+ "border border-white/15 bg-black/30 backdrop-blur-sm",
11138
+ "transition-colors hover:bg-white/10 hover:border-white/50",
11139
+ favorited ? "text-white" : "text-white/85 hover:text-white"
11140
+ ),
11141
+ children: /* @__PURE__ */ jsx(HeartIcon, { filled: favorited })
11142
+ }
11143
+ ),
11144
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 bottom-0 p-5 text-white", children: /* @__PURE__ */ jsx("h3", { className: "text-lg sm:text-xl font-bold font-heading leading-tight", children: title }) })
11145
+ ] }),
11146
+ (description || price || nights || location || difficulty) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 bg-card p-6", children: [
11147
+ (location || difficulty) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
11148
+ location ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-foreground/85", children: [
11149
+ /* @__PURE__ */ jsx(MapPinIcon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
11150
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-ui font-semibold", children: location })
11151
+ ] }) : /* @__PURE__ */ jsx("span", {}),
11152
+ difficulty && /* @__PURE__ */ jsx(Chip, { variant: "outline", size: "sm", className: "capitalize text-muted-foreground", children: difficulty })
11153
+ ] }),
11154
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed line-clamp-3", children: description }),
11155
+ (nights || price) && /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between gap-3", children: [
11156
+ nights ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-foreground/80", children: [
11157
+ /* @__PURE__ */ jsx(MoonIcon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
11158
+ /* @__PURE__ */ jsxs("span", { className: "text-sm font-ui font-semibold", children: [
11159
+ nights,
11160
+ " ",
11161
+ nights === 1 ? "night" : "nights"
11162
+ ] })
11163
+ ] }) : /* @__PURE__ */ jsx("span", {}),
11164
+ price && /* @__PURE__ */ jsx("p", { className: "text-base font-bold text-foreground font-ui", children: price })
11165
+ ] })
11166
+ ] })
11167
+ ] });
11168
+ const baseClasses = cn(
11169
+ "group relative flex flex-col overflow-hidden rounded-2xl bg-card border border-border/50",
11170
+ "shadow-md transition-shadow duration-300 hover:shadow-xl",
11171
+ className
11172
+ );
11173
+ return href ? /* @__PURE__ */ jsx("a", { href, className: baseClasses, "aria-label": title, children: body }) : /* @__PURE__ */ jsx("div", { className: baseClasses, children: body });
11174
+ }
11175
+ function TripCard(props) {
11176
+ if (props.variant === "editorial") {
11177
+ return /* @__PURE__ */ jsx(TripCardEditorial, __spreadValues({}, props));
11178
+ }
11179
+ const {
11180
+ image,
11181
+ imageAlt = "",
11182
+ status,
11183
+ nights,
11184
+ period,
11185
+ title,
11186
+ description,
11187
+ cta,
11188
+ price,
11189
+ size = "md",
11190
+ className
11191
+ } = props;
10405
11192
  const s = sizeConfig[size];
10406
11193
  const statusInfo = status ? statusConfig[status] : null;
10407
11194
  const meta = [
@@ -10461,7 +11248,7 @@ function TripCard({
10461
11248
  );
10462
11249
  }
10463
11250
  function useHlsVideo(videoRef, src) {
10464
- React8.useEffect(() => {
11251
+ React28.useEffect(() => {
10465
11252
  if (!src || !videoRef.current) return;
10466
11253
  const video = videoRef.current;
10467
11254
  if (!src.includes(".m3u8")) return;
@@ -10498,17 +11285,18 @@ function TripHeader({
10498
11285
  destination,
10499
11286
  duration,
10500
11287
  tagline,
11288
+ chips,
10501
11289
  belowMeta,
10502
11290
  siteHeader,
10503
11291
  uiVariant = "v1",
10504
11292
  className
10505
11293
  }) {
10506
11294
  var _a;
10507
- const [heroIndex, setHeroIndex] = React8.useState(0);
10508
- const [videoReady, setVideoReady] = React8.useState(false);
10509
- const videoRef = React8.useRef(null);
11295
+ const [heroIndex, setHeroIndex] = React28.useState(0);
11296
+ const [videoReady, setVideoReady] = React28.useState(false);
11297
+ const videoRef = React28.useRef(null);
10510
11298
  const isHls = !!(videoUrl == null ? void 0 : videoUrl.includes(".m3u8"));
10511
- const validImages = React8.useMemo(
11299
+ const validImages = React28.useMemo(
10512
11300
  () => images.map((u) => u == null ? void 0 : u.trim()).filter(Boolean),
10513
11301
  [images]
10514
11302
  );
@@ -10523,7 +11311,7 @@ function TripHeader({
10523
11311
  const nights = duration ? (_a = duration.nights) != null ? _a : Math.max(duration.days - 1, 1) : null;
10524
11312
  const hasMeta = !!(destination || duration);
10525
11313
  useHlsVideo(videoRef, isHls ? videoUrl : void 0);
10526
- React8.useEffect(() => {
11314
+ React28.useEffect(() => {
10527
11315
  if (!videoUrl) return;
10528
11316
  const el = videoRef.current;
10529
11317
  if (!el) return;
@@ -10657,15 +11445,15 @@ function TripHeader({
10657
11445
  ]
10658
11446
  }
10659
11447
  ),
10660
- /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-5xl px-4 sm:px-6", children: /* @__PURE__ */ jsxs(
11448
+ /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-6xl px-6 sm:px-8", children: /* @__PURE__ */ jsxs(
10661
11449
  "div",
10662
11450
  {
10663
11451
  className: cn(
10664
11452
  "relative z-10 pb-10",
10665
- siteHeader ? "-mt-44" : "-mt-36"
11453
+ chips && chips.length > 0 ? siteHeader ? "-mt-[200px] sm:-mt-[214px]" : "-mt-[168px] sm:-mt-[182px]" : siteHeader ? "-mt-44" : "-mt-36"
10666
11454
  ),
10667
11455
  children: [
10668
- 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(React8.Fragment, { children: [
11456
+ 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: [
10669
11457
  i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 text-white/50 shrink-0" }),
10670
11458
  /* @__PURE__ */ jsx("span", { className: "text-xs text-white/70 font-ui hover:text-white/90 cursor-default", children: crumb.label })
10671
11459
  ] }, i)) }),
@@ -10691,6 +11479,7 @@ function TripHeader({
10691
11479
  ] })
10692
11480
  ] })
10693
11481
  ] }) : tagline ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm sm:text-base text-white/80 font-ui", children: tagline }) : null,
11482
+ chips && chips.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap items-center gap-1.5", children: chips.map((chip, i) => /* @__PURE__ */ jsx(Chip, { href: chip.href, children: chip.label }, i)) }),
10694
11483
  belowMeta && /* @__PURE__ */ jsx("div", { className: "mt-3", children: belowMeta })
10695
11484
  ]
10696
11485
  }
@@ -10699,6 +11488,427 @@ function TripHeader({
10699
11488
  }
10700
11489
  );
10701
11490
  }
11491
+ var VARIANT2 = {
11492
+ light: {
11493
+ footer: "bg-primary-50 text-foreground",
11494
+ heading: "text-foreground",
11495
+ body: "text-foreground/75",
11496
+ muted: "text-foreground/60",
11497
+ link: "text-foreground/85 hover:text-primary-800 underline decoration-foreground/25 underline-offset-4 hover:decoration-primary-800",
11498
+ badgeStroke: "text-foreground/80",
11499
+ /** Inverts white logos so they read on the light background. */
11500
+ badgeFilter: "[filter:invert(1)_brightness(0.2)]",
11501
+ socialBtn: "bg-foreground text-white hover:bg-primary-800",
11502
+ langTrigger: "text-foreground hover:bg-white",
11503
+ langOpen: "text-foreground bg-white",
11504
+ langChevron: "text-foreground/40",
11505
+ bottomBar: "border-t border-foreground/10",
11506
+ bottomText: "text-foreground/60",
11507
+ bottomLink: "text-foreground/80 hover:text-foreground underline decoration-foreground/20 underline-offset-4 hover:decoration-foreground"
11508
+ },
11509
+ dark: {
11510
+ footer: "bg-brand-charcoal text-white",
11511
+ heading: "text-white",
11512
+ body: "text-white/75",
11513
+ muted: "text-white/55",
11514
+ link: "text-white/85 hover:text-primary-400 underline decoration-white/20 underline-offset-4 hover:decoration-primary-400",
11515
+ badgeStroke: "text-white",
11516
+ badgeFilter: "",
11517
+ socialBtn: "bg-white/10 text-white hover:bg-primary-400 hover:text-primary-900",
11518
+ langTrigger: "text-white/85 hover:bg-white/10",
11519
+ langOpen: "text-white bg-white/10",
11520
+ langChevron: "text-white/40",
11521
+ bottomBar: "border-t border-white/10",
11522
+ bottomText: "text-white/55",
11523
+ bottomLink: "text-white/80 hover:text-white underline decoration-white/20 underline-offset-4 hover:decoration-white"
11524
+ }
11525
+ };
11526
+ var DEFAULT_FOOTER_THEMES = [
11527
+ { label: "Roadtrips", href: "#" },
11528
+ { label: "Saf\xE1ri", href: "#" },
11529
+ { label: "Trilhas", href: "#" },
11530
+ { label: "Caiaque & Canoa", href: "#" },
11531
+ { label: "Aurora boreal", href: "#" },
11532
+ { label: "Micro-aventuras", href: "#" },
11533
+ { label: "Packrafting", href: "#" },
11534
+ { label: "Glamping", href: "#" },
11535
+ { label: "Surf", href: "#" },
11536
+ { label: "Viagens em fam\xEDlia", href: "#" }
11537
+ ];
11538
+ var DEFAULT_FOOTER_DESTINATIONS = [
11539
+ { label: "Brasil", href: "#" },
11540
+ { label: "Patag\xF4nia", href: "#" },
11541
+ { label: "Argentina", href: "#" },
11542
+ { label: "Chile", href: "#" },
11543
+ { label: "Bol\xEDvia", href: "#" },
11544
+ { label: "Peru", href: "#" },
11545
+ { label: "Equador", href: "#" },
11546
+ { label: "Col\xF4mbia", href: "#" },
11547
+ { label: "Costa Rica", href: "#" },
11548
+ { label: "Filipinas", href: "#" }
11549
+ ];
11550
+ var DEFAULT_FOOTER_PAGES = [
11551
+ { label: "Contato", href: "#" },
11552
+ { label: "Pol\xEDtica de cookies", href: "#" },
11553
+ { label: "FAQ", href: "#" },
11554
+ { label: "Sobre n\xF3s", href: "#" }
11555
+ ];
11556
+ var DEFAULT_FOOTER_LEGAL = [
11557
+ { label: "Termos e condi\xE7\xF5es", href: "#" },
11558
+ { label: "Mapa do site", href: "#" }
11559
+ ];
11560
+ var DEFAULT_FOOTER_LANGUAGES = [
11561
+ { code: "PT", label: "Portugu\xEAs" },
11562
+ { code: "EN", label: "English" },
11563
+ { code: "NL", label: "Nederlands" },
11564
+ { code: "DE", label: "Deutsch" },
11565
+ { code: "FR", label: "Fran\xE7ais" },
11566
+ { code: "ES", label: "Espa\xF1ol" }
11567
+ ];
11568
+ var DEFAULT_FOOTER_SOCIALS = [
11569
+ { network: "facebook", href: "#" },
11570
+ { network: "instagram", href: "#" },
11571
+ { network: "linkedin", href: "#" }
11572
+ ];
11573
+ var DEFAULT_FOOTER_BADGES = [
11574
+ {
11575
+ src: "https://static.planetaexo.com/trips/wp-content/uploads/2025/04/member_of_TLR-white-1.png",
11576
+ alt: "Member of The Long Run",
11577
+ height: 80
11578
+ },
11579
+ {
11580
+ src: "https://static.planetaexo.com/trips/wp-content/uploads/2025/04/atta-member_white.png",
11581
+ alt: "Member \xB7 Adventure Travel Trade Association",
11582
+ height: 56
11583
+ }
11584
+ ];
11585
+ var SOCIAL_ICON = {
11586
+ facebook: FacebookIcon,
11587
+ instagram: InstagramIcon,
11588
+ linkedin: LinkedinIcon,
11589
+ youtube: YoutubeIcon,
11590
+ twitter: TwitterIcon
11591
+ };
11592
+ var SOCIAL_LABEL = {
11593
+ facebook: "Facebook",
11594
+ instagram: "Instagram",
11595
+ linkedin: "LinkedIn",
11596
+ youtube: "YouTube",
11597
+ twitter: "Twitter"
11598
+ };
11599
+ function ColumnHeading({
11600
+ children,
11601
+ className
11602
+ }) {
11603
+ return /* @__PURE__ */ jsx(
11604
+ "h3",
11605
+ {
11606
+ className: cn(
11607
+ "font-heading font-black text-base mb-5 tracking-tight",
11608
+ className
11609
+ ),
11610
+ children
11611
+ }
11612
+ );
11613
+ }
11614
+ function LanguagePicker({
11615
+ variant,
11616
+ languages,
11617
+ currentLanguage,
11618
+ onChange
11619
+ }) {
11620
+ var _a;
11621
+ const t = VARIANT2[variant];
11622
+ const [open, setOpen] = React28.useState(false);
11623
+ const ref = React28.useRef(null);
11624
+ const active = (_a = languages.find((l) => l.code === currentLanguage)) != null ? _a : languages[0];
11625
+ React28.useEffect(() => {
11626
+ if (!open) return;
11627
+ const onDocClick = (e) => {
11628
+ if (ref.current && !ref.current.contains(e.target)) {
11629
+ setOpen(false);
11630
+ }
11631
+ };
11632
+ document.addEventListener("mousedown", onDocClick);
11633
+ return () => document.removeEventListener("mousedown", onDocClick);
11634
+ }, [open]);
11635
+ return /* @__PURE__ */ jsxs("div", { ref, className: "relative inline-block", children: [
11636
+ /* @__PURE__ */ jsxs(
11637
+ "button",
11638
+ {
11639
+ type: "button",
11640
+ onClick: () => setOpen((v) => !v),
11641
+ "aria-haspopup": "listbox",
11642
+ "aria-expanded": open,
11643
+ className: cn(
11644
+ "inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-sm font-ui transition-colors",
11645
+ t.langTrigger,
11646
+ open && t.langOpen
11647
+ ),
11648
+ children: [
11649
+ active == null ? void 0 : active.code,
11650
+ /* @__PURE__ */ jsx(
11651
+ ChevronDownIcon,
11652
+ {
11653
+ className: cn(
11654
+ "h-3 w-3 transition-transform duration-150",
11655
+ t.langChevron,
11656
+ open && "rotate-180"
11657
+ )
11658
+ }
11659
+ )
11660
+ ]
11661
+ }
11662
+ ),
11663
+ open && /* @__PURE__ */ jsx(
11664
+ "div",
11665
+ {
11666
+ role: "listbox",
11667
+ className: "absolute left-0 bottom-[calc(100%+8px)] min-w-[180px] rounded-xl bg-white shadow-2xl border border-black/8 py-1.5 z-10",
11668
+ children: languages.map((lang) => {
11669
+ const isActive = lang.code === (active == null ? void 0 : active.code);
11670
+ return /* @__PURE__ */ jsxs(
11671
+ "button",
11672
+ {
11673
+ type: "button",
11674
+ role: "option",
11675
+ "aria-selected": isActive,
11676
+ onClick: () => {
11677
+ onChange == null ? void 0 : onChange(lang.code);
11678
+ setOpen(false);
11679
+ },
11680
+ className: cn(
11681
+ "flex items-center gap-3 w-full px-5 py-2.5 text-sm font-ui text-left transition-colors hover:bg-muted",
11682
+ isActive ? "text-primary font-semibold" : "text-foreground"
11683
+ ),
11684
+ children: [
11685
+ /* @__PURE__ */ jsx("span", { className: "font-semibold w-8 shrink-0", children: lang.code }),
11686
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: lang.label })
11687
+ ]
11688
+ },
11689
+ lang.code
11690
+ );
11691
+ })
11692
+ }
11693
+ )
11694
+ ] });
11695
+ }
11696
+ function SiteFooter({
11697
+ variant = "dark",
11698
+ brandTitle = "PlanetaEXO",
11699
+ logoSrcLight = "/logo-planetaexo-white.png",
11700
+ logoSrcDark = "/logo-planetaexo-green.png",
11701
+ logoSrc,
11702
+ logoAlt = "PlanetaEXO",
11703
+ logoHref = "#",
11704
+ brandDescription = /* @__PURE__ */ jsxs(Fragment, { children: [
11705
+ "A PlanetaEXO \xE9 uma ag\xEAncia brasileira especializada em viagens de ecoturismo e aventura. Operamos com guias locais credenciados e parceiros que respeitam comunidades e ecossistemas.",
11706
+ " ",
11707
+ /* @__PURE__ */ jsx(
11708
+ "a",
11709
+ {
11710
+ href: "#",
11711
+ className: "font-bold underline decoration-current/30 underline-offset-4 hover:decoration-current",
11712
+ children: "Pol\xEDtica de privacidade"
11713
+ }
11714
+ )
11715
+ ] }),
11716
+ badges = DEFAULT_FOOTER_BADGES,
11717
+ languages = DEFAULT_FOOTER_LANGUAGES,
11718
+ currentLanguage = "PT",
11719
+ onLanguageChange,
11720
+ address = {
11721
+ title: "Basecamp S\xE3o Paulo",
11722
+ lines: ["Av. Paulista, 1234", "01310-100 S\xE3o Paulo \xB7 Brasil"]
11723
+ },
11724
+ phone = "+55 11 9999-0000",
11725
+ email = "ola@planetaexo.com",
11726
+ socials = DEFAULT_FOOTER_SOCIALS,
11727
+ themesTitle = "Temas",
11728
+ themes = DEFAULT_FOOTER_THEMES,
11729
+ destinationsTitle = "Destinos",
11730
+ destinations = DEFAULT_FOOTER_DESTINATIONS,
11731
+ destinationsMore = { label: "Ver todos os destinos", href: "#" },
11732
+ pagesTitle = "P\xE1ginas",
11733
+ pages = DEFAULT_FOOTER_PAGES,
11734
+ cta = {
11735
+ title: "Colaborar?",
11736
+ label: "parceiros@planetaexo.com",
11737
+ href: "mailto:parceiros@planetaexo.com"
11738
+ },
11739
+ copyright,
11740
+ legalLinks = DEFAULT_FOOTER_LEGAL,
11741
+ className
11742
+ }) {
11743
+ const t = VARIANT2[variant];
11744
+ const resolvedLogo = logoSrc != null ? logoSrc : variant === "light" ? logoSrcDark : logoSrcLight;
11745
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
11746
+ const copy = copyright != null ? copyright : `\xA9 ${year} ${brandTitle}. Todos os direitos reservados.`;
11747
+ return /* @__PURE__ */ jsxs("footer", { className: cn(t.footer, className), children: [
11748
+ /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-6 sm:px-10 pt-16 pb-10", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-x-8 gap-y-12", children: [
11749
+ /* @__PURE__ */ jsxs("div", { className: "lg:col-span-4 space-y-6", children: [
11750
+ /* @__PURE__ */ jsx(
11751
+ "a",
11752
+ {
11753
+ href: logoHref,
11754
+ className: "inline-flex items-center",
11755
+ "aria-label": logoAlt,
11756
+ children: /* @__PURE__ */ jsx(
11757
+ "img",
11758
+ {
11759
+ src: resolvedLogo,
11760
+ alt: logoAlt,
11761
+ className: "h-16 w-auto select-none",
11762
+ draggable: false
11763
+ }
11764
+ )
11765
+ }
11766
+ ),
11767
+ brandDescription && /* @__PURE__ */ jsx("p", { className: cn("font-sans text-sm leading-relaxed", t.body), children: brandDescription }),
11768
+ address && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
11769
+ /* @__PURE__ */ jsx("h4", { className: cn("font-heading font-black text-base", t.heading), children: address.title }),
11770
+ /* @__PURE__ */ jsx("address", { className: cn("not-italic text-sm leading-relaxed font-sans", t.body), children: address.lines.map((line, i) => /* @__PURE__ */ jsx("div", { children: line }, i)) })
11771
+ ] }),
11772
+ (phone || email) && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-sm font-ui font-bold", children: [
11773
+ phone && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("a", { href: `tel:${phone.replace(/\s+/g, "")}`, className: t.link, children: phone }) }),
11774
+ email && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("a", { href: `mailto:${email}`, className: t.link, children: email }) })
11775
+ ] }),
11776
+ socials.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: socials.map((s) => {
11777
+ var _a;
11778
+ const Icon = SOCIAL_ICON[s.network];
11779
+ const label = (_a = s.label) != null ? _a : SOCIAL_LABEL[s.network];
11780
+ return /* @__PURE__ */ jsx(
11781
+ "a",
11782
+ {
11783
+ href: s.href,
11784
+ "aria-label": label,
11785
+ className: cn(
11786
+ "flex h-9 w-9 items-center justify-center rounded-full transition-colors",
11787
+ t.socialBtn
11788
+ ),
11789
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4", strokeWidth: 2.25 })
11790
+ },
11791
+ s.network + s.href
11792
+ );
11793
+ }) }),
11794
+ badges && badges.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-5 pt-2", children: badges.map((b, i) => {
11795
+ var _a, _b;
11796
+ const content = (_b = b.node) != null ? _b : /* @__PURE__ */ jsx(
11797
+ "img",
11798
+ {
11799
+ src: b.src,
11800
+ alt: b.alt,
11801
+ style: { height: (_a = b.height) != null ? _a : 56 },
11802
+ className: "block w-auto object-contain",
11803
+ draggable: false
11804
+ }
11805
+ );
11806
+ const wrapper = /* @__PURE__ */ jsx(
11807
+ "span",
11808
+ {
11809
+ className: cn(
11810
+ "inline-flex items-center",
11811
+ t.badgeStroke,
11812
+ t.badgeFilter
11813
+ ),
11814
+ children: content
11815
+ }
11816
+ );
11817
+ return b.href ? /* @__PURE__ */ jsx(
11818
+ "a",
11819
+ {
11820
+ href: b.href,
11821
+ "aria-label": b.alt,
11822
+ className: "hover:opacity-80 transition-opacity",
11823
+ children: wrapper
11824
+ },
11825
+ b.alt + i
11826
+ ) : /* @__PURE__ */ jsx(React28.Fragment, { children: wrapper }, b.alt + i);
11827
+ }) })
11828
+ ] }),
11829
+ themes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "lg:col-span-3", children: [
11830
+ /* @__PURE__ */ jsx(ColumnHeading, { className: t.heading, children: themesTitle }),
11831
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2.5", children: themes.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
11832
+ "a",
11833
+ {
11834
+ href: c.href,
11835
+ className: cn("text-sm font-ui font-bold", t.link),
11836
+ children: c.label
11837
+ }
11838
+ ) }, c.label)) })
11839
+ ] }),
11840
+ destinations.length > 0 && /* @__PURE__ */ jsxs("div", { className: "lg:col-span-3", children: [
11841
+ /* @__PURE__ */ jsx(ColumnHeading, { className: t.heading, children: destinationsTitle }),
11842
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2.5", children: destinations.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
11843
+ "a",
11844
+ {
11845
+ href: c.href,
11846
+ className: cn("text-sm font-ui font-bold", t.link),
11847
+ children: c.label
11848
+ }
11849
+ ) }, c.label)) }),
11850
+ destinationsMore && /* @__PURE__ */ jsxs(
11851
+ "a",
11852
+ {
11853
+ href: destinationsMore.href,
11854
+ className: cn(
11855
+ "inline-flex items-center gap-1.5 mt-5 text-sm font-ui font-bold",
11856
+ t.link
11857
+ ),
11858
+ children: [
11859
+ destinationsMore.label,
11860
+ /* @__PURE__ */ jsx(ArrowRightIcon, { className: "h-3.5 w-3.5 no-underline" })
11861
+ ]
11862
+ }
11863
+ )
11864
+ ] }),
11865
+ /* @__PURE__ */ jsxs("div", { className: "lg:col-span-2 space-y-8", children: [
11866
+ pages.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
11867
+ /* @__PURE__ */ jsx(ColumnHeading, { className: t.heading, children: pagesTitle }),
11868
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2.5", children: pages.map((p) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
11869
+ "a",
11870
+ {
11871
+ href: p.href,
11872
+ className: cn("text-sm font-ui font-bold", t.link),
11873
+ children: p.label
11874
+ }
11875
+ ) }, p.label)) })
11876
+ ] }),
11877
+ cta && /* @__PURE__ */ jsxs("div", { children: [
11878
+ /* @__PURE__ */ jsx(ColumnHeading, { className: t.heading, children: cta.title }),
11879
+ /* @__PURE__ */ jsx(
11880
+ "a",
11881
+ {
11882
+ href: cta.href,
11883
+ className: cn("text-sm font-ui font-bold break-all", t.link),
11884
+ children: cta.label
11885
+ }
11886
+ )
11887
+ ] })
11888
+ ] })
11889
+ ] }) }),
11890
+ /* @__PURE__ */ jsx("div", { className: cn(t.bottomBar), children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto px-6 sm:px-10 py-4 flex flex-wrap items-center gap-x-6 gap-y-3", children: [
11891
+ languages.length > 0 && /* @__PURE__ */ jsx(
11892
+ LanguagePicker,
11893
+ {
11894
+ variant,
11895
+ languages,
11896
+ currentLanguage,
11897
+ onChange: onLanguageChange
11898
+ }
11899
+ ),
11900
+ /* @__PURE__ */ jsx("p", { className: cn("text-xs font-ui", t.bottomText), children: copy }),
11901
+ legalLinks.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap items-center gap-x-6 gap-y-2", children: legalLinks.map((l) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
11902
+ "a",
11903
+ {
11904
+ href: l.href,
11905
+ className: cn("text-xs font-ui font-bold", t.bottomLink),
11906
+ children: l.label
11907
+ }
11908
+ ) }, l.label)) })
11909
+ ] }) })
11910
+ ] });
11911
+ }
10702
11912
  function Stars({ count = 5 }) {
10703
11913
  return /* @__PURE__ */ jsx("span", { className: "flex gap-0.5", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(
10704
11914
  StarIcon,
@@ -10742,9 +11952,9 @@ function TripPage({
10742
11952
  images,
10743
11953
  videoUrl,
10744
11954
  breadcrumb,
11955
+ chips,
10745
11956
  highlights,
10746
- infoGroups,
10747
- keyInfo,
11957
+ howToGetThere,
10748
11958
  recommendedFor,
10749
11959
  overview,
10750
11960
  overviewHighlights,
@@ -10762,6 +11972,7 @@ function TripPage({
10762
11972
  meetingPoints,
10763
11973
  meetingPoint,
10764
11974
  faqs,
11975
+ faqInitialCount = 5,
10765
11976
  sectionIcons,
10766
11977
  reviews,
10767
11978
  trustpilot,
@@ -10781,11 +11992,12 @@ function TripPage({
10781
11992
  features,
10782
11993
  className
10783
11994
  }) {
10784
- const [activeSection, setActiveSection] = React8.useState("");
10785
- const [accordionValue, setAccordionValue] = React8.useState([]);
10786
- const accordionSectionIds = React8.useMemo(
11995
+ const [activeSection, setActiveSection] = React28.useState("");
11996
+ const [accordionValue, setAccordionValue] = React28.useState([]);
11997
+ const [faqsExpanded, setFaqsExpanded] = React28.useState(false);
11998
+ const accordionSectionIds = React28.useMemo(
10787
11999
  () => /* @__PURE__ */ new Set([
10788
- "key-info",
12000
+ "how-to-get-there",
10789
12001
  "what-to-bring",
10790
12002
  "weather",
10791
12003
  "optional-extras",
@@ -10796,18 +12008,18 @@ function TripPage({
10796
12008
  ]),
10797
12009
  []
10798
12010
  );
10799
- const [navFloating, setNavFloating] = React8.useState(false);
10800
- const [navHidden, setNavHidden] = React8.useState(false);
10801
- const [isFloating, setIsFloating] = React8.useState(false);
10802
- const [sidebarPos, setSidebarPos] = React8.useState(null);
10803
- const [pricingBarVisible, setPricingBarVisible] = React8.useState(false);
10804
- const navRef = React8.useRef(null);
10805
- const navSentinelRef = React8.useRef(null);
10806
- const sentinelRef = React8.useRef(null);
10807
- const sidebarPlaceholderRef = React8.useRef(null);
10808
- const pricingBarRef = React8.useRef(null);
10809
- const galleryRef = React8.useRef(null);
10810
- const sections = React8.useMemo(
12011
+ const [navFloating, setNavFloating] = React28.useState(false);
12012
+ const [navHidden, setNavHidden] = React28.useState(false);
12013
+ const [isFloating, setIsFloating] = React28.useState(false);
12014
+ const [sidebarPos, setSidebarPos] = React28.useState(null);
12015
+ const [pricingBarVisible, setPricingBarVisible] = React28.useState(false);
12016
+ const navRef = React28.useRef(null);
12017
+ const navSentinelRef = React28.useRef(null);
12018
+ const sentinelRef = React28.useRef(null);
12019
+ const sidebarPlaceholderRef = React28.useRef(null);
12020
+ const pricingBarRef = React28.useRef(null);
12021
+ const galleryRef = React28.useRef(null);
12022
+ const sections = React28.useMemo(
10811
12023
  () => [
10812
12024
  { id: "overview", label: "Overview", show: !!(overview || (overviewHighlights == null ? void 0 : overviewHighlights.length)) },
10813
12025
  {
@@ -10825,7 +12037,7 @@ function TripPage({
10825
12037
  // eslint-disable-next-line react-hooks/exhaustive-deps
10826
12038
  []
10827
12039
  );
10828
- React8.useEffect(() => {
12040
+ React28.useEffect(() => {
10829
12041
  const sentinel = navSentinelRef.current;
10830
12042
  if (!sentinel) return;
10831
12043
  const update = () => setNavFloating(sentinel.getBoundingClientRect().top < 1);
@@ -10833,7 +12045,7 @@ function TripPage({
10833
12045
  update();
10834
12046
  return () => document.removeEventListener("scroll", update, { capture: true });
10835
12047
  }, []);
10836
- React8.useEffect(() => {
12048
+ React28.useEffect(() => {
10837
12049
  const sentinel = sentinelRef.current;
10838
12050
  if (!sentinel) return;
10839
12051
  const update = () => setIsFloating(sentinel.getBoundingClientRect().top < 1);
@@ -10841,7 +12053,7 @@ function TripPage({
10841
12053
  update();
10842
12054
  return () => document.removeEventListener("scroll", update, { capture: true });
10843
12055
  }, []);
10844
- React8.useEffect(() => {
12056
+ React28.useEffect(() => {
10845
12057
  const measure = () => {
10846
12058
  if (!sidebarPlaceholderRef.current) return;
10847
12059
  const rect = sidebarPlaceholderRef.current.getBoundingClientRect();
@@ -10851,7 +12063,7 @@ function TripPage({
10851
12063
  window.addEventListener("resize", measure);
10852
12064
  return () => window.removeEventListener("resize", measure);
10853
12065
  }, [isFloating]);
10854
- React8.useEffect(() => {
12066
+ React28.useEffect(() => {
10855
12067
  const check = () => {
10856
12068
  var _a;
10857
12069
  const target = (_a = galleryRef.current) != null ? _a : pricingBarRef.current;
@@ -10862,7 +12074,7 @@ function TripPage({
10862
12074
  check();
10863
12075
  return () => document.removeEventListener("scroll", check, { capture: true });
10864
12076
  }, []);
10865
- React8.useEffect(() => {
12077
+ React28.useEffect(() => {
10866
12078
  const check = () => {
10867
12079
  if (!pricingBarRef.current) return;
10868
12080
  setNavHidden(pricingBarRef.current.getBoundingClientRect().top < window.innerHeight * 0.92);
@@ -10871,7 +12083,7 @@ function TripPage({
10871
12083
  check();
10872
12084
  return () => document.removeEventListener("scroll", check, { capture: true });
10873
12085
  }, []);
10874
- React8.useEffect(() => {
12086
+ React28.useEffect(() => {
10875
12087
  if (sections.length === 0) return;
10876
12088
  setActiveSection(sections[0].id);
10877
12089
  const update = () => {
@@ -10946,6 +12158,7 @@ function TripPage({
10946
12158
  destination,
10947
12159
  duration,
10948
12160
  tagline,
12161
+ chips,
10949
12162
  siteHeader,
10950
12163
  uiVariant,
10951
12164
  belowMeta: trustpilotHero ? /* @__PURE__ */ jsx(TrustpilotEmbed, { config: trustpilotHero }) : void 0
@@ -10979,10 +12192,7 @@ function TripPage({
10979
12192
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-8 mt-4", children: [
10980
12193
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 space-y-12 pb-12", children: [
10981
12194
  (overview || (overviewHighlights == null ? void 0 : overviewHighlights.length)) && /* @__PURE__ */ jsxs("section", { id: "trip-section-overview", className: "scroll-mt-20", children: [
10982
- /* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground font-heading mb-4 flex items-center gap-2", children: [
10983
- (sectionIcons == null ? void 0 : sectionIcons.overview) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.overview }) : /* @__PURE__ */ jsx(InfoIcon, { className: "h-5 w-5 text-primary" }),
10984
- "Overview"
10985
- ] }),
12195
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-4", children: "Overview" }),
10986
12196
  overview && /* @__PURE__ */ jsx("div", { className: "text-lg text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: overview }),
10987
12197
  overviewHighlights && overviewHighlights.length > 0 && /* @__PURE__ */ jsx("ul", { className: cn("flex flex-col gap-5", overview && "mt-8"), children: overviewHighlights.map((h, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4", children: [
10988
12198
  h.icon && /* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center text-foreground [&_svg]:h-8 [&_svg]:w-8", children: h.icon }),
@@ -11029,7 +12239,7 @@ function TripPage({
11029
12239
  }
11030
12240
  )
11031
12241
  ] }),
11032
- ((infoGroups == null ? void 0 : infoGroups.length) || keyInfo || (whatToBring == null ? void 0 : whatToBring.length) || weather || optionalExtras || accommodation || food || (meetingPoints == null ? void 0 : meetingPoints.length) || meetingPoint || termsAndConditions) && /* @__PURE__ */ jsxs(
12242
+ (howToGetThere || (whatToBring == null ? void 0 : whatToBring.length) || weather || optionalExtras || accommodation || food || (meetingPoints == null ? void 0 : meetingPoints.length) || meetingPoint || termsAndConditions) && /* @__PURE__ */ jsxs(
11033
12243
  Accordion,
11034
12244
  {
11035
12245
  multiple: false,
@@ -11037,25 +12247,33 @@ function TripPage({
11037
12247
  onValueChange: setAccordionValue,
11038
12248
  className: "border-t border-border",
11039
12249
  children: [
11040
- (keyInfo || infoGroups && infoGroups.length > 0) && /* @__PURE__ */ jsxs(
12250
+ accommodation && /* @__PURE__ */ jsxs(
12251
+ AccordionItem,
12252
+ {
12253
+ value: "accommodation",
12254
+ id: "trip-section-accommodation",
12255
+ className: "scroll-mt-20 border-b border-border",
12256
+ children: [
12257
+ /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
12258
+ (sectionIcons == null ? void 0 : sectionIcons.accommodation) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.accommodation }) : /* @__PURE__ */ jsx(BedDoubleIcon, { className: "h-5 w-5 text-primary" }),
12259
+ "Accommodation"
12260
+ ] }) }),
12261
+ /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: accommodation }) })
12262
+ ]
12263
+ }
12264
+ ),
12265
+ food && /* @__PURE__ */ jsxs(
11041
12266
  AccordionItem,
11042
12267
  {
11043
- value: "key-info",
11044
- id: "trip-section-key-info",
12268
+ value: "food",
12269
+ id: "trip-section-food",
11045
12270
  className: "scroll-mt-20 border-b border-border",
11046
12271
  children: [
11047
12272
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
11048
- (sectionIcons == null ? void 0 : sectionIcons.keyInfo) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.keyInfo }) : /* @__PURE__ */ jsx(InfoIcon, { className: "h-5 w-5 text-primary" }),
11049
- "Key info"
12273
+ (sectionIcons == null ? void 0 : sectionIcons.food) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.food }) : /* @__PURE__ */ jsx(UtensilsIcon, { className: "h-5 w-5 text-primary" }),
12274
+ "Food"
11050
12275
  ] }) }),
11051
- /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: keyInfo ? /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: keyInfo }) : /* @__PURE__ */ jsx("div", { className: "space-y-6", children: infoGroups.map((group, i) => /* @__PURE__ */ jsxs("div", { children: [
11052
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
11053
- group.icon && /* @__PURE__ */ jsx("span", { className: "text-primary", children: group.icon }),
11054
- /* @__PURE__ */ jsx("h3", { className: "text-base font-bold text-foreground font-heading", children: group.title })
11055
- ] }),
11056
- /* @__PURE__ */ jsx(Checklist, { items: group.items }),
11057
- i < infoGroups.length - 1 && /* @__PURE__ */ jsx(Separator, { className: "mt-6" })
11058
- ] }, i)) }) })
12276
+ /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: food }) })
11059
12277
  ]
11060
12278
  }
11061
12279
  ),
@@ -11081,78 +12299,63 @@ function TripPage({
11081
12299
  ]
11082
12300
  }
11083
12301
  ),
11084
- optionalExtras && /* @__PURE__ */ jsxs(
12302
+ howToGetThere && /* @__PURE__ */ jsxs(
11085
12303
  AccordionItem,
11086
12304
  {
11087
- value: "optional-extras",
11088
- id: "trip-section-optional-extras",
12305
+ value: "how-to-get-there",
12306
+ id: "trip-section-how-to-get-there",
11089
12307
  className: "scroll-mt-20 border-b border-border",
11090
12308
  children: [
11091
12309
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
11092
- (sectionIcons == null ? void 0 : sectionIcons.optionalExtras) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.optionalExtras }) : /* @__PURE__ */ jsx(SparklesIcon, { className: "h-5 w-5 text-primary" }),
11093
- "Optional extras"
12310
+ (sectionIcons == null ? void 0 : sectionIcons.howToGetThere) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.howToGetThere }) : /* @__PURE__ */ jsx(CompassIcon, { className: "h-5 w-5 text-primary" }),
12311
+ "How to get there"
11094
12312
  ] }) }),
11095
- /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: optionalExtras }) })
12313
+ /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: howToGetThere }) })
11096
12314
  ]
11097
12315
  }
11098
12316
  ),
11099
- whatToBring && whatToBring.length > 0 && /* @__PURE__ */ jsxs(
11100
- AccordionItem,
11101
- {
11102
- value: "what-to-bring",
11103
- id: "trip-section-what-to-bring",
11104
- className: "scroll-mt-20 border-b border-border",
11105
- children: [
11106
- /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
11107
- (sectionIcons == null ? void 0 : sectionIcons.whatToBring) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.whatToBring }) : /* @__PURE__ */ jsx(BackpackIcon, { className: "h-5 w-5 text-primary" }),
11108
- "What to bring"
11109
- ] }) }),
11110
- /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx(Checklist, { items: whatToBring, icon: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4" }) }) })
11111
- ]
11112
- }
11113
- ),
11114
- accommodation && /* @__PURE__ */ jsxs(
12317
+ weather && /* @__PURE__ */ jsxs(
11115
12318
  AccordionItem,
11116
12319
  {
11117
- value: "accommodation",
11118
- id: "trip-section-accommodation",
12320
+ value: "weather",
12321
+ id: "trip-section-weather",
11119
12322
  className: "scroll-mt-20 border-b border-border",
11120
12323
  children: [
11121
12324
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
11122
- (sectionIcons == null ? void 0 : sectionIcons.accommodation) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.accommodation }) : /* @__PURE__ */ jsx(BedDoubleIcon, { className: "h-5 w-5 text-primary" }),
11123
- "Accommodation"
12325
+ (sectionIcons == null ? void 0 : sectionIcons.weather) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.weather }) : /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 text-primary" }),
12326
+ "Weather"
11124
12327
  ] }) }),
11125
- /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: accommodation }) })
12328
+ /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "flex items-start gap-3 rounded-xl bg-muted/60 border border-border p-5", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-2 [&_strong]:font-semibold", children: weather }) }) })
11126
12329
  ]
11127
12330
  }
11128
12331
  ),
11129
- food && /* @__PURE__ */ jsxs(
12332
+ whatToBring && whatToBring.length > 0 && /* @__PURE__ */ jsxs(
11130
12333
  AccordionItem,
11131
12334
  {
11132
- value: "food",
11133
- id: "trip-section-food",
12335
+ value: "what-to-bring",
12336
+ id: "trip-section-what-to-bring",
11134
12337
  className: "scroll-mt-20 border-b border-border",
11135
12338
  children: [
11136
12339
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
11137
- (sectionIcons == null ? void 0 : sectionIcons.food) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.food }) : /* @__PURE__ */ jsx(UtensilsIcon, { className: "h-5 w-5 text-primary" }),
11138
- "Food"
12340
+ (sectionIcons == null ? void 0 : sectionIcons.whatToBring) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.whatToBring }) : /* @__PURE__ */ jsx(BackpackIcon, { className: "h-5 w-5 text-primary" }),
12341
+ "What to bring"
11139
12342
  ] }) }),
11140
- /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: food }) })
12343
+ /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx(Checklist, { items: whatToBring, icon: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4" }) }) })
11141
12344
  ]
11142
12345
  }
11143
12346
  ),
11144
- weather && /* @__PURE__ */ jsxs(
12347
+ optionalExtras && /* @__PURE__ */ jsxs(
11145
12348
  AccordionItem,
11146
12349
  {
11147
- value: "weather",
11148
- id: "trip-section-weather",
12350
+ value: "optional-extras",
12351
+ id: "trip-section-optional-extras",
11149
12352
  className: "scroll-mt-20 border-b border-border",
11150
12353
  children: [
11151
12354
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "py-5 text-xl font-bold text-foreground font-heading hover:no-underline", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
11152
- (sectionIcons == null ? void 0 : sectionIcons.weather) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.weather }) : /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 text-primary" }),
11153
- "Weather"
12355
+ (sectionIcons == null ? void 0 : sectionIcons.optionalExtras) ? /* @__PURE__ */ jsx("span", { className: "text-primary [&>svg]:h-5 [&>svg]:w-5", children: sectionIcons.optionalExtras }) : /* @__PURE__ */ jsx(CherryIcon, { className: "h-5 w-5 text-primary" }),
12356
+ "Optional extras"
11154
12357
  ] }) }),
11155
- /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "flex items-start gap-3 rounded-xl bg-muted/60 border border-border p-5", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-2 [&_strong]:font-semibold", children: weather }) }) })
12358
+ /* @__PURE__ */ jsx(AccordionContent, { className: "pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-base text-foreground leading-relaxed space-y-3 [&_strong]:font-semibold [&_a]:text-primary [&_a]:underline", children: optionalExtras }) })
11156
12359
  ]
11157
12360
  }
11158
12361
  ),
@@ -11174,13 +12377,39 @@ function TripPage({
11174
12377
  ]
11175
12378
  }
11176
12379
  ),
11177
- faqs && faqs.length > 0 && /* @__PURE__ */ jsxs("section", { id: "trip-section-faq", className: "scroll-mt-20", children: [
11178
- /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-6", children: "FAQ" }),
11179
- /* @__PURE__ */ jsx(Accordion, { variant: "faq", children: faqs.map((faq, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: `faq-${i}`, children: [
11180
- /* @__PURE__ */ jsx(AccordionTrigger, { children: faq.question }),
11181
- /* @__PURE__ */ jsx(AccordionContent, { children: faq.answer })
11182
- ] }, i)) })
11183
- ] }),
12380
+ faqs && faqs.length > 0 && (() => {
12381
+ const visibleFaqs = faqsExpanded ? faqs : faqs.slice(0, faqInitialCount);
12382
+ const hiddenCount = faqs.length - visibleFaqs.length;
12383
+ return /* @__PURE__ */ jsxs("section", { id: "trip-section-faq", className: "scroll-mt-20", children: [
12384
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-6", children: "FAQ" }),
12385
+ /* @__PURE__ */ jsx(Accordion, { variant: "faq", children: visibleFaqs.map((faq, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: `faq-${i}`, children: [
12386
+ /* @__PURE__ */ jsx(AccordionTrigger, { children: faq.question }),
12387
+ /* @__PURE__ */ jsx(AccordionContent, { children: faq.answer })
12388
+ ] }, i)) }),
12389
+ faqs.length > faqInitialCount && /* @__PURE__ */ jsx("div", { className: "mt-5 flex justify-center", children: /* @__PURE__ */ jsx(
12390
+ "button",
12391
+ {
12392
+ type: "button",
12393
+ onClick: () => setFaqsExpanded((v) => !v),
12394
+ className: cn(
12395
+ "inline-flex items-center gap-2 rounded-full border border-border bg-background px-5 py-2.5",
12396
+ "text-sm font-semibold text-foreground shadow-sm",
12397
+ "hover:bg-muted transition-colors duration-150",
12398
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
12399
+ ),
12400
+ children: faqsExpanded ? /* @__PURE__ */ jsxs(Fragment, { children: [
12401
+ /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-4 w-4 text-muted-foreground" }),
12402
+ "Show less"
12403
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
12404
+ /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-4 w-4 text-muted-foreground" }),
12405
+ "See more (",
12406
+ hiddenCount,
12407
+ ")"
12408
+ ] })
12409
+ }
12410
+ ) })
12411
+ ] });
12412
+ })(),
11184
12413
  trustpilot ? /* @__PURE__ */ jsxs("section", { id: "trip-section-reviews", className: "scroll-mt-20", children: [
11185
12414
  /* @__PURE__ */ jsx(Separator, { className: "mb-10" }),
11186
12415
  /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground font-heading mb-5", children: "What our guests think" }),
@@ -11269,8 +12498,8 @@ function TripPage({
11269
12498
  PhotoGallery,
11270
12499
  {
11271
12500
  photos: gallery,
11272
- variant: "grid",
11273
- initialVisible: 6
12501
+ variant: "gridCompact",
12502
+ initialVisible: 8
11274
12503
  }
11275
12504
  ) }),
11276
12505
  gallery && gallery.length > 0 && /* @__PURE__ */ jsx("div", { ref: pricingBarRef, className: "mx-auto w-full max-w-6xl px-6 sm:px-8 py-12", children: /* @__PURE__ */ jsx("div", { id: "trip-booking-form", className: "rounded-2xl border border-border bg-card p-8 shadow-sm", children: /* @__PURE__ */ jsx(BookingForm, { onSubmit: onBook ? (values) => onBook() : void 0 }) }) }),
@@ -11287,7 +12516,8 @@ function TripPage({
11287
12516
  currencyEstimates
11288
12517
  }
11289
12518
  ) }),
11290
- /* @__PURE__ */ jsx("div", { className: "h-20 lg:hidden" })
12519
+ /* @__PURE__ */ jsx("div", { className: "h-20 lg:hidden" }),
12520
+ /* @__PURE__ */ jsx(SiteFooter, {})
11291
12521
  ]
11292
12522
  }
11293
12523
  );
@@ -11393,12 +12623,12 @@ function Toast({
11393
12623
  duration = 6e3,
11394
12624
  className
11395
12625
  }) {
11396
- const [mounted, setMounted] = React8.useState(false);
11397
- const [visible, setVisible] = React8.useState(true);
11398
- React8.useEffect(() => {
12626
+ const [mounted, setMounted] = React28.useState(false);
12627
+ const [visible, setVisible] = React28.useState(true);
12628
+ React28.useEffect(() => {
11399
12629
  setMounted(true);
11400
12630
  }, []);
11401
- React8.useEffect(() => {
12631
+ React28.useEffect(() => {
11402
12632
  if (duration === 0) return;
11403
12633
  const t = setTimeout(() => {
11404
12634
  setVisible(false);