@uptrademedia/site-kit 1.0.24 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1948,13 +1948,86 @@ function formatDuration(minutes) {
1948
1948
  return `${hours}h ${mins}m`;
1949
1949
  }
1950
1950
  var DEFAULT_API_URL2 = "https://api.uptrademedia.com";
1951
+ var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1952
+ var MONTHS = [
1953
+ "January",
1954
+ "February",
1955
+ "March",
1956
+ "April",
1957
+ "May",
1958
+ "June",
1959
+ "July",
1960
+ "August",
1961
+ "September",
1962
+ "October",
1963
+ "November",
1964
+ "December"
1965
+ ];
1966
+ function isSameDay(a, b) {
1967
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
1968
+ }
1969
+ function isBeforeDay(a, b) {
1970
+ const ac = new Date(a.getFullYear(), a.getMonth(), a.getDate());
1971
+ const bc = new Date(b.getFullYear(), b.getMonth(), b.getDate());
1972
+ return ac < bc;
1973
+ }
1974
+ function calendarDays(year, month) {
1975
+ const first = new Date(year, month, 1);
1976
+ const last = new Date(year, month + 1, 0);
1977
+ const cells = [];
1978
+ for (let i = 0; i < first.getDay(); i++) cells.push(null);
1979
+ for (let d = 1; d <= last.getDate(); d++) cells.push(new Date(year, month, d));
1980
+ return cells;
1981
+ }
1982
+ function ChevronLeft() {
1983
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.5 15L7.5 10L12.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
1984
+ }
1985
+ function ChevronRight() {
1986
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.5 5L12.5 10L7.5 15", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
1987
+ }
1988
+ function ClockIcon() {
1989
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
1990
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.2" }),
1991
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 4.5V8L10 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
1992
+ ] });
1993
+ }
1994
+ function GlobeIcon() {
1995
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
1996
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.2" }),
1997
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1.5 8H14.5", stroke: "currentColor", strokeWidth: "1.2" }),
1998
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 1.5C9.66 3.34 10.61 5.62 10.61 8C10.61 10.38 9.66 12.66 8 14.5C6.34 12.66 5.39 10.38 5.39 8C5.39 5.62 6.34 3.34 8 1.5Z", stroke: "currentColor", strokeWidth: "1.2" })
1999
+ ] });
2000
+ }
2001
+ function CheckCircleIcon() {
2002
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "56", height: "56", viewBox: "0 0 56 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
2003
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "28", cy: "28", r: "28", fill: "var(--bw-primary)" }),
2004
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 28.5L24.5 35L38 21.5", stroke: "white", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" })
2005
+ ] });
2006
+ }
2007
+ function CalendarPlusIcon() {
2008
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
2009
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1.5", y: "2.5", width: "13", height: "12", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
2010
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1.5 6.5H14.5", stroke: "currentColor", strokeWidth: "1.2" }),
2011
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 1V4M11 1V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
2012
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 9V12M6.5 10.5H9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
2013
+ ] });
2014
+ }
2015
+ function ArrowLeftIcon() {
2016
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8L10 13", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
2017
+ }
2018
+ function SpinnerIcon() {
2019
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "bw-spinner", children: [
2020
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "50.265", strokeDashoffset: "25", opacity: "0.3" }),
2021
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "50.265", strokeDashoffset: "37.7" })
2022
+ ] });
2023
+ }
1951
2024
  function BookingWidget({
1952
2025
  orgSlug,
1953
2026
  apiUrl = DEFAULT_API_URL2,
1954
2027
  bookingTypeSlug,
1955
2028
  timezone: propTimezone,
1956
2029
  className = "",
1957
- daysToShow = 14,
2030
+ daysToShow = 60,
1958
2031
  onBookingComplete,
1959
2032
  onError,
1960
2033
  hideTypeSelector = false,
@@ -1962,73 +2035,83 @@ function BookingWidget({
1962
2035
  }) {
1963
2036
  const [step, setStep] = React3.useState(bookingTypeSlug ? "datetime" : "type");
1964
2037
  const [loading, setLoading] = React3.useState(false);
2038
+ const [slotsLoading, setSlotsLoading] = React3.useState(false);
1965
2039
  const [error, setError] = React3.useState(null);
1966
2040
  const [bookingTypes, setBookingTypes] = React3.useState([]);
1967
2041
  const [selectedType, setSelectedType] = React3.useState(null);
2042
+ const [viewMonth, setViewMonth] = React3.useState(() => /* @__PURE__ */ new Date());
1968
2043
  const [selectedDate, setSelectedDate] = React3.useState(null);
1969
2044
  const [slots, setSlots] = React3.useState([]);
1970
2045
  const [selectedSlot, setSelectedSlot] = React3.useState(null);
2046
+ const [confirmedSlot, setConfirmedSlot] = React3.useState(false);
1971
2047
  const [hold, setHold] = React3.useState(null);
1972
2048
  const [guestInfo, setGuestInfo] = React3.useState({ name: "", email: "" });
1973
2049
  const [bookingResult, setBookingResult] = React3.useState(null);
2050
+ const [submitting, setSubmitting] = React3.useState(false);
2051
+ const slotsRef = React3.useRef(null);
2052
+ const today = React3.useMemo(() => {
2053
+ const d = /* @__PURE__ */ new Date();
2054
+ d.setHours(0, 0, 0, 0);
2055
+ return d;
2056
+ }, []);
1974
2057
  const timezone = React3.useMemo(() => propTimezone || detectTimezone(), [propTimezone]);
1975
- const availableDates = React3.useMemo(() => {
1976
- const dates = [];
1977
- const today = /* @__PURE__ */ new Date();
1978
- today.setHours(0, 0, 0, 0);
1979
- for (let i = 0; i < daysToShow; i++) {
1980
- const date = new Date(today);
1981
- date.setDate(date.getDate() + i);
1982
- if (date.getDay() !== 0 && date.getDay() !== 6) {
1983
- dates.push(date);
1984
- }
2058
+ const shortTz = React3.useMemo(() => {
2059
+ try {
2060
+ const parts = Intl.DateTimeFormat("en-US", { timeZone: timezone, timeZoneName: "short" }).formatToParts(/* @__PURE__ */ new Date());
2061
+ return parts.find((p) => p.type === "timeZoneName")?.value || timezone;
2062
+ } catch {
2063
+ return timezone;
1985
2064
  }
1986
- return dates;
1987
- }, [daysToShow]);
2065
+ }, [timezone]);
2066
+ const days = React3.useMemo(() => calendarDays(viewMonth.getFullYear(), viewMonth.getMonth()), [viewMonth]);
2067
+ const maxDate = React3.useMemo(() => {
2068
+ const d = new Date(today);
2069
+ d.setDate(d.getDate() + daysToShow);
2070
+ return d;
2071
+ }, [today, daysToShow]);
1988
2072
  React3.useEffect(() => {
1989
2073
  if (bookingTypeSlug) {
2074
+ setLoading(true);
1990
2075
  fetchBookingTypeDetails(orgSlug, bookingTypeSlug, apiUrl).then((type) => {
1991
2076
  setSelectedType(type);
1992
2077
  setStep("datetime");
1993
2078
  }).catch((err) => {
1994
2079
  setError(err.message);
1995
2080
  onError?.(err);
1996
- });
2081
+ }).finally(() => setLoading(false));
1997
2082
  } else {
2083
+ setLoading(true);
1998
2084
  fetchBookingTypes(orgSlug, apiUrl).then((types) => setBookingTypes(types.filter((t) => t.is_active))).catch((err) => {
1999
2085
  setError(err.message);
2000
2086
  onError?.(err);
2001
- });
2087
+ }).finally(() => setLoading(false));
2002
2088
  }
2003
2089
  }, [orgSlug, bookingTypeSlug, apiUrl, onError]);
2004
2090
  React3.useEffect(() => {
2005
2091
  if (!selectedDate || !selectedType) return;
2006
2092
  const dateStr = selectedDate.toISOString().split("T")[0];
2007
- setLoading(true);
2093
+ setSlotsLoading(true);
2008
2094
  setSlots([]);
2009
2095
  setSelectedSlot(null);
2096
+ setConfirmedSlot(false);
2010
2097
  fetchAvailability(orgSlug, selectedType.slug, dateStr, apiUrl, timezone).then((s) => setSlots(s.filter((slot) => slot.available))).catch((err) => {
2011
2098
  setError(err.message);
2012
2099
  onError?.(err);
2013
- }).finally(() => setLoading(false));
2100
+ }).finally(() => setSlotsLoading(false));
2014
2101
  }, [selectedDate, selectedType, orgSlug, apiUrl, timezone, onError]);
2015
- const handleSlotSelect = React3.useCallback(async (slot) => {
2016
- if (!selectedType) return;
2017
- if (hold) {
2018
- await releaseSlotHold(hold.holdId, apiUrl).catch(() => {
2019
- });
2020
- }
2102
+ const handleSlotSelect = React3.useCallback((slot) => {
2021
2103
  setSelectedSlot(slot);
2104
+ setConfirmedSlot(false);
2105
+ }, []);
2106
+ const handleSlotConfirm = React3.useCallback(async () => {
2107
+ if (!selectedType || !selectedSlot) return;
2108
+ if (hold) await releaseSlotHold(hold.holdId, apiUrl).catch(() => {
2109
+ });
2022
2110
  setLoading(true);
2023
2111
  try {
2024
- const newHold = await createSlotHold(
2025
- selectedType.id,
2026
- slot.start,
2027
- slot.hostId,
2028
- timezone,
2029
- apiUrl
2030
- );
2112
+ const newHold = await createSlotHold(selectedType.id, selectedSlot.start, selectedSlot.hostId, timezone, apiUrl);
2031
2113
  setHold(newHold);
2114
+ setConfirmedSlot(true);
2032
2115
  setStep("form");
2033
2116
  } catch (err) {
2034
2117
  setError(err.message);
@@ -2036,22 +2119,14 @@ function BookingWidget({
2036
2119
  } finally {
2037
2120
  setLoading(false);
2038
2121
  }
2039
- }, [selectedType, hold, timezone, apiUrl, onError]);
2122
+ }, [selectedType, selectedSlot, hold, timezone, apiUrl, onError]);
2040
2123
  const handleBookingSubmit = React3.useCallback(async (e) => {
2041
2124
  e.preventDefault();
2042
2125
  if (!selectedType || !selectedSlot) return;
2043
- setLoading(true);
2126
+ setSubmitting(true);
2044
2127
  setError(null);
2045
2128
  try {
2046
- const result = await createBooking(
2047
- selectedType.id,
2048
- selectedSlot.start,
2049
- guestInfo,
2050
- timezone,
2051
- selectedSlot.hostId,
2052
- hold?.holdId,
2053
- apiUrl
2054
- );
2129
+ const result = await createBooking(selectedType.id, selectedSlot.start, guestInfo, timezone, selectedSlot.hostId, hold?.holdId, apiUrl);
2055
2130
  setBookingResult(result);
2056
2131
  setStep("success");
2057
2132
  onBookingComplete?.(result);
@@ -2059,577 +2134,539 @@ function BookingWidget({
2059
2134
  setError(err.message);
2060
2135
  onError?.(err);
2061
2136
  } finally {
2062
- setLoading(false);
2137
+ setSubmitting(false);
2063
2138
  }
2064
2139
  }, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, onBookingComplete, onError]);
2065
2140
  React3.useEffect(() => {
2066
2141
  return () => {
2067
- if (hold) {
2068
- releaseSlotHold(hold.holdId, apiUrl).catch(() => {
2069
- });
2070
- }
2142
+ if (hold) releaseSlotHold(hold.holdId, apiUrl).catch(() => {
2143
+ });
2071
2144
  };
2072
2145
  }, [hold, apiUrl]);
2146
+ const canGoPrev = viewMonth.getFullYear() > today.getFullYear() || viewMonth.getMonth() > today.getMonth();
2147
+ const canGoNext = viewMonth < maxDate;
2148
+ const goMonth = (dir) => {
2149
+ setViewMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + dir, 1));
2150
+ };
2151
+ const groupedSlots = React3.useMemo(() => {
2152
+ const morning = [];
2153
+ const afternoon = [];
2154
+ const evening = [];
2155
+ for (const s of slots) {
2156
+ const h = new Date(s.start).getHours();
2157
+ if (h < 12) morning.push(s);
2158
+ else if (h < 17) afternoon.push(s);
2159
+ else evening.push(s);
2160
+ }
2161
+ return { morning, afternoon, evening };
2162
+ }, [slots]);
2073
2163
  const cssVars = {
2074
- "--booking-primary": styles2.primaryColor || "#4bbf39",
2075
- "--booking-radius": styles2.borderRadius || "8px",
2076
- "--booking-font": styles2.fontFamily || "inherit"
2164
+ "--bw-primary": styles2.primaryColor || "#0069ff",
2165
+ "--bw-primary-light": styles2.primaryColor ? `color-mix(in srgb, ${styles2.primaryColor} 12%, white)` : "#e8f1ff",
2166
+ "--bw-primary-hover": styles2.primaryColor ? `color-mix(in srgb, ${styles2.primaryColor} 90%, black)` : "#0055d4",
2167
+ "--bw-radius": styles2.borderRadius || "8px",
2168
+ "--bw-font": styles2.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
2077
2169
  };
2078
- return /* @__PURE__ */ jsxRuntime.jsxs(
2079
- "div",
2080
- {
2081
- className: `uptrade-booking-widget ${className}`,
2082
- style: cssVars,
2083
- children: [
2084
- error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-error", children: [
2085
- error,
2086
- /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setError(null), children: "Dismiss" })
2087
- ] }),
2088
- step === "type" && !hideTypeSelector && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-types", children: [
2089
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "uptrade-booking-title", children: "Select a Service" }),
2090
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-type-list", children: bookingTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsxs(
2091
- "button",
2092
- {
2093
- className: "uptrade-booking-type-card",
2094
- onClick: () => {
2095
- setSelectedType(type);
2096
- setStep("datetime");
2097
- },
2098
- children: [
2099
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-type-name", children: type.name }),
2100
- type.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-type-desc", children: type.description }),
2101
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-type-meta", children: [
2102
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatDuration(type.duration_minutes) }),
2103
- type.price_cents ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2104
- "$",
2105
- (type.price_cents / 100).toFixed(2)
2106
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Free" })
2107
- ] })
2108
- ]
2109
- },
2110
- type.id
2111
- )) })
2112
- ] }),
2113
- step === "datetime" && selectedType && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-datetime", children: [
2114
- /* @__PURE__ */ jsxRuntime.jsx(
2115
- "button",
2116
- {
2117
- className: "uptrade-booking-back",
2118
- onClick: () => {
2119
- if (bookingTypeSlug) return;
2120
- setSelectedType(null);
2121
- setStep("type");
2122
- },
2123
- disabled: !!bookingTypeSlug,
2124
- children: "\u2190 Back"
2125
- }
2126
- ),
2127
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "uptrade-booking-title", children: selectedType.name }),
2128
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "uptrade-booking-subtitle", children: [
2129
- formatDuration(selectedType.duration_minutes),
2130
- " \u2022 ",
2131
- selectedType.location_type
2132
- ] }),
2133
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-dates", children: [
2134
- /* @__PURE__ */ jsxRuntime.jsx("h4", { children: "Select a Date" }),
2135
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-date-grid", children: availableDates.map((date) => {
2136
- const dateStr = date.toISOString().split("T")[0];
2137
- const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
2138
- return /* @__PURE__ */ jsxRuntime.jsxs(
2139
- "button",
2140
- {
2141
- className: `uptrade-booking-date ${isSelected ? "selected" : ""}`,
2142
- onClick: () => setSelectedDate(date),
2143
- children: [
2144
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "uptrade-booking-date-day", children: date.toLocaleDateString("en-US", { weekday: "short" }) }),
2145
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "uptrade-booking-date-num", children: date.getDate() })
2146
- ]
2147
- },
2148
- dateStr
2149
- );
2150
- }) })
2170
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bw-root ${className}`, style: cssVars, children: [
2171
+ error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-error", role: "alert", children: [
2172
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: error }),
2173
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setError(null), "aria-label": "Dismiss error", children: "\xD7" })
2174
+ ] }),
2175
+ step === "type" && !hideTypeSelector && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in", children: [
2176
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: "Select a Service" }),
2177
+ loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-loading", children: [
2178
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
2179
+ " Loading services..."
2180
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-type-list", children: bookingTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsxs(
2181
+ "button",
2182
+ {
2183
+ className: "bw-type-card",
2184
+ onClick: () => {
2185
+ setSelectedType(type);
2186
+ setStep("datetime");
2187
+ },
2188
+ children: [
2189
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-type-name", children: type.name }),
2190
+ type.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-type-desc", children: type.description }),
2191
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-type-meta", children: [
2192
+ /* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
2193
+ " ",
2194
+ formatDuration(type.duration_minutes),
2195
+ type.price_cents ? ` \xB7 $${(type.price_cents / 100).toFixed(2)}` : " \xB7 Free"
2196
+ ] })
2197
+ ]
2198
+ },
2199
+ type.id
2200
+ )) })
2201
+ ] }),
2202
+ step === "datetime" && selectedType && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in", children: [
2203
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-info-header", children: [
2204
+ !bookingTypeSlug && /* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-back", onClick: () => {
2205
+ setSelectedType(null);
2206
+ setStep("type");
2207
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ArrowLeftIcon, {}) }),
2208
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2209
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: selectedType.name }),
2210
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-meta-row", children: [
2211
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge", children: [
2212
+ /* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
2213
+ " ",
2214
+ formatDuration(selectedType.duration_minutes)
2215
+ ] }),
2216
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge", children: [
2217
+ /* @__PURE__ */ jsxRuntime.jsx(GlobeIcon, {}),
2218
+ " ",
2219
+ shortTz
2220
+ ] })
2221
+ ] })
2222
+ ] })
2223
+ ] }),
2224
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-datetime-layout", children: [
2225
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-calendar", children: [
2226
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-cal-header", children: [
2227
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(-1), disabled: !canGoPrev, "aria-label": "Previous month", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, {}) }),
2228
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-cal-title", children: [
2229
+ MONTHS[viewMonth.getMonth()],
2230
+ " ",
2231
+ viewMonth.getFullYear()
2232
+ ] }),
2233
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(1), disabled: !canGoNext, "aria-label": "Next month", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {}) })
2151
2234
  ] }),
2152
- selectedDate && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-times", children: [
2153
- /* @__PURE__ */ jsxRuntime.jsx("h4", { children: "Select a Time" }),
2154
- loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-loading", children: "Loading available times..." }) : slots.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-empty", children: "No times available on this date" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-time-grid", children: slots.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(
2235
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-cal-weekdays", children: DAYS.map((d) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-cal-wd", children: d }, d)) }),
2236
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-cal-grid", children: days.map((date, i) => {
2237
+ if (!date) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-cal-empty" }, `e-${i}`);
2238
+ const past = isBeforeDay(date, today);
2239
+ const future = date > maxDate;
2240
+ const disabled = past || future;
2241
+ const sel = selectedDate && isSameDay(date, selectedDate);
2242
+ const isToday = isSameDay(date, today);
2243
+ return /* @__PURE__ */ jsxRuntime.jsx(
2155
2244
  "button",
2156
2245
  {
2157
- className: `uptrade-booking-time ${selectedSlot?.start === slot.start ? "selected" : ""}`,
2158
- onClick: () => handleSlotSelect(slot),
2159
- disabled: loading,
2160
- children: formatTime(slot.start, timezone)
2246
+ className: `bw-cal-day${sel ? " selected" : ""}${isToday ? " today" : ""}${disabled ? " disabled" : ""}`,
2247
+ onClick: () => !disabled && setSelectedDate(date),
2248
+ disabled,
2249
+ "aria-label": date.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" }),
2250
+ "aria-pressed": sel || void 0,
2251
+ children: date.getDate()
2161
2252
  },
2162
- slot.start
2163
- )) })
2164
- ] })
2253
+ date.toISOString()
2254
+ );
2255
+ }) })
2165
2256
  ] }),
2166
- step === "form" && selectedType && selectedSlot && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-form", children: [
2167
- /* @__PURE__ */ jsxRuntime.jsx(
2168
- "button",
2169
- {
2170
- className: "uptrade-booking-back",
2171
- onClick: () => setStep("datetime"),
2172
- children: "\u2190 Back"
2173
- }
2174
- ),
2175
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "uptrade-booking-title", children: "Your Information" }),
2176
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "uptrade-booking-subtitle", children: [
2177
- selectedType.name,
2178
- " on ",
2179
- formatDate2(selectedSlot.start, timezone),
2180
- " at ",
2181
- formatTime(selectedSlot.start, timezone)
2257
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `bw-times${selectedDate ? " visible" : ""}`, ref: slotsRef, children: !selectedDate ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-times-placeholder", children: [
2258
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
2259
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Select a date to view available times" })
2260
+ ] }) : slotsLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-loading", children: [
2261
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
2262
+ " Loading times..."
2263
+ ] }) : slots.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-times-empty", children: "No available times on this date. Try another day." }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-times-scroll", children: [
2264
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "bw-times-date", children: selectedDate.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }) }),
2265
+ groupedSlots.morning.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-group", children: [
2266
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-label", children: "Morning" }),
2267
+ groupedSlots.morning.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
2182
2268
  ] }),
2183
- hold && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "uptrade-booking-hold-notice", children: [
2184
- "This time is held for you for ",
2185
- Math.floor((new Date(hold.expiresAt).getTime() - Date.now()) / 6e4),
2186
- " minutes"
2269
+ groupedSlots.afternoon.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-group", children: [
2270
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-label", children: "Afternoon" }),
2271
+ groupedSlots.afternoon.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
2187
2272
  ] }),
2188
- /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleBookingSubmit, children: [
2189
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
2190
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-name", children: "Name *" }),
2191
- /* @__PURE__ */ jsxRuntime.jsx(
2192
- "input",
2193
- {
2194
- id: "guest-name",
2195
- type: "text",
2196
- required: true,
2197
- value: guestInfo.name,
2198
- onChange: (e) => setGuestInfo((prev) => ({ ...prev, name: e.target.value })),
2199
- placeholder: "Your full name"
2200
- }
2201
- )
2202
- ] }),
2203
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
2204
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-email", children: "Email *" }),
2205
- /* @__PURE__ */ jsxRuntime.jsx(
2206
- "input",
2207
- {
2208
- id: "guest-email",
2209
- type: "email",
2210
- required: true,
2211
- value: guestInfo.email,
2212
- onChange: (e) => setGuestInfo((prev) => ({ ...prev, email: e.target.value })),
2213
- placeholder: "your@email.com"
2214
- }
2215
- )
2216
- ] }),
2217
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
2218
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-phone", children: "Phone" }),
2219
- /* @__PURE__ */ jsxRuntime.jsx(
2220
- "input",
2221
- {
2222
- id: "guest-phone",
2223
- type: "tel",
2224
- value: guestInfo.phone || "",
2225
- onChange: (e) => setGuestInfo((prev) => ({ ...prev, phone: e.target.value })),
2226
- placeholder: "(555) 123-4567"
2227
- }
2228
- )
2229
- ] }),
2230
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
2231
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-notes", children: "Additional Notes" }),
2232
- /* @__PURE__ */ jsxRuntime.jsx(
2233
- "textarea",
2234
- {
2235
- id: "guest-notes",
2236
- value: guestInfo.notes || "",
2237
- onChange: (e) => setGuestInfo((prev) => ({ ...prev, notes: e.target.value })),
2238
- placeholder: "Anything you'd like us to know...",
2239
- rows: 3
2240
- }
2241
- )
2242
- ] }),
2243
- /* @__PURE__ */ jsxRuntime.jsx(
2244
- "button",
2245
- {
2246
- type: "submit",
2247
- className: "uptrade-booking-submit",
2248
- disabled: loading,
2249
- children: loading ? "Booking..." : "Confirm Booking"
2250
- }
2251
- )
2273
+ groupedSlots.evening.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-group", children: [
2274
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-label", children: "Evening" }),
2275
+ groupedSlots.evening.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
2252
2276
  ] })
2253
- ] }),
2254
- step === "success" && bookingResult && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-success", children: [
2255
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "uptrade-booking-success-icon", children: "\u2713" }),
2256
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "uptrade-booking-title", children: "Booking Confirmed!" }),
2257
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "uptrade-booking-confirmation-code", children: [
2258
- "Confirmation: ",
2259
- bookingResult.booking.confirmationCode
2260
- ] }),
2261
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-details", children: [
2262
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2263
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "When:" }),
2264
- " ",
2265
- formatDate2(bookingResult.booking.scheduledAt, timezone),
2266
- " at ",
2267
- formatTime(bookingResult.booking.scheduledAt, timezone)
2268
- ] }),
2269
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2270
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Duration:" }),
2277
+ ] }) })
2278
+ ] })
2279
+ ] }),
2280
+ step === "form" && selectedType && selectedSlot && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in", children: [
2281
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-info-header", children: [
2282
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-back", onClick: () => setStep("datetime"), children: /* @__PURE__ */ jsxRuntime.jsx(ArrowLeftIcon, {}) }),
2283
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2284
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: "Your Details" }),
2285
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-meta-row", children: [
2286
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge", children: [
2287
+ /* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
2271
2288
  " ",
2272
- formatDuration(bookingResult.booking.durationMinutes)
2289
+ formatDuration(selectedType.duration_minutes)
2273
2290
  ] }),
2274
- bookingResult.booking.hostName && /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
2275
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "With:" }),
2276
- " ",
2277
- bookingResult.booking.hostName
2291
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge-accent", children: [
2292
+ formatDate2(selectedSlot.start, timezone),
2293
+ " \xB7 ",
2294
+ formatTime(selectedSlot.start, timezone)
2278
2295
  ] })
2296
+ ] })
2297
+ ] })
2298
+ ] }),
2299
+ hold && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-hold-notice", children: [
2300
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
2301
+ " Slot held for you \u2014 complete your details to confirm."
2302
+ ] }),
2303
+ /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleBookingSubmit, className: "bw-form", children: [
2304
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
2305
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "bw-name", children: [
2306
+ "Name ",
2307
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-req", children: "*" })
2279
2308
  ] }),
2280
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-calendar-links", children: [
2281
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Add to calendar:" }),
2282
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-calendar-buttons", children: [
2283
- /* @__PURE__ */ jsxRuntime.jsx(
2284
- "a",
2285
- {
2286
- href: bookingResult.calendarLinks.google,
2287
- target: "_blank",
2288
- rel: "noopener noreferrer",
2289
- className: "uptrade-booking-calendar-btn",
2290
- children: "Google"
2291
- }
2292
- ),
2293
- /* @__PURE__ */ jsxRuntime.jsx(
2294
- "a",
2295
- {
2296
- href: bookingResult.calendarLinks.outlook,
2297
- target: "_blank",
2298
- rel: "noopener noreferrer",
2299
- className: "uptrade-booking-calendar-btn",
2300
- children: "Outlook"
2301
- }
2302
- ),
2303
- /* @__PURE__ */ jsxRuntime.jsx(
2304
- "a",
2305
- {
2306
- href: bookingResult.calendarLinks.ics,
2307
- download: true,
2308
- className: "uptrade-booking-calendar-btn",
2309
- children: "Download .ics"
2310
- }
2311
- )
2312
- ] })
2309
+ /* @__PURE__ */ jsxRuntime.jsx(
2310
+ "input",
2311
+ {
2312
+ id: "bw-name",
2313
+ type: "text",
2314
+ required: true,
2315
+ value: guestInfo.name,
2316
+ onChange: (e) => setGuestInfo((p) => ({ ...p, name: e.target.value })),
2317
+ placeholder: "Jane Smith",
2318
+ autoComplete: "name"
2319
+ }
2320
+ )
2321
+ ] }),
2322
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
2323
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "bw-email", children: [
2324
+ "Email ",
2325
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-req", children: "*" })
2313
2326
  ] }),
2314
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "uptrade-booking-email-notice", children: "A confirmation email has been sent to your email address." })
2327
+ /* @__PURE__ */ jsxRuntime.jsx(
2328
+ "input",
2329
+ {
2330
+ id: "bw-email",
2331
+ type: "email",
2332
+ required: true,
2333
+ value: guestInfo.email,
2334
+ onChange: (e) => setGuestInfo((p) => ({ ...p, email: e.target.value })),
2335
+ placeholder: "jane@example.com",
2336
+ autoComplete: "email"
2337
+ }
2338
+ )
2315
2339
  ] }),
2316
- /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
2317
- .uptrade-booking-widget {
2318
- font-family: var(--booking-font);
2319
- max-width: 480px;
2320
- margin: 0 auto;
2321
- padding: 24px;
2322
- border: 1px solid #e5e5e5;
2323
- border-radius: var(--booking-radius);
2324
- background: #fff;
2325
- }
2326
-
2327
- .uptrade-booking-error {
2328
- background: #fef2f2;
2329
- border: 1px solid #fecaca;
2330
- color: #b91c1c;
2331
- padding: 12px;
2332
- border-radius: var(--booking-radius);
2333
- margin-bottom: 16px;
2334
- display: flex;
2335
- justify-content: space-between;
2336
- align-items: center;
2337
- }
2338
-
2339
- .uptrade-booking-error button {
2340
- background: none;
2341
- border: none;
2342
- color: inherit;
2343
- cursor: pointer;
2344
- text-decoration: underline;
2345
- }
2346
-
2347
- .uptrade-booking-title {
2348
- font-size: 1.25rem;
2349
- font-weight: 600;
2350
- margin: 0 0 8px 0;
2351
- }
2352
-
2353
- .uptrade-booking-subtitle {
2354
- color: #666;
2355
- margin: 0 0 16px 0;
2356
- }
2357
-
2358
- .uptrade-booking-back {
2359
- background: none;
2360
- border: none;
2361
- color: var(--booking-primary);
2362
- cursor: pointer;
2363
- padding: 0;
2364
- margin-bottom: 16px;
2365
- font-size: 0.875rem;
2366
- }
2367
-
2368
- .uptrade-booking-back:disabled {
2369
- display: none;
2370
- }
2371
-
2372
- .uptrade-booking-type-list {
2373
- display: flex;
2374
- flex-direction: column;
2375
- gap: 12px;
2376
- }
2377
-
2378
- .uptrade-booking-type-card {
2379
- text-align: left;
2380
- padding: 16px;
2381
- border: 1px solid #e5e5e5;
2382
- border-radius: var(--booking-radius);
2383
- background: #fff;
2384
- cursor: pointer;
2385
- transition: border-color 0.2s, box-shadow 0.2s;
2386
- }
2387
-
2388
- .uptrade-booking-type-card:hover {
2389
- border-color: var(--booking-primary);
2390
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--booking-primary) 15%, transparent);
2391
- }
2392
-
2393
- .uptrade-booking-type-name {
2394
- font-weight: 600;
2395
- margin-bottom: 4px;
2396
- }
2397
-
2398
- .uptrade-booking-type-desc {
2399
- color: #666;
2400
- font-size: 0.875rem;
2401
- margin-bottom: 8px;
2402
- }
2403
-
2404
- .uptrade-booking-type-meta {
2405
- display: flex;
2406
- gap: 12px;
2407
- font-size: 0.75rem;
2408
- color: #888;
2409
- }
2410
-
2411
- .uptrade-booking-date-grid {
2412
- display: flex;
2413
- gap: 8px;
2414
- flex-wrap: wrap;
2415
- margin-bottom: 24px;
2416
- }
2417
-
2418
- .uptrade-booking-date {
2419
- display: flex;
2420
- flex-direction: column;
2421
- align-items: center;
2422
- padding: 8px 12px;
2423
- border: 1px solid #e5e5e5;
2424
- border-radius: var(--booking-radius);
2425
- background: #fff;
2426
- cursor: pointer;
2427
- transition: all 0.2s;
2428
- }
2429
-
2430
- .uptrade-booking-date:hover {
2431
- border-color: var(--booking-primary);
2432
- }
2433
-
2434
- .uptrade-booking-date.selected {
2435
- background: var(--booking-primary);
2436
- border-color: var(--booking-primary);
2437
- color: #fff;
2438
- }
2439
-
2440
- .uptrade-booking-date-day {
2441
- font-size: 0.625rem;
2442
- text-transform: uppercase;
2443
- }
2444
-
2445
- .uptrade-booking-date-num {
2446
- font-size: 1.125rem;
2447
- font-weight: 600;
2448
- }
2449
-
2450
- .uptrade-booking-time-grid {
2451
- display: grid;
2452
- grid-template-columns: repeat(3, 1fr);
2453
- gap: 8px;
2454
- }
2455
-
2456
- .uptrade-booking-time {
2457
- padding: 10px;
2458
- border: 1px solid #e5e5e5;
2459
- border-radius: var(--booking-radius);
2460
- background: #fff;
2461
- cursor: pointer;
2462
- font-size: 0.875rem;
2463
- transition: all 0.2s;
2464
- }
2465
-
2466
- .uptrade-booking-time:hover:not(:disabled) {
2467
- border-color: var(--booking-primary);
2468
- }
2469
-
2470
- .uptrade-booking-time.selected {
2471
- background: var(--booking-primary);
2472
- border-color: var(--booking-primary);
2473
- color: #fff;
2474
- }
2475
-
2476
- .uptrade-booking-time:disabled {
2477
- opacity: 0.5;
2478
- cursor: not-allowed;
2479
- }
2480
-
2481
- .uptrade-booking-loading,
2482
- .uptrade-booking-empty {
2483
- text-align: center;
2484
- padding: 24px;
2485
- color: #666;
2486
- }
2487
-
2488
- .uptrade-booking-hold-notice {
2489
- background: #fef3c7;
2490
- border: 1px solid #fcd34d;
2491
- color: #92400e;
2492
- padding: 8px 12px;
2493
- border-radius: var(--booking-radius);
2494
- font-size: 0.875rem;
2495
- margin-bottom: 16px;
2496
- }
2497
-
2498
- .uptrade-booking-field {
2499
- margin-bottom: 16px;
2500
- }
2501
-
2502
- .uptrade-booking-field label {
2503
- display: block;
2504
- margin-bottom: 4px;
2505
- font-size: 0.875rem;
2506
- font-weight: 500;
2507
- }
2508
-
2509
- .uptrade-booking-field input,
2510
- .uptrade-booking-field textarea {
2511
- width: 100%;
2512
- padding: 10px 12px;
2513
- border: 1px solid #e5e5e5;
2514
- border-radius: var(--booking-radius);
2515
- font-size: 1rem;
2516
- font-family: inherit;
2517
- }
2518
-
2519
- .uptrade-booking-field input:focus,
2520
- .uptrade-booking-field textarea:focus {
2521
- outline: none;
2522
- border-color: var(--booking-primary);
2523
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--booking-primary) 15%, transparent);
2524
- }
2525
-
2526
- .uptrade-booking-submit {
2527
- width: 100%;
2528
- padding: 14px;
2529
- background: var(--booking-primary);
2530
- color: #fff;
2531
- border: none;
2532
- border-radius: var(--booking-radius);
2533
- font-size: 1rem;
2534
- font-weight: 600;
2535
- cursor: pointer;
2536
- transition: opacity 0.2s;
2537
- }
2538
-
2539
- .uptrade-booking-submit:hover:not(:disabled) {
2540
- opacity: 0.9;
2541
- }
2542
-
2543
- .uptrade-booking-submit:disabled {
2544
- opacity: 0.5;
2545
- cursor: not-allowed;
2546
- }
2547
-
2548
- .uptrade-booking-success {
2549
- text-align: center;
2550
- }
2551
-
2552
- .uptrade-booking-success-icon {
2553
- width: 64px;
2554
- height: 64px;
2555
- margin: 0 auto 16px;
2556
- background: var(--booking-primary);
2557
- color: #fff;
2558
- border-radius: 50%;
2559
- display: flex;
2560
- align-items: center;
2561
- justify-content: center;
2562
- font-size: 2rem;
2563
- }
2564
-
2565
- .uptrade-booking-confirmation-code {
2566
- font-family: monospace;
2567
- background: #f5f5f5;
2568
- padding: 8px 16px;
2569
- border-radius: var(--booking-radius);
2570
- display: inline-block;
2571
- margin-bottom: 24px;
2572
- }
2573
-
2574
- .uptrade-booking-details {
2575
- text-align: left;
2576
- background: #f9f9f9;
2577
- padding: 16px;
2578
- border-radius: var(--booking-radius);
2579
- margin-bottom: 24px;
2580
- }
2581
-
2582
- .uptrade-booking-details p {
2583
- margin: 0 0 8px 0;
2584
- }
2585
-
2586
- .uptrade-booking-details p:last-child {
2587
- margin-bottom: 0;
2588
- }
2589
-
2590
- .uptrade-booking-calendar-links {
2591
- margin-bottom: 24px;
2592
- }
2593
-
2594
- .uptrade-booking-calendar-buttons {
2595
- display: flex;
2596
- gap: 8px;
2597
- justify-content: center;
2598
- margin-top: 8px;
2599
- }
2600
-
2601
- .uptrade-booking-calendar-btn {
2602
- padding: 8px 16px;
2603
- border: 1px solid #e5e5e5;
2604
- border-radius: var(--booking-radius);
2605
- text-decoration: none;
2606
- color: #333;
2607
- font-size: 0.875rem;
2608
- transition: all 0.2s;
2609
- }
2610
-
2611
- .uptrade-booking-calendar-btn:hover {
2612
- border-color: var(--booking-primary);
2613
- color: var(--booking-primary);
2614
- }
2615
-
2616
- .uptrade-booking-email-notice {
2617
- color: #666;
2618
- font-size: 0.875rem;
2619
- }
2620
-
2621
- h4 {
2622
- font-size: 0.875rem;
2623
- font-weight: 600;
2624
- margin: 0 0 12px 0;
2625
- color: #666;
2626
- }
2627
- ` })
2628
- ]
2629
- }
2630
- );
2340
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
2341
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "bw-phone", children: "Phone" }),
2342
+ /* @__PURE__ */ jsxRuntime.jsx(
2343
+ "input",
2344
+ {
2345
+ id: "bw-phone",
2346
+ type: "tel",
2347
+ value: guestInfo.phone || "",
2348
+ onChange: (e) => setGuestInfo((p) => ({ ...p, phone: e.target.value })),
2349
+ placeholder: "(555) 123-4567",
2350
+ autoComplete: "tel"
2351
+ }
2352
+ )
2353
+ ] }),
2354
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
2355
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "bw-notes", children: "Notes" }),
2356
+ /* @__PURE__ */ jsxRuntime.jsx(
2357
+ "textarea",
2358
+ {
2359
+ id: "bw-notes",
2360
+ value: guestInfo.notes || "",
2361
+ onChange: (e) => setGuestInfo((p) => ({ ...p, notes: e.target.value })),
2362
+ placeholder: "Anything you'd like us to know...",
2363
+ rows: 3
2364
+ }
2365
+ )
2366
+ ] }),
2367
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "bw-submit", disabled: submitting || !guestInfo.name || !guestInfo.email, children: submitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2368
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
2369
+ " Confirming..."
2370
+ ] }) : "Confirm Booking" })
2371
+ ] })
2372
+ ] }),
2373
+ step === "success" && bookingResult && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in bw-success", children: [
2374
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-success-icon", children: /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, {}) }),
2375
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: "You\u2019re Booked!" }),
2376
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "bw-conf-code", children: bookingResult.booking.confirmationCode }),
2377
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-details-card", children: [
2378
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-detail-row", children: [
2379
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-label", children: "When" }),
2380
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-detail-value", children: [
2381
+ formatDate2(bookingResult.booking.scheduledAt, timezone),
2382
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
2383
+ formatTime(bookingResult.booking.scheduledAt, timezone),
2384
+ " (",
2385
+ shortTz,
2386
+ ")"
2387
+ ] })
2388
+ ] }),
2389
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-detail-row", children: [
2390
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-label", children: "Duration" }),
2391
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-value", children: formatDuration(bookingResult.booking.durationMinutes) })
2392
+ ] }),
2393
+ bookingResult.booking.hostName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-detail-row", children: [
2394
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-label", children: "With" }),
2395
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-value", children: bookingResult.booking.hostName })
2396
+ ] })
2397
+ ] }),
2398
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "bw-cal-links-label", children: "Add to your calendar" }),
2399
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-cal-links", children: [
2400
+ /* @__PURE__ */ jsxRuntime.jsxs("a", { href: bookingResult.calendarLinks.google, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
2401
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
2402
+ " Google"
2403
+ ] }),
2404
+ /* @__PURE__ */ jsxRuntime.jsxs("a", { href: bookingResult.calendarLinks.outlook, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
2405
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
2406
+ " Outlook"
2407
+ ] }),
2408
+ /* @__PURE__ */ jsxRuntime.jsxs("a", { href: bookingResult.calendarLinks.ics, download: true, className: "bw-cal-link", children: [
2409
+ /* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
2410
+ " iCal"
2411
+ ] })
2412
+ ] }),
2413
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "bw-email-notice", children: [
2414
+ "A confirmation email has been sent to ",
2415
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: guestInfo.email }),
2416
+ "."
2417
+ ] })
2418
+ ] }),
2419
+ loading && step === "datetime" && !selectedType && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-loading", children: [
2420
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
2421
+ " Loading..."
2422
+ ] }),
2423
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: WIDGET_CSS })
2424
+ ] });
2425
+ }
2426
+ function TimeButton({
2427
+ slot,
2428
+ selected,
2429
+ confirmed,
2430
+ onClick,
2431
+ onConfirm,
2432
+ timezone,
2433
+ loading
2434
+ }) {
2435
+ if (selected && !confirmed) {
2436
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-btn-wrap selected", children: [
2437
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-text", children: formatTime(slot.start, timezone) }),
2438
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-time-confirm", onClick: onConfirm, disabled: loading, children: loading ? /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}) : "Confirm" })
2439
+ ] });
2440
+ }
2441
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { className: `bw-time-btn${selected ? " selected" : ""}`, onClick, disabled: loading, children: formatTime(slot.start, timezone) });
2442
+ }
2443
+ var WIDGET_CSS = `
2444
+ /* \u2500\u2500 Base \u2500\u2500 */
2445
+ .bw-root {
2446
+ font-family: var(--bw-font);
2447
+ color: #1a1a1a;
2448
+ line-height: 1.5;
2449
+ -webkit-font-smoothing: antialiased;
2450
+ box-sizing: border-box;
2451
+ }
2452
+ .bw-root *, .bw-root *::before, .bw-root *::after { box-sizing: border-box; }
2453
+
2454
+ /* \u2500\u2500 Animation \u2500\u2500 */
2455
+ @keyframes bw-fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
2456
+ @keyframes bw-spin { to { transform: rotate(360deg); } }
2457
+ .bw-fade-in { animation: bw-fade-in 0.25s ease-out; }
2458
+ .bw-spinner { animation: bw-spin 0.8s linear infinite; }
2459
+
2460
+ /* \u2500\u2500 Error \u2500\u2500 */
2461
+ .bw-error {
2462
+ display: flex; align-items: center; justify-content: space-between; gap: 12px;
2463
+ background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c;
2464
+ padding: 10px 14px; border-radius: var(--bw-radius); margin-bottom: 16px; font-size: 0.875rem;
2465
+ }
2466
+ .bw-error button { background: none; border: none; color: inherit; cursor: pointer; font-size: 1.25rem; line-height: 1; padding: 0; }
2467
+
2468
+ /* \u2500\u2500 Headings \u2500\u2500 */
2469
+ .bw-heading { font-size: 1.125rem; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
2470
+ .bw-meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
2471
+ .bw-badge {
2472
+ display: inline-flex; align-items: center; gap: 4px;
2473
+ font-size: 0.8125rem; color: #6b7280; font-weight: 400;
2474
+ }
2475
+ .bw-badge-accent {
2476
+ display: inline-flex; align-items: center; gap: 4px;
2477
+ font-size: 0.8125rem; color: var(--bw-primary); font-weight: 500;
2478
+ }
2479
+
2480
+ /* \u2500\u2500 Info Header \u2500\u2500 */
2481
+ .bw-info-header { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 20px; }
2482
+ .bw-back {
2483
+ display: inline-flex; align-items: center; justify-content: center;
2484
+ width: 32px; height: 32px; border-radius: 50%; border: 1px solid #e5e7eb;
2485
+ background: #fff; cursor: pointer; color: #4b5563; flex-shrink: 0; margin-top: 1px;
2486
+ transition: all 0.15s;
2487
+ }
2488
+ .bw-back:hover { background: #f3f4f6; border-color: #d1d5db; }
2489
+
2490
+ /* \u2500\u2500 Loading \u2500\u2500 */
2491
+ .bw-loading {
2492
+ display: flex; align-items: center; justify-content: center; gap: 8px;
2493
+ padding: 32px; color: #6b7280; font-size: 0.875rem;
2494
+ }
2495
+
2496
+ /* \u2500\u2500 Type Selection \u2500\u2500 */
2497
+ .bw-type-list { display: flex; flex-direction: column; gap: 10px; }
2498
+ .bw-type-card {
2499
+ display: flex; flex-direction: column; text-align: left; gap: 4px;
2500
+ padding: 16px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
2501
+ background: #fff; cursor: pointer; transition: all 0.15s;
2502
+ }
2503
+ .bw-type-card:hover { border-color: var(--bw-primary); box-shadow: 0 0 0 3px var(--bw-primary-light); }
2504
+ .bw-type-name { font-weight: 600; font-size: 0.9375rem; }
2505
+ .bw-type-desc { color: #6b7280; font-size: 0.8125rem; }
2506
+ .bw-type-meta { display: flex; align-items: center; gap: 4px; font-size: 0.8125rem; color: #9ca3af; margin-top: 4px; }
2507
+
2508
+ /* \u2500\u2500 Date-Time Layout \u2500\u2500 */
2509
+ .bw-datetime-layout {
2510
+ display: flex; gap: 0; border-top: 1px solid #f0f0f0; padding-top: 16px;
2511
+ }
2512
+ @media (max-width: 559px) {
2513
+ .bw-datetime-layout { flex-direction: column; }
2514
+ }
2515
+ @media (min-width: 560px) {
2516
+ .bw-datetime-layout { min-height: 340px; }
2517
+ .bw-calendar { flex: 1 1 auto; padding-right: 16px; border-right: 1px solid #f0f0f0; }
2518
+ .bw-times { width: 180px; flex-shrink: 0; padding-left: 16px; }
2631
2519
  }
2632
2520
 
2521
+ /* \u2500\u2500 Calendar \u2500\u2500 */
2522
+ .bw-cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
2523
+ .bw-cal-title { font-weight: 600; font-size: 0.9375rem; }
2524
+ .bw-cal-nav {
2525
+ display: inline-flex; align-items: center; justify-content: center;
2526
+ width: 32px; height: 32px; border-radius: 50%; border: none;
2527
+ background: transparent; cursor: pointer; color: #374151; transition: background 0.15s;
2528
+ }
2529
+ .bw-cal-nav:hover:not(:disabled) { background: #f3f4f6; }
2530
+ .bw-cal-nav:disabled { opacity: 0.25; cursor: default; }
2531
+
2532
+ .bw-cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0; text-align: center; margin-bottom: 4px; }
2533
+ .bw-cal-wd { font-size: 0.6875rem; font-weight: 600; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.04em; padding: 4px 0; }
2534
+
2535
+ .bw-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
2536
+ .bw-cal-empty { aspect-ratio: 1; }
2537
+ .bw-cal-day {
2538
+ aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
2539
+ border: none; background: none; border-radius: 50%;
2540
+ font-size: 0.8125rem; font-weight: 500; cursor: pointer;
2541
+ color: #1a1a1a; transition: all 0.15s; position: relative;
2542
+ }
2543
+ .bw-cal-day:hover:not(.disabled):not(.selected) { background: #f3f4f6; }
2544
+ .bw-cal-day.today:not(.selected)::after {
2545
+ content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
2546
+ width: 4px; height: 4px; border-radius: 50%; background: var(--bw-primary);
2547
+ }
2548
+ .bw-cal-day.selected {
2549
+ background: var(--bw-primary); color: #fff; font-weight: 600;
2550
+ }
2551
+ .bw-cal-day.disabled { color: #d1d5db; cursor: default; }
2552
+
2553
+ /* \u2500\u2500 Time Slots \u2500\u2500 */
2554
+ .bw-times { transition: opacity 0.2s; }
2555
+ .bw-times:not(.visible) { opacity: 0.5; }
2556
+ .bw-times.visible { opacity: 1; }
2557
+ .bw-times-placeholder {
2558
+ display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
2559
+ height: 100%; min-height: 160px; color: #9ca3af; font-size: 0.8125rem; text-align: center; padding: 16px;
2560
+ }
2561
+ .bw-times-empty {
2562
+ display: flex; align-items: center; justify-content: center;
2563
+ height: 100%; min-height: 160px; color: #9ca3af; font-size: 0.8125rem; text-align: center; padding: 16px;
2564
+ }
2565
+ .bw-times-scroll { overflow-y: auto; max-height: 340px; }
2566
+ .bw-times-date { font-weight: 600; font-size: 0.8125rem; color: #374151; margin: 0 0 12px 0; }
2567
+ .bw-time-group { margin-bottom: 16px; }
2568
+ .bw-time-label { display: block; font-size: 0.6875rem; font-weight: 600; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
2569
+
2570
+ .bw-time-btn {
2571
+ display: block; width: 100%;
2572
+ padding: 10px 12px; margin-bottom: 6px;
2573
+ border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
2574
+ background: #fff; cursor: pointer;
2575
+ font-size: 0.875rem; font-weight: 500; color: var(--bw-primary); text-align: center;
2576
+ transition: all 0.15s;
2577
+ }
2578
+ .bw-time-btn:hover:not(:disabled) {
2579
+ border-color: var(--bw-primary); background: var(--bw-primary-light);
2580
+ }
2581
+ .bw-time-btn.selected {
2582
+ border-color: var(--bw-primary); background: var(--bw-primary); color: #fff;
2583
+ }
2584
+ .bw-time-btn:disabled { opacity: 0.5; cursor: not-allowed; }
2585
+
2586
+ .bw-time-btn-wrap {
2587
+ display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
2588
+ border: 1.5px solid var(--bw-primary); border-radius: var(--bw-radius); overflow: hidden;
2589
+ animation: bw-fade-in 0.15s ease-out;
2590
+ }
2591
+ .bw-time-btn-wrap .bw-time-text {
2592
+ flex: 1; padding: 10px 12px; font-size: 0.875rem; font-weight: 500; color: #374151; text-align: center;
2593
+ background: var(--bw-primary-light);
2594
+ }
2595
+ .bw-time-confirm {
2596
+ display: inline-flex; align-items: center; justify-content: center; gap: 4px;
2597
+ padding: 10px 16px; border: none;
2598
+ background: var(--bw-primary); color: #fff;
2599
+ font-size: 0.8125rem; font-weight: 600; cursor: pointer;
2600
+ transition: background 0.15s;
2601
+ }
2602
+ .bw-time-confirm:hover:not(:disabled) { background: var(--bw-primary-hover); }
2603
+ .bw-time-confirm:disabled { opacity: 0.7; cursor: not-allowed; }
2604
+
2605
+ /* \u2500\u2500 Form \u2500\u2500 */
2606
+ .bw-hold-notice {
2607
+ display: flex; align-items: center; gap: 8px;
2608
+ background: var(--bw-primary-light); color: var(--bw-primary);
2609
+ padding: 10px 14px; border-radius: var(--bw-radius);
2610
+ font-size: 0.8125rem; font-weight: 500; margin-bottom: 20px;
2611
+ }
2612
+ .bw-form { display: flex; flex-direction: column; gap: 16px; }
2613
+ .bw-field label {
2614
+ display: block; font-size: 0.8125rem; font-weight: 500; color: #374151; margin-bottom: 4px;
2615
+ }
2616
+ .bw-req { color: #ef4444; }
2617
+ .bw-field input, .bw-field textarea {
2618
+ display: block; width: 100%;
2619
+ padding: 10px 12px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
2620
+ font-size: 0.9375rem; font-family: inherit; color: #1a1a1a; background: #fff;
2621
+ transition: border-color 0.15s, box-shadow 0.15s;
2622
+ }
2623
+ .bw-field input::placeholder, .bw-field textarea::placeholder { color: #c0c5cc; }
2624
+ .bw-field input:focus, .bw-field textarea:focus {
2625
+ outline: none; border-color: var(--bw-primary);
2626
+ box-shadow: 0 0 0 3px var(--bw-primary-light);
2627
+ }
2628
+ .bw-submit {
2629
+ display: inline-flex; align-items: center; justify-content: center; gap: 8px;
2630
+ width: 100%; padding: 14px; margin-top: 4px;
2631
+ background: var(--bw-primary); color: #fff; border: none;
2632
+ border-radius: var(--bw-radius); font-size: 0.9375rem; font-weight: 600;
2633
+ cursor: pointer; transition: background 0.15s;
2634
+ }
2635
+ .bw-submit:hover:not(:disabled) { background: var(--bw-primary-hover); }
2636
+ .bw-submit:disabled { opacity: 0.55; cursor: not-allowed; }
2637
+
2638
+ /* \u2500\u2500 Success \u2500\u2500 */
2639
+ .bw-success { text-align: center; }
2640
+ .bw-success-icon { margin: 0 auto 16px; width: 56px; height: 56px; animation: bw-fade-in 0.4s ease-out; }
2641
+ .bw-conf-code {
2642
+ display: inline-block; font-family: 'SF Mono', 'Fira Code', monospace;
2643
+ background: #f3f4f6; padding: 6px 14px; border-radius: 6px;
2644
+ font-size: 0.8125rem; color: #6b7280; margin: 4px 0 20px; letter-spacing: 0.04em;
2645
+ }
2646
+
2647
+ .bw-details-card {
2648
+ text-align: left; background: #f9fafb; border: 1px solid #f0f0f0;
2649
+ border-radius: var(--bw-radius); padding: 16px; margin-bottom: 20px;
2650
+ }
2651
+ .bw-detail-row { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
2652
+ .bw-detail-row:last-child { border-bottom: none; }
2653
+ .bw-detail-label { width: 70px; flex-shrink: 0; font-size: 0.8125rem; color: #9ca3af; font-weight: 500; }
2654
+ .bw-detail-value { font-size: 0.875rem; font-weight: 500; color: #374151; }
2655
+
2656
+ .bw-cal-links-label { font-size: 0.8125rem; color: #6b7280; margin: 0 0 8px 0; }
2657
+ .bw-cal-links { display: flex; gap: 8px; justify-content: center; margin-bottom: 20px; flex-wrap: wrap; }
2658
+ .bw-cal-link {
2659
+ display: inline-flex; align-items: center; gap: 6px;
2660
+ padding: 8px 14px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
2661
+ text-decoration: none; color: #374151; font-size: 0.8125rem; font-weight: 500;
2662
+ transition: all 0.15s;
2663
+ }
2664
+ .bw-cal-link:hover { border-color: var(--bw-primary); color: var(--bw-primary); }
2665
+
2666
+ .bw-email-notice { font-size: 0.8125rem; color: #9ca3af; margin: 0; }
2667
+ .bw-email-notice strong { color: #374151; font-weight: 500; }
2668
+ `;
2669
+
2633
2670
  Object.defineProperty(exports, "TestimonialSection", {
2634
2671
  enumerable: true,
2635
2672
  get: function () { return chunkUJQ73OS6_js.TestimonialSection; }