@bigz-app/booking-widget 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -253,6 +253,7 @@ const de$1 = {
253
253
  "events.soldOut": "Ausgebucht",
254
254
  "events.availableFrom": "Freie Plätze ab {{date}}",
255
255
  "events.noAvailableDates": "Keine Termine frei",
256
+ "events.previewSectionTitle": "Specials & nächste Termine",
256
257
  // Event instances
257
258
  "instances.title": "Terminauswahl",
258
259
  "instances.noAvailable": "Keine verfügbaren Termine",
@@ -269,6 +270,15 @@ const de$1 = {
269
270
  "nextEvents.noUpcomingMessage": "Aktuell sind keine Termine verfügbar. Bitte schaue später noch einmal vorbei oder kontaktiere uns direkt.",
270
271
  "nextEvents.showAll": "Alle Events anzeigen",
271
272
  "nextEvents.priceOnRequest": "Preis auf Anfrage",
273
+ // Specials view
274
+ "specials.title": "Sonderangebote",
275
+ "specials.subtitle": "Unsere aktuellen Angebote auf einen Blick",
276
+ "specials.noSpecials": "Keine Sonderangebote",
277
+ "specials.noSpecialsMessage": "Derzeit sind keine Sonderangebote verfügbar. Bitte schaue später noch einmal vorbei.",
278
+ "specials.save": "Spare {{amount}}",
279
+ "specials.savePercent": "{{percent}}% Rabatt",
280
+ "specials.spotsLeft": "Noch {{count}} Plätze frei",
281
+ "specials.bookNow": "Jetzt buchen",
272
282
  // Booking form
273
283
  "booking.title": "Buchung - {{name}}",
274
284
  "booking.notPossible": "Buchung nicht möglich",
@@ -513,6 +523,7 @@ const en = {
513
523
  "events.soldOut": "Sold out",
514
524
  "events.availableFrom": "Available from {{date}}",
515
525
  "events.noAvailableDates": "No dates available",
526
+ "events.previewSectionTitle": "Specials & upcoming dates",
516
527
  // Event instances
517
528
  "instances.title": "Select a date",
518
529
  "instances.noAvailable": "No available dates",
@@ -529,6 +540,15 @@ const en = {
529
540
  "nextEvents.noUpcomingMessage": "There are currently no dates available. Please check back later or contact us directly.",
530
541
  "nextEvents.showAll": "Show all events",
531
542
  "nextEvents.priceOnRequest": "Price on request",
543
+ // Specials view
544
+ "specials.title": "Special Offers",
545
+ "specials.subtitle": "Our current deals at a glance",
546
+ "specials.noSpecials": "No special offers",
547
+ "specials.noSpecialsMessage": "There are currently no special offers available. Please check back later.",
548
+ "specials.save": "Save {{amount}}",
549
+ "specials.savePercent": "{{percent}}% off",
550
+ "specials.spotsLeft": "{{count}} spots left",
551
+ "specials.bookNow": "Book now",
532
552
  // Booking form
533
553
  "booking.title": "Booking - {{name}}",
534
554
  "booking.notPossible": "Booking not possible",
@@ -773,6 +793,7 @@ const es = {
773
793
  "events.soldOut": "Agotado",
774
794
  "events.availableFrom": "Disponible desde {{date}}",
775
795
  "events.noAvailableDates": "Sin fechas disponibles",
796
+ "events.previewSectionTitle": "Especiales & próximas fechas",
776
797
  // Event instances
777
798
  "instances.title": "Seleccionar fecha",
778
799
  "instances.noAvailable": "Sin fechas disponibles",
@@ -789,6 +810,15 @@ const es = {
789
810
  "nextEvents.noUpcomingMessage": "Actualmente no hay fechas disponibles. Por favor, vuelve más tarde o contáctanos directamente.",
790
811
  "nextEvents.showAll": "Mostrar todos los eventos",
791
812
  "nextEvents.priceOnRequest": "Precio bajo consulta",
813
+ // Specials view
814
+ "specials.title": "Ofertas especiales",
815
+ "specials.subtitle": "Nuestras ofertas actuales de un vistazo",
816
+ "specials.noSpecials": "Sin ofertas especiales",
817
+ "specials.noSpecialsMessage": "Actualmente no hay ofertas especiales disponibles. Vuelve más tarde.",
818
+ "specials.save": "Ahorra {{amount}}",
819
+ "specials.savePercent": "{{percent}}% de descuento",
820
+ "specials.spotsLeft": "{{count}} plazas disponibles",
821
+ "specials.bookNow": "Reservar ahora",
792
822
  // Booking form
793
823
  "booking.title": "Reserva - {{name}}",
794
824
  "booking.notPossible": "Reserva no posible",
@@ -1033,6 +1063,7 @@ const pt = {
1033
1063
  "events.soldOut": "Esgotado",
1034
1064
  "events.availableFrom": "Disponível a partir de {{date}}",
1035
1065
  "events.noAvailableDates": "Sem datas disponíveis",
1066
+ "events.previewSectionTitle": "Especiais & próximas datas",
1036
1067
  // Event instances
1037
1068
  "instances.title": "Selecionar data",
1038
1069
  "instances.noAvailable": "Sem datas disponíveis",
@@ -1049,6 +1080,15 @@ const pt = {
1049
1080
  "nextEvents.noUpcomingMessage": "Atualmente não há datas disponíveis. Por favor, volte mais tarde ou contacte-nos diretamente.",
1050
1081
  "nextEvents.showAll": "Mostrar todos os eventos",
1051
1082
  "nextEvents.priceOnRequest": "Preço sob consulta",
1083
+ // Specials view
1084
+ "specials.title": "Ofertas especiais",
1085
+ "specials.subtitle": "As nossas ofertas atuais num relance",
1086
+ "specials.noSpecials": "Sem ofertas especiais",
1087
+ "specials.noSpecialsMessage": "Atualmente não há ofertas especiais disponíveis. Por favor, volte mais tarde.",
1088
+ "specials.save": "Poupe {{amount}}",
1089
+ "specials.savePercent": "{{percent}}% de desconto",
1090
+ "specials.spotsLeft": "{{count}} lugares disponíveis",
1091
+ "specials.bookNow": "Reservar agora",
1052
1092
  // Booking form
1053
1093
  "booking.title": "Reserva - {{name}}",
1054
1094
  "booking.notPossible": "Reserva não possível",
@@ -1293,6 +1333,7 @@ const sv = {
1293
1333
  "events.soldOut": "Fullbokat",
1294
1334
  "events.availableFrom": "Lediga platser från {{date}}",
1295
1335
  "events.noAvailableDates": "Inga datum lediga",
1336
+ "events.previewSectionTitle": "Specials & kommande datum",
1296
1337
  // Event instances
1297
1338
  "instances.title": "Välj datum",
1298
1339
  "instances.noAvailable": "Inga tillgängliga datum",
@@ -1309,6 +1350,15 @@ const sv = {
1309
1350
  "nextEvents.noUpcomingMessage": "Det finns för närvarande inga datum tillgängliga. Kom tillbaka senare eller kontakta oss direkt.",
1310
1351
  "nextEvents.showAll": "Visa alla evenemang",
1311
1352
  "nextEvents.priceOnRequest": "Pris på förfrågan",
1353
+ // Specials view
1354
+ "specials.title": "Specialerbjudanden",
1355
+ "specials.subtitle": "Våra aktuella erbjudanden i korthet",
1356
+ "specials.noSpecials": "Inga specialerbjudanden",
1357
+ "specials.noSpecialsMessage": "Det finns för närvarande inga specialerbjudanden tillgängliga. Kom tillbaka senare.",
1358
+ "specials.save": "Spara {{amount}}",
1359
+ "specials.savePercent": "{{percent}}% rabatt",
1360
+ "specials.spotsLeft": "{{count}} platser kvar",
1361
+ "specials.bookNow": "Boka nu",
1312
1362
  // Booking form
1313
1363
  "booking.title": "Bokning - {{name}}",
1314
1364
  "booking.notPossible": "Bokning inte möjlig",
@@ -1714,129 +1764,143 @@ const resolveSemanticColor = (colorValue, fallbackValue) => {
1714
1764
  // If semantic resolution fails, use fallback or return the original value
1715
1765
  return fallbackValue || colorValue;
1716
1766
  };
1717
- // Predefined themes (modern, accessibility-tested)
1767
+ // Predefined themes
1718
1768
  const themes = {
1719
1769
  // --- Light Themes ---
1720
- "light-fresh": {
1721
- highlight: "#00b1aa", // accent-strong
1722
- background: "#f8fdfe", // neutral-strong (background)
1723
- surface: "#ffffff", // card (pure white)
1724
- text: "#0e7490", // Turquoise 800
1725
- border: "#bae6fd", // Blue 200
1726
- success: "#38bdf8", // Blue 400
1727
- warning: "#fbbf24", // Amber 400
1728
- error: "#f43f5e", // Rose 500
1729
- borderRadius: "18px", // Very rounded corners
1770
+ "teal-minimal": {
1771
+ highlight: "#00b1aa",
1772
+ background: "#f8fdfe",
1773
+ surface: "#ffffff",
1774
+ text: "#0e7490",
1775
+ border: "#bae6fd",
1776
+ success: "#38bdf8",
1777
+ warning: "#fbbf24",
1778
+ error: "#f43f5e",
1779
+ borderRadius: "18px",
1730
1780
  fontFamily: "'Inter', system-ui, sans-serif",
1731
1781
  },
1732
- "light-elegant": {
1733
- highlight: "#8b5cf6", // Violet 500
1734
- background: "#f5f3ff", // Violet 50
1735
- surface: "#ffffff", // White
1736
- text: "#4c1d95", // Violet 900
1737
- border: "#ede9fe", // Violet 100
1738
- success: "#16a34a", // Green 600
1739
- warning: "#ca8a04", // Yellow 600
1740
- error: "#dc2626", // Red 600
1741
- borderRadius: "12px",
1742
- fontFamily: "'Playfair Display', serif",
1782
+ "blue-business": {
1783
+ highlight: "#2563eb",
1784
+ background: "#f8fafc",
1785
+ surface: "#ffffff",
1786
+ text: "#0f172a",
1787
+ border: "#cbd5e1",
1788
+ success: "#059669",
1789
+ warning: "#d97706",
1790
+ error: "#b91c1c",
1791
+ borderRadius: "6px",
1792
+ fontFamily: "'Plus Jakarta Sans', system-ui, sans-serif",
1743
1793
  },
1744
- "light-vibrant": {
1745
- highlight: "#ed702d", // blue-500 - bright blue accent
1746
- background: "#1f2630", // slate-900 - dark background
1747
- surface: "#1f2630", // slate-800 - dark cards
1748
- text: "#f1f5f9", // slate-100 - light text
1749
- border: "#ed702d", // slate-700 - subtle borders
1750
- success: "#22c55e", // green-500
1751
- warning: "#eab308", // yellow-500
1752
- error: "#ef4444", // red-500
1794
+ "orange-raw": {
1795
+ highlight: "#ed702d",
1796
+ background: "#1f2630",
1797
+ surface: "#1f2630",
1798
+ text: "#f1f5f9",
1799
+ border: "#ed702d",
1800
+ success: "#22c55e",
1801
+ warning: "#eab308",
1802
+ error: "#ef4444",
1753
1803
  borderRadius: "0px",
1754
1804
  fontFamily: "Inter, system-ui, sans-serif",
1755
1805
  },
1756
- "light-professional": {
1757
- highlight: "#2563eb", // Blue 600
1758
- background: "#f8fafc", // Slate 50
1759
- surface: "#ffffff", // White
1760
- text: "#1e293b", // Slate 800
1761
- border: "#e2e8f0", // Slate 200
1762
- success: "#059669", // Emerald 600
1763
- warning: "#d97706", // Amber 600
1764
- error: "#b91c1c", // Red 700
1765
- borderRadius: "4px",
1766
- fontFamily: "system-ui, -apple-system, sans-serif",
1767
- },
1768
- "dark-night": {
1769
- highlight: "#3b82f6", // blue-500 - bright blue accent
1770
- background: "#0f172a", // slate-900 - dark background
1771
- surface: "#1e293b", // slate-800 - dark cards
1772
- text: "#f1f5f9", // slate-100 - light text
1773
- border: "#334155", // slate-700 - subtle borders
1774
- success: "#22c55e", // green-500
1775
- warning: "#eab308", // yellow-500
1776
- error: "#ef4444", // red-500
1777
- borderRadius: "8px",
1778
- fontFamily: "Inter, system-ui, sans-serif",
1806
+ // --- Dark Themes ---
1807
+ "navy-night": {
1808
+ highlight: "#60a5fa",
1809
+ background: "#0b1120",
1810
+ surface: "#111827",
1811
+ text: "#e2e8f0",
1812
+ border: "#1e3a5f",
1813
+ success: "#34d399",
1814
+ warning: "#fbbf24",
1815
+ error: "#f87171",
1816
+ borderRadius: "10px",
1817
+ fontFamily: "'Outfit', system-ui, sans-serif",
1779
1818
  },
1780
- "dark-modern": {
1781
- highlight: "#3b82f6", // blue-500 - bright blue accent
1782
- background: "#0f172a", // slate-900 - dark background
1783
- surface: "#1e293b", // slate-800 - dark cards
1784
- text: "#f1f5f9", // slate-100 - light text
1785
- border: "#334155", // slate-700 - subtle borders
1786
- success: "#22c55e", // green-500
1787
- warning: "#eab308", // yellow-500
1788
- error: "#ef4444", // red-500
1789
- borderRadius: "8px",
1790
- fontFamily: "Inter, system-ui, sans-serif",
1791
- },
1792
- "dark-forest": {
1793
- highlight: "#34d399", // Emerald 400
1794
- background: "#05140d",
1795
- surface: "#062215",
1796
- text: "#d1fae5", // Emerald 100
1797
- border: "#043322",
1798
- success: "#4ade80", // Green 400
1799
- warning: "#facc15", // Yellow 400
1800
- error: "#f87171", // Red 400
1819
+ "green-deep": {
1820
+ highlight: "#34d399",
1821
+ background: "#030d07",
1822
+ surface: "#051a0e",
1823
+ text: "#d1fae5",
1824
+ border: "#064e20",
1825
+ success: "#4ade80",
1826
+ warning: "#facc15",
1827
+ error: "#f87171",
1801
1828
  borderRadius: "12px",
1802
- fontFamily: "system-ui, -apple-system, sans-serif",
1829
+ fontFamily: "'Instrument Sans', system-ui, sans-serif",
1803
1830
  },
1804
- "dark-matrix": {
1805
- highlight: "#33ff33",
1831
+ "green-matrix": {
1832
+ highlight: "#39ff14",
1806
1833
  background: "#000000",
1807
- surface: "#0a0a0a",
1808
- text: "#00ff00",
1809
- border: "#1a1a1a",
1810
- success: "#33ff33",
1834
+ surface: "#060f06",
1835
+ text: "#00ff41",
1836
+ border: "#0d2b0d",
1837
+ success: "#39ff14",
1811
1838
  warning: "#ffff00",
1812
1839
  error: "#ff3333",
1813
1840
  borderRadius: "0px",
1814
- fontFamily: "'Courier New', monospace",
1841
+ fontFamily: "'Share Tech Mono', monospace",
1815
1842
  },
1816
- "dark-luxury": {
1817
- highlight: "#fde047", // Yellow 300
1818
- background: "#1c1917", // Stone 900
1819
- surface: "#292524", // Stone 800
1820
- text: "#fafaf9", // Stone 50
1821
- border: "#44403c", // Stone 700
1822
- success: "#a3e635", // Lime 400
1823
- warning: "#f59e0b", // Amber 500
1824
- error: "#fca5a5", // Red 300
1843
+ "gold-luxury": {
1844
+ highlight: "#fde047",
1845
+ background: "#1c1917",
1846
+ surface: "#292524",
1847
+ text: "#fafaf9",
1848
+ border: "#44403c",
1849
+ success: "#a3e635",
1850
+ warning: "#f59e0b",
1851
+ error: "#fca5a5",
1825
1852
  borderRadius: "24px",
1826
- fontFamily: "'Cinzel', serif",
1853
+ fontFamily: "'Bodoni Moda', serif",
1827
1854
  },
1828
- "dark-energetic": {
1829
- highlight: "#d946ef", // Fuchsia 500
1830
- background: "#2e1046",
1831
- surface: "#401561",
1832
- text: "#f3e8ff", // Purple 50
1833
- border: "#581c87", // Purple 900
1834
- success: "#4ade80", // Green 400
1835
- warning: "#facc15", // Yellow 400
1836
- error: "#f87171", // Red 400
1855
+ "purple-electric": {
1856
+ highlight: "#d946ef",
1857
+ background: "#110820",
1858
+ surface: "#1a0d30",
1859
+ text: "#f3e8ff",
1860
+ border: "#3b0764",
1861
+ success: "#4ade80",
1862
+ warning: "#facc15",
1863
+ error: "#f87171",
1837
1864
  borderRadius: "14px",
1838
1865
  fontFamily: "'Geologica', sans-serif",
1839
1866
  },
1867
+ "dark-neon-brutalism": {
1868
+ highlight: "#00e5cc",
1869
+ background: "#0e1420",
1870
+ surface: "#0e1420",
1871
+ text: "#e8eef5",
1872
+ border: "#00e5cc",
1873
+ success: "#00e5cc",
1874
+ warning: "#ffe45e",
1875
+ error: "#ff4d6d",
1876
+ borderRadius: "4px",
1877
+ fontFamily: "'JetBrains Mono', monospace",
1878
+ buttonTextColor: "#0e1420",
1879
+ },
1880
+ "rose-editorial": {
1881
+ highlight: "#be3455",
1882
+ background: "#fdf8f5",
1883
+ surface: "#ffffff",
1884
+ text: "#1a0a0f",
1885
+ border: "#f2d5db",
1886
+ success: "#2d6a4f",
1887
+ warning: "#b5451b",
1888
+ error: "#9b1d20",
1889
+ borderRadius: "0px",
1890
+ fontFamily: "'Cormorant', serif",
1891
+ },
1892
+ "amber-retro": {
1893
+ highlight: "#f59e0b",
1894
+ background: "#1a1008",
1895
+ surface: "#241a0a",
1896
+ text: "#fef3c7",
1897
+ border: "#78350f",
1898
+ success: "#84cc16",
1899
+ warning: "#f59e0b",
1900
+ error: "#ef4444",
1901
+ borderRadius: "6px",
1902
+ fontFamily: "'Syne', sans-serif",
1903
+ },
1840
1904
  };
1841
1905
  const StyleProvider = ({ config, children, }) => {
1842
1906
  // Track hydration state to prevent mismatches
@@ -1846,8 +1910,8 @@ const StyleProvider = ({ config, children, }) => {
1846
1910
  }, []);
1847
1911
  // PERFORMANCE OPTIMIZATION: Memoize style calculations
1848
1912
  const themedStyles = React.useMemo(() => {
1849
- const themeName = config.theme || "light-fresh";
1850
- const themeDefaults = themes[themeName] || themes["light-fresh"];
1913
+ const themeName = config.theme || "teal-minimal";
1914
+ const themeDefaults = themes[themeName] || themes["teal-minimal"];
1851
1915
  const getCSSValue = (value, fallback) => {
1852
1916
  if (!value)
1853
1917
  return fallback;
@@ -1917,6 +1981,7 @@ const StyleProvider = ({ config, children, }) => {
1917
1981
  "--bw-surface-color": finalColors.surface,
1918
1982
  "--bw-text-color": finalColors.text,
1919
1983
  "--bw-text-muted": addOpacity(finalColors.text, 0.7),
1984
+ "--bw-button-text-color": themeDefaults.buttonTextColor || "#ffffff",
1920
1985
  "--bw-border-color": finalColors.border,
1921
1986
  "--bw-success-color": finalColors.success,
1922
1987
  "--bw-warning-color": finalColors.warning,
@@ -1934,7 +1999,7 @@ const StyleProvider = ({ config, children, }) => {
1934
1999
  "--bw-highlight-muted": addOpacity(finalColors.highlight, 0.1),
1935
2000
  "--bw-highlight-subtle": addOpacity(finalColors.highlight, 0.05),
1936
2001
  "--bw-text-subtle": addOpacity(finalColors.text, 0.4),
1937
- colorScheme: themeName.startsWith("dark-") || themeName === "dark-night" ? "dark" : "light",
2002
+ colorScheme: (["navy-night", "green-deep", "green-matrix", "gold-luxury", "purple-electric", "dark-neon-brutalism", "amber-retro", "orange-raw"].includes(themeName) || themeName.startsWith("dark-")) ? "dark" : "light",
1938
2003
  };
1939
2004
  }, [
1940
2005
  config.theme,
@@ -4488,6 +4553,7 @@ function DialogWrapper({ isOpen, onClose, children, maxWidth = "700px", classNam
4488
4553
  "--bw-font-family": computedStyles.getPropertyValue("--bw-font-family").trim() || "system-ui, sans-serif",
4489
4554
  "--bw-shadow-md": computedStyles.getPropertyValue("--bw-shadow-md").trim() ||
4490
4555
  "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
4556
+ "--bw-button-text-color": computedStyles.getPropertyValue("--bw-button-text-color").trim() || "#ffffff",
4491
4557
  };
4492
4558
  setFallbackStyles(fallbacks);
4493
4559
  }
@@ -11197,11 +11263,13 @@ const buttonBase = {
11197
11263
  whiteSpace: "nowrap",
11198
11264
  border: "none",
11199
11265
  };
11266
+ // CSS class name for button hover effects
11267
+ const buttonClassName = "bw-button-hover";
11200
11268
  const buttonStyles = {
11201
11269
  primary: {
11202
11270
  ...buttonBase,
11203
11271
  backgroundColor: "var(--bw-highlight-color)",
11204
- color: "#ffffff",
11272
+ color: "var(--bw-button-text-color, #ffffff)",
11205
11273
  border: "none",
11206
11274
  },
11207
11275
  secondary: {
@@ -13688,8 +13756,48 @@ function formatDurationInfo(info, t) {
13688
13756
  const rest = formatted.slice(0, -1).join(", ");
13689
13757
  return `${t("duration.optionally")} ${rest} ${t("duration.or")} ${last} ${unitPlural}`;
13690
13758
  }
13691
- function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false, skeletonCount = 4, showVoucherAttachment = false, onVoucherClick, }) {
13759
+ function InfoBadge({ text }) {
13760
+ const [open, setOpen] = React.useState(false);
13761
+ const ref = React.useRef(null);
13762
+ return (jsxRuntime.jsxs("span", { ref: ref, onClick: (e) => { e.stopPropagation(); setOpen((v) => !v); }, style: {
13763
+ position: "relative",
13764
+ display: "inline-flex",
13765
+ alignItems: "center",
13766
+ justifyContent: "center",
13767
+ width: "16px",
13768
+ height: "16px",
13769
+ borderRadius: "50%",
13770
+ border: "1px solid var(--bw-highlight-color)",
13771
+ color: "var(--bw-highlight-color)",
13772
+ fontSize: "9px",
13773
+ fontWeight: 700,
13774
+ cursor: "pointer",
13775
+ flexShrink: 0,
13776
+ userSelect: "none",
13777
+ }, children: ["i", open && (jsxRuntime.jsx("span", { style: {
13778
+ position: "absolute",
13779
+ bottom: "calc(100% + 6px)",
13780
+ right: 0,
13781
+ backgroundColor: "var(--bw-surface-color)",
13782
+ border: "1px solid var(--bw-border-color)",
13783
+ borderRadius: "var(--bw-border-radius-small)",
13784
+ boxShadow: "var(--bw-shadow-md)",
13785
+ padding: "6px 10px",
13786
+ fontSize: "14px",
13787
+ color: "var(--bw-text-color)",
13788
+ fontWeight: 400,
13789
+ whiteSpace: "normal",
13790
+ width: "160px",
13791
+ lineHeight: 1.4,
13792
+ zIndex: 100,
13793
+ textAlign: "left",
13794
+ pointerEvents: "none",
13795
+ }, children: text }))] }));
13796
+ }
13797
+ function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview, isLoading = false, skeletonCount = 4, showVoucherAttachment = false, onVoucherClick, }) {
13692
13798
  const t = useTranslations();
13799
+ const { locale } = useLocale();
13800
+ const timezone = useTimezone();
13693
13801
  // State for details dialog
13694
13802
  const [detailsDialogOpen, setDetailsDialogOpen] = React.useState(false);
13695
13803
  const [selectedEventTypeForDetails, setSelectedEventTypeForDetails] = React.useState(null);
@@ -13799,7 +13907,7 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13799
13907
  display: "flex",
13800
13908
  flexDirection: "column",
13801
13909
  justifyContent: "space-between",
13802
- height: "400px",
13910
+ height: "490px",
13803
13911
  }, children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("h2", { className: "event-type-title", style: {
13804
13912
  fontSize: "clamp(1.1rem, 2.5vw, 24px)",
13805
13913
  fontWeight: 700,
@@ -13880,7 +13988,43 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13880
13988
  color: "var(--bw-text-color)",
13881
13989
  fontFamily: "var(--bw-font-family)",
13882
13990
  textAlign: "right",
13883
- }, children: jsxRuntime.jsxs("span", { children: [t("common.from"), " ", formatCurrency(eventType.minPrice)] }) })] }), jsxRuntime.jsxs("div", { style: {
13991
+ }, children: jsxRuntime.jsxs("span", { children: [t("common.from"), " ", formatCurrency(eventType.minPrice)] }) })] }), (() => {
13992
+ const preview = eventType.cardPreview ?? [];
13993
+ return (jsxRuntime.jsxs("div", { style: {
13994
+ marginTop: "12px",
13995
+ borderTop: "1px solid var(--bw-border-color)",
13996
+ paddingTop: "8px",
13997
+ marginBottom: "16px",
13998
+ }, children: [jsxRuntime.jsx("div", { style: {
13999
+ fontSize: "11px",
14000
+ fontWeight: 700,
14001
+ color: "var(--bw-text-muted)",
14002
+ textTransform: "uppercase",
14003
+ letterSpacing: "0.05em",
14004
+ marginBottom: "4px",
14005
+ }, children: t("events.previewSectionTitle") }), jsxRuntime.jsx("div", { style: { height: "102px" }, children: Array.from({ length: 3 }).map((_, i) => {
14006
+ const item = preview[i];
14007
+ if (!item)
14008
+ return jsxRuntime.jsx("div", { style: { height: "34px" } }, i);
14009
+ const hasDiscount = item.basePrice > 0 && item.price < item.basePrice;
14010
+ return (jsxRuntime.jsxs("div", { onClick: (e) => { e.stopPropagation(); onInstancePreview?.(item.id, eventType.id); }, onMouseEnter: (e) => { if (onInstancePreview)
14011
+ e.currentTarget.style.backgroundColor = "var(--bw-border-color)"; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = "transparent"; }, style: {
14012
+ height: "34px",
14013
+ display: "grid",
14014
+ gridTemplateColumns: "auto 1fr auto 20px",
14015
+ alignItems: "center",
14016
+ gap: "8px",
14017
+ width: "100%",
14018
+ fontSize: "13px",
14019
+ color: "var(--bw-text-muted)",
14020
+ cursor: onInstancePreview ? "pointer" : "default",
14021
+ borderRadius: "4px",
14022
+ padding: "0 2px",
14023
+ transition: "background 0.15s",
14024
+ boxSizing: "border-box",
14025
+ }, children: [jsxRuntime.jsxs("span", { style: { whiteSpace: "nowrap", display: "flex", alignItems: "center", gap: "3px" }, children: [item.isSpecial && (jsxRuntime.jsx("span", { style: { color: "var(--bw-highlight-color)", fontSize: "11px", lineHeight: 1 }, children: "\u2605" })), formatWeekday(item.startTime, timezone, locale), " ", formatDate(item.startTime, timezone, locale)] }), jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", opacity: 0.75 }, children: item.name }), jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px", whiteSpace: "nowrap" }, children: [hasDiscount && (jsxRuntime.jsx("span", { style: { textDecoration: "line-through", opacity: 0.55, fontSize: "11px" }, children: formatCurrency(item.basePrice) })), jsxRuntime.jsx("span", { style: { fontWeight: 700, color: item.isSpecial ? "var(--bw-highlight-color)" : "var(--bw-text-color)" }, children: formatCurrency(item.price) })] }), item.specialDescription ? (jsxRuntime.jsx(InfoBadge, { text: item.specialDescription })) : (jsxRuntime.jsx("span", {}))] }, item.id));
14026
+ }) })] }));
14027
+ })(), jsxRuntime.jsxs("div", { style: {
13884
14028
  display: "flex",
13885
14029
  justifyContent: "flex-end",
13886
14030
  alignItems: "center",
@@ -13895,7 +14039,6 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13895
14039
  backgroundColor: "var(--bw-surface-color)",
13896
14040
  padding: "12px",
13897
14041
  borderRadius: "var(--bw-border-radius)",
13898
- fontSize: "clamp(0.8rem, 2vw, 16px)",
13899
14042
  fontWeight: 600,
13900
14043
  fontFamily: "var(--bw-font-family)",
13901
14044
  display: "flex",
@@ -13908,7 +14051,7 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13908
14051
  }, children: t("button.moreDetails") })), isAvailable && (jsxRuntime.jsxs("div", { style: {
13909
14052
  backgroundColor: "var(--bw-highlight-color)",
13910
14053
  color: "var(--bw-surface-color)",
13911
- padding: "12px 24px",
14054
+ padding: "12px 14px",
13912
14055
  borderRadius: "var(--bw-border-radius)",
13913
14056
  fontSize: "clamp(1rem, 2vw, 16px)",
13914
14057
  fontWeight: 600,
@@ -14566,6 +14709,172 @@ function NextEventsPreview({ events, onEventSelect, onShowAll, showAllButtonText
14566
14709
  }, children: "\u27F3" }), t("common.loading")] })) : (showAllButtonText) }) }))] }));
14567
14710
  }
14568
14711
 
14712
+ function SpecialsView({ specials, onEventSelect, isLoading = false, showSavingsAmount = true, showSavingsPercent = false, emptyStateText, isLoadingEventDetails = false, }) {
14713
+ const t = useTranslations();
14714
+ const { locale } = useLocale();
14715
+ const timezone = useTimezone();
14716
+ const [selectedId, setSelectedId] = React.useState(null);
14717
+ const handleSelect = (id) => {
14718
+ setSelectedId(id);
14719
+ onEventSelect(id);
14720
+ };
14721
+ if (isLoading) {
14722
+ return jsxRuntime.jsx(NextEventsSkeleton, { count: 3 });
14723
+ }
14724
+ if (specials.length === 0) {
14725
+ return (jsxRuntime.jsx("div", { style: { maxWidth: "500px", margin: "0 auto", padding: "16px" }, children: jsxRuntime.jsxs("div", { style: {
14726
+ display: "flex",
14727
+ flexDirection: "column",
14728
+ alignItems: "center",
14729
+ justifyContent: "center",
14730
+ textAlign: "center",
14731
+ backgroundColor: "var(--bw-surface-color)",
14732
+ border: "1px solid var(--bw-border-color)",
14733
+ borderRadius: "var(--bw-border-radius)",
14734
+ padding: "24px",
14735
+ fontFamily: "var(--bw-font-family)",
14736
+ minHeight: "300px",
14737
+ }, children: [jsxRuntime.jsx("div", { style: {
14738
+ display: "flex",
14739
+ alignItems: "center",
14740
+ justifyContent: "center",
14741
+ borderRadius: "50%",
14742
+ width: "64px",
14743
+ height: "64px",
14744
+ backgroundColor: "var(--bw-highlight-color)",
14745
+ marginBottom: "16px",
14746
+ fontSize: "32px",
14747
+ color: "#ffffff",
14748
+ opacity: 0.8,
14749
+ }, children: "\uD83C\uDFF7\uFE0F" }), jsxRuntime.jsx("h3", { style: {
14750
+ fontWeight: 600,
14751
+ margin: "0 0 8px 0",
14752
+ fontSize: "20px",
14753
+ color: "var(--bw-text-color)",
14754
+ fontFamily: "var(--bw-font-family)",
14755
+ }, children: t("specials.noSpecials") }), jsxRuntime.jsx("p", { style: {
14756
+ margin: 0,
14757
+ color: "var(--bw-text-muted)",
14758
+ fontSize: "16px",
14759
+ lineHeight: 1.6,
14760
+ fontFamily: "var(--bw-font-family)",
14761
+ maxWidth: "400px",
14762
+ }, children: emptyStateText ?? t("specials.noSpecialsMessage") })] }) }));
14763
+ }
14764
+ return (jsxRuntime.jsxs("div", { style: {
14765
+ maxWidth: "500px",
14766
+ margin: "0 auto",
14767
+ padding: "16px",
14768
+ fontFamily: "var(--bw-font-family)",
14769
+ }, children: [jsxRuntime.jsxs("div", { style: { textAlign: "center", marginBottom: "24px" }, children: [jsxRuntime.jsx("h2", { style: {
14770
+ fontWeight: 600,
14771
+ margin: "0 0 8px 0",
14772
+ fontSize: "18px",
14773
+ color: "var(--bw-text-color)",
14774
+ fontFamily: "var(--bw-font-family)",
14775
+ }, children: t("specials.title") }), jsxRuntime.jsx("p", { style: {
14776
+ margin: 0,
14777
+ fontSize: "16px",
14778
+ color: "var(--bw-text-muted)",
14779
+ fontFamily: "var(--bw-font-family)",
14780
+ }, children: t("specials.subtitle") })] }), jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: specials.map((special) => {
14781
+ const isFullyBooked = special.availableSpots === 0;
14782
+ const isDisabled = isFullyBooked || !special.bookingOpen;
14783
+ const hasDiscount = special.basePrice > 0 && special.price < special.basePrice;
14784
+ return (jsxRuntime.jsxs("div", { style: {
14785
+ position: "relative",
14786
+ backgroundColor: "var(--bw-surface-color)",
14787
+ borderRadius: "var(--bw-border-radius)",
14788
+ border: "1px solid var(--bw-highlight-color)",
14789
+ overflow: "hidden",
14790
+ opacity: isDisabled ? 0.5 : 1,
14791
+ cursor: isDisabled ? "not-allowed" : "pointer",
14792
+ transition: "all 0.2s ease",
14793
+ }, onClick: () => {
14794
+ if (!isDisabled)
14795
+ handleSelect(special.id);
14796
+ }, children: [selectedId === special.id && isLoadingEventDetails && (jsxRuntime.jsx("div", { style: {
14797
+ position: "absolute",
14798
+ inset: 0,
14799
+ display: "flex",
14800
+ alignItems: "center",
14801
+ justifyContent: "center",
14802
+ backgroundColor: "rgba(15, 23, 42, 0.8)",
14803
+ borderRadius: "var(--bw-border-radius)",
14804
+ zIndex: 10,
14805
+ }, children: jsxRuntime.jsx("div", { style: { fontSize: "32px", color: "var(--bw-highlight-color)", animation: "spin 1s linear infinite" }, children: "\u27F3" }) })), jsxRuntime.jsxs("div", { style: { display: "flex", gap: "12px", padding: "12px" }, children: [special.images.length > 0 && (jsxRuntime.jsx("div", { style: {
14806
+ flexShrink: 0,
14807
+ width: "72px",
14808
+ height: "72px",
14809
+ borderRadius: "var(--bw-border-radius-small)",
14810
+ overflow: "hidden",
14811
+ }, children: jsxRuntime.jsx("img", { src: special.images[0], alt: special.eventTypeName, style: { width: "100%", height: "100%", objectFit: "cover" } }) })), jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [jsxRuntime.jsx("div", { style: { marginBottom: "4px" }, children: jsxRuntime.jsx("span", { style: {
14812
+ fontSize: "11px",
14813
+ fontWeight: 600,
14814
+ color: "var(--bw-text-muted)",
14815
+ textTransform: "uppercase",
14816
+ letterSpacing: "0.05em",
14817
+ }, children: special.categoryName }) }), jsxRuntime.jsx("h4", { style: {
14818
+ margin: "0 0 2px 0",
14819
+ fontSize: "15px",
14820
+ fontWeight: 600,
14821
+ color: "var(--bw-text-color)",
14822
+ lineHeight: 1.3,
14823
+ overflow: "hidden",
14824
+ textOverflow: "ellipsis",
14825
+ whiteSpace: "nowrap",
14826
+ }, children: special.eventTypeName }), jsxRuntime.jsxs("div", { style: {
14827
+ fontSize: "13px",
14828
+ fontWeight: 500,
14829
+ color: "var(--bw-highlight-color)",
14830
+ marginBottom: "2px",
14831
+ overflow: "hidden",
14832
+ textOverflow: "ellipsis",
14833
+ whiteSpace: "nowrap",
14834
+ }, children: ["\u2605 ", special.name] }), special.specialDescription && (jsxRuntime.jsx("div", { style: {
14835
+ fontSize: "12px",
14836
+ color: "var(--bw-text-muted)",
14837
+ marginBottom: "6px",
14838
+ lineHeight: 1.4,
14839
+ }, children: special.specialDescription })), jsxRuntime.jsxs("div", { style: { fontSize: "13px", color: "var(--bw-text-muted)", marginBottom: "8px" }, children: [formatWeekday(special.startTime, timezone, locale), ",", " ", formatDate(special.startTime, timezone, locale)] }), jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap" }, children: [hasDiscount && (jsxRuntime.jsx("span", { style: {
14840
+ fontSize: "13px",
14841
+ color: "var(--bw-text-muted)",
14842
+ textDecoration: "line-through",
14843
+ }, children: formatCurrency(special.basePrice) })), jsxRuntime.jsx("span", { style: {
14844
+ fontSize: "16px",
14845
+ fontWeight: 700,
14846
+ color: "var(--bw-highlight-color)",
14847
+ }, children: formatCurrency(special.price) }), hasDiscount && showSavingsAmount && (jsxRuntime.jsx("span", { style: {
14848
+ fontSize: "12px",
14849
+ fontWeight: 600,
14850
+ color: "#ffffff",
14851
+ backgroundColor: "var(--bw-success-color, #22c55e)",
14852
+ borderRadius: "4px",
14853
+ padding: "2px 6px",
14854
+ }, children: t("specials.save").replace("{{amount}}", formatCurrency(special.savings)) })), hasDiscount && showSavingsPercent && (jsxRuntime.jsx("span", { style: {
14855
+ fontSize: "12px",
14856
+ fontWeight: 600,
14857
+ color: "#ffffff",
14858
+ backgroundColor: "var(--bw-success-color, #22c55e)",
14859
+ borderRadius: "4px",
14860
+ padding: "2px 6px",
14861
+ }, children: t("specials.savePercent").replace("{{percent}}", String(special.savingsPercent)) }))] })] })] }), jsxRuntime.jsxs("div", { style: {
14862
+ borderTop: "1px solid var(--bw-border-color)",
14863
+ padding: "8px 12px",
14864
+ display: "flex",
14865
+ justifyContent: "space-between",
14866
+ alignItems: "center",
14867
+ backgroundColor: "var(--bw-background-color)",
14868
+ }, children: [jsxRuntime.jsx("span", { style: { fontSize: "12px", color: "var(--bw-text-muted)" }, children: isFullyBooked
14869
+ ? t("common.fullyBooked")
14870
+ : t("specials.spotsLeft").replace("{{count}}", String(special.availableSpots)) }), jsxRuntime.jsxs("span", { style: {
14871
+ fontSize: "13px",
14872
+ fontWeight: 600,
14873
+ color: "var(--bw-highlight-color)",
14874
+ }, children: [t("specials.bookNow"), " \u2192"] })] })] }, special.id));
14875
+ }) })] }));
14876
+ }
14877
+
14569
14878
  const getThemeConfig = (theme = "generic") => {
14570
14879
  switch (theme) {
14571
14880
  case "christmas":
@@ -14825,8 +15134,8 @@ const cardDisabledStyles = {
14825
15134
  };
14826
15135
  const checkboxContainerStyles = {
14827
15136
  position: "absolute",
14828
- top: "12px",
14829
- right: "12px",
15137
+ bottom: "12px",
15138
+ left: "12px",
14830
15139
  zIndex: 1,
14831
15140
  };
14832
15141
  const checkboxInnerStyles = {
@@ -14921,6 +15230,7 @@ const priceContainerStyles = {
14921
15230
  alignItems: "flex-end",
14922
15231
  marginTop: "8px",
14923
15232
  paddingTop: "8px",
15233
+ paddingBottom: "0px",
14924
15234
  borderTop: "1px solid var(--bw-border-color)",
14925
15235
  };
14926
15236
  const pricePerPersonStyles = {
@@ -15012,7 +15322,7 @@ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, is
15012
15322
  };
15013
15323
  const selectedTotal = calculateTotal();
15014
15324
  const selectedCount = selectedUpsells.length;
15015
- const footerContent = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: onBack, style: mergeStyles(buttonStyles.secondary, buttonStyles.fullWidth), children: t("common.back") }), jsxRuntime.jsx("button", { type: "button", onClick: onContinue, style: mergeStyles(buttonStyles.primary, buttonStyles.fullWidth), children: selectedCount === 0 ? t("button.continueWithout") : t("button.continue") })] }));
15325
+ const footerContent = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: onBack, style: mergeStyles(buttonStyles.secondary, buttonStyles.fullWidth), className: buttonClassName, children: t("common.back") }), jsxRuntime.jsx("button", { type: "button", onClick: onContinue, style: mergeStyles(buttonStyles.primary, buttonStyles.fullWidth), className: buttonClassName, children: selectedCount === 0 ? t("button.continueWithout") : t("button.continue") })] }));
15016
15326
  return (jsxRuntime.jsx(Sidebar, { isOpen: isOpen, onClose: onClose, title: t("upsells.title"), footer: footerContent, children: jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", padding: "16px 16px" }, children: [isLoading && (jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: "12px", padding: "40px 20px", ...textStyles.muted }, children: [spinner(), jsxRuntime.jsx("span", { children: t("upsells.loading") })] })), !isLoading && upsells.length === 0 && (jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "40px 20px", ...textStyles.muted }, children: jsxRuntime.jsx("p", { children: t("upsells.noExtras") }) })), !isLoading && upsells.length > 0 && (jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", flex: 1, overflowY: "auto", paddingBottom: "16px" }, children: upsells.map((upsell) => (jsxRuntime.jsx(UpsellCard, { upsell: upsell, isSelected: isSelected(upsell.id), participantCount: participantCount, onSelect: () => selectUpsell(upsell.id) }, upsell.id))) })), selectedCount > 0 && (jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: "16px", paddingBottom: "16px", paddingTop: "16px", borderTop: "1px solid var(--bw-border-color)", fontSize: "14px" }, children: [jsxRuntime.jsx("span", { style: textStyles.muted, children: selectedCount === 1 ? t("upsells.selected", { count: selectedCount }) : t("upsells.selectedPlural", { count: selectedCount }) }), jsxRuntime.jsxs("span", { style: { fontWeight: 600, color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: ["+", formatCurrency(selectedTotal)] })] }))] }) }));
15017
15327
  }
15018
15328
 
@@ -15060,6 +15370,8 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15060
15370
  : (config.voucherIntegration ?? (hasEventSelection && !isDirectInstanceMode));
15061
15371
  // Selection flow state
15062
15372
  const [currentStep, setCurrentStep] = React.useState("eventTypes");
15373
+ // Tracks where to return when closing the booking form
15374
+ const bookingReturnStep = React.useRef("eventInstances");
15063
15375
  const [eventTypes, setEventTypes] = React.useState([]);
15064
15376
  const [selectedEventType, setSelectedEventType] = React.useState(null);
15065
15377
  const [eventInstances, setEventInstances] = React.useState([]);
@@ -15072,6 +15384,9 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15072
15384
  // State for upcoming events (next-events view mode)
15073
15385
  const [upcomingEvents, setUpcomingEvents] = React.useState([]);
15074
15386
  const [showingPreview, setShowingPreview] = React.useState(true);
15387
+ // State for specials view mode
15388
+ const [specials, setSpecials] = React.useState([]);
15389
+ const [isLoadingSpecials, setIsLoadingSpecials] = React.useState(false);
15075
15390
  // New: sidebar open state for single event type mode
15076
15391
  const [sidebarOpen, setSidebarOpen] = React.useState(false);
15077
15392
  // Booking flow state
@@ -15222,6 +15537,11 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15222
15537
  await loadUpcomingEvents();
15223
15538
  return;
15224
15539
  }
15540
+ // Specials view mode: load special offers
15541
+ if (viewMode === "specials") {
15542
+ await loadSpecials();
15543
+ return;
15544
+ }
15225
15545
  // Single event type mode: load event type and instances, but don't open sidebar yet
15226
15546
  if (isSingleEventTypeMode) {
15227
15547
  await loadEventTypes();
@@ -15445,6 +15765,45 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15445
15765
  setError(data.error || t("error.loadUpcomingEvents"));
15446
15766
  }
15447
15767
  };
15768
+ const loadSpecials = async () => {
15769
+ setIsLoadingSpecials(true);
15770
+ const specialsSettings = config.specialsSettings ?? {};
15771
+ const requestBody = {
15772
+ organizationId: config.organizationId,
15773
+ limit: specialsSettings.count ?? 20,
15774
+ };
15775
+ if (config.categoryId) {
15776
+ requestBody.categoryId = config.categoryId;
15777
+ }
15778
+ else if (config.eventTypeIds) {
15779
+ requestBody.eventTypeIds = config.eventTypeIds;
15780
+ }
15781
+ else if (config.eventTypeId) {
15782
+ requestBody.eventTypeId = config.eventTypeId;
15783
+ }
15784
+ try {
15785
+ const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/specials"), {
15786
+ method: "POST",
15787
+ headers: createApiHeaders(config, locale),
15788
+ body: JSON.stringify(requestBody),
15789
+ });
15790
+ const data = await response.json();
15791
+ if (response.ok) {
15792
+ const wl = extractWidgetLanguagePayload(data);
15793
+ if (wl) {
15794
+ onWidgetLanguage?.(wl);
15795
+ onTimezone?.(wl.timezone);
15796
+ }
15797
+ setSpecials(data.specials || []);
15798
+ }
15799
+ else {
15800
+ setError(data.error || t("error.loadUpcomingEvents"));
15801
+ }
15802
+ }
15803
+ finally {
15804
+ setIsLoadingSpecials(false);
15805
+ }
15806
+ };
15448
15807
  const loadEventInstances = async (eventTypeId) => {
15449
15808
  const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/event-instances"), {
15450
15809
  method: "POST",
@@ -15629,6 +15988,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15629
15988
  // Event instance selection handlers
15630
15989
  const handleEventInstanceSelect = async (eventInstance) => {
15631
15990
  setSelectedEventInstance(eventInstance);
15991
+ bookingReturnStep.current = "eventInstances";
15632
15992
  // Set default participant count for upsell calculations
15633
15993
  const defaultParticipantCount = 1;
15634
15994
  setTempParticipantCount(defaultParticipantCount);
@@ -15641,7 +16001,14 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15641
16001
  if (availableUpsells.length > 0) {
15642
16002
  // Show upsells step
15643
16003
  setUpsells(availableUpsells);
15644
- setSelectedUpsells([]);
16004
+ // Pre-select default-checked upsells
16005
+ const defaultSelections = availableUpsells
16006
+ .filter((upsell) => upsell.defaultChecked && upsell.available)
16007
+ .map((upsell) => ({
16008
+ upsellPackageId: upsell.id,
16009
+ quantity: defaultParticipantCount,
16010
+ }));
16011
+ setSelectedUpsells(defaultSelections);
15645
16012
  setCurrentStep("upsells");
15646
16013
  setIsLoadingUpsells(false);
15647
16014
  return; // Don't proceed to booking yet
@@ -15672,7 +16039,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15672
16039
  setEventInstances([]);
15673
16040
  };
15674
16041
  const handleBackToEventInstances = () => {
15675
- setCurrentStep("eventInstances");
16042
+ setCurrentStep(bookingReturnStep.current);
15676
16043
  setSelectedEventInstance(null);
15677
16044
  setEventDetails(null);
15678
16045
  };
@@ -15706,8 +16073,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15706
16073
  }
15707
16074
  };
15708
16075
  const handleUpsellsBack = () => {
15709
- // Go back to event instance selection
15710
- setCurrentStep("eventInstances");
16076
+ setCurrentStep(bookingReturnStep.current);
15711
16077
  setSelectedUpsells([]);
15712
16078
  setUpsells([]);
15713
16079
  };
@@ -15742,10 +16108,36 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15742
16108
  setError(errorMessage);
15743
16109
  config.onError?.(errorMessage);
15744
16110
  };
15745
- const handleUpcomingEventSelect = async (eventInstanceId) => {
16111
+ const handleUpcomingEventSelect = async (eventInstanceId, eventTypeId) => {
16112
+ // Resolve the event type — may come from card preview (eventTypeId provided) or
16113
+ // from the next-events list where selectedEventType is already set
16114
+ const resolvedEventType = eventTypeId != null
16115
+ ? (eventTypes.find((et) => et.id === eventTypeId) ?? selectedEventType)
16116
+ : selectedEventType;
16117
+ if (resolvedEventType && resolvedEventType !== selectedEventType) {
16118
+ setSelectedEventType(resolvedEventType);
16119
+ }
16120
+ // Check if this is coming from a card preview (eventTypeId was provided)
16121
+ // In that case, we need to load event instances so back navigation works properly
16122
+ const isFromCardPreview = eventTypeId != null;
16123
+ if (isFromCardPreview && resolvedEventType) {
16124
+ // Load event instances in background so back navigation shows instances
16125
+ setShouldRenderInstanceSelection(true);
16126
+ void loadEventInstances(resolvedEventType.id);
16127
+ // Record that we should return to instance selection (not event types)
16128
+ bookingReturnStep.current = "eventInstances";
16129
+ }
16130
+ else {
16131
+ // Record where to return when the booking form is closed
16132
+ bookingReturnStep.current = currentStep === "eventInstances" ? "eventInstances" : "eventTypes";
16133
+ }
16134
+ // First try to find the event in upcomingEvents (for next-events view mode)
15746
16135
  const upcomingEvent = upcomingEvents.find((event) => event.id === eventInstanceId);
15747
- if (upcomingEvent) {
15748
- const eventInstance = {
16136
+ // If not found in upcomingEvents, try to find in card preview items
16137
+ const cardPreviewItem = !upcomingEvent && resolvedEventType?.cardPreview?.find((item) => item.id === eventInstanceId);
16138
+ // Build the event instance from either source
16139
+ const eventInstance = upcomingEvent
16140
+ ? {
15749
16141
  id: upcomingEvent.id,
15750
16142
  name: upcomingEvent.name,
15751
16143
  startTime: upcomingEvent.startTime,
@@ -15759,13 +16151,63 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15759
16151
  bookingOpen: upcomingEvent.bookingOpen,
15760
16152
  ...(upcomingEvent.deposit !== undefined && { deposit: upcomingEvent.deposit }),
15761
16153
  ...(upcomingEvent.notes !== undefined && { notes: upcomingEvent.notes }),
15762
- };
16154
+ }
16155
+ : cardPreviewItem
16156
+ ? {
16157
+ id: cardPreviewItem.id,
16158
+ name: cardPreviewItem.name,
16159
+ startTime: cardPreviewItem.startTime,
16160
+ endTime: cardPreviewItem.startTime,
16161
+ price: cardPreviewItem.price,
16162
+ maxParticipants: cardPreviewItem.availableSpots + 1,
16163
+ participantCount: 1,
16164
+ availableSpots: cardPreviewItem.availableSpots,
16165
+ durationDays: 1,
16166
+ durationPerDay: 1,
16167
+ bookingOpen: true,
16168
+ }
16169
+ : null;
16170
+ if (eventInstance) {
15763
16171
  setSelectedEventInstance(eventInstance);
15764
16172
  }
16173
+ setError(null);
16174
+ // Check for upsells before going to booking (same as handleEventInstanceSelect)
16175
+ const eventTypeForUpsells = resolvedEventType;
16176
+ if (eventTypeForUpsells) {
16177
+ const defaultParticipantCount = 1;
16178
+ setTempParticipantCount(defaultParticipantCount);
16179
+ setIsLoadingUpsells(true);
16180
+ setShouldRenderUpsells(true);
16181
+ try {
16182
+ const availableUpsells = await loadUpsells(eventTypeForUpsells.id, eventInstanceId, defaultParticipantCount);
16183
+ if (availableUpsells.length > 0) {
16184
+ setUpsells(availableUpsells);
16185
+ // Pre-select default-checked upsells
16186
+ const defaultSelections = availableUpsells
16187
+ .filter((upsell) => upsell.defaultChecked && upsell.available)
16188
+ .map((upsell) => ({
16189
+ upsellPackageId: upsell.id,
16190
+ quantity: defaultParticipantCount,
16191
+ }));
16192
+ setSelectedUpsells(defaultSelections);
16193
+ setCurrentStep("upsells");
16194
+ setIsLoadingUpsells(false);
16195
+ // Load event details in background for when user continues past upsells
16196
+ void loadEventDetails(eventInstanceId);
16197
+ return;
16198
+ }
16199
+ }
16200
+ catch (err) {
16201
+ console.error("Error loading upsells:", err);
16202
+ }
16203
+ finally {
16204
+ setIsLoadingUpsells(false);
16205
+ }
16206
+ }
16207
+ // No upsells — go directly to booking
15765
16208
  setCurrentStep("booking");
15766
16209
  setShouldRenderBookingForm(true);
15767
16210
  setIsLoadingEventDetails(true);
15768
- setError(null);
15769
16211
  try {
15770
16212
  await loadEventDetails(eventInstanceId);
15771
16213
  }
@@ -15922,6 +16364,31 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15922
16364
  window.history.replaceState({}, "", url.toString());
15923
16365
  }, config: config, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsxRuntime.jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
15924
16366
  }
16367
+ if (viewMode === "specials" && showingPreview) {
16368
+ return (jsxRuntime.jsxs(StyleProvider, { config: config, children: [jsxRuntime.jsxs("div", { ref: setWidgetContainerRef, children: [jsxRuntime.jsx(SpecialsView, { specials: specials, onEventSelect: handleUpcomingEventSelect, isLoading: isLoadingSpecials, showSavingsAmount: config.specialsSettings?.showSavingsAmount ?? true, showSavingsPercent: config.specialsSettings?.showSavingsPercent ?? false, emptyStateText: config.specialsSettings?.emptyStateText }), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => {
16369
+ setCurrentStep("eventTypes");
16370
+ setShowingPreview(true);
16371
+ setEventDetails(null);
16372
+ }, onBackToEventTypes: () => {
16373
+ setCurrentStep("eventTypes");
16374
+ setShowingPreview(true);
16375
+ setEventDetails(null);
16376
+ }, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => {
16377
+ setCurrentStep("eventTypes");
16378
+ setShowingPreview(true);
16379
+ setEventDetails(null);
16380
+ }, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
16381
+ setIsSuccess(false);
16382
+ setCurrentStep("eventTypes");
16383
+ setShowingPreview(true);
16384
+ setSuccessPaymentId(null);
16385
+ setShouldRenderInstanceSelection(false);
16386
+ setShouldRenderUpsells(false);
16387
+ setShouldRenderBookingForm(false);
16388
+ setSelectedUpsells([]);
16389
+ setUpsells([]);
16390
+ }, config: config, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsxRuntime.jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
16391
+ }
15925
16392
  if (viewMode === "next-events" && !showingPreview && currentStep === "eventInstances") {
15926
16393
  return (jsxRuntime.jsxs(StyleProvider, { config: config, children: [jsxRuntime.jsxs("div", { ref: setWidgetContainerRef, children: [shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => {
15927
16394
  setShowingPreview(true);
@@ -15992,7 +16459,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15992
16459
  }, config: config, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsxRuntime.jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
15993
16460
  }
15994
16461
  // Cards mode (default) - show event type selection with optional voucher card
15995
- const cardsView = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasEventSelection && (jsxRuntime.jsx(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, isLoading: isLoading, skeletonCount: getSkeletonCount(), showVoucherAttachment: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled && !isStandaloneVoucherMode), onVoucherClick: handleVoucherAttachmentClick })), isStandaloneVoucherMode && (jsxRuntime.jsx(VoucherIntegration, { config: config, voucherConfig: voucherConfig, eventTypes: voucherEventTypes, systemConfig: systemConfig, isFormOpen: false, isLoadingConfig: isLoadingVoucherConfig, preselectedEventTypeId: null, voucherPurchaseResult: null, isSuccess: false, showStandaloneCard: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled), onCardClick: handleVoucherCardClick, onFormClose: handleVoucherFormClose, onSuccess: handleVoucherSuccess, onError: handleVoucherError, onSuccessModalClose: () => { } })), isStandaloneVoucherMode && isLoading && !voucherConfig && (jsxRuntime.jsx("div", { style: { padding: "24px", textAlign: "center" }, children: jsxRuntime.jsx("div", { style: {
16462
+ const cardsView = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [hasEventSelection && (jsxRuntime.jsx(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, onInstancePreview: (instanceId, eventTypeId) => void handleUpcomingEventSelect(instanceId, eventTypeId), isLoading: isLoading, skeletonCount: getSkeletonCount(), showVoucherAttachment: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled && !isStandaloneVoucherMode), onVoucherClick: handleVoucherAttachmentClick })), isStandaloneVoucherMode && (jsxRuntime.jsx(VoucherIntegration, { config: config, voucherConfig: voucherConfig, eventTypes: voucherEventTypes, systemConfig: systemConfig, isFormOpen: false, isLoadingConfig: isLoadingVoucherConfig, preselectedEventTypeId: null, voucherPurchaseResult: null, isSuccess: false, showStandaloneCard: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled), onCardClick: handleVoucherCardClick, onFormClose: handleVoucherFormClose, onSuccess: handleVoucherSuccess, onError: handleVoucherError, onSuccessModalClose: () => { } })), isStandaloneVoucherMode && isLoading && !voucherConfig && (jsxRuntime.jsx("div", { style: { padding: "24px", textAlign: "center" }, children: jsxRuntime.jsx("div", { style: {
15996
16463
  display: "inline-block",
15997
16464
  width: "32px",
15998
16465
  height: "32px",
@@ -16097,7 +16564,7 @@ function styleInject(css, ref) {
16097
16564
  }
16098
16565
  }
16099
16566
 
16100
- var css_248z = ".booking-widget-container{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;color:var(--bw-text-color,#1e293b);direction:ltr;display:block;font-family:var(--bw-font-family,system-ui,-apple-system,sans-serif);font-size:var(--bw-font-size,14px);isolation:isolate;line-height:1.5;position:relative;text-align:left}.booking-widget-container *,.booking-widget-container :after,.booking-widget-container :before{box-sizing:border-box;margin:0;padding:0}.booking-widget-container input,.booking-widget-container select,.booking-widget-container textarea{font-family:inherit;font-size:inherit;line-height:inherit}.booking-widget-container button{background:none;border:none;cursor:pointer;font-family:inherit;font-size:inherit}.booking-widget-container a{color:inherit;text-decoration:none}.booking-widget-container img{display:block;height:auto;max-width:100%;vertical-align:middle}.booking-widget-container ol,.booking-widget-container ul{list-style:none}.booking-widget-container h1,.booking-widget-container h2,.booking-widget-container h3,.booking-widget-container h4,.booking-widget-container h5,.booking-widget-container h6{font-size:inherit;font-weight:inherit}#booking-widget-portal{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:var(--bw-text-color,#1e293b);direction:ltr;font-family:var(--bw-font-family,system-ui,-apple-system,sans-serif);font-size:var(--bw-font-size,14px);isolation:isolate;line-height:1.5;text-align:left}#booking-widget-portal *,#booking-widget-portal :after,#booking-widget-portal :before{box-sizing:border-box}#booking-widget-portal-root{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:var(--bw-text-color,#1e293b);font-family:var(--bw-font-family,system-ui,-apple-system,sans-serif);font-size:var(--bw-font-size,14px);line-height:1.5}:root{--bw-highlight-color:#00b1aa;--bw-highlight-color-rgb:0,177,170;--bw-background-color:#f8fdfe;--bw-surface-color:#fff;--bw-text-color:#0e7490;--bw-text-muted:rgba(14,116,144,.7);--bw-border-color:#bae6fd;--bw-success-color:#38bdf8;--bw-warning-color:#fbbf24;--bw-error-color:#f43f5e;--bw-border-radius:18px;--bw-border-radius-small:calc(var(--bw-border-radius)*0.8);--bw-spacing:16px;--bw-spacing-large:24px;--bw-font-family:\"Inter\",system-ui,sans-serif;--bw-font-size:14px;--bw-font-size-large:18px;--bw-font-size-small:12px;--bw-shadow-md:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--bw-shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--bw-highlight-muted:rgba(0,177,170,.1);--bw-highlight-subtle:rgba(0,177,170,.05);--bw-text-subtle:rgba(14,116,144,.4)}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes shimmer{0%{transform:translateX(-100%)}to{transform:translateX(100%)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-out{0%{opacity:1}to{opacity:0}}@keyframes slide-in-right{0%{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}@keyframes slide-out-right{0%{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(100%)}}@keyframes slide-in-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes scale-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.animate-spin{animation:spin 1s linear infinite}.animate-shimmer{animation:shimmer 2s infinite}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-in-up{animation:slide-in-up .3s ease-out}.animate-scale-in{animation:scale-in .2s ease-out}.skeleton-shimmer{overflow:hidden;position:relative}.skeleton-shimmer:after{animation:shimmer 1.5s infinite;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.3),transparent);content:\"\";height:100%;left:0;position:absolute;top:0;width:100%}@media (max-width:768px){.sidebar-mobile{border-radius:0!important;max-width:100%!important;width:100%!important}}@media (max-width:600px){.event-type-list{gap:12px!important;padding:8px!important}.event-type-card{flex:1 1 100%!important;max-width:100%!important;padding:0!important}.event-type-img{height:160px!important}.event-type-title{font-size:1.1rem!important}.event-type-desc{font-size:.8rem!important;max-height:100px!important;min-height:100px!important}.event-type-content{padding:16px 24px!important}}.event-type-markdown{overflow:visible!important}.event-type-markdown p{color:var(--bw-text-muted);font-family:var(--bw-font-family);line-height:1.6;margin:0 0 8px}.event-type-markdown p:last-child{margin-bottom:0}.event-type-markdown h2{font-size:18px!important;font-weight:700!important;margin:12px 0 6px!important}.event-type-markdown h2,.event-type-markdown h3{color:var(--bw-text-color)!important;line-height:1.3!important}.event-type-markdown h3{font-size:16px!important;font-weight:600!important;margin:10px 0 4px!important}.event-type-markdown strong{color:var(--bw-text-color);font-weight:600}.event-type-markdown em{font-style:italic}.event-type-markdown u{text-decoration:underline}.event-type-markdown ul{list-style:none!important;margin:6px 0!important;padding:0 0 0 24px!important;position:relative!important}.event-type-markdown ul li{color:var(--bw-text-muted)!important;font-family:var(--bw-font-family)!important;margin-bottom:2px!important;padding-left:0!important;position:relative!important}.event-type-markdown ul li:before{color:var(--bw-text-color)!important;content:\"•\"!important;font-weight:700!important;left:-16px!important;position:absolute!important;top:0!important}.event-type-markdown ol{counter-reset:list-counter!important;list-style:none!important;margin:6px 0!important;padding:0 0 0 24px!important;position:relative!important}.event-type-markdown ol li{color:var(--bw-text-muted)!important;counter-increment:list-counter!important;font-family:var(--bw-font-family)!important;margin-bottom:2px!important;padding-left:0!important;position:relative!important}.event-type-markdown ol li:before{color:var(--bw-text-color)!important;content:counter(list-counter) \".\"!important;font-weight:700!important;left:-20px!important;position:absolute!important;top:0!important}.event-type-markdown blockquote{border-left:2px solid var(--bw-border-color);color:var(--bw-text-muted);font-style:italic;margin:4px 0;padding-left:12px}.event-type-markdown a{color:var(--bw-highlight-color);text-decoration:underline}.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5,.markdown-content h6{color:var(--bw-text-color);font-weight:600;margin-bottom:.5em}.markdown-content h1{font-size:1.5em}.markdown-content h2{font-size:1.25em}.markdown-content h3{font-size:1.1em}.markdown-content p{line-height:1.6;margin-bottom:1em}.markdown-content ol,.markdown-content ul{margin-bottom:1em;padding-left:1.5em}.markdown-content ul{list-style-type:disc}.markdown-content ol{list-style-type:decimal}.markdown-content li{margin-bottom:.25em}.markdown-content a{color:var(--bw-highlight-color);text-decoration:underline}.markdown-content a:hover{opacity:.8}.markdown-content strong{font-weight:600}.markdown-content em{font-style:italic}.markdown-content code{background:var(--bw-highlight-subtle);border-radius:4px;font-family:monospace;font-size:.9em;padding:.125em .25em}.markdown-content blockquote{border-left:3px solid var(--bw-highlight-color);color:var(--bw-text-muted);margin:1em 0;padding-left:1em}.print-only{display:none}.print-hidden{display:block}@media print{.print-only{display:block}.print-hidden{display:none!important}.print-booking-header{border-bottom:2px solid #000;display:block;margin-bottom:24px;padding-bottom:16px;text-align:center}.print-booking-header h1{font-size:24px;margin:0 0 8px}.print-booking-header .subtitle{color:#666;font-size:14px}.print-booking-card{border:1px solid #ccc;border-radius:8px;margin-bottom:16px;padding:16px;page-break-inside:avoid}.print-section-title{border-bottom:1px solid #ddd;display:block;font-size:16px;font-weight:600;margin-bottom:12px;padding-bottom:8px}.print-detail-grid{display:grid;gap:12px;grid-template-columns:1fr 1fr}.print-detail-item{margin-bottom:8px}.print-detail-label{color:#666;font-size:12px;margin-bottom:4px}.print-detail-value{font-size:14px;font-weight:600}.print-status-badge{border-radius:9999px;display:inline-block;font-size:12px;font-weight:600;padding:4px 12px}.print-status-paid{background-color:#dcfce7;color:#166534;display:inline-block}.print-participant{align-items:center;background-color:#f9fafb;border-radius:4px;display:flex;justify-content:space-between;margin-bottom:8px;padding:8px}.print-participant-name{font-weight:600}.print-participant-age{color:#666;font-size:12px}.print-payment-summary{display:block}.print-payment-row{border-bottom:1px solid #eee;display:flex;justify-content:space-between;padding:4px 0}.print-payment-row:last-child{border-bottom:none;font-weight:600}.print-footer{border-top:1px solid #ddd;color:#666;display:block;font-size:12px;margin-top:24px;padding-top:16px;text-align:center}.print-footer p{margin:4px 0}}";
16567
+ var css_248z = ".booking-widget-container{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box;color:var(--bw-text-color,#1e293b);direction:ltr;display:block;font-family:var(--bw-font-family,system-ui,-apple-system,sans-serif);font-size:var(--bw-font-size,14px);isolation:isolate;line-height:1.5;position:relative;text-align:left}.booking-widget-container *,.booking-widget-container :after,.booking-widget-container :before{box-sizing:border-box;margin:0;padding:0}.booking-widget-container input,.booking-widget-container select,.booking-widget-container textarea{font-family:inherit;font-size:inherit;line-height:inherit}.booking-widget-container button{background:none;border:none;cursor:pointer;font-family:inherit;font-size:inherit}.booking-widget-container a{color:inherit;text-decoration:none}.booking-widget-container img{display:block;height:auto;max-width:100%;vertical-align:middle}.booking-widget-container ol,.booking-widget-container ul{list-style:none}.booking-widget-container h1,.booking-widget-container h2,.booking-widget-container h3,.booking-widget-container h4,.booking-widget-container h5,.booking-widget-container h6{font-size:inherit;font-weight:inherit}#booking-widget-portal{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:var(--bw-text-color,#1e293b);direction:ltr;font-family:var(--bw-font-family,system-ui,-apple-system,sans-serif);font-size:var(--bw-font-size,14px);isolation:isolate;line-height:1.5;text-align:left}#booking-widget-portal *,#booking-widget-portal :after,#booking-widget-portal :before{box-sizing:border-box}#booking-widget-portal-root{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:var(--bw-text-color,#1e293b);font-family:var(--bw-font-family,system-ui,-apple-system,sans-serif);font-size:var(--bw-font-size,14px);line-height:1.5}:root{--bw-highlight-color:#00b1aa;--bw-highlight-color-rgb:0,177,170;--bw-background-color:#f8fdfe;--bw-surface-color:#fff;--bw-text-color:#0e7490;--bw-text-muted:rgba(14,116,144,.7);--bw-border-color:#bae6fd;--bw-success-color:#38bdf8;--bw-warning-color:#fbbf24;--bw-error-color:#f43f5e;--bw-border-radius:18px;--bw-border-radius-small:calc(var(--bw-border-radius)*0.8);--bw-spacing:16px;--bw-spacing-large:24px;--bw-font-family:\"Inter\",system-ui,sans-serif;--bw-font-size:14px;--bw-font-size-large:18px;--bw-font-size-small:12px;--bw-shadow-md:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--bw-shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--bw-highlight-muted:rgba(0,177,170,.1);--bw-highlight-subtle:rgba(0,177,170,.05);--bw-text-subtle:rgba(14,116,144,.4)}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes shimmer{0%{transform:translateX(-100%)}to{transform:translateX(100%)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-out{0%{opacity:1}to{opacity:0}}@keyframes slide-in-right{0%{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}@keyframes slide-out-right{0%{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(100%)}}@keyframes slide-in-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes scale-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.animate-spin{animation:spin 1s linear infinite}.animate-shimmer{animation:shimmer 2s infinite}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.animate-fade-in{animation:fade-in .2s ease-out}.animate-slide-in-up{animation:slide-in-up .3s ease-out}.animate-scale-in{animation:scale-in .2s ease-out}.skeleton-shimmer{overflow:hidden;position:relative}.skeleton-shimmer:after{animation:shimmer 1.5s infinite;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.3),transparent);content:\"\";height:100%;left:0;position:absolute;top:0;width:100%}.bw-btn{transition:all .2s ease!important}.bw-btn:hover:not(:disabled):not([disabled]){box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.bw-btn:active:not(:disabled):not([disabled]){box-shadow:0 2px 4px rgba(0,0,0,.1)}.bw-btn-primary:hover:not(:disabled):not([disabled]){background-color:var(--bw-highlight-color);filter:brightness(1.1)}.bw-btn-secondary:hover:not(:disabled):not([disabled]){background-color:var(--bw-surface-color);border-color:var(--bw-highlight-color);color:var(--bw-highlight-color)}.bw-btn-ghost:hover:not(:disabled):not([disabled]){background-color:var(--bw-highlight-muted)}.bw-btn-outline:hover:not(:disabled):not([disabled]){background-color:var(--bw-highlight-color);color:var(--bw-button-text-color,#fff)}.bw-btn:disabled,.bw-btn[disabled]{cursor:not-allowed!important;opacity:.5!important}button[class*=bw-btn],button[style*=transition]{transition:all .2s ease!important}button[data-variant=primary]:hover:not(:disabled),button[style*=\"--bw-highlight-color\"]:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,0,0,.15);filter:brightness(1.1);transform:translateY(-1px)}button[data-variant=secondary]:hover:not(:disabled){border-color:var(--bw-highlight-color)!important;color:var(--bw-highlight-color)!important}button[data-variant=ghost]:hover:not(:disabled){background-color:var(--bw-highlight-muted)!important}button[data-variant=outline]:hover:not(:disabled){background-color:var(--bw-highlight-color)!important;color:var(--bw-button-text-color,#fff)!important}.bw-button-hover:hover:not(:disabled){box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-1px)}.bw-button-hover:active:not(:disabled){box-shadow:0 2px 4px rgba(0,0,0,.1);transform:translateY(0)}@media (max-width:768px){.sidebar-mobile{border-radius:0!important;max-width:100%!important;width:100%!important}}@media (max-width:600px){.event-type-list{gap:12px!important;padding:8px!important}.event-type-card{flex:1 1 100%!important;max-width:100%!important;padding:0!important}.event-type-img{height:160px!important}.event-type-title{font-size:1.1rem!important}.event-type-desc{font-size:.8rem!important;max-height:100px!important;min-height:100px!important}.event-type-content{padding:16px 24px!important}}.event-type-markdown{overflow:visible!important}.event-type-markdown p{color:var(--bw-text-muted);font-family:var(--bw-font-family);line-height:1.6;margin:0 0 8px}.event-type-markdown p:last-child{margin-bottom:0}.event-type-markdown h2{font-size:18px!important;font-weight:700!important;margin:12px 0 6px!important}.event-type-markdown h2,.event-type-markdown h3{color:var(--bw-text-color)!important;line-height:1.3!important}.event-type-markdown h3{font-size:16px!important;font-weight:600!important;margin:10px 0 4px!important}.event-type-markdown strong{color:var(--bw-text-color);font-weight:600}.event-type-markdown em{font-style:italic}.event-type-markdown u{text-decoration:underline}.event-type-markdown ul{list-style:none!important;margin:6px 0!important;padding:0 0 0 24px!important;position:relative!important}.event-type-markdown ul li{color:var(--bw-text-muted)!important;font-family:var(--bw-font-family)!important;margin-bottom:2px!important;padding-left:0!important;position:relative!important}.event-type-markdown ul li:before{color:var(--bw-text-color)!important;content:\"•\"!important;font-weight:700!important;left:-16px!important;position:absolute!important;top:0!important}.event-type-markdown ol{counter-reset:list-counter!important;list-style:none!important;margin:6px 0!important;padding:0 0 0 24px!important;position:relative!important}.event-type-markdown ol li{color:var(--bw-text-muted)!important;counter-increment:list-counter!important;font-family:var(--bw-font-family)!important;margin-bottom:2px!important;padding-left:0!important;position:relative!important}.event-type-markdown ol li:before{color:var(--bw-text-color)!important;content:counter(list-counter) \".\"!important;font-weight:700!important;left:-20px!important;position:absolute!important;top:0!important}.event-type-markdown blockquote{border-left:2px solid var(--bw-border-color);color:var(--bw-text-muted);font-style:italic;margin:4px 0;padding-left:12px}.event-type-markdown a{color:var(--bw-highlight-color);text-decoration:underline}.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4,.markdown-content h5,.markdown-content h6{color:var(--bw-text-color);font-weight:600;margin-bottom:.5em}.markdown-content h1{font-size:1.5em}.markdown-content h2{font-size:1.25em}.markdown-content h3{font-size:1.1em}.markdown-content p{line-height:1.6;margin-bottom:1em}.markdown-content ol,.markdown-content ul{margin-bottom:1em;padding-left:1.5em}.markdown-content ul{list-style-type:disc}.markdown-content ol{list-style-type:decimal}.markdown-content li{margin-bottom:.25em}.markdown-content a{color:var(--bw-highlight-color);text-decoration:underline}.markdown-content a:hover{opacity:.8}.markdown-content strong{font-weight:600}.markdown-content em{font-style:italic}.markdown-content code{background:var(--bw-highlight-subtle);border-radius:4px;font-family:monospace;font-size:.9em;padding:.125em .25em}.markdown-content blockquote{border-left:3px solid var(--bw-highlight-color);color:var(--bw-text-muted);margin:1em 0;padding-left:1em}.print-only{display:none}.print-hidden{display:block}@media print{.print-only{display:block}.print-hidden{display:none!important}.print-booking-header{border-bottom:2px solid #000;display:block;margin-bottom:24px;padding-bottom:16px;text-align:center}.print-booking-header h1{font-size:24px;margin:0 0 8px}.print-booking-header .subtitle{color:#666;font-size:14px}.print-booking-card{border:1px solid #ccc;border-radius:8px;margin-bottom:16px;padding:16px;page-break-inside:avoid}.print-section-title{border-bottom:1px solid #ddd;display:block;font-size:16px;font-weight:600;margin-bottom:12px;padding-bottom:8px}.print-detail-grid{display:grid;gap:12px;grid-template-columns:1fr 1fr}.print-detail-item{margin-bottom:8px}.print-detail-label{color:#666;font-size:12px;margin-bottom:4px}.print-detail-value{font-size:14px;font-weight:600}.print-status-badge{border-radius:9999px;display:inline-block;font-size:12px;font-weight:600;padding:4px 12px}.print-status-paid{background-color:#dcfce7;color:#166534;display:inline-block}.print-participant{align-items:center;background-color:#f9fafb;border-radius:4px;display:flex;justify-content:space-between;margin-bottom:8px;padding:8px}.print-participant-name{font-weight:600}.print-participant-age{color:#666;font-size:12px}.print-payment-summary{display:block}.print-payment-row{border-bottom:1px solid #eee;display:flex;justify-content:space-between;padding:4px 0}.print-payment-row:last-child{border-bottom:none;font-weight:600}.print-footer{border-top:1px solid #ddd;color:#666;display:block;font-size:12px;margin-top:24px;padding-top:16px;text-align:center}.print-footer p{margin:4px 0}}";
16101
16568
  styleInject(css_248z);
16102
16569
 
16103
16570
  // Export init function for vanilla JS usage