@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.esm.js CHANGED
@@ -233,6 +233,7 @@ const de$1 = {
233
233
  "events.soldOut": "Ausgebucht",
234
234
  "events.availableFrom": "Freie Plätze ab {{date}}",
235
235
  "events.noAvailableDates": "Keine Termine frei",
236
+ "events.previewSectionTitle": "Specials & nächste Termine",
236
237
  // Event instances
237
238
  "instances.title": "Terminauswahl",
238
239
  "instances.noAvailable": "Keine verfügbaren Termine",
@@ -249,6 +250,15 @@ const de$1 = {
249
250
  "nextEvents.noUpcomingMessage": "Aktuell sind keine Termine verfügbar. Bitte schaue später noch einmal vorbei oder kontaktiere uns direkt.",
250
251
  "nextEvents.showAll": "Alle Events anzeigen",
251
252
  "nextEvents.priceOnRequest": "Preis auf Anfrage",
253
+ // Specials view
254
+ "specials.title": "Sonderangebote",
255
+ "specials.subtitle": "Unsere aktuellen Angebote auf einen Blick",
256
+ "specials.noSpecials": "Keine Sonderangebote",
257
+ "specials.noSpecialsMessage": "Derzeit sind keine Sonderangebote verfügbar. Bitte schaue später noch einmal vorbei.",
258
+ "specials.save": "Spare {{amount}}",
259
+ "specials.savePercent": "{{percent}}% Rabatt",
260
+ "specials.spotsLeft": "Noch {{count}} Plätze frei",
261
+ "specials.bookNow": "Jetzt buchen",
252
262
  // Booking form
253
263
  "booking.title": "Buchung - {{name}}",
254
264
  "booking.notPossible": "Buchung nicht möglich",
@@ -493,6 +503,7 @@ const en = {
493
503
  "events.soldOut": "Sold out",
494
504
  "events.availableFrom": "Available from {{date}}",
495
505
  "events.noAvailableDates": "No dates available",
506
+ "events.previewSectionTitle": "Specials & upcoming dates",
496
507
  // Event instances
497
508
  "instances.title": "Select a date",
498
509
  "instances.noAvailable": "No available dates",
@@ -509,6 +520,15 @@ const en = {
509
520
  "nextEvents.noUpcomingMessage": "There are currently no dates available. Please check back later or contact us directly.",
510
521
  "nextEvents.showAll": "Show all events",
511
522
  "nextEvents.priceOnRequest": "Price on request",
523
+ // Specials view
524
+ "specials.title": "Special Offers",
525
+ "specials.subtitle": "Our current deals at a glance",
526
+ "specials.noSpecials": "No special offers",
527
+ "specials.noSpecialsMessage": "There are currently no special offers available. Please check back later.",
528
+ "specials.save": "Save {{amount}}",
529
+ "specials.savePercent": "{{percent}}% off",
530
+ "specials.spotsLeft": "{{count}} spots left",
531
+ "specials.bookNow": "Book now",
512
532
  // Booking form
513
533
  "booking.title": "Booking - {{name}}",
514
534
  "booking.notPossible": "Booking not possible",
@@ -753,6 +773,7 @@ const es = {
753
773
  "events.soldOut": "Agotado",
754
774
  "events.availableFrom": "Disponible desde {{date}}",
755
775
  "events.noAvailableDates": "Sin fechas disponibles",
776
+ "events.previewSectionTitle": "Especiales & próximas fechas",
756
777
  // Event instances
757
778
  "instances.title": "Seleccionar fecha",
758
779
  "instances.noAvailable": "Sin fechas disponibles",
@@ -769,6 +790,15 @@ const es = {
769
790
  "nextEvents.noUpcomingMessage": "Actualmente no hay fechas disponibles. Por favor, vuelve más tarde o contáctanos directamente.",
770
791
  "nextEvents.showAll": "Mostrar todos los eventos",
771
792
  "nextEvents.priceOnRequest": "Precio bajo consulta",
793
+ // Specials view
794
+ "specials.title": "Ofertas especiales",
795
+ "specials.subtitle": "Nuestras ofertas actuales de un vistazo",
796
+ "specials.noSpecials": "Sin ofertas especiales",
797
+ "specials.noSpecialsMessage": "Actualmente no hay ofertas especiales disponibles. Vuelve más tarde.",
798
+ "specials.save": "Ahorra {{amount}}",
799
+ "specials.savePercent": "{{percent}}% de descuento",
800
+ "specials.spotsLeft": "{{count}} plazas disponibles",
801
+ "specials.bookNow": "Reservar ahora",
772
802
  // Booking form
773
803
  "booking.title": "Reserva - {{name}}",
774
804
  "booking.notPossible": "Reserva no posible",
@@ -1013,6 +1043,7 @@ const pt = {
1013
1043
  "events.soldOut": "Esgotado",
1014
1044
  "events.availableFrom": "Disponível a partir de {{date}}",
1015
1045
  "events.noAvailableDates": "Sem datas disponíveis",
1046
+ "events.previewSectionTitle": "Especiais & próximas datas",
1016
1047
  // Event instances
1017
1048
  "instances.title": "Selecionar data",
1018
1049
  "instances.noAvailable": "Sem datas disponíveis",
@@ -1029,6 +1060,15 @@ const pt = {
1029
1060
  "nextEvents.noUpcomingMessage": "Atualmente não há datas disponíveis. Por favor, volte mais tarde ou contacte-nos diretamente.",
1030
1061
  "nextEvents.showAll": "Mostrar todos os eventos",
1031
1062
  "nextEvents.priceOnRequest": "Preço sob consulta",
1063
+ // Specials view
1064
+ "specials.title": "Ofertas especiais",
1065
+ "specials.subtitle": "As nossas ofertas atuais num relance",
1066
+ "specials.noSpecials": "Sem ofertas especiais",
1067
+ "specials.noSpecialsMessage": "Atualmente não há ofertas especiais disponíveis. Por favor, volte mais tarde.",
1068
+ "specials.save": "Poupe {{amount}}",
1069
+ "specials.savePercent": "{{percent}}% de desconto",
1070
+ "specials.spotsLeft": "{{count}} lugares disponíveis",
1071
+ "specials.bookNow": "Reservar agora",
1032
1072
  // Booking form
1033
1073
  "booking.title": "Reserva - {{name}}",
1034
1074
  "booking.notPossible": "Reserva não possível",
@@ -1273,6 +1313,7 @@ const sv = {
1273
1313
  "events.soldOut": "Fullbokat",
1274
1314
  "events.availableFrom": "Lediga platser från {{date}}",
1275
1315
  "events.noAvailableDates": "Inga datum lediga",
1316
+ "events.previewSectionTitle": "Specials & kommande datum",
1276
1317
  // Event instances
1277
1318
  "instances.title": "Välj datum",
1278
1319
  "instances.noAvailable": "Inga tillgängliga datum",
@@ -1289,6 +1330,15 @@ const sv = {
1289
1330
  "nextEvents.noUpcomingMessage": "Det finns för närvarande inga datum tillgängliga. Kom tillbaka senare eller kontakta oss direkt.",
1290
1331
  "nextEvents.showAll": "Visa alla evenemang",
1291
1332
  "nextEvents.priceOnRequest": "Pris på förfrågan",
1333
+ // Specials view
1334
+ "specials.title": "Specialerbjudanden",
1335
+ "specials.subtitle": "Våra aktuella erbjudanden i korthet",
1336
+ "specials.noSpecials": "Inga specialerbjudanden",
1337
+ "specials.noSpecialsMessage": "Det finns för närvarande inga specialerbjudanden tillgängliga. Kom tillbaka senare.",
1338
+ "specials.save": "Spara {{amount}}",
1339
+ "specials.savePercent": "{{percent}}% rabatt",
1340
+ "specials.spotsLeft": "{{count}} platser kvar",
1341
+ "specials.bookNow": "Boka nu",
1292
1342
  // Booking form
1293
1343
  "booking.title": "Bokning - {{name}}",
1294
1344
  "booking.notPossible": "Bokning inte möjlig",
@@ -1694,129 +1744,143 @@ const resolveSemanticColor = (colorValue, fallbackValue) => {
1694
1744
  // If semantic resolution fails, use fallback or return the original value
1695
1745
  return fallbackValue || colorValue;
1696
1746
  };
1697
- // Predefined themes (modern, accessibility-tested)
1747
+ // Predefined themes
1698
1748
  const themes = {
1699
1749
  // --- Light Themes ---
1700
- "light-fresh": {
1701
- highlight: "#00b1aa", // accent-strong
1702
- background: "#f8fdfe", // neutral-strong (background)
1703
- surface: "#ffffff", // card (pure white)
1704
- text: "#0e7490", // Turquoise 800
1705
- border: "#bae6fd", // Blue 200
1706
- success: "#38bdf8", // Blue 400
1707
- warning: "#fbbf24", // Amber 400
1708
- error: "#f43f5e", // Rose 500
1709
- borderRadius: "18px", // Very rounded corners
1750
+ "teal-minimal": {
1751
+ highlight: "#00b1aa",
1752
+ background: "#f8fdfe",
1753
+ surface: "#ffffff",
1754
+ text: "#0e7490",
1755
+ border: "#bae6fd",
1756
+ success: "#38bdf8",
1757
+ warning: "#fbbf24",
1758
+ error: "#f43f5e",
1759
+ borderRadius: "18px",
1710
1760
  fontFamily: "'Inter', system-ui, sans-serif",
1711
1761
  },
1712
- "light-elegant": {
1713
- highlight: "#8b5cf6", // Violet 500
1714
- background: "#f5f3ff", // Violet 50
1715
- surface: "#ffffff", // White
1716
- text: "#4c1d95", // Violet 900
1717
- border: "#ede9fe", // Violet 100
1718
- success: "#16a34a", // Green 600
1719
- warning: "#ca8a04", // Yellow 600
1720
- error: "#dc2626", // Red 600
1721
- borderRadius: "12px",
1722
- fontFamily: "'Playfair Display', serif",
1762
+ "blue-business": {
1763
+ highlight: "#2563eb",
1764
+ background: "#f8fafc",
1765
+ surface: "#ffffff",
1766
+ text: "#0f172a",
1767
+ border: "#cbd5e1",
1768
+ success: "#059669",
1769
+ warning: "#d97706",
1770
+ error: "#b91c1c",
1771
+ borderRadius: "6px",
1772
+ fontFamily: "'Plus Jakarta Sans', system-ui, sans-serif",
1723
1773
  },
1724
- "light-vibrant": {
1725
- highlight: "#ed702d", // blue-500 - bright blue accent
1726
- background: "#1f2630", // slate-900 - dark background
1727
- surface: "#1f2630", // slate-800 - dark cards
1728
- text: "#f1f5f9", // slate-100 - light text
1729
- border: "#ed702d", // slate-700 - subtle borders
1730
- success: "#22c55e", // green-500
1731
- warning: "#eab308", // yellow-500
1732
- error: "#ef4444", // red-500
1774
+ "orange-raw": {
1775
+ highlight: "#ed702d",
1776
+ background: "#1f2630",
1777
+ surface: "#1f2630",
1778
+ text: "#f1f5f9",
1779
+ border: "#ed702d",
1780
+ success: "#22c55e",
1781
+ warning: "#eab308",
1782
+ error: "#ef4444",
1733
1783
  borderRadius: "0px",
1734
1784
  fontFamily: "Inter, system-ui, sans-serif",
1735
1785
  },
1736
- "light-professional": {
1737
- highlight: "#2563eb", // Blue 600
1738
- background: "#f8fafc", // Slate 50
1739
- surface: "#ffffff", // White
1740
- text: "#1e293b", // Slate 800
1741
- border: "#e2e8f0", // Slate 200
1742
- success: "#059669", // Emerald 600
1743
- warning: "#d97706", // Amber 600
1744
- error: "#b91c1c", // Red 700
1745
- borderRadius: "4px",
1746
- fontFamily: "system-ui, -apple-system, sans-serif",
1747
- },
1748
- "dark-night": {
1749
- highlight: "#3b82f6", // blue-500 - bright blue accent
1750
- background: "#0f172a", // slate-900 - dark background
1751
- surface: "#1e293b", // slate-800 - dark cards
1752
- text: "#f1f5f9", // slate-100 - light text
1753
- border: "#334155", // slate-700 - subtle borders
1754
- success: "#22c55e", // green-500
1755
- warning: "#eab308", // yellow-500
1756
- error: "#ef4444", // red-500
1757
- borderRadius: "8px",
1758
- fontFamily: "Inter, system-ui, sans-serif",
1786
+ // --- Dark Themes ---
1787
+ "navy-night": {
1788
+ highlight: "#60a5fa",
1789
+ background: "#0b1120",
1790
+ surface: "#111827",
1791
+ text: "#e2e8f0",
1792
+ border: "#1e3a5f",
1793
+ success: "#34d399",
1794
+ warning: "#fbbf24",
1795
+ error: "#f87171",
1796
+ borderRadius: "10px",
1797
+ fontFamily: "'Outfit', system-ui, sans-serif",
1759
1798
  },
1760
- "dark-modern": {
1761
- highlight: "#3b82f6", // blue-500 - bright blue accent
1762
- background: "#0f172a", // slate-900 - dark background
1763
- surface: "#1e293b", // slate-800 - dark cards
1764
- text: "#f1f5f9", // slate-100 - light text
1765
- border: "#334155", // slate-700 - subtle borders
1766
- success: "#22c55e", // green-500
1767
- warning: "#eab308", // yellow-500
1768
- error: "#ef4444", // red-500
1769
- borderRadius: "8px",
1770
- fontFamily: "Inter, system-ui, sans-serif",
1771
- },
1772
- "dark-forest": {
1773
- highlight: "#34d399", // Emerald 400
1774
- background: "#05140d",
1775
- surface: "#062215",
1776
- text: "#d1fae5", // Emerald 100
1777
- border: "#043322",
1778
- success: "#4ade80", // Green 400
1779
- warning: "#facc15", // Yellow 400
1780
- error: "#f87171", // Red 400
1799
+ "green-deep": {
1800
+ highlight: "#34d399",
1801
+ background: "#030d07",
1802
+ surface: "#051a0e",
1803
+ text: "#d1fae5",
1804
+ border: "#064e20",
1805
+ success: "#4ade80",
1806
+ warning: "#facc15",
1807
+ error: "#f87171",
1781
1808
  borderRadius: "12px",
1782
- fontFamily: "system-ui, -apple-system, sans-serif",
1809
+ fontFamily: "'Instrument Sans', system-ui, sans-serif",
1783
1810
  },
1784
- "dark-matrix": {
1785
- highlight: "#33ff33",
1811
+ "green-matrix": {
1812
+ highlight: "#39ff14",
1786
1813
  background: "#000000",
1787
- surface: "#0a0a0a",
1788
- text: "#00ff00",
1789
- border: "#1a1a1a",
1790
- success: "#33ff33",
1814
+ surface: "#060f06",
1815
+ text: "#00ff41",
1816
+ border: "#0d2b0d",
1817
+ success: "#39ff14",
1791
1818
  warning: "#ffff00",
1792
1819
  error: "#ff3333",
1793
1820
  borderRadius: "0px",
1794
- fontFamily: "'Courier New', monospace",
1821
+ fontFamily: "'Share Tech Mono', monospace",
1795
1822
  },
1796
- "dark-luxury": {
1797
- highlight: "#fde047", // Yellow 300
1798
- background: "#1c1917", // Stone 900
1799
- surface: "#292524", // Stone 800
1800
- text: "#fafaf9", // Stone 50
1801
- border: "#44403c", // Stone 700
1802
- success: "#a3e635", // Lime 400
1803
- warning: "#f59e0b", // Amber 500
1804
- error: "#fca5a5", // Red 300
1823
+ "gold-luxury": {
1824
+ highlight: "#fde047",
1825
+ background: "#1c1917",
1826
+ surface: "#292524",
1827
+ text: "#fafaf9",
1828
+ border: "#44403c",
1829
+ success: "#a3e635",
1830
+ warning: "#f59e0b",
1831
+ error: "#fca5a5",
1805
1832
  borderRadius: "24px",
1806
- fontFamily: "'Cinzel', serif",
1833
+ fontFamily: "'Bodoni Moda', serif",
1807
1834
  },
1808
- "dark-energetic": {
1809
- highlight: "#d946ef", // Fuchsia 500
1810
- background: "#2e1046",
1811
- surface: "#401561",
1812
- text: "#f3e8ff", // Purple 50
1813
- border: "#581c87", // Purple 900
1814
- success: "#4ade80", // Green 400
1815
- warning: "#facc15", // Yellow 400
1816
- error: "#f87171", // Red 400
1835
+ "purple-electric": {
1836
+ highlight: "#d946ef",
1837
+ background: "#110820",
1838
+ surface: "#1a0d30",
1839
+ text: "#f3e8ff",
1840
+ border: "#3b0764",
1841
+ success: "#4ade80",
1842
+ warning: "#facc15",
1843
+ error: "#f87171",
1817
1844
  borderRadius: "14px",
1818
1845
  fontFamily: "'Geologica', sans-serif",
1819
1846
  },
1847
+ "dark-neon-brutalism": {
1848
+ highlight: "#00e5cc",
1849
+ background: "#0e1420",
1850
+ surface: "#0e1420",
1851
+ text: "#e8eef5",
1852
+ border: "#00e5cc",
1853
+ success: "#00e5cc",
1854
+ warning: "#ffe45e",
1855
+ error: "#ff4d6d",
1856
+ borderRadius: "4px",
1857
+ fontFamily: "'JetBrains Mono', monospace",
1858
+ buttonTextColor: "#0e1420",
1859
+ },
1860
+ "rose-editorial": {
1861
+ highlight: "#be3455",
1862
+ background: "#fdf8f5",
1863
+ surface: "#ffffff",
1864
+ text: "#1a0a0f",
1865
+ border: "#f2d5db",
1866
+ success: "#2d6a4f",
1867
+ warning: "#b5451b",
1868
+ error: "#9b1d20",
1869
+ borderRadius: "0px",
1870
+ fontFamily: "'Cormorant', serif",
1871
+ },
1872
+ "amber-retro": {
1873
+ highlight: "#f59e0b",
1874
+ background: "#1a1008",
1875
+ surface: "#241a0a",
1876
+ text: "#fef3c7",
1877
+ border: "#78350f",
1878
+ success: "#84cc16",
1879
+ warning: "#f59e0b",
1880
+ error: "#ef4444",
1881
+ borderRadius: "6px",
1882
+ fontFamily: "'Syne', sans-serif",
1883
+ },
1820
1884
  };
1821
1885
  const StyleProvider = ({ config, children, }) => {
1822
1886
  // Track hydration state to prevent mismatches
@@ -1826,8 +1890,8 @@ const StyleProvider = ({ config, children, }) => {
1826
1890
  }, []);
1827
1891
  // PERFORMANCE OPTIMIZATION: Memoize style calculations
1828
1892
  const themedStyles = useMemo(() => {
1829
- const themeName = config.theme || "light-fresh";
1830
- const themeDefaults = themes[themeName] || themes["light-fresh"];
1893
+ const themeName = config.theme || "teal-minimal";
1894
+ const themeDefaults = themes[themeName] || themes["teal-minimal"];
1831
1895
  const getCSSValue = (value, fallback) => {
1832
1896
  if (!value)
1833
1897
  return fallback;
@@ -1897,6 +1961,7 @@ const StyleProvider = ({ config, children, }) => {
1897
1961
  "--bw-surface-color": finalColors.surface,
1898
1962
  "--bw-text-color": finalColors.text,
1899
1963
  "--bw-text-muted": addOpacity(finalColors.text, 0.7),
1964
+ "--bw-button-text-color": themeDefaults.buttonTextColor || "#ffffff",
1900
1965
  "--bw-border-color": finalColors.border,
1901
1966
  "--bw-success-color": finalColors.success,
1902
1967
  "--bw-warning-color": finalColors.warning,
@@ -1914,7 +1979,7 @@ const StyleProvider = ({ config, children, }) => {
1914
1979
  "--bw-highlight-muted": addOpacity(finalColors.highlight, 0.1),
1915
1980
  "--bw-highlight-subtle": addOpacity(finalColors.highlight, 0.05),
1916
1981
  "--bw-text-subtle": addOpacity(finalColors.text, 0.4),
1917
- colorScheme: themeName.startsWith("dark-") || themeName === "dark-night" ? "dark" : "light",
1982
+ 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",
1918
1983
  };
1919
1984
  }, [
1920
1985
  config.theme,
@@ -4468,6 +4533,7 @@ function DialogWrapper({ isOpen, onClose, children, maxWidth = "700px", classNam
4468
4533
  "--bw-font-family": computedStyles.getPropertyValue("--bw-font-family").trim() || "system-ui, sans-serif",
4469
4534
  "--bw-shadow-md": computedStyles.getPropertyValue("--bw-shadow-md").trim() ||
4470
4535
  "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
4536
+ "--bw-button-text-color": computedStyles.getPropertyValue("--bw-button-text-color").trim() || "#ffffff",
4471
4537
  };
4472
4538
  setFallbackStyles(fallbacks);
4473
4539
  }
@@ -11177,11 +11243,13 @@ const buttonBase = {
11177
11243
  whiteSpace: "nowrap",
11178
11244
  border: "none",
11179
11245
  };
11246
+ // CSS class name for button hover effects
11247
+ const buttonClassName = "bw-button-hover";
11180
11248
  const buttonStyles = {
11181
11249
  primary: {
11182
11250
  ...buttonBase,
11183
11251
  backgroundColor: "var(--bw-highlight-color)",
11184
- color: "#ffffff",
11252
+ color: "var(--bw-button-text-color, #ffffff)",
11185
11253
  border: "none",
11186
11254
  },
11187
11255
  secondary: {
@@ -13668,8 +13736,48 @@ function formatDurationInfo(info, t) {
13668
13736
  const rest = formatted.slice(0, -1).join(", ");
13669
13737
  return `${t("duration.optionally")} ${rest} ${t("duration.or")} ${last} ${unitPlural}`;
13670
13738
  }
13671
- function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false, skeletonCount = 4, showVoucherAttachment = false, onVoucherClick, }) {
13739
+ function InfoBadge({ text }) {
13740
+ const [open, setOpen] = useState(false);
13741
+ const ref = useRef(null);
13742
+ return (jsxs("span", { ref: ref, onClick: (e) => { e.stopPropagation(); setOpen((v) => !v); }, style: {
13743
+ position: "relative",
13744
+ display: "inline-flex",
13745
+ alignItems: "center",
13746
+ justifyContent: "center",
13747
+ width: "16px",
13748
+ height: "16px",
13749
+ borderRadius: "50%",
13750
+ border: "1px solid var(--bw-highlight-color)",
13751
+ color: "var(--bw-highlight-color)",
13752
+ fontSize: "9px",
13753
+ fontWeight: 700,
13754
+ cursor: "pointer",
13755
+ flexShrink: 0,
13756
+ userSelect: "none",
13757
+ }, children: ["i", open && (jsx("span", { style: {
13758
+ position: "absolute",
13759
+ bottom: "calc(100% + 6px)",
13760
+ right: 0,
13761
+ backgroundColor: "var(--bw-surface-color)",
13762
+ border: "1px solid var(--bw-border-color)",
13763
+ borderRadius: "var(--bw-border-radius-small)",
13764
+ boxShadow: "var(--bw-shadow-md)",
13765
+ padding: "6px 10px",
13766
+ fontSize: "14px",
13767
+ color: "var(--bw-text-color)",
13768
+ fontWeight: 400,
13769
+ whiteSpace: "normal",
13770
+ width: "160px",
13771
+ lineHeight: 1.4,
13772
+ zIndex: 100,
13773
+ textAlign: "left",
13774
+ pointerEvents: "none",
13775
+ }, children: text }))] }));
13776
+ }
13777
+ function EventTypeSelection({ eventTypes, onEventTypeSelect, onInstancePreview, isLoading = false, skeletonCount = 4, showVoucherAttachment = false, onVoucherClick, }) {
13672
13778
  const t = useTranslations();
13779
+ const { locale } = useLocale();
13780
+ const timezone = useTimezone();
13673
13781
  // State for details dialog
13674
13782
  const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
13675
13783
  const [selectedEventTypeForDetails, setSelectedEventTypeForDetails] = useState(null);
@@ -13779,7 +13887,7 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13779
13887
  display: "flex",
13780
13888
  flexDirection: "column",
13781
13889
  justifyContent: "space-between",
13782
- height: "400px",
13890
+ height: "490px",
13783
13891
  }, children: [jsxs("div", { children: [jsx("h2", { className: "event-type-title", style: {
13784
13892
  fontSize: "clamp(1.1rem, 2.5vw, 24px)",
13785
13893
  fontWeight: 700,
@@ -13860,7 +13968,43 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13860
13968
  color: "var(--bw-text-color)",
13861
13969
  fontFamily: "var(--bw-font-family)",
13862
13970
  textAlign: "right",
13863
- }, children: jsxs("span", { children: [t("common.from"), " ", formatCurrency(eventType.minPrice)] }) })] }), jsxs("div", { style: {
13971
+ }, children: jsxs("span", { children: [t("common.from"), " ", formatCurrency(eventType.minPrice)] }) })] }), (() => {
13972
+ const preview = eventType.cardPreview ?? [];
13973
+ return (jsxs("div", { style: {
13974
+ marginTop: "12px",
13975
+ borderTop: "1px solid var(--bw-border-color)",
13976
+ paddingTop: "8px",
13977
+ marginBottom: "16px",
13978
+ }, children: [jsx("div", { style: {
13979
+ fontSize: "11px",
13980
+ fontWeight: 700,
13981
+ color: "var(--bw-text-muted)",
13982
+ textTransform: "uppercase",
13983
+ letterSpacing: "0.05em",
13984
+ marginBottom: "4px",
13985
+ }, children: t("events.previewSectionTitle") }), jsx("div", { style: { height: "102px" }, children: Array.from({ length: 3 }).map((_, i) => {
13986
+ const item = preview[i];
13987
+ if (!item)
13988
+ return jsx("div", { style: { height: "34px" } }, i);
13989
+ const hasDiscount = item.basePrice > 0 && item.price < item.basePrice;
13990
+ return (jsxs("div", { onClick: (e) => { e.stopPropagation(); onInstancePreview?.(item.id, eventType.id); }, onMouseEnter: (e) => { if (onInstancePreview)
13991
+ e.currentTarget.style.backgroundColor = "var(--bw-border-color)"; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = "transparent"; }, style: {
13992
+ height: "34px",
13993
+ display: "grid",
13994
+ gridTemplateColumns: "auto 1fr auto 20px",
13995
+ alignItems: "center",
13996
+ gap: "8px",
13997
+ width: "100%",
13998
+ fontSize: "13px",
13999
+ color: "var(--bw-text-muted)",
14000
+ cursor: onInstancePreview ? "pointer" : "default",
14001
+ borderRadius: "4px",
14002
+ padding: "0 2px",
14003
+ transition: "background 0.15s",
14004
+ boxSizing: "border-box",
14005
+ }, children: [jsxs("span", { style: { whiteSpace: "nowrap", display: "flex", alignItems: "center", gap: "3px" }, children: [item.isSpecial && (jsx("span", { style: { color: "var(--bw-highlight-color)", fontSize: "11px", lineHeight: 1 }, children: "\u2605" })), formatWeekday(item.startTime, timezone, locale), " ", formatDate(item.startTime, timezone, locale)] }), jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", opacity: 0.75 }, children: item.name }), jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px", whiteSpace: "nowrap" }, children: [hasDiscount && (jsx("span", { style: { textDecoration: "line-through", opacity: 0.55, fontSize: "11px" }, children: formatCurrency(item.basePrice) })), jsx("span", { style: { fontWeight: 700, color: item.isSpecial ? "var(--bw-highlight-color)" : "var(--bw-text-color)" }, children: formatCurrency(item.price) })] }), item.specialDescription ? (jsx(InfoBadge, { text: item.specialDescription })) : (jsx("span", {}))] }, item.id));
14006
+ }) })] }));
14007
+ })(), jsxs("div", { style: {
13864
14008
  display: "flex",
13865
14009
  justifyContent: "flex-end",
13866
14010
  alignItems: "center",
@@ -13875,7 +14019,6 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13875
14019
  backgroundColor: "var(--bw-surface-color)",
13876
14020
  padding: "12px",
13877
14021
  borderRadius: "var(--bw-border-radius)",
13878
- fontSize: "clamp(0.8rem, 2vw, 16px)",
13879
14022
  fontWeight: 600,
13880
14023
  fontFamily: "var(--bw-font-family)",
13881
14024
  display: "flex",
@@ -13888,7 +14031,7 @@ function EventTypeSelection({ eventTypes, onEventTypeSelect, isLoading = false,
13888
14031
  }, children: t("button.moreDetails") })), isAvailable && (jsxs("div", { style: {
13889
14032
  backgroundColor: "var(--bw-highlight-color)",
13890
14033
  color: "var(--bw-surface-color)",
13891
- padding: "12px 24px",
14034
+ padding: "12px 14px",
13892
14035
  borderRadius: "var(--bw-border-radius)",
13893
14036
  fontSize: "clamp(1rem, 2vw, 16px)",
13894
14037
  fontWeight: 600,
@@ -14546,6 +14689,172 @@ function NextEventsPreview({ events, onEventSelect, onShowAll, showAllButtonText
14546
14689
  }, children: "\u27F3" }), t("common.loading")] })) : (showAllButtonText) }) }))] }));
14547
14690
  }
14548
14691
 
14692
+ function SpecialsView({ specials, onEventSelect, isLoading = false, showSavingsAmount = true, showSavingsPercent = false, emptyStateText, isLoadingEventDetails = false, }) {
14693
+ const t = useTranslations();
14694
+ const { locale } = useLocale();
14695
+ const timezone = useTimezone();
14696
+ const [selectedId, setSelectedId] = useState(null);
14697
+ const handleSelect = (id) => {
14698
+ setSelectedId(id);
14699
+ onEventSelect(id);
14700
+ };
14701
+ if (isLoading) {
14702
+ return jsx(NextEventsSkeleton, { count: 3 });
14703
+ }
14704
+ if (specials.length === 0) {
14705
+ return (jsx("div", { style: { maxWidth: "500px", margin: "0 auto", padding: "16px" }, children: jsxs("div", { style: {
14706
+ display: "flex",
14707
+ flexDirection: "column",
14708
+ alignItems: "center",
14709
+ justifyContent: "center",
14710
+ textAlign: "center",
14711
+ backgroundColor: "var(--bw-surface-color)",
14712
+ border: "1px solid var(--bw-border-color)",
14713
+ borderRadius: "var(--bw-border-radius)",
14714
+ padding: "24px",
14715
+ fontFamily: "var(--bw-font-family)",
14716
+ minHeight: "300px",
14717
+ }, children: [jsx("div", { style: {
14718
+ display: "flex",
14719
+ alignItems: "center",
14720
+ justifyContent: "center",
14721
+ borderRadius: "50%",
14722
+ width: "64px",
14723
+ height: "64px",
14724
+ backgroundColor: "var(--bw-highlight-color)",
14725
+ marginBottom: "16px",
14726
+ fontSize: "32px",
14727
+ color: "#ffffff",
14728
+ opacity: 0.8,
14729
+ }, children: "\uD83C\uDFF7\uFE0F" }), jsx("h3", { style: {
14730
+ fontWeight: 600,
14731
+ margin: "0 0 8px 0",
14732
+ fontSize: "20px",
14733
+ color: "var(--bw-text-color)",
14734
+ fontFamily: "var(--bw-font-family)",
14735
+ }, children: t("specials.noSpecials") }), jsx("p", { style: {
14736
+ margin: 0,
14737
+ color: "var(--bw-text-muted)",
14738
+ fontSize: "16px",
14739
+ lineHeight: 1.6,
14740
+ fontFamily: "var(--bw-font-family)",
14741
+ maxWidth: "400px",
14742
+ }, children: emptyStateText ?? t("specials.noSpecialsMessage") })] }) }));
14743
+ }
14744
+ return (jsxs("div", { style: {
14745
+ maxWidth: "500px",
14746
+ margin: "0 auto",
14747
+ padding: "16px",
14748
+ fontFamily: "var(--bw-font-family)",
14749
+ }, children: [jsxs("div", { style: { textAlign: "center", marginBottom: "24px" }, children: [jsx("h2", { style: {
14750
+ fontWeight: 600,
14751
+ margin: "0 0 8px 0",
14752
+ fontSize: "18px",
14753
+ color: "var(--bw-text-color)",
14754
+ fontFamily: "var(--bw-font-family)",
14755
+ }, children: t("specials.title") }), jsx("p", { style: {
14756
+ margin: 0,
14757
+ fontSize: "16px",
14758
+ color: "var(--bw-text-muted)",
14759
+ fontFamily: "var(--bw-font-family)",
14760
+ }, children: t("specials.subtitle") })] }), jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: specials.map((special) => {
14761
+ const isFullyBooked = special.availableSpots === 0;
14762
+ const isDisabled = isFullyBooked || !special.bookingOpen;
14763
+ const hasDiscount = special.basePrice > 0 && special.price < special.basePrice;
14764
+ return (jsxs("div", { style: {
14765
+ position: "relative",
14766
+ backgroundColor: "var(--bw-surface-color)",
14767
+ borderRadius: "var(--bw-border-radius)",
14768
+ border: "1px solid var(--bw-highlight-color)",
14769
+ overflow: "hidden",
14770
+ opacity: isDisabled ? 0.5 : 1,
14771
+ cursor: isDisabled ? "not-allowed" : "pointer",
14772
+ transition: "all 0.2s ease",
14773
+ }, onClick: () => {
14774
+ if (!isDisabled)
14775
+ handleSelect(special.id);
14776
+ }, children: [selectedId === special.id && isLoadingEventDetails && (jsx("div", { style: {
14777
+ position: "absolute",
14778
+ inset: 0,
14779
+ display: "flex",
14780
+ alignItems: "center",
14781
+ justifyContent: "center",
14782
+ backgroundColor: "rgba(15, 23, 42, 0.8)",
14783
+ borderRadius: "var(--bw-border-radius)",
14784
+ zIndex: 10,
14785
+ }, children: jsx("div", { style: { fontSize: "32px", color: "var(--bw-highlight-color)", animation: "spin 1s linear infinite" }, children: "\u27F3" }) })), jsxs("div", { style: { display: "flex", gap: "12px", padding: "12px" }, children: [special.images.length > 0 && (jsx("div", { style: {
14786
+ flexShrink: 0,
14787
+ width: "72px",
14788
+ height: "72px",
14789
+ borderRadius: "var(--bw-border-radius-small)",
14790
+ overflow: "hidden",
14791
+ }, children: jsx("img", { src: special.images[0], alt: special.eventTypeName, style: { width: "100%", height: "100%", objectFit: "cover" } }) })), jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [jsx("div", { style: { marginBottom: "4px" }, children: jsx("span", { style: {
14792
+ fontSize: "11px",
14793
+ fontWeight: 600,
14794
+ color: "var(--bw-text-muted)",
14795
+ textTransform: "uppercase",
14796
+ letterSpacing: "0.05em",
14797
+ }, children: special.categoryName }) }), jsx("h4", { style: {
14798
+ margin: "0 0 2px 0",
14799
+ fontSize: "15px",
14800
+ fontWeight: 600,
14801
+ color: "var(--bw-text-color)",
14802
+ lineHeight: 1.3,
14803
+ overflow: "hidden",
14804
+ textOverflow: "ellipsis",
14805
+ whiteSpace: "nowrap",
14806
+ }, children: special.eventTypeName }), jsxs("div", { style: {
14807
+ fontSize: "13px",
14808
+ fontWeight: 500,
14809
+ color: "var(--bw-highlight-color)",
14810
+ marginBottom: "2px",
14811
+ overflow: "hidden",
14812
+ textOverflow: "ellipsis",
14813
+ whiteSpace: "nowrap",
14814
+ }, children: ["\u2605 ", special.name] }), special.specialDescription && (jsx("div", { style: {
14815
+ fontSize: "12px",
14816
+ color: "var(--bw-text-muted)",
14817
+ marginBottom: "6px",
14818
+ lineHeight: 1.4,
14819
+ }, children: special.specialDescription })), jsxs("div", { style: { fontSize: "13px", color: "var(--bw-text-muted)", marginBottom: "8px" }, children: [formatWeekday(special.startTime, timezone, locale), ",", " ", formatDate(special.startTime, timezone, locale)] }), jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap" }, children: [hasDiscount && (jsx("span", { style: {
14820
+ fontSize: "13px",
14821
+ color: "var(--bw-text-muted)",
14822
+ textDecoration: "line-through",
14823
+ }, children: formatCurrency(special.basePrice) })), jsx("span", { style: {
14824
+ fontSize: "16px",
14825
+ fontWeight: 700,
14826
+ color: "var(--bw-highlight-color)",
14827
+ }, children: formatCurrency(special.price) }), hasDiscount && showSavingsAmount && (jsx("span", { style: {
14828
+ fontSize: "12px",
14829
+ fontWeight: 600,
14830
+ color: "#ffffff",
14831
+ backgroundColor: "var(--bw-success-color, #22c55e)",
14832
+ borderRadius: "4px",
14833
+ padding: "2px 6px",
14834
+ }, children: t("specials.save").replace("{{amount}}", formatCurrency(special.savings)) })), hasDiscount && showSavingsPercent && (jsx("span", { style: {
14835
+ fontSize: "12px",
14836
+ fontWeight: 600,
14837
+ color: "#ffffff",
14838
+ backgroundColor: "var(--bw-success-color, #22c55e)",
14839
+ borderRadius: "4px",
14840
+ padding: "2px 6px",
14841
+ }, children: t("specials.savePercent").replace("{{percent}}", String(special.savingsPercent)) }))] })] })] }), jsxs("div", { style: {
14842
+ borderTop: "1px solid var(--bw-border-color)",
14843
+ padding: "8px 12px",
14844
+ display: "flex",
14845
+ justifyContent: "space-between",
14846
+ alignItems: "center",
14847
+ backgroundColor: "var(--bw-background-color)",
14848
+ }, children: [jsx("span", { style: { fontSize: "12px", color: "var(--bw-text-muted)" }, children: isFullyBooked
14849
+ ? t("common.fullyBooked")
14850
+ : t("specials.spotsLeft").replace("{{count}}", String(special.availableSpots)) }), jsxs("span", { style: {
14851
+ fontSize: "13px",
14852
+ fontWeight: 600,
14853
+ color: "var(--bw-highlight-color)",
14854
+ }, children: [t("specials.bookNow"), " \u2192"] })] })] }, special.id));
14855
+ }) })] }));
14856
+ }
14857
+
14549
14858
  const getThemeConfig = (theme = "generic") => {
14550
14859
  switch (theme) {
14551
14860
  case "christmas":
@@ -14805,8 +15114,8 @@ const cardDisabledStyles = {
14805
15114
  };
14806
15115
  const checkboxContainerStyles = {
14807
15116
  position: "absolute",
14808
- top: "12px",
14809
- right: "12px",
15117
+ bottom: "12px",
15118
+ left: "12px",
14810
15119
  zIndex: 1,
14811
15120
  };
14812
15121
  const checkboxInnerStyles = {
@@ -14901,6 +15210,7 @@ const priceContainerStyles = {
14901
15210
  alignItems: "flex-end",
14902
15211
  marginTop: "8px",
14903
15212
  paddingTop: "8px",
15213
+ paddingBottom: "0px",
14904
15214
  borderTop: "1px solid var(--bw-border-color)",
14905
15215
  };
14906
15216
  const pricePerPersonStyles = {
@@ -14992,7 +15302,7 @@ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, is
14992
15302
  };
14993
15303
  const selectedTotal = calculateTotal();
14994
15304
  const selectedCount = selectedUpsells.length;
14995
- const footerContent = (jsxs(Fragment, { children: [jsx("button", { type: "button", onClick: onBack, style: mergeStyles(buttonStyles.secondary, buttonStyles.fullWidth), children: t("common.back") }), jsx("button", { type: "button", onClick: onContinue, style: mergeStyles(buttonStyles.primary, buttonStyles.fullWidth), children: selectedCount === 0 ? t("button.continueWithout") : t("button.continue") })] }));
15305
+ const footerContent = (jsxs(Fragment, { children: [jsx("button", { type: "button", onClick: onBack, style: mergeStyles(buttonStyles.secondary, buttonStyles.fullWidth), className: buttonClassName, children: t("common.back") }), jsx("button", { type: "button", onClick: onContinue, style: mergeStyles(buttonStyles.primary, buttonStyles.fullWidth), className: buttonClassName, children: selectedCount === 0 ? t("button.continueWithout") : t("button.continue") })] }));
14996
15306
  return (jsx(Sidebar, { isOpen: isOpen, onClose: onClose, title: t("upsells.title"), footer: footerContent, children: jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", padding: "16px 16px" }, children: [isLoading && (jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: "12px", padding: "40px 20px", ...textStyles.muted }, children: [spinner(), jsx("span", { children: t("upsells.loading") })] })), !isLoading && upsells.length === 0 && (jsx("div", { style: { textAlign: "center", padding: "40px 20px", ...textStyles.muted }, children: jsx("p", { children: t("upsells.noExtras") }) })), !isLoading && upsells.length > 0 && (jsx("div", { style: { display: "flex", flexDirection: "column", gap: "12px", flex: 1, overflowY: "auto", paddingBottom: "16px" }, children: upsells.map((upsell) => (jsx(UpsellCard, { upsell: upsell, isSelected: isSelected(upsell.id), participantCount: participantCount, onSelect: () => selectUpsell(upsell.id) }, upsell.id))) })), selectedCount > 0 && (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: [jsx("span", { style: textStyles.muted, children: selectedCount === 1 ? t("upsells.selected", { count: selectedCount }) : t("upsells.selectedPlural", { count: selectedCount }) }), jsxs("span", { style: { fontWeight: 600, color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: ["+", formatCurrency(selectedTotal)] })] }))] }) }));
14997
15307
  }
14998
15308
 
@@ -15040,6 +15350,8 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15040
15350
  : (config.voucherIntegration ?? (hasEventSelection && !isDirectInstanceMode));
15041
15351
  // Selection flow state
15042
15352
  const [currentStep, setCurrentStep] = useState("eventTypes");
15353
+ // Tracks where to return when closing the booking form
15354
+ const bookingReturnStep = useRef("eventInstances");
15043
15355
  const [eventTypes, setEventTypes] = useState([]);
15044
15356
  const [selectedEventType, setSelectedEventType] = useState(null);
15045
15357
  const [eventInstances, setEventInstances] = useState([]);
@@ -15052,6 +15364,9 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15052
15364
  // State for upcoming events (next-events view mode)
15053
15365
  const [upcomingEvents, setUpcomingEvents] = useState([]);
15054
15366
  const [showingPreview, setShowingPreview] = useState(true);
15367
+ // State for specials view mode
15368
+ const [specials, setSpecials] = useState([]);
15369
+ const [isLoadingSpecials, setIsLoadingSpecials] = useState(false);
15055
15370
  // New: sidebar open state for single event type mode
15056
15371
  const [sidebarOpen, setSidebarOpen] = useState(false);
15057
15372
  // Booking flow state
@@ -15202,6 +15517,11 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15202
15517
  await loadUpcomingEvents();
15203
15518
  return;
15204
15519
  }
15520
+ // Specials view mode: load special offers
15521
+ if (viewMode === "specials") {
15522
+ await loadSpecials();
15523
+ return;
15524
+ }
15205
15525
  // Single event type mode: load event type and instances, but don't open sidebar yet
15206
15526
  if (isSingleEventTypeMode) {
15207
15527
  await loadEventTypes();
@@ -15425,6 +15745,45 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15425
15745
  setError(data.error || t("error.loadUpcomingEvents"));
15426
15746
  }
15427
15747
  };
15748
+ const loadSpecials = async () => {
15749
+ setIsLoadingSpecials(true);
15750
+ const specialsSettings = config.specialsSettings ?? {};
15751
+ const requestBody = {
15752
+ organizationId: config.organizationId,
15753
+ limit: specialsSettings.count ?? 20,
15754
+ };
15755
+ if (config.categoryId) {
15756
+ requestBody.categoryId = config.categoryId;
15757
+ }
15758
+ else if (config.eventTypeIds) {
15759
+ requestBody.eventTypeIds = config.eventTypeIds;
15760
+ }
15761
+ else if (config.eventTypeId) {
15762
+ requestBody.eventTypeId = config.eventTypeId;
15763
+ }
15764
+ try {
15765
+ const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/specials"), {
15766
+ method: "POST",
15767
+ headers: createApiHeaders(config, locale),
15768
+ body: JSON.stringify(requestBody),
15769
+ });
15770
+ const data = await response.json();
15771
+ if (response.ok) {
15772
+ const wl = extractWidgetLanguagePayload(data);
15773
+ if (wl) {
15774
+ onWidgetLanguage?.(wl);
15775
+ onTimezone?.(wl.timezone);
15776
+ }
15777
+ setSpecials(data.specials || []);
15778
+ }
15779
+ else {
15780
+ setError(data.error || t("error.loadUpcomingEvents"));
15781
+ }
15782
+ }
15783
+ finally {
15784
+ setIsLoadingSpecials(false);
15785
+ }
15786
+ };
15428
15787
  const loadEventInstances = async (eventTypeId) => {
15429
15788
  const response = await fetch(getApiUrl(config.apiBaseUrl, "/booking/event-instances"), {
15430
15789
  method: "POST",
@@ -15609,6 +15968,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15609
15968
  // Event instance selection handlers
15610
15969
  const handleEventInstanceSelect = async (eventInstance) => {
15611
15970
  setSelectedEventInstance(eventInstance);
15971
+ bookingReturnStep.current = "eventInstances";
15612
15972
  // Set default participant count for upsell calculations
15613
15973
  const defaultParticipantCount = 1;
15614
15974
  setTempParticipantCount(defaultParticipantCount);
@@ -15621,7 +15981,14 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15621
15981
  if (availableUpsells.length > 0) {
15622
15982
  // Show upsells step
15623
15983
  setUpsells(availableUpsells);
15624
- setSelectedUpsells([]);
15984
+ // Pre-select default-checked upsells
15985
+ const defaultSelections = availableUpsells
15986
+ .filter((upsell) => upsell.defaultChecked && upsell.available)
15987
+ .map((upsell) => ({
15988
+ upsellPackageId: upsell.id,
15989
+ quantity: defaultParticipantCount,
15990
+ }));
15991
+ setSelectedUpsells(defaultSelections);
15625
15992
  setCurrentStep("upsells");
15626
15993
  setIsLoadingUpsells(false);
15627
15994
  return; // Don't proceed to booking yet
@@ -15652,7 +16019,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15652
16019
  setEventInstances([]);
15653
16020
  };
15654
16021
  const handleBackToEventInstances = () => {
15655
- setCurrentStep("eventInstances");
16022
+ setCurrentStep(bookingReturnStep.current);
15656
16023
  setSelectedEventInstance(null);
15657
16024
  setEventDetails(null);
15658
16025
  };
@@ -15686,8 +16053,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15686
16053
  }
15687
16054
  };
15688
16055
  const handleUpsellsBack = () => {
15689
- // Go back to event instance selection
15690
- setCurrentStep("eventInstances");
16056
+ setCurrentStep(bookingReturnStep.current);
15691
16057
  setSelectedUpsells([]);
15692
16058
  setUpsells([]);
15693
16059
  };
@@ -15722,10 +16088,36 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15722
16088
  setError(errorMessage);
15723
16089
  config.onError?.(errorMessage);
15724
16090
  };
15725
- const handleUpcomingEventSelect = async (eventInstanceId) => {
16091
+ const handleUpcomingEventSelect = async (eventInstanceId, eventTypeId) => {
16092
+ // Resolve the event type — may come from card preview (eventTypeId provided) or
16093
+ // from the next-events list where selectedEventType is already set
16094
+ const resolvedEventType = eventTypeId != null
16095
+ ? (eventTypes.find((et) => et.id === eventTypeId) ?? selectedEventType)
16096
+ : selectedEventType;
16097
+ if (resolvedEventType && resolvedEventType !== selectedEventType) {
16098
+ setSelectedEventType(resolvedEventType);
16099
+ }
16100
+ // Check if this is coming from a card preview (eventTypeId was provided)
16101
+ // In that case, we need to load event instances so back navigation works properly
16102
+ const isFromCardPreview = eventTypeId != null;
16103
+ if (isFromCardPreview && resolvedEventType) {
16104
+ // Load event instances in background so back navigation shows instances
16105
+ setShouldRenderInstanceSelection(true);
16106
+ void loadEventInstances(resolvedEventType.id);
16107
+ // Record that we should return to instance selection (not event types)
16108
+ bookingReturnStep.current = "eventInstances";
16109
+ }
16110
+ else {
16111
+ // Record where to return when the booking form is closed
16112
+ bookingReturnStep.current = currentStep === "eventInstances" ? "eventInstances" : "eventTypes";
16113
+ }
16114
+ // First try to find the event in upcomingEvents (for next-events view mode)
15726
16115
  const upcomingEvent = upcomingEvents.find((event) => event.id === eventInstanceId);
15727
- if (upcomingEvent) {
15728
- const eventInstance = {
16116
+ // If not found in upcomingEvents, try to find in card preview items
16117
+ const cardPreviewItem = !upcomingEvent && resolvedEventType?.cardPreview?.find((item) => item.id === eventInstanceId);
16118
+ // Build the event instance from either source
16119
+ const eventInstance = upcomingEvent
16120
+ ? {
15729
16121
  id: upcomingEvent.id,
15730
16122
  name: upcomingEvent.name,
15731
16123
  startTime: upcomingEvent.startTime,
@@ -15739,13 +16131,63 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15739
16131
  bookingOpen: upcomingEvent.bookingOpen,
15740
16132
  ...(upcomingEvent.deposit !== undefined && { deposit: upcomingEvent.deposit }),
15741
16133
  ...(upcomingEvent.notes !== undefined && { notes: upcomingEvent.notes }),
15742
- };
16134
+ }
16135
+ : cardPreviewItem
16136
+ ? {
16137
+ id: cardPreviewItem.id,
16138
+ name: cardPreviewItem.name,
16139
+ startTime: cardPreviewItem.startTime,
16140
+ endTime: cardPreviewItem.startTime,
16141
+ price: cardPreviewItem.price,
16142
+ maxParticipants: cardPreviewItem.availableSpots + 1,
16143
+ participantCount: 1,
16144
+ availableSpots: cardPreviewItem.availableSpots,
16145
+ durationDays: 1,
16146
+ durationPerDay: 1,
16147
+ bookingOpen: true,
16148
+ }
16149
+ : null;
16150
+ if (eventInstance) {
15743
16151
  setSelectedEventInstance(eventInstance);
15744
16152
  }
16153
+ setError(null);
16154
+ // Check for upsells before going to booking (same as handleEventInstanceSelect)
16155
+ const eventTypeForUpsells = resolvedEventType;
16156
+ if (eventTypeForUpsells) {
16157
+ const defaultParticipantCount = 1;
16158
+ setTempParticipantCount(defaultParticipantCount);
16159
+ setIsLoadingUpsells(true);
16160
+ setShouldRenderUpsells(true);
16161
+ try {
16162
+ const availableUpsells = await loadUpsells(eventTypeForUpsells.id, eventInstanceId, defaultParticipantCount);
16163
+ if (availableUpsells.length > 0) {
16164
+ setUpsells(availableUpsells);
16165
+ // Pre-select default-checked upsells
16166
+ const defaultSelections = availableUpsells
16167
+ .filter((upsell) => upsell.defaultChecked && upsell.available)
16168
+ .map((upsell) => ({
16169
+ upsellPackageId: upsell.id,
16170
+ quantity: defaultParticipantCount,
16171
+ }));
16172
+ setSelectedUpsells(defaultSelections);
16173
+ setCurrentStep("upsells");
16174
+ setIsLoadingUpsells(false);
16175
+ // Load event details in background for when user continues past upsells
16176
+ void loadEventDetails(eventInstanceId);
16177
+ return;
16178
+ }
16179
+ }
16180
+ catch (err) {
16181
+ console.error("Error loading upsells:", err);
16182
+ }
16183
+ finally {
16184
+ setIsLoadingUpsells(false);
16185
+ }
16186
+ }
16187
+ // No upsells — go directly to booking
15745
16188
  setCurrentStep("booking");
15746
16189
  setShouldRenderBookingForm(true);
15747
16190
  setIsLoadingEventDetails(true);
15748
- setError(null);
15749
16191
  try {
15750
16192
  await loadEventDetails(eventInstanceId);
15751
16193
  }
@@ -15902,6 +16344,31 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15902
16344
  window.history.replaceState({}, "", url.toString());
15903
16345
  }, config: config, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
15904
16346
  }
16347
+ if (viewMode === "specials" && showingPreview) {
16348
+ return (jsxs(StyleProvider, { config: config, children: [jsxs("div", { ref: setWidgetContainerRef, children: [jsx(SpecialsView, { specials: specials, onEventSelect: handleUpcomingEventSelect, isLoading: isLoadingSpecials, showSavingsAmount: config.specialsSettings?.showSavingsAmount ?? true, showSavingsPercent: config.specialsSettings?.showSavingsPercent ?? false, emptyStateText: config.specialsSettings?.emptyStateText }), shouldRenderBookingForm && eventDetails && (jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => {
16349
+ setCurrentStep("eventTypes");
16350
+ setShowingPreview(true);
16351
+ setEventDetails(null);
16352
+ }, onBackToEventTypes: () => {
16353
+ setCurrentStep("eventTypes");
16354
+ setShowingPreview(true);
16355
+ setEventDetails(null);
16356
+ }, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => {
16357
+ setCurrentStep("eventTypes");
16358
+ setShowingPreview(true);
16359
+ setEventDetails(null);
16360
+ }, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
16361
+ setIsSuccess(false);
16362
+ setCurrentStep("eventTypes");
16363
+ setShowingPreview(true);
16364
+ setSuccessPaymentId(null);
16365
+ setShouldRenderInstanceSelection(false);
16366
+ setShouldRenderUpsells(false);
16367
+ setShouldRenderBookingForm(false);
16368
+ setSelectedUpsells([]);
16369
+ setUpsells([]);
16370
+ }, config: config, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
16371
+ }
15905
16372
  if (viewMode === "next-events" && !showingPreview && currentStep === "eventInstances") {
15906
16373
  return (jsxs(StyleProvider, { config: config, children: [jsxs("div", { ref: setWidgetContainerRef, children: [shouldRenderInstanceSelection && (jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => {
15907
16374
  setShowingPreview(true);
@@ -15972,7 +16439,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
15972
16439
  }, config: config, onError: setError, paymentIntentId: successPaymentId })] }), showPromoDialog && config.promo && (jsx(PromoDialog, { config: config.promo, onClose: handlePromoDialogClose, onCtaClick: handlePromoCtaClick }))] }));
15973
16440
  }
15974
16441
  // Cards mode (default) - show event type selection with optional voucher card
15975
- const cardsView = (jsxs(Fragment, { children: [hasEventSelection && (jsx(EventTypeSelection, { eventTypes: eventTypes, onEventTypeSelect: handleEventTypeSelect, isLoading: isLoading, skeletonCount: getSkeletonCount(), showVoucherAttachment: Boolean(voucherConfig?.enabled && voucherCardIntegrationEnabled && !isStandaloneVoucherMode), onVoucherClick: handleVoucherAttachmentClick })), isStandaloneVoucherMode && (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 && (jsx("div", { style: { padding: "24px", textAlign: "center" }, children: jsx("div", { style: {
16442
+ const cardsView = (jsxs(Fragment, { children: [hasEventSelection && (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 && (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 && (jsx("div", { style: { padding: "24px", textAlign: "center" }, children: jsx("div", { style: {
15976
16443
  display: "inline-block",
15977
16444
  width: "32px",
15978
16445
  height: "32px",
@@ -16077,7 +16544,7 @@ function styleInject(css, ref) {
16077
16544
  }
16078
16545
  }
16079
16546
 
16080
- 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}}";
16547
+ 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}}";
16081
16548
  styleInject(css_248z);
16082
16549
 
16083
16550
  // Export init function for vanilla JS usage