@bigz-app/booking-widget 1.1.4 → 1.1.6

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
@@ -354,6 +354,7 @@ const de$1 = {
354
354
  "success.age": "{{age}} Jahre",
355
355
  "success.paymentSummary": "Zahlungsübersicht",
356
356
  "success.total": "Gesamtbetrag",
357
+ "success.discount": "Rabatt",
357
358
  "success.product": "Produkt",
358
359
  "success.contactInfo": "Kontaktdaten",
359
360
  "success.name": "Name:",
@@ -562,6 +563,7 @@ const en = {
562
563
  "success.age": "{{age}} years",
563
564
  "success.paymentSummary": "Payment Summary",
564
565
  "success.total": "Total",
566
+ "success.discount": "Discount",
565
567
  "success.product": "Product",
566
568
  "success.contactInfo": "Contact Information",
567
569
  "success.name": "Name:",
@@ -770,6 +772,7 @@ const es = {
770
772
  "success.age": "{{age}} años",
771
773
  "success.paymentSummary": "Resumen del pago",
772
774
  "success.total": "Total",
775
+ "success.discount": "Descuento",
773
776
  "success.product": "Producto",
774
777
  "success.contactInfo": "Datos de contacto",
775
778
  "success.name": "Nombre:",
@@ -978,6 +981,7 @@ const pt = {
978
981
  "success.age": "{{age}} anos",
979
982
  "success.paymentSummary": "Resumo do pagamento",
980
983
  "success.total": "Total",
984
+ "success.discount": "Desconto",
981
985
  "success.product": "Produto",
982
986
  "success.contactInfo": "Dados de contacto",
983
987
  "success.name": "Nome:",
@@ -1186,6 +1190,7 @@ const sv = {
1186
1190
  "success.age": "{{age}} år",
1187
1191
  "success.paymentSummary": "Betalningssammanfattning",
1188
1192
  "success.total": "Totalt",
1193
+ "success.discount": "Rabatt",
1189
1194
  "success.product": "Produkt",
1190
1195
  "success.contactInfo": "Kontaktuppgifter",
1191
1196
  "success.name": "Namn:",
@@ -1312,7 +1317,7 @@ function persistLocale(locale) {
1312
1317
  const I18nContext = React.createContext(null);
1313
1318
  function I18nProvider({ configLocale, children }) {
1314
1319
  // Priority: configLocale (site owner) > persisted user choice > browser language > "de"
1315
- // If configLocale is set, the site owner has locked the language don't restore user choice.
1320
+ // If configLocale is set, the site owner has locked the language - don't restore user choice.
1316
1321
  const [overrideLocale, setOverrideLocale] = React.useState(() => {
1317
1322
  if (configLocale)
1318
1323
  return null;
@@ -11021,6 +11026,13 @@ function mergeStyles(...styles) {
11021
11026
  return Object.assign({}, ...styles.filter(Boolean));
11022
11027
  }
11023
11028
 
11029
+ function getEffectivePrice(upsell, round) {
11030
+ const dp = upsell.discountPercent ?? 0;
11031
+ if (dp <= 0)
11032
+ return upsell.price;
11033
+ const raw = Math.round(upsell.price * (100 - dp) / 100);
11034
+ return round ? Math.floor(raw / 100) * 100 : raw;
11035
+ }
11024
11036
  // Local style aliases from shared styles
11025
11037
  const cardStyles = cardStyles$1.base;
11026
11038
  const sectionHeaderStyles = sectionStyles.header;
@@ -11031,6 +11043,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11031
11043
  const t$1 = useTranslations();
11032
11044
  const { locale } = useLocale();
11033
11045
  const timezone = useTimezone();
11046
+ const roundEnabled = systemConfig?.roundPricesEnabled !== false;
11034
11047
  const [appliedVouchers, setAppliedVouchers] = React.useState([]);
11035
11048
  const paymentSectionRef = React.useRef(null);
11036
11049
  // Payment option: "deposit" or "full" - only relevant when deposit is available
@@ -11101,7 +11114,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11101
11114
  participantUpsellIds.forEach(upsellId => {
11102
11115
  const upsell = upsells.find(u => u.id === upsellId);
11103
11116
  if (upsell) {
11104
- total += upsell.price;
11117
+ total += getEffectivePrice(upsell, roundEnabled);
11105
11118
  }
11106
11119
  });
11107
11120
  }
@@ -11377,7 +11390,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11377
11390
  padding: 0,
11378
11391
  }, children: "\u00D7" })] }))] }), upsells.length > 0 && (jsxRuntime.jsx("div", { style: participantUpsellStyles.container, children: upsells.map((upsell) => {
11379
11392
  const isSelected = (participantUpsells[index] || []).includes(upsell.id);
11380
- return (jsxRuntime.jsxs("label", { htmlFor: `upsell-${index}-${upsell.id}`, style: isSelected ? participantUpsellStyles.labelSelected : participantUpsellStyles.label, children: [jsxRuntime.jsx("input", { id: `upsell-${index}-${upsell.id}`, type: "checkbox", style: participantUpsellStyles.checkbox, checked: isSelected, onChange: () => toggleParticipantUpsell(index, upsell.id) }), jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: upsell.name }), jsxRuntime.jsxs("span", { style: { fontSize: "12px", opacity: 0.8 }, children: ["(+", formatCurrency(upsell.price), ")"] })] }, upsell.id));
11393
+ return (jsxRuntime.jsxs("label", { htmlFor: `upsell-${index}-${upsell.id}`, style: isSelected ? participantUpsellStyles.labelSelected : participantUpsellStyles.label, children: [jsxRuntime.jsx("input", { id: `upsell-${index}-${upsell.id}`, type: "checkbox", style: participantUpsellStyles.checkbox, checked: isSelected, onChange: () => toggleParticipantUpsell(index, upsell.id) }), jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: upsell.name }), jsxRuntime.jsxs("span", { style: { fontSize: "12px", opacity: 0.8 }, children: ["(+", formatCurrency(getEffectivePrice(upsell, roundEnabled)), ")"] })] }, upsell.id));
11381
11394
  }) }))] }, index))), watchedParticipants.length < eventDetails.availableSpots ? (jsxRuntime.jsx("div", { style: {
11382
11395
  display: "flex",
11383
11396
  flexDirection: "column",
@@ -11409,7 +11422,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11409
11422
  const countWithUpsell = watchedParticipants.filter((p, idx) => p.name.trim() && (participantUpsells[idx] || []).includes(upsell.id)).length;
11410
11423
  if (countWithUpsell === 0)
11411
11424
  return null;
11412
- const upsellLineTotal = upsell.price * countWithUpsell;
11425
+ const upsellLineTotal = getEffectivePrice(upsell, roundEnabled) * countWithUpsell;
11413
11426
  return (jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", fontSize: "13px" }, children: [jsxRuntime.jsxs("span", { style: { color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: ["+ ", upsell.name, " (", countWithUpsell, "\u00D7)"] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-highlight-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(upsellLineTotal) })] }, upsell.id));
11414
11427
  })] })), appliedVouchers.length > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxRuntime.jsx("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)" }, children: t$1("summary.subtotal") }), jsxRuntime.jsx("span", { style: {
11415
11428
  fontFamily: "var(--bw-font-family)",
@@ -11534,7 +11547,7 @@ function BookingForm({ config, eventDetails, stripePromise, onSuccess, onError,
11534
11547
  : t$1("payment.fillRequired");
11535
11548
  return (jsxRuntime.jsx("div", { style: {
11536
11549
  ...cardStyles,
11537
- borderColor: "var(--bw-warning-color)",
11550
+ border: "1px solid var(--bw-warning-color)",
11538
11551
  color: "var(--bw-warning-color)",
11539
11552
  fontFamily: "var(--bw-font-family)",
11540
11553
  textAlign: "center",
@@ -11703,6 +11716,7 @@ const BookingSuccessModal = ({ isOpen, onClose, config, onError, paymentIntentId
11703
11716
  payments: data.payments,
11704
11717
  orderItems: data.orderItems,
11705
11718
  purchases: data.purchases || [],
11719
+ discount: data.discount || null,
11706
11720
  stripePaymentIntent: data.stripePaymentIntent,
11707
11721
  });
11708
11722
  setEventDetails({
@@ -11952,7 +11966,7 @@ const BookingSuccessModal = ({ isOpen, onClose, config, onError, paymentIntentId
11952
11966
  color: "var(--bw-text-color)",
11953
11967
  margin: "0",
11954
11968
  fontFamily: "var(--bw-font-family)",
11955
- }, children: t("success.paymentSummary") }) }), jsxRuntime.jsx("div", { className: "print-only", children: jsxRuntime.jsx("div", { className: "print-section-title", children: t("success.paymentSummary") }) }), jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [jsxRuntime.jsxs("div", { className: "print-hidden", style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-small)" }, children: [jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxRuntime.jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [eventDetails.name, " (", booking.participantCount, "x ", formatCurrency(eventDetails.price), ")"] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(eventDetails.price * booking.participantCount) })] }), bookingData.purchases && bookingData.purchases.length > 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: bookingData.purchases.map((purchase) => (jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxRuntime.jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [purchase.product?.name || t("success.product"), " (", purchase.quantity, "x ", formatCurrency(purchase.unitPrice), ")"] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(purchase.totalPrice) })] }, purchase.id))) })), jsxRuntime.jsxs("div", { style: {
11969
+ }, children: t("success.paymentSummary") }) }), jsxRuntime.jsx("div", { className: "print-only", children: jsxRuntime.jsx("div", { className: "print-section-title", children: t("success.paymentSummary") }) }), jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [jsxRuntime.jsxs("div", { className: "print-hidden", style: { display: "flex", flexDirection: "column", gap: "var(--bw-spacing-small)" }, children: [jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxRuntime.jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [eventDetails.name, " (", booking.participantCount, "x ", formatCurrency(eventDetails.price), ")"] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(eventDetails.price * booking.participantCount) })] }), bookingData.discount && bookingData.discount.amount > 0 && (jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxRuntime.jsxs("span", { style: { color: "var(--bw-success-color, #10B981)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [t("success.discount"), " (", bookingData.discount.code, ")"] }), jsxRuntime.jsxs("span", { style: { color: "var(--bw-success-color, #10B981)", fontFamily: "var(--bw-font-family)" }, children: ["-", formatCurrency(bookingData.discount.amount)] })] })), bookingData.purchases && bookingData.purchases.length > 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: bookingData.purchases.map((purchase) => (jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [jsxRuntime.jsxs("span", { style: { color: "var(--bw-text-muted)", fontFamily: "var(--bw-font-family)", fontSize: "var(--bw-font-size-small)" }, children: [purchase.product?.name || t("success.product"), " (", purchase.quantity, "x ", formatCurrency(purchase.unitPrice), ")"] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-text-color)", fontFamily: "var(--bw-font-family)" }, children: formatCurrency(purchase.totalPrice) })] }, purchase.id))) })), jsxRuntime.jsxs("div", { style: {
11956
11970
  display: "flex",
11957
11971
  justifyContent: "space-between",
11958
11972
  alignItems: "center",
@@ -13284,52 +13298,24 @@ const getThemeConfig = (theme = "generic") => {
13284
13298
  backgroundImage: "https://images.unsplash.com/photo-1502680390469-be75c86b636f?w=600&q=80",
13285
13299
  primaryColor: "#0c4a6e",
13286
13300
  secondaryColor: "#0891b2",
13287
- icon: "🏄‍♂️",
13288
- decorations: ["🎄", "⭐"],
13289
- animation: {
13290
- floatDuration: 3,
13291
- sparkleEnabled: true,
13292
- snowfallEnabled: true,
13293
- },
13294
13301
  };
13295
13302
  case "summer":
13296
13303
  return {
13297
13304
  backgroundImage: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=600&q=80",
13298
13305
  primaryColor: "#059669",
13299
13306
  secondaryColor: "#10b981",
13300
- icon: "☀️",
13301
- decorations: ["🌴", "🏖️"],
13302
- animation: {
13303
- floatDuration: 2.5,
13304
- sparkleEnabled: true,
13305
- snowfallEnabled: false,
13306
- },
13307
13307
  };
13308
13308
  case "beach":
13309
13309
  return {
13310
13310
  backgroundImage: "https://images.unsplash.com/photo-1502680390469-be75c86b636f?w=600&q=80",
13311
13311
  primaryColor: "#0891b2",
13312
13312
  secondaryColor: "#06b6d4",
13313
- icon: "🏄‍♀️",
13314
- decorations: ["🌊", "🏄"],
13315
- animation: {
13316
- floatDuration: 3,
13317
- sparkleEnabled: false,
13318
- snowfallEnabled: false,
13319
- },
13320
13313
  };
13321
13314
  default:
13322
13315
  return {
13323
13316
  backgroundImage: undefined,
13324
13317
  primaryColor: "#0c4a6e",
13325
13318
  secondaryColor: "#0891b2",
13326
- icon: "🎁",
13327
- decorations: [],
13328
- animation: {
13329
- floatDuration: 3,
13330
- sparkleEnabled: false,
13331
- snowfallEnabled: false,
13332
- },
13333
13319
  };
13334
13320
  }
13335
13321
  };
@@ -13387,192 +13373,152 @@ function PromoDialog({ config, onClose, onCtaClick }) {
13387
13373
  position: "fixed",
13388
13374
  inset: 0,
13389
13375
  zIndex: 60,
13390
- backgroundColor: "rgba(0, 20, 40, 0.85)",
13391
- backdropFilter: "blur(4px)",
13376
+ backgroundColor: "rgba(0, 20, 40, 0.8)",
13377
+ backdropFilter: "blur(6px)",
13392
13378
  transition: "opacity 0.3s ease-out",
13393
13379
  opacity: isVisible ? 1 : 0,
13394
13380
  } }), jsxRuntime.jsx("div", { style: {
13395
13381
  position: "fixed",
13396
13382
  zIndex: 61,
13397
- width: "92%",
13398
- maxWidth: "440px",
13383
+ width: "90%",
13384
+ maxWidth: "400px",
13399
13385
  transition: "all 0.3s",
13400
13386
  top: "50%",
13401
13387
  left: "50%",
13402
- transform: `translate(-50%, -50%) scale(${isVisible ? 1 : 0.9})`,
13388
+ transform: `translate(-50%, -50%) scale(${isVisible ? 1 : 0.95})`,
13403
13389
  opacity: isVisible ? 1 : 0,
13404
- transitionTimingFunction: "cubic-bezier(0.34, 1.56, 0.64, 1)",
13390
+ transitionTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)",
13405
13391
  }, children: jsxRuntime.jsxs("div", { style: {
13406
13392
  position: "relative",
13407
13393
  overflow: "hidden",
13408
- borderRadius: "28px",
13409
- boxShadow: "0 25px 60px -12px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.2)",
13394
+ borderRadius: "20px",
13395
+ boxShadow: "0 25px 50px -12px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.08)",
13410
13396
  background: `linear-gradient(165deg, ${themeConfig.primaryColor} 0%, ${themeConfig.primaryColor} 40%, ${themeConfig.secondaryColor} 100%)`,
13411
- }, children: [themeConfig.animation?.snowfallEnabled &&
13412
- Array.from({ length: 15 }).map((_, i) => (jsxRuntime.jsx("div", { style: {
13413
- position: "absolute",
13414
- pointerEvents: "none",
13415
- zIndex: 1,
13416
- color: "white",
13417
- opacity: 0,
13418
- left: `${5 + Math.random() * 90}%`,
13419
- top: "-10px",
13420
- fontSize: `${10 + Math.random() * 14}px`,
13421
- animation: `promo-snow ${4 + Math.random() * 3}s linear infinite`,
13422
- animationDelay: `${Math.random() * 4}s`,
13423
- }, children: "\u2744" }, i))), jsxRuntime.jsxs("div", { style: {
13397
+ }, children: [themeConfig.backgroundImage && (jsxRuntime.jsxs("div", { style: {
13424
13398
  position: "relative",
13425
- display: "flex",
13426
- alignItems: "center",
13427
- justifyContent: "center",
13399
+ height: "120px",
13428
13400
  overflow: "hidden",
13429
- height: "180px",
13430
- background: `linear-gradient(180deg, rgba(0,0,0,0) 0%, ${themeConfig.primaryColor}cc 100%)`,
13431
- }, children: [themeConfig.backgroundImage && (jsxRuntime.jsx("img", { src: themeConfig.backgroundImage, alt: "Background", style: {
13401
+ }, children: [jsxRuntime.jsx("img", { src: themeConfig.backgroundImage, alt: "", style: {
13432
13402
  position: "absolute",
13433
13403
  inset: 0,
13434
13404
  width: "100%",
13435
13405
  height: "100%",
13436
13406
  objectFit: "cover",
13437
- opacity: 0.6,
13438
- } })), jsxRuntime.jsx("div", { style: {
13407
+ opacity: 0.5,
13408
+ } }), jsxRuntime.jsx("div", { style: {
13439
13409
  position: "absolute",
13440
13410
  inset: 0,
13441
- background: `linear-gradient(180deg, ${themeConfig.primaryColor}4d 0%, ${themeConfig.primaryColor}e6 100%)`,
13442
- } }), jsxRuntime.jsx("div", { style: {
13443
- position: "relative",
13444
- zIndex: 2,
13445
- fontSize: "64px",
13446
- filter: "drop-shadow(0 8px 16px rgba(0,0,0,0.4))",
13447
- animation: `promo-float ${themeConfig.animation?.floatDuration || 3}s ease-in-out infinite`,
13448
- }, children: themeConfig.icon }), themeConfig.decorations &&
13449
- themeConfig.decorations.map((decoration, i) => (jsxRuntime.jsx("div", { style: {
13450
- position: "absolute",
13451
- top: i === 0 ? "16px" : "20px",
13452
- left: i === 0 ? "20px" : "auto",
13453
- right: i === 1 ? "20px" : "auto",
13454
- fontSize: i === 0 ? "28px" : "24px",
13455
- animation: themeConfig.animation?.sparkleEnabled
13456
- ? `promo-sparkle 2s ease-in-out infinite ${i * 0.5}s`
13457
- : undefined,
13458
- }, children: decoration }, i)))] }), jsxRuntime.jsx("button", { onClick: handleClose, style: {
13411
+ background: `linear-gradient(180deg, ${themeConfig.primaryColor}33 0%, ${themeConfig.primaryColor}ee 100%)`,
13412
+ } })] })), jsxRuntime.jsx("button", { onClick: handleClose, style: {
13459
13413
  position: "absolute",
13460
- top: "16px",
13461
- right: "16px",
13414
+ top: "12px",
13415
+ right: "12px",
13462
13416
  display: "flex",
13463
13417
  alignItems: "center",
13464
13418
  justifyContent: "center",
13465
13419
  cursor: "pointer",
13466
13420
  zIndex: 10,
13467
- width: "36px",
13468
- height: "36px",
13421
+ width: "32px",
13422
+ height: "32px",
13469
13423
  borderRadius: "50%",
13470
13424
  border: "none",
13471
- backgroundColor: "rgba(0, 0, 0, 0.3)",
13425
+ backgroundColor: "rgba(0, 0, 0, 0.25)",
13472
13426
  backdropFilter: "blur(4px)",
13473
- color: "white",
13474
- fontSize: "22px",
13427
+ color: "rgba(255,255,255,0.8)",
13428
+ fontSize: "18px",
13475
13429
  lineHeight: 1,
13476
- transition: "all 0.15s ease",
13430
+ transition: "background-color 0.15s ease",
13477
13431
  }, children: "\u00D7" }), jsxRuntime.jsxs("div", { style: {
13478
13432
  position: "relative",
13479
13433
  textAlign: "center",
13480
13434
  zIndex: 2,
13481
- padding: "28px 28px 32px 28px",
13435
+ padding: "20px 24px 24px",
13482
13436
  }, children: [jsxRuntime.jsx("h2", { style: {
13483
- fontWeight: 800,
13484
- fontSize: "26px",
13437
+ fontWeight: 700,
13438
+ fontSize: "20px",
13485
13439
  color: "white",
13486
- marginBottom: "6px",
13487
- letterSpacing: "-0.025em",
13488
- filter: "drop-shadow(0 2px 8px rgba(0,0,0,0.3))",
13440
+ letterSpacing: "-0.02em",
13441
+ lineHeight: 1.25,
13489
13442
  margin: "0 0 6px 0",
13490
13443
  }, children: config.title }), jsxRuntime.jsxs("p", { style: {
13491
- fontSize: "17px",
13492
- color: "rgba(255, 255, 255, 0.9)",
13493
- marginBottom: "20px",
13444
+ fontSize: "14px",
13445
+ color: "rgba(255, 255, 255, 0.85)",
13494
13446
  lineHeight: 1.5,
13495
- margin: "0 0 20px 0",
13496
- }, children: [config.subtitle, config.discountAmount && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("br", {}), jsxRuntime.jsxs("strong", { style: { color: themeConfig.secondaryColor }, children: [config.discountAmount, " ", t("promo.discount")] })] }))] }), config.discountCode && (jsxRuntime.jsxs("div", { style: {
13497
- marginBottom: "20px",
13498
- backgroundColor: "white",
13499
- borderRadius: "16px",
13500
- padding: "18px 20px",
13501
- boxShadow: "0 8px 24px rgba(0,0,0,0.15), inset 0 -2px 0 rgba(0,0,0,0.05)",
13447
+ margin: "0 0 16px 0",
13448
+ }, children: [config.subtitle, config.discountAmount && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [" - ", jsxRuntime.jsxs("strong", { style: { color: "white" }, children: [config.discountAmount, " ", t("promo.discount")] })] }))] }), config.discountCode && (jsxRuntime.jsxs("div", { style: {
13449
+ marginBottom: "16px",
13450
+ backgroundColor: "rgba(255,255,255,0.12)",
13451
+ borderRadius: "12px",
13452
+ padding: "12px 16px",
13453
+ border: "1px solid rgba(255,255,255,0.1)",
13502
13454
  }, children: [jsxRuntime.jsx("p", { style: {
13503
13455
  textTransform: "uppercase",
13504
- fontWeight: 600,
13505
- fontSize: "11px",
13456
+ fontWeight: 500,
13457
+ fontSize: "10px",
13506
13458
  letterSpacing: "1.5px",
13507
- color: "#64748b",
13508
- marginBottom: "10px",
13509
- margin: "0 0 10px 0",
13459
+ color: "rgba(255,255,255,0.6)",
13460
+ margin: "0 0 8px 0",
13510
13461
  }, children: t("promo.giftCode") }), jsxRuntime.jsxs("div", { style: {
13511
13462
  display: "flex",
13512
13463
  alignItems: "center",
13513
13464
  justifyContent: "center",
13514
- gap: "12px",
13515
- }, children: [jsxRuntime.jsx("div", { style: {
13516
- padding: "10px 20px",
13517
- borderRadius: "10px",
13518
- background: `linear-gradient(135deg, ${themeConfig.secondaryColor} 0%, ${themeConfig.primaryColor} 100%)`,
13519
- boxShadow: `0 4px 12px ${themeConfig.secondaryColor}4d`,
13520
- }, children: jsxRuntime.jsx("span", { style: {
13521
- fontWeight: 900,
13522
- fontSize: "28px",
13523
- color: "white",
13524
- letterSpacing: "6px",
13525
- filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))",
13526
- }, children: discountCode }) }), jsxRuntime.jsx("button", { onClick: handleCopyCode, style: {
13465
+ gap: "10px",
13466
+ }, children: [jsxRuntime.jsx("span", { style: {
13467
+ fontWeight: 800,
13468
+ fontSize: "22px",
13469
+ color: "white",
13470
+ letterSpacing: "4px",
13471
+ fontFamily: "monospace, monospace",
13472
+ }, children: discountCode }), jsxRuntime.jsx("button", { onClick: handleCopyCode, style: {
13527
13473
  display: "flex",
13528
13474
  alignItems: "center",
13529
13475
  cursor: "pointer",
13530
13476
  whiteSpace: "nowrap",
13531
- padding: "12px 16px",
13532
- borderRadius: "10px",
13533
- border: "2px solid",
13534
- borderColor: copied ? "#22c55e" : "#e2e8f0",
13535
- backgroundColor: copied ? "#dcfce7" : "#f8fafc",
13536
- color: copied ? "#15803d" : "#475569",
13537
- fontSize: "13px",
13477
+ padding: "6px 12px",
13478
+ borderRadius: "8px",
13479
+ border: "1px solid rgba(255,255,255,0.2)",
13480
+ backgroundColor: copied
13481
+ ? "rgba(34, 197, 94, 0.2)"
13482
+ : "rgba(255,255,255,0.1)",
13483
+ color: copied ? "#86efac" : "rgba(255,255,255,0.8)",
13484
+ fontSize: "12px",
13538
13485
  fontWeight: 600,
13539
13486
  transition: "all 0.15s ease",
13540
- gap: "6px",
13541
- }, children: copied ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: ["\u2713 ", t("promo.copied")] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }), t("promo.copy")] })) })] })] })), config.activities && config.activities.length > 0 && (jsxRuntime.jsx("div", { style: {
13487
+ gap: "4px",
13488
+ }, children: copied ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: ["\u2713 ", t("promo.copied")] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: [jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }), t("promo.copy")] })) })] })] })), config.activities && config.activities.length > 0 && (jsxRuntime.jsx("div", { style: {
13542
13489
  display: "flex",
13543
13490
  justifyContent: "center",
13544
- gap: "8px",
13545
- marginBottom: "20px",
13491
+ gap: "6px",
13492
+ marginBottom: "16px",
13546
13493
  flexWrap: "wrap",
13547
13494
  }, children: config.activities.map((activity) => (jsxRuntime.jsx("span", { style: {
13548
13495
  fontWeight: 500,
13549
- backgroundColor: "rgba(255, 255, 255, 0.15)",
13550
- backdropFilter: "blur(4px)",
13551
- padding: "6px 12px",
13552
- borderRadius: "20px",
13553
- fontSize: "13px",
13554
- color: "white",
13496
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
13497
+ padding: "4px 10px",
13498
+ borderRadius: "16px",
13499
+ fontSize: "12px",
13500
+ color: "rgba(255,255,255,0.85)",
13501
+ border: "1px solid rgba(255,255,255,0.08)",
13555
13502
  }, children: activity }, activity))) })), jsxRuntime.jsxs("button", { onClick: handleCtaClick, style: {
13556
13503
  width: "100%",
13557
13504
  display: "flex",
13558
13505
  alignItems: "center",
13559
13506
  justifyContent: "center",
13560
13507
  cursor: "pointer",
13561
- fontWeight: 700,
13562
- padding: "18px 24px",
13563
- borderRadius: "14px",
13508
+ fontWeight: 600,
13509
+ padding: "14px 20px",
13510
+ borderRadius: "12px",
13564
13511
  border: "none",
13565
- color: "white",
13566
- fontSize: "18px",
13512
+ color: themeConfig.primaryColor,
13513
+ fontSize: "15px",
13567
13514
  transition: "all 0.15s ease",
13568
- gap: "10px",
13569
- background: `linear-gradient(135deg, ${themeConfig.secondaryColor} 0%, ${themeConfig.primaryColor} 100%)`,
13570
- boxShadow: `0 8px 24px ${themeConfig.secondaryColor}66, inset 0 1px 0 rgba(255,255,255,0.2)`,
13571
- }, children: [config.ctaText, jsxRuntime.jsx("span", { children: "\u2192" })] }), config.validityText && (jsxRuntime.jsx("p", { style: {
13572
- marginTop: "16px",
13573
- fontSize: "12px",
13574
- color: "rgba(255, 255, 255, 0.6)",
13575
- margin: "16px 0 0 0",
13515
+ gap: "8px",
13516
+ background: "white",
13517
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
13518
+ }, children: [config.ctaText, jsxRuntime.jsx("span", { style: { fontSize: "14px" }, children: "\u2192" })] }), config.validityText && (jsxRuntime.jsx("p", { style: {
13519
+ fontSize: "11px",
13520
+ color: "rgba(255, 255, 255, 0.5)",
13521
+ margin: "12px 0 0 0",
13576
13522
  }, children: config.validityText }))] })] }) })] }));
13577
13523
  return ReactDOM.createPortal(dialogContent, portalContainer);
13578
13524
  }
@@ -13584,7 +13530,9 @@ const cardBaseStyles = {
13584
13530
  flexDirection: "column",
13585
13531
  padding: "16px",
13586
13532
  backgroundColor: "var(--bw-surface-color)",
13587
- border: "2px solid var(--bw-border-color)",
13533
+ borderWidth: "2px",
13534
+ borderStyle: "solid",
13535
+ borderColor: "var(--bw-border-color)",
13588
13536
  borderRadius: "var(--bw-border-radius)",
13589
13537
  cursor: "pointer",
13590
13538
  transition: "all 0.2s ease",
@@ -13609,7 +13557,9 @@ const checkboxContainerStyles = {
13609
13557
  const checkboxInnerStyles = {
13610
13558
  width: "24px",
13611
13559
  height: "24px",
13612
- border: "2px solid var(--bw-border-color)",
13560
+ borderWidth: "2px",
13561
+ borderStyle: "solid",
13562
+ borderColor: "var(--bw-border-color)",
13613
13563
  borderRadius: "6px",
13614
13564
  display: "flex",
13615
13565
  alignItems: "center",
@@ -13735,10 +13685,11 @@ function formatUnavailableReason(reason, t) {
13735
13685
  return t("upsells.reason.notEnoughSpots", { eventTypeName: reason.eventTypeName });
13736
13686
  }
13737
13687
  }
13738
- function UpsellCard({ upsell, isSelected, participantCount, onSelect, }) {
13688
+ function UpsellCard({ upsell, isSelected, participantCount, onSelect, roundPricesEnabled = true, }) {
13739
13689
  const t = useTranslations();
13740
13690
  const { locale } = useLocale();
13741
- const totalPrice = upsell.price * participantCount;
13691
+ const effectivePrice = getEffectiveUpsellPrice(upsell, roundPricesEnabled);
13692
+ const totalPrice = effectivePrice * participantCount;
13742
13693
  const isDisabled = !upsell.available;
13743
13694
  const getCardStyles = () => {
13744
13695
  if (isDisabled)
@@ -13756,12 +13707,19 @@ function UpsellCard({ upsell, isSelected, participantCount, onSelect, }) {
13756
13707
  weekday: "short",
13757
13708
  day: "numeric",
13758
13709
  month: "short",
13759
- })] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-text-muted)" }, children: t("upsells.spotsFree", { count: upsell.suggestedEventInstance.availableSpots }) })] }))] }), jsxRuntime.jsxs("div", { style: priceContainerStyles, children: [jsxRuntime.jsxs("span", { style: pricePerPersonStyles, children: [formatCurrency(upsell.price), "/", t("common.perPerson")] }), participantCount > 1 && (jsxRuntime.jsxs("span", { style: priceTotalStyles, children: ["= ", formatCurrency(totalPrice)] }))] }), isDisabled && (jsxRuntime.jsx("div", { style: unavailableOverlayStyles, children: jsxRuntime.jsx("span", { children: upsell.unavailableReason
13710
+ })] }), jsxRuntime.jsx("span", { style: { color: "var(--bw-text-muted)" }, children: t("upsells.spotsFree", { count: upsell.suggestedEventInstance.availableSpots }) })] }))] }), jsxRuntime.jsxs("div", { style: priceContainerStyles, children: [jsxRuntime.jsxs("span", { style: pricePerPersonStyles, children: [formatCurrency(effectivePrice), "/", t("common.perPerson")] }), participantCount > 1 && (jsxRuntime.jsxs("span", { style: priceTotalStyles, children: ["= ", formatCurrency(totalPrice)] }))] }), isDisabled && (jsxRuntime.jsx("div", { style: unavailableOverlayStyles, children: jsxRuntime.jsx("span", { children: upsell.unavailableReason
13760
13711
  ? formatUnavailableReason(upsell.unavailableReason, t)
13761
13712
  : t("upsells.notAvailable") }) }))] }));
13762
13713
  }
13763
13714
 
13764
- function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, isOpen, onClose, onSelect, onContinue, onBack, }) {
13715
+ function getEffectiveUpsellPrice(upsell, round = true) {
13716
+ const dp = upsell.discountPercent ?? 0;
13717
+ if (dp <= 0)
13718
+ return upsell.price;
13719
+ const raw = Math.round(upsell.price * (100 - dp) / 100);
13720
+ return round ? Math.floor(raw / 100) * 100 : raw;
13721
+ }
13722
+ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, isOpen, onClose, onSelect, onContinue, onBack, roundPricesEnabled = true, }) {
13765
13723
  const t = useTranslations();
13766
13724
  const selectUpsell = (upsellId) => {
13767
13725
  const exists = selectedUpsells.find((s) => s.upsellPackageId === upsellId);
@@ -13780,7 +13738,7 @@ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, is
13780
13738
  return selectedUpsells.reduce((total, selection) => {
13781
13739
  const upsell = upsells.find((u) => u.id === selection.upsellPackageId);
13782
13740
  if (upsell) {
13783
- return total + upsell.price * selection.quantity;
13741
+ return total + getEffectiveUpsellPrice(upsell, roundPricesEnabled) * selection.quantity;
13784
13742
  }
13785
13743
  return total;
13786
13744
  }, 0);
@@ -13788,7 +13746,7 @@ function UpsellsStep({ upsells, selectedUpsells, participantCount, isLoading, is
13788
13746
  const selectedTotal = calculateTotal();
13789
13747
  const selectedCount = selectedUpsells.length;
13790
13748
  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") })] }));
13791
- 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)] })] }))] }) }));
13749
+ 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), roundPricesEnabled: roundPricesEnabled }, 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)] })] }))] }) }));
13792
13750
  }
13793
13751
 
13794
13752
  // Main widget component
@@ -14048,6 +14006,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14048
14006
  connectedAccountId: data.connectedAccountId,
14049
14007
  mollieProfileId: data.mollieProfileId,
14050
14008
  mollieTestmode: data.mollieTestmode,
14009
+ roundPricesEnabled: data.roundPricesEnabled ?? true,
14051
14010
  });
14052
14011
  }
14053
14012
  if (data.stripePublishableKey) {
@@ -14106,6 +14065,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14106
14065
  connectedAccountId: data.connectedAccountId,
14107
14066
  mollieProfileId: data.mollieProfileId,
14108
14067
  mollieTestmode: data.mollieTestmode,
14068
+ roundPricesEnabled: data.roundPricesEnabled ?? true,
14109
14069
  });
14110
14070
  if (!stripePromise && data.stripePublishableKey) {
14111
14071
  const stripeOptions = {
@@ -14254,6 +14214,8 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14254
14214
  const handleBookingSuccess = (result) => {
14255
14215
  setIsSuccess(true);
14256
14216
  setSuccessPaymentIntentId(result.paymentIntent.id);
14217
+ setSidebarOpen(false);
14218
+ setShouldRenderBookingForm(false);
14257
14219
  config.onSuccess?.(result);
14258
14220
  };
14259
14221
  const handleBookingError = (errorMessage) => {
@@ -14510,7 +14472,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14510
14472
  setShouldRenderInstanceSelection(true);
14511
14473
  }
14512
14474
  }, children: config.buttonText ||
14513
- (isDirectInstanceMode ? t("button.bookNow") : t("button.selectDate")) }), shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen && currentStep === "eventInstances", onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), onBackToEventTypes: () => setSidebarOpen(false), selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14475
+ (isDirectInstanceMode ? t("button.bookNow") : t("button.selectDate")) }), shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: () => setSidebarOpen(false), isOpen: sidebarOpen && currentStep === "eventInstances", onClose: () => setSidebarOpen(false), isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack, roundPricesEnabled: systemConfig?.roundPricesEnabled !== false })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), onBackToEventTypes: () => setSidebarOpen(false), selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: () => setCurrentStep(isDirectInstanceMode ? "eventTypes" : "eventInstances"), systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14514
14476
  setIsSuccess(false);
14515
14477
  setCurrentStep("eventTypes");
14516
14478
  setSidebarOpen(false);
@@ -14557,7 +14519,7 @@ function UniversalBookingWidgetInner({ config: baseConfig, onWidgetLanguage, onT
14557
14519
  };
14558
14520
  };
14559
14521
  const backHandlers = getBackHandlers();
14560
- return (jsxRuntime.jsxs(StyleProvider, { config: config, children: [jsxRuntime.jsxs("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: backHandlers.onBackToEventInstances, onBackToEventTypes: backHandlers.onBackToEventTypes, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: backHandlers.onClose, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14522
+ return (jsxRuntime.jsxs(StyleProvider, { config: config, children: [jsxRuntime.jsxs("div", { ref: setWidgetContainerRef, children: [cardsView, shouldRenderInstanceSelection && (jsxRuntime.jsx(EventInstanceSelection, { eventInstances: eventInstances, selectedEventType: selectedEventType, onEventInstanceSelect: handleEventInstanceSelect, onBackToEventTypes: handleBackToEventTypes, isOpen: currentStep === "eventInstances", onClose: handleBackToEventTypes, isLoadingEventInstances: isLoadingEventInstances, isLoadingEventDetails: isLoadingEventDetails })), shouldRenderUpsells && (jsxRuntime.jsx(UpsellsStep, { upsells: upsells, selectedUpsells: selectedUpsells, participantCount: tempParticipantCount, isLoading: isLoadingUpsells, isOpen: currentStep === "upsells", onClose: () => setCurrentStep("eventInstances"), onSelect: handleUpsellsSelect, onContinue: handleUpsellsContinue, onBack: handleUpsellsBack, roundPricesEnabled: systemConfig?.roundPricesEnabled !== false })), shouldRenderBookingForm && eventDetails && (jsxRuntime.jsx(BookingForm, { config: config, eventDetails: eventDetails, stripePromise: stripePromise, onSuccess: handleBookingSuccess, onError: handleBookingError, onBackToEventInstances: backHandlers.onBackToEventInstances, onBackToEventTypes: backHandlers.onBackToEventTypes, selectedEventType: selectedEventType, selectedEventInstance: selectedEventInstance, isOpen: currentStep === "booking" && !!eventDetails, onClose: backHandlers.onClose, systemConfig: systemConfig, selectedUpsells: selectedUpsells, upsells: upsells })), jsxRuntime.jsx(BookingSuccessModal, { isOpen: isSuccess, onClose: () => {
14561
14523
  setIsSuccess(false);
14562
14524
  setCurrentStep("eventTypes");
14563
14525
  setSuccessPaymentIntentId(null);
@@ -14613,7 +14575,7 @@ function styleInject(css, ref) {
14613
14575
  }
14614
14576
  }
14615
14577
 
14616
- 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 promo-wave{0%,to{transform:translateX(0) translateY(0)}25%{transform:translateX(5px) translateY(-3px)}50%{transform:translateX(0) translateY(-5px)}75%{transform:translateX(-5px) translateY(-3px)}}@keyframes promo-float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}@keyframes promo-shimmer{0%{background-position:-200%}to{background-position:200%}}@keyframes promo-sparkle{0%,to{opacity:.3;transform:scale(1)}50%{opacity:1;transform:scale(1.2)}}@keyframes promo-snow{0%{opacity:0;transform:translateY(-10px) rotate(0deg)}10%{opacity:1}90%{opacity:1}to{opacity:0;transform:translateY(350px) rotate(1turn)}}@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}}";
14578
+ 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}}";
14617
14579
  styleInject(css_248z);
14618
14580
 
14619
14581
  // Export init function for vanilla JS usage