@odla-ai/chapter 0.40.3 → 0.41.1

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.
@@ -27,7 +27,12 @@ function dayLabel(ms, tz) {
27
27
  return new Date(ms).toLocaleDateString(void 0, { timeZone: tz, weekday: "short", month: "short", day: "numeric" });
28
28
  }
29
29
  function timeLabel(ms, tz) {
30
- return new Date(ms).toLocaleTimeString(void 0, { timeZone: tz, hour: "numeric", minute: "2-digit" });
30
+ return new Date(ms).toLocaleTimeString(void 0, {
31
+ timeZone: tz,
32
+ hour: "numeric",
33
+ minute: "2-digit",
34
+ timeZoneName: "short"
35
+ });
31
36
  }
32
37
  function fullLabel(ms, tz) {
33
38
  return new Date(ms).toLocaleString(void 0, {
@@ -105,7 +110,7 @@ function SlotPicker(props) {
105
110
  }
106
111
 
107
112
  // src/ui/members.tsx
108
- import { useEffect as useEffect3, useState as useState6 } from "preact/hooks";
113
+ import { useEffect as useEffect3, useState as useState7 } from "preact/hooks";
109
114
 
110
115
  // src/ui/reschedule.tsx
111
116
  import { useState as useState2 } from "preact/hooks";
@@ -190,7 +195,7 @@ function Rescheduler(props) {
190
195
  }
191
196
 
192
197
  // src/ui/member-gifts.tsx
193
- import { useEffect, useRef as useRef2, useState as useState4 } from "preact/hooks";
198
+ import { useEffect, useRef as useRef2, useState as useState5 } from "preact/hooks";
194
199
 
195
200
  // src/ui/gift-offer-cards.tsx
196
201
  import { jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
@@ -208,9 +213,94 @@ function GiftOfferCards(props) {
208
213
  ] }, offer.id)) });
209
214
  }
210
215
 
216
+ // src/ui/gift-code-redeemer.tsx
217
+ import { InlineActionField } from "@odla-ai/ui/components";
218
+ import { useState as useState3 } from "preact/hooks";
219
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
220
+ var GIFT_CODE_REDEEMER_CSS = `
221
+ .gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
222
+ .gift-code-redeemer .inline-action-field-label{display:block;color:var(--ui-text-muted,#66777f);font-size:var(--ui-text-xs,.72rem);font-weight:var(--ui-weight-strong,700);letter-spacing:var(--ui-tracking-caps,.08em);text-transform:uppercase}
223
+ .gift-code-redeemer .inline-action-field-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--ui-space-2,.65rem);align-items:stretch}
224
+ .gift-code-redeemer .inline-action-field-input,.gift-code-redeemer .inline-action-field-action{min-height:var(--ui-inline-action-control-height,38px)}
225
+ .gift-code-redeemer .inline-action-field-input.code{font-family:var(--ui-font-mono,ui-monospace,monospace);font-variant-ligatures:none;letter-spacing:var(--ui-tracking-wide,.04em)}
226
+ .gift-code-redeemer .inline-action-field-input:focus-visible{outline:none;border-color:var(--ui-accent,#168c84);box-shadow:var(--ui-focus,0 0 0 3px rgb(22 140 132 / .18))}
227
+ .gift-code-redeemer .inline-action-field-action{white-space:nowrap}
228
+ .gift-code-redeemer .inline-action-field-status{display:block;min-block-size:1.4em;margin:0;color:var(--ui-text-muted,#66777f);font-size:var(--ui-text-sm,.8rem);line-height:1.4}
229
+ .gift-code-redeemer .inline-action-field-status.success{color:var(--ui-good,#1f7a52)}
230
+ .gift-code-redeemer .inline-action-field-status.error{color:var(--ui-danger,#b42318)}
231
+ @container (max-width:26rem){.gift-code-redeemer .inline-action-field-row{grid-template-columns:minmax(0,1fr)}.gift-code-redeemer .inline-action-field-action{width:100%}}
232
+ `;
233
+ function GiftCodeRedeemer({ api, copy, id, onRedeemed }) {
234
+ const [code, setCode] = useState3("");
235
+ const [loading, setLoading] = useState3(false);
236
+ const [message, setMessage] = useState3("");
237
+ const [messageTone, setMessageTone] = useState3("neutral");
238
+ const normalizedCode = code.trim();
239
+ const redeem = async () => {
240
+ if (!normalizedCode || loading) return;
241
+ setLoading(true);
242
+ setMessage("");
243
+ setMessageTone("neutral");
244
+ try {
245
+ await api("/api/gifts/redeem", {
246
+ method: "POST",
247
+ headers: { "content-type": "application/json" },
248
+ body: JSON.stringify({ code: normalizedCode })
249
+ });
250
+ setCode("");
251
+ setMessage(copy.redeemed);
252
+ setMessageTone("success");
253
+ try {
254
+ await onRedeemed?.();
255
+ } catch {
256
+ }
257
+ } catch {
258
+ setMessage(copy.redeemFailed);
259
+ setMessageTone("error");
260
+ } finally {
261
+ setLoading(false);
262
+ }
263
+ };
264
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
265
+ /* @__PURE__ */ jsx4("style", { children: GIFT_CODE_REDEEMER_CSS }),
266
+ /* @__PURE__ */ jsx4(
267
+ InlineActionField,
268
+ {
269
+ id,
270
+ className: "gift-code-redeemer",
271
+ label: copy.code,
272
+ value: code,
273
+ code: true,
274
+ actionLabel: copy.redeem,
275
+ loadingLabel: `${copy.redeem}\u2026`,
276
+ loading,
277
+ actionDisabled: !normalizedCode,
278
+ message,
279
+ messageTone,
280
+ inputProps: {
281
+ name: "giftCode",
282
+ maxLength: 64,
283
+ autoComplete: "one-time-code",
284
+ autoCapitalize: "none",
285
+ autocorrect: "off",
286
+ spellcheck: false
287
+ },
288
+ onValueChange: (value) => {
289
+ setCode(value);
290
+ if (message) {
291
+ setMessage("");
292
+ setMessageTone("neutral");
293
+ }
294
+ },
295
+ onAction: () => void redeem()
296
+ }
297
+ )
298
+ ] });
299
+ }
300
+
211
301
  // src/ui/payment-step.tsx
212
- import { useRef, useState as useState3 } from "preact/hooks";
213
- import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
302
+ import { useRef, useState as useState4 } from "preact/hooks";
303
+ import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
214
304
  var loader = null;
215
305
  function loadStripe() {
216
306
  const existing = globalThis.Stripe;
@@ -244,9 +334,9 @@ function PaymentStep(props) {
244
334
  simulation
245
335
  } = props;
246
336
  const copy = props.copy ?? inheritedCopy.join.payment;
247
- const [status, setStatus] = useState3("idle");
248
- const [error, setError] = useState3(null);
249
- const [lineItems, setLineItems] = useState3(null);
337
+ const [status, setStatus] = useState4("idle");
338
+ const [error, setError] = useState4(null);
339
+ const [lineItems, setLineItems] = useState4(null);
250
340
  const mountRef = useRef(null);
251
341
  const stripeRef = useRef(null);
252
342
  const elementsRef = useRef(null);
@@ -320,12 +410,12 @@ function PaymentStep(props) {
320
410
  setStatus("ready");
321
411
  }
322
412
  };
323
- return /* @__PURE__ */ jsxs4("div", { className: "join-pay", children: [
324
- /* @__PURE__ */ jsxs4("div", { className: "compliance-box", children: [
325
- merchantDisclosureText ? /* @__PURE__ */ jsx4("p", { className: "compliance-merchant", children: merchantDisclosureText }) : null,
326
- /* @__PURE__ */ jsx4("p", { className: "compliance-policy", children: refundPolicyText }),
327
- /* @__PURE__ */ jsxs4("label", { className: "compliance-check", children: [
328
- /* @__PURE__ */ jsx4(
413
+ return /* @__PURE__ */ jsxs5("div", { className: "join-pay", children: [
414
+ /* @__PURE__ */ jsxs5("div", { className: "compliance-box", children: [
415
+ merchantDisclosureText ? /* @__PURE__ */ jsx5("p", { className: "compliance-merchant", children: merchantDisclosureText }) : null,
416
+ /* @__PURE__ */ jsx5("p", { className: "compliance-policy", children: refundPolicyText }),
417
+ /* @__PURE__ */ jsxs5("label", { className: "compliance-check", children: [
418
+ /* @__PURE__ */ jsx5(
329
419
  "input",
330
420
  {
331
421
  type: "checkbox",
@@ -335,42 +425,41 @@ function PaymentStep(props) {
335
425
  }
336
426
  }
337
427
  ),
338
- copy.consent ? /* @__PURE__ */ jsx4("span", { children: copy.consent }) : null
428
+ copy.consent ? /* @__PURE__ */ jsx5("span", { children: copy.consent }) : null
339
429
  ] })
340
430
  ] }),
341
- status === "loading" ? /* @__PURE__ */ jsx4("p", { className: "pay-status", children: copy.preparing }) : null,
431
+ status === "loading" ? /* @__PURE__ */ jsx5("p", { className: "pay-status", children: copy.preparing }) : null,
342
432
  lineItems && renderPriceLines ? renderPriceLines(lineItems) : null,
343
433
  children,
344
- simulation && (status === "ready" || status === "confirming") ? /* @__PURE__ */ jsxs4("fieldset", { className: "join-pay-simulation", children: [
345
- /* @__PURE__ */ jsx4("legend", { children: "Payment details" }),
346
- /* @__PURE__ */ jsxs4("label", { children: [
434
+ simulation && (status === "ready" || status === "confirming") ? /* @__PURE__ */ jsxs5("fieldset", { className: "join-pay-simulation", children: [
435
+ /* @__PURE__ */ jsx5("legend", { children: "Payment details" }),
436
+ /* @__PURE__ */ jsxs5("label", { children: [
347
437
  "Card number",
348
- /* @__PURE__ */ jsx4("input", { name: "simulationCardNumber", inputMode: "numeric", autoComplete: "off", defaultValue: "4242 4242 4242 4242" })
438
+ /* @__PURE__ */ jsx5("input", { name: "simulationCardNumber", inputMode: "numeric", autoComplete: "off", defaultValue: "4242 4242 4242 4242" })
349
439
  ] }),
350
- /* @__PURE__ */ jsxs4("label", { children: [
440
+ /* @__PURE__ */ jsxs5("label", { children: [
351
441
  "Expiration",
352
- /* @__PURE__ */ jsx4("input", { name: "simulationCardExpiry", inputMode: "numeric", autoComplete: "off", defaultValue: "12 / 34" })
442
+ /* @__PURE__ */ jsx5("input", { name: "simulationCardExpiry", inputMode: "numeric", autoComplete: "off", defaultValue: "12 / 34" })
353
443
  ] }),
354
- /* @__PURE__ */ jsxs4("label", { children: [
444
+ /* @__PURE__ */ jsxs5("label", { children: [
355
445
  "Security code",
356
- /* @__PURE__ */ jsx4("input", { name: "simulationCardCvc", inputMode: "numeric", autoComplete: "off", defaultValue: "123" })
446
+ /* @__PURE__ */ jsx5("input", { name: "simulationCardCvc", inputMode: "numeric", autoComplete: "off", defaultValue: "123" })
357
447
  ] }),
358
- /* @__PURE__ */ jsx4("p", { children: "This is a simulation. No card data is sent and no charge is created." })
448
+ /* @__PURE__ */ jsx5("p", { children: "This is a simulation. No card data is sent and no charge is created." })
359
449
  ] }) : null,
360
- /* @__PURE__ */ jsx4("div", { ref: mountRef, hidden: status === "idle" || status === "loading" }),
361
- status === "ready" || status === "confirming" ? /* @__PURE__ */ jsx4("button", { className: "submit-btn", disabled: status === "confirming", onClick: () => void pay(), children: status === "confirming" ? copy.processing : copy.payAndContinue }) : null,
362
- error ? /* @__PURE__ */ jsx4("p", { className: "pay-error", children: error }) : null
450
+ /* @__PURE__ */ jsx5("div", { ref: mountRef, hidden: status === "idle" || status === "loading" }),
451
+ status === "ready" || status === "confirming" ? /* @__PURE__ */ jsx5("button", { className: "submit-btn", disabled: status === "confirming", onClick: () => void pay(), children: status === "confirming" ? copy.processing : copy.payAndContinue }) : null,
452
+ error ? /* @__PURE__ */ jsx5("p", { className: "pay-error", children: error }) : null
363
453
  ] });
364
454
  }
365
455
 
366
456
  // src/ui/member-gifts.tsx
367
- import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
457
+ import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
368
458
  function MemberGifts(props) {
369
- const [data, setData] = useState4(null);
370
- const [selected, setSelected] = useState4(null);
371
- const [code, setCode] = useState4("");
372
- const [redeemCode, setRedeemCode] = useState4("");
373
- const [message, setMessage] = useState4("");
459
+ const [data, setData] = useState5(null);
460
+ const [selected, setSelected] = useState5(null);
461
+ const [code, setCode] = useState5("");
462
+ const [message, setMessage] = useState5("");
374
463
  const purchaseId = useRef2(crypto.randomUUID());
375
464
  const load = async () => setData(await props.api("/api/gifts"));
376
465
  useEffect(() => {
@@ -385,32 +474,18 @@ function MemberGifts(props) {
385
474
  setMessage(props.copy.rotateFailed);
386
475
  }
387
476
  };
388
- const redeem = async () => {
389
- try {
390
- await props.api("/api/gifts/redeem", {
391
- method: "POST",
392
- headers: { "content-type": "application/json" },
393
- body: JSON.stringify({ code: redeemCode })
394
- });
395
- setRedeemCode("");
396
- setMessage(props.copy.redeemed);
397
- await load();
398
- } catch {
399
- setMessage(props.copy.redeemFailed);
400
- }
401
- };
402
477
  if (!data) return null;
403
478
  const offer = data.offers.find((item) => item.id === selected);
404
- return /* @__PURE__ */ jsxs5("section", { className: "member-gifts", children: [
405
- /* @__PURE__ */ jsxs5("div", { className: "card", children: [
406
- /* @__PURE__ */ jsx5("div", { className: "card-label", children: props.copy.title }),
407
- /* @__PURE__ */ jsx5("p", { children: props.copy.body }),
408
- data.offers.length ? /* @__PURE__ */ jsx5(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
479
+ return /* @__PURE__ */ jsxs6("section", { className: "member-gifts", children: [
480
+ /* @__PURE__ */ jsxs6("div", { className: "card", children: [
481
+ /* @__PURE__ */ jsx6("div", { className: "card-label", children: props.copy.title }),
482
+ /* @__PURE__ */ jsx6("p", { children: props.copy.body }),
483
+ data.offers.length ? /* @__PURE__ */ jsx6(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
409
484
  setSelected(id);
410
485
  setCode("");
411
486
  purchaseId.current = crypto.randomUUID();
412
- } }) : /* @__PURE__ */ jsx5("p", { children: props.copy.noneAvailable }),
413
- offer ? /* @__PURE__ */ jsx5(
487
+ } }) : /* @__PURE__ */ jsx6("p", { children: props.copy.noneAvailable }),
488
+ offer ? /* @__PURE__ */ jsx6(
414
489
  PaymentStep,
415
490
  {
416
491
  applicationId: purchaseId.current,
@@ -430,35 +505,31 @@ function MemberGifts(props) {
430
505
  }
431
506
  }
432
507
  ) : null,
433
- code ? /* @__PURE__ */ jsxs5("div", { className: "gift-code-once", children: [
434
- /* @__PURE__ */ jsx5("output", { children: code }),
435
- /* @__PURE__ */ jsx5("p", { children: props.copy.saveCode })
508
+ code ? /* @__PURE__ */ jsxs6("div", { className: "gift-code-once", children: [
509
+ /* @__PURE__ */ jsx6("output", { children: code }),
510
+ /* @__PURE__ */ jsx6("p", { children: props.copy.saveCode })
436
511
  ] }) : null
437
512
  ] }),
438
- /* @__PURE__ */ jsxs5("div", { className: "card", children: [
439
- /* @__PURE__ */ jsx5("div", { className: "card-label", children: props.copy.purchases }),
440
- data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs5("div", { className: "member-row", children: [
441
- /* @__PURE__ */ jsx5("span", { children: claim.offerId }),
442
- /* @__PURE__ */ jsx5("span", { children: props.copy[claim.status] }),
443
- claim.status === "pending" ? /* @__PURE__ */ jsx5("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
444
- ] }, claim.id)) : /* @__PURE__ */ jsx5("p", { children: props.copy.noPurchases })
513
+ /* @__PURE__ */ jsxs6("div", { className: "card", children: [
514
+ /* @__PURE__ */ jsx6("div", { className: "card-label", children: props.copy.purchases }),
515
+ data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs6("div", { className: "member-row", children: [
516
+ /* @__PURE__ */ jsx6("span", { children: claim.offerId }),
517
+ /* @__PURE__ */ jsx6("span", { children: props.copy[claim.status] }),
518
+ claim.status === "pending" ? /* @__PURE__ */ jsx6("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
519
+ ] }, claim.id)) : /* @__PURE__ */ jsx6("p", { children: props.copy.noPurchases })
445
520
  ] }),
446
- /* @__PURE__ */ jsxs5("div", { className: "card", children: [
447
- /* @__PURE__ */ jsx5("div", { className: "card-label", children: props.copy.redeemTitle }),
448
- /* @__PURE__ */ jsxs5("label", { children: [
449
- props.copy.code,
450
- /* @__PURE__ */ jsx5("input", { value: redeemCode, maxLength: 64, onInput: (event) => setRedeemCode(event.currentTarget.value) })
451
- ] }),
452
- /* @__PURE__ */ jsx5("button", { className: "btn secondary", disabled: !redeemCode, onClick: () => void redeem(), children: props.copy.redeem }),
453
- message ? /* @__PURE__ */ jsx5("p", { role: "status", children: message }) : null
521
+ /* @__PURE__ */ jsxs6("div", { className: "card", children: [
522
+ /* @__PURE__ */ jsx6("div", { className: "card-label", children: props.copy.redeemTitle }),
523
+ /* @__PURE__ */ jsx6(GiftCodeRedeemer, { api: props.api, copy: props.copy, onRedeemed: load }),
524
+ message ? /* @__PURE__ */ jsx6("p", { role: "status", children: message }) : null
454
525
  ] })
455
526
  ] });
456
527
  }
457
528
 
458
529
  // src/ui/member-content.tsx
459
- import { useEffect as useEffect2, useMemo as useMemo2, useState as useState5 } from "preact/hooks";
530
+ import { useEffect as useEffect2, useMemo as useMemo2, useState as useState6 } from "preact/hooks";
460
531
  import { Markdown } from "@odla-ai/ui/components";
461
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
532
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
462
533
  var pageLabel = (page) => `${page.title}${page.access === "locked" ? " \xB7 Locked" : ""}`;
463
534
  function MemberContentArea(props) {
464
535
  const {
@@ -466,12 +537,12 @@ function MemberContentArea(props) {
466
537
  path = "/api/member-content",
467
538
  upsellHref,
468
539
  onUpsell,
469
- loadingContent = /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
470
- emptyContent = /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: "No member pages have been published yet." })
540
+ loadingContent = /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
541
+ emptyContent = /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: "No member pages have been published yet." })
471
542
  } = props;
472
- const [data, setData] = useState5(props.initialData ?? null);
473
- const [error, setError] = useState5(null);
474
- const [selectedId, setSelectedId] = useState5(
543
+ const [data, setData] = useState6(props.initialData ?? null);
544
+ const [error, setError] = useState6(null);
545
+ const [selectedId, setSelectedId] = useState6(
475
546
  props.initialPageId ?? props.initialData?.pages[0]?.id ?? ""
476
547
  );
477
548
  useEffect2(() => {
@@ -496,18 +567,18 @@ function MemberContentArea(props) {
496
567
  }
497
568
  return [...result.entries()];
498
569
  }, [data]);
499
- if (error) return /* @__PURE__ */ jsxs6("p", { className: "meeting-note", role: "alert", children: [
570
+ if (error) return /* @__PURE__ */ jsxs7("p", { className: "meeting-note", role: "alert", children: [
500
571
  "Member pages could not be loaded: ",
501
572
  error
502
573
  ] });
503
- if (!data) return /* @__PURE__ */ jsx6(Fragment2, { children: loadingContent });
504
- if (data.pages.length === 0) return /* @__PURE__ */ jsx6(Fragment2, { children: emptyContent });
574
+ if (!data) return /* @__PURE__ */ jsx7(Fragment3, { children: loadingContent });
575
+ if (data.pages.length === 0) return /* @__PURE__ */ jsx7(Fragment3, { children: emptyContent });
505
576
  const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
506
577
  const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
507
- return /* @__PURE__ */ jsxs6("div", { className: "chapter-member-content", "data-member-content": true, children: [
508
- /* @__PURE__ */ jsx6("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs6("section", { className: "chapter-member-content-section", children: [
509
- /* @__PURE__ */ jsx6("h2", { children: section }),
510
- /* @__PURE__ */ jsx6("ul", { children: pages.map((page) => /* @__PURE__ */ jsx6("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx6(
578
+ return /* @__PURE__ */ jsxs7("div", { className: "chapter-member-content", "data-member-content": true, children: [
579
+ /* @__PURE__ */ jsx7("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs7("section", { className: "chapter-member-content-section", children: [
580
+ /* @__PURE__ */ jsx7("h2", { children: section }),
581
+ /* @__PURE__ */ jsx7("ul", { children: pages.map((page) => /* @__PURE__ */ jsx7("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx7(
511
582
  "button",
512
583
  {
513
584
  type: "button",
@@ -517,23 +588,23 @@ function MemberContentArea(props) {
517
588
  }
518
589
  ) }, page.id)) })
519
590
  ] }, section)) }),
520
- /* @__PURE__ */ jsxs6("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
521
- /* @__PURE__ */ jsxs6("header", { children: [
522
- /* @__PURE__ */ jsxs6("div", { className: "card-label", children: [
591
+ /* @__PURE__ */ jsxs7("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
592
+ /* @__PURE__ */ jsxs7("header", { children: [
593
+ /* @__PURE__ */ jsxs7("div", { className: "card-label", children: [
523
594
  selected.source.type === "parent" ? "Parent" : "Chapter",
524
595
  " \xB7 ",
525
596
  selected.access
526
597
  ] }),
527
- /* @__PURE__ */ jsx6("h1", { children: selected.title }),
528
- selected.summary ? /* @__PURE__ */ jsx6("p", { children: selected.summary }) : null
598
+ /* @__PURE__ */ jsx7("h1", { children: selected.title }),
599
+ selected.summary ? /* @__PURE__ */ jsx7("p", { children: selected.summary }) : null
529
600
  ] }),
530
- selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx6(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs6("div", { className: "chapter-member-content-locked", children: [
531
- selected.teaserMarkdown ? /* @__PURE__ */ jsx6(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx6("p", { children: "This page is not included in your current membership." }),
532
- selected.upsell ? /* @__PURE__ */ jsxs6("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
533
- /* @__PURE__ */ jsx6("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
534
- /* @__PURE__ */ jsx6("p", { children: fmtMoney(selected.upsell.priceCents) }),
535
- selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx6(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
536
- href ? /* @__PURE__ */ jsx6("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx6("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
601
+ selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx7(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs7("div", { className: "chapter-member-content-locked", children: [
602
+ selected.teaserMarkdown ? /* @__PURE__ */ jsx7(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx7("p", { children: "This page is not included in your current membership." }),
603
+ selected.upsell ? /* @__PURE__ */ jsxs7("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
604
+ /* @__PURE__ */ jsx7("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
605
+ /* @__PURE__ */ jsx7("p", { children: fmtMoney(selected.upsell.priceCents) }),
606
+ selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx7(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
607
+ href ? /* @__PURE__ */ jsx7("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx7("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
537
608
  ] }) : null
538
609
  ] })
539
610
  ] })
@@ -541,12 +612,12 @@ function MemberContentArea(props) {
541
612
  }
542
613
 
543
614
  // src/ui/members.tsx
544
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
615
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
545
616
  function card(copy, kicker, body) {
546
- return /* @__PURE__ */ jsxs7("div", { className: "card", children: [
547
- /* @__PURE__ */ jsx7("div", { className: "card-label", children: copy.provisional.cardLabel }),
548
- /* @__PURE__ */ jsxs7("div", { className: "meeting-block", children: [
549
- /* @__PURE__ */ jsx7("div", { className: "meeting-kicker", children: kicker }),
617
+ return /* @__PURE__ */ jsxs8("div", { className: "card", children: [
618
+ /* @__PURE__ */ jsx8("div", { className: "card-label", children: copy.provisional.cardLabel }),
619
+ /* @__PURE__ */ jsxs8("div", { className: "meeting-block", children: [
620
+ /* @__PURE__ */ jsx8("div", { className: "meeting-kicker", children: kicker }),
550
621
  body
551
622
  ] })
552
623
  ] });
@@ -557,9 +628,9 @@ function ProvisionalCard(props) {
557
628
  return card(
558
629
  copy,
559
630
  copy.provisional.applicationNeeded,
560
- /* @__PURE__ */ jsxs7(Fragment3, { children: [
561
- /* @__PURE__ */ jsx7("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
562
- /* @__PURE__ */ jsx7("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
631
+ /* @__PURE__ */ jsxs8(Fragment4, { children: [
632
+ /* @__PURE__ */ jsx8("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
633
+ /* @__PURE__ */ jsx8("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
563
634
  ] })
564
635
  );
565
636
  }
@@ -567,19 +638,19 @@ function ProvisionalCard(props) {
567
638
  return card(
568
639
  copy,
569
640
  copy.provisional.refunded,
570
- /* @__PURE__ */ jsx7("div", { className: "meeting-note", children: copy.provisional.refundedBody })
641
+ /* @__PURE__ */ jsx8("div", { className: "meeting-note", children: copy.provisional.refundedBody })
571
642
  );
572
643
  }
573
- const membership = application.paid ? /* @__PURE__ */ jsx7("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
644
+ const membership = application.paid ? /* @__PURE__ */ jsx8("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
574
645
  if (application.meetingAt) {
575
646
  return card(
576
647
  copy,
577
648
  copy.provisional.introductionCall,
578
- /* @__PURE__ */ jsxs7(Fragment3, { children: [
579
- /* @__PURE__ */ jsx7("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
580
- /* @__PURE__ */ jsx7("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
581
- application.meetUrl ? /* @__PURE__ */ jsx7("div", { className: "meeting-note", children: /* @__PURE__ */ jsx7("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
582
- /* @__PURE__ */ jsx7(
649
+ /* @__PURE__ */ jsxs8(Fragment4, { children: [
650
+ /* @__PURE__ */ jsx8("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
651
+ /* @__PURE__ */ jsx8("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
652
+ application.meetUrl ? /* @__PURE__ */ jsx8("div", { className: "meeting-note", children: /* @__PURE__ */ jsx8("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
653
+ /* @__PURE__ */ jsx8(
583
654
  Rescheduler,
584
655
  {
585
656
  api,
@@ -596,9 +667,9 @@ function ProvisionalCard(props) {
596
667
  return card(
597
668
  copy,
598
669
  copy.provisional.bookCall,
599
- /* @__PURE__ */ jsxs7(Fragment3, { children: [
600
- /* @__PURE__ */ jsx7("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
601
- /* @__PURE__ */ jsx7(
670
+ /* @__PURE__ */ jsxs8(Fragment4, { children: [
671
+ /* @__PURE__ */ jsx8("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
672
+ /* @__PURE__ */ jsx8(
602
673
  Rescheduler,
603
674
  {
604
675
  api,
@@ -625,8 +696,8 @@ function MembersArea(props) {
625
696
  renderProvisional
626
697
  } = props;
627
698
  const copy = props.copy ?? inheritedCopy.members;
628
- const [me, setMe] = useState6(null);
629
- const [error, setError] = useState6(false);
699
+ const [me, setMe] = useState7(null);
700
+ const [error, setError] = useState7(false);
630
701
  const reload = async () => {
631
702
  try {
632
703
  setMe(await api("/api/me"));
@@ -637,22 +708,22 @@ function MembersArea(props) {
637
708
  useEffect3(() => {
638
709
  void reload();
639
710
  }, []);
640
- if (error) return /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: copy.loadFailed });
641
- if (!me) return /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: inheritedCopy.common.loading });
711
+ if (error) return /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: copy.loadFailed });
712
+ if (!me) return /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: inheritedCopy.common.loading });
642
713
  const role = me.role || "provisional";
643
- return /* @__PURE__ */ jsxs7(Fragment3, { children: [
644
- /* @__PURE__ */ jsxs7("div", { className: "card", children: [
645
- /* @__PURE__ */ jsxs7("div", { className: "member-row", children: [
646
- /* @__PURE__ */ jsx7("span", { className: "member-email", children: me.email }),
647
- /* @__PURE__ */ jsx7("span", { className: "role-badge " + role, children: role })
714
+ return /* @__PURE__ */ jsxs8(Fragment4, { children: [
715
+ /* @__PURE__ */ jsxs8("div", { className: "card", children: [
716
+ /* @__PURE__ */ jsxs8("div", { className: "member-row", children: [
717
+ /* @__PURE__ */ jsx8("span", { className: "member-email", children: me.email }),
718
+ /* @__PURE__ */ jsx8("span", { className: "role-badge " + role, children: role })
648
719
  ] }),
649
- /* @__PURE__ */ jsxs7("div", { className: "account-actions", children: [
650
- /* @__PURE__ */ jsx7("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
651
- role === "admin" ? /* @__PURE__ */ jsx7("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
720
+ /* @__PURE__ */ jsxs8("div", { className: "account-actions", children: [
721
+ /* @__PURE__ */ jsx8("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
722
+ role === "admin" ? /* @__PURE__ */ jsx8("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
652
723
  ] })
653
724
  ] }),
654
725
  role === "provisional" ? (() => {
655
- const defaultContent = /* @__PURE__ */ jsx7(
726
+ const defaultContent = /* @__PURE__ */ jsx8(
656
727
  ProvisionalCard,
657
728
  {
658
729
  api,
@@ -669,29 +740,29 @@ function MembersArea(props) {
669
740
  reload,
670
741
  defaultContent
671
742
  }) ?? defaultContent;
672
- })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx7(
743
+ })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx8(
673
744
  MemberContentArea,
674
745
  {
675
746
  api,
676
747
  ...memberPages === true ? {} : memberPages
677
748
  }
678
- ) : /* @__PURE__ */ jsx7("div", { className: "card", children: /* @__PURE__ */ jsx7("div", { className: "card-label", children: copy.full.welcome }) })),
679
- /* @__PURE__ */ jsx7(MemberGifts, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment })
749
+ ) : /* @__PURE__ */ jsx8("div", { className: "card", children: /* @__PURE__ */ jsx8("div", { className: "card-label", children: copy.full.welcome }) })),
750
+ /* @__PURE__ */ jsx8(MemberGifts, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment })
680
751
  ] });
681
752
  }
682
753
 
683
754
  // src/ui/join.tsx
684
- import { useEffect as useEffect5, useRef as useRef3, useState as useState10 } from "preact/hooks";
755
+ import { useEffect as useEffect5, useRef as useRef3, useState as useState11 } from "preact/hooks";
685
756
 
686
757
  // src/ui/join-booking.tsx
687
- import { useEffect as useEffect4, useState as useState7 } from "preact/hooks";
688
- import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
758
+ import { useEffect as useEffect4, useState as useState8 } from "preact/hooks";
759
+ import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
689
760
  function JoinBooking(props) {
690
761
  const { applicationId, copy, onBooked, simulation } = props;
691
- const [state, setState] = useState7(null);
692
- const [msg, setMsg] = useState7(null);
693
- const [busy, setBusy] = useState7(false);
694
- const [selected, setSelected] = useState7(null);
762
+ const [state, setState] = useState8(null);
763
+ const [msg, setMsg] = useState8(null);
764
+ const [busy, setBusy] = useState8(false);
765
+ const [selected, setSelected] = useState8(null);
695
766
  const load = async () => {
696
767
  setMsg(null);
697
768
  try {
@@ -748,9 +819,9 @@ function JoinBooking(props) {
748
819
  setBusy(false);
749
820
  }
750
821
  };
751
- if (!state) return /* @__PURE__ */ jsx8("p", { className: "slots-status", children: msg ?? copy.loading });
752
- return /* @__PURE__ */ jsxs8("div", { className: "join-book", children: [
753
- /* @__PURE__ */ jsx8(
822
+ if (!state) return /* @__PURE__ */ jsx9("p", { className: "slots-status", children: msg ?? copy.loading });
823
+ return /* @__PURE__ */ jsxs9("div", { className: "join-book", children: [
824
+ /* @__PURE__ */ jsx9(
754
825
  SlotPicker,
755
826
  {
756
827
  slots: state.slots,
@@ -760,29 +831,29 @@ function JoinBooking(props) {
760
831
  onDayChange: () => setSelected(null)
761
832
  }
762
833
  ),
763
- /* @__PURE__ */ jsxs8("div", { className: "slot-confirm", hidden: !selected, children: [
764
- /* @__PURE__ */ jsx8("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
765
- msg ? /* @__PURE__ */ jsx8("p", { className: "step2-note", children: msg }) : null
834
+ /* @__PURE__ */ jsxs9("div", { className: "slot-confirm", hidden: !selected, children: [
835
+ /* @__PURE__ */ jsx9("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
836
+ msg ? /* @__PURE__ */ jsx9("p", { className: "step2-note", children: msg }) : null
766
837
  ] })
767
838
  ] });
768
839
  }
769
840
 
770
841
  // src/ui/join-accepted.tsx
771
- import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
842
+ import { jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
772
843
  function JoinAccepted(props) {
773
- return /* @__PURE__ */ jsxs9("div", { className: "join-done card", children: [
774
- /* @__PURE__ */ jsx9("div", { className: "card-label", children: props.copy.accepted.label }),
775
- /* @__PURE__ */ jsx9("p", { className: "meeting-note", children: props.copy.accepted.body }),
776
- /* @__PURE__ */ jsx9("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
844
+ return /* @__PURE__ */ jsxs10("div", { className: "join-done card", children: [
845
+ /* @__PURE__ */ jsx10("div", { className: "card-label", children: props.copy.accepted.label }),
846
+ /* @__PURE__ */ jsx10("p", { className: "meeting-note", children: props.copy.accepted.body }),
847
+ /* @__PURE__ */ jsx10("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
777
848
  ] });
778
849
  }
779
850
 
780
851
  // src/ui/gift-claim-card.tsx
781
- import { useState as useState8 } from "preact/hooks";
782
- import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
852
+ import { useState as useState9 } from "preact/hooks";
853
+ import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
783
854
  function GiftClaimCard(props) {
784
- const [code, setCode] = useState8(props.initialCode ?? "");
785
- const [error, setError] = useState8(false);
855
+ const [code, setCode] = useState9(props.initialCode ?? "");
856
+ const [error, setError] = useState9(false);
786
857
  const rotate = async () => {
787
858
  if (!props.claimId) return;
788
859
  setError(false);
@@ -795,23 +866,23 @@ function GiftClaimCard(props) {
795
866
  if (response.ok && body.code) setCode(body.code);
796
867
  else setError(true);
797
868
  };
798
- return /* @__PURE__ */ jsxs10("div", { className: "join-done card", children: [
799
- /* @__PURE__ */ jsx10("div", { className: "card-label", children: props.copy.label }),
800
- /* @__PURE__ */ jsx10("p", { className: "meeting-note", children: props.copy.body }),
801
- code ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
802
- /* @__PURE__ */ jsx10("output", { className: "gift-code", children: code }),
803
- /* @__PURE__ */ jsx10("p", { children: props.copy.save })
869
+ return /* @__PURE__ */ jsxs11("div", { className: "join-done card", children: [
870
+ /* @__PURE__ */ jsx11("div", { className: "card-label", children: props.copy.label }),
871
+ /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: props.copy.body }),
872
+ code ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
873
+ /* @__PURE__ */ jsx11("output", { className: "gift-code", children: code }),
874
+ /* @__PURE__ */ jsx11("p", { children: props.copy.save })
804
875
  ] }) : null,
805
- !code && props.claimId ? /* @__PURE__ */ jsx10("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
806
- error ? /* @__PURE__ */ jsx10("p", { role: "alert", children: props.copy.rotateFailed }) : null
876
+ !code && props.claimId ? /* @__PURE__ */ jsx11("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
877
+ error ? /* @__PURE__ */ jsx11("p", { role: "alert", children: props.copy.rotateFailed }) : null
807
878
  ] });
808
879
  }
809
880
 
810
881
  // src/ui/join-tiers.tsx
811
- import { useState as useState9 } from "preact/hooks";
812
- import { jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
882
+ import { useState as useState10 } from "preact/hooks";
883
+ import { jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
813
884
  function useTierSelection(tiers, initialTierId) {
814
- const [selectedTierId, setSelectedTierId] = useState9(() => {
885
+ const [selectedTierId, setSelectedTierId] = useState10(() => {
815
886
  const preset = tiers.find((tier) => tier.id === initialTierId);
816
887
  if (preset) return preset.id;
817
888
  return tiers.length === 1 ? tiers[0].id : null;
@@ -826,10 +897,10 @@ function useTierSelection(tiers, initialTierId) {
826
897
  };
827
898
  }
828
899
  function TierPlaceholder(context) {
829
- return /* @__PURE__ */ jsxs11("fieldset", { "data-chapter-placeholder": "tiers", children: [
830
- /* @__PURE__ */ jsx11("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
831
- context.tiers.map((tier) => /* @__PURE__ */ jsxs11("label", { children: [
832
- /* @__PURE__ */ jsx11(
900
+ return /* @__PURE__ */ jsxs12("fieldset", { "data-chapter-placeholder": "tiers", children: [
901
+ /* @__PURE__ */ jsx12("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
902
+ context.tiers.map((tier) => /* @__PURE__ */ jsxs12("label", { children: [
903
+ /* @__PURE__ */ jsx12(
833
904
  "input",
834
905
  {
835
906
  type: "radio",
@@ -861,7 +932,7 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
861
932
  }
862
933
 
863
934
  // src/ui/join.tsx
864
- import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
935
+ import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
865
936
  function JoinIsland(props) {
866
937
  const inheritedCopy = useChapterCopy();
867
938
  const {
@@ -878,10 +949,10 @@ function JoinIsland(props) {
878
949
  const tiers = config.tiers ?? [];
879
950
  const tierSelection = useTierSelection(tiers, props.initialTierId);
880
951
  const { selectedTierId, selected: selectedTier } = tierSelection;
881
- const [state, setState] = useState10(props.initialState ?? { step: "form" });
882
- const [error, setError] = useState10(null);
883
- const [submitting, setSubmitting] = useState10(false);
884
- const [giftOfferId, setGiftOfferId] = useState10(props.initialGiftOfferId ?? null);
952
+ const [state, setState] = useState11(props.initialState ?? { step: "form" });
953
+ const [error, setError] = useState11(null);
954
+ const [submitting, setSubmitting] = useState11(false);
955
+ const [giftOfferId, setGiftOfferId] = useState11(props.initialGiftOfferId ?? null);
885
956
  const simulatedPayment = props.simulation ? props.simulation.payment ?? {
886
957
  lineItems: {
887
958
  standardCents: selectedTier?.priceCents ?? 0,
@@ -981,35 +1052,35 @@ function JoinIsland(props) {
981
1052
  ..."applicationId" in state ? { applicationId: state.applicationId } : {}
982
1053
  });
983
1054
  if (state.step === "done") {
984
- const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs12("div", { className: "join-done card", children: [
985
- /* @__PURE__ */ jsx12("div", { className: "card-label", children: copy.done.label }),
986
- /* @__PURE__ */ jsx12("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
987
- /* @__PURE__ */ jsx12("p", { className: "meeting-note", children: copy.done.calendarInvite }),
988
- /* @__PURE__ */ jsx12("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1055
+ const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs13("div", { className: "join-done card", children: [
1056
+ /* @__PURE__ */ jsx13("div", { className: "card-label", children: copy.done.label }),
1057
+ /* @__PURE__ */ jsx13("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
1058
+ /* @__PURE__ */ jsx13("p", { className: "meeting-note", children: copy.done.calendarInvite }),
1059
+ /* @__PURE__ */ jsx13("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
989
1060
  ] });
990
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1061
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
991
1062
  header,
992
1063
  body
993
1064
  ] });
994
1065
  }
995
1066
  if (state.step === "accepted") {
996
- const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx12(JoinAccepted, { copy, membersHref });
997
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1067
+ const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx13(JoinAccepted, { copy, membersHref });
1068
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
998
1069
  header,
999
1070
  body
1000
1071
  ] });
1001
1072
  }
1002
1073
  if (state.step === "gift") {
1003
- const body = renderGift?.(state) ?? /* @__PURE__ */ jsx12(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1004
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1074
+ const body = renderGift?.(state) ?? /* @__PURE__ */ jsx13(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1075
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
1005
1076
  header,
1006
1077
  body
1007
1078
  ] });
1008
1079
  }
1009
1080
  if (state.step === "booking") {
1010
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1081
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
1011
1082
  header,
1012
- /* @__PURE__ */ jsx12(
1083
+ /* @__PURE__ */ jsx13(
1013
1084
  JoinBooking,
1014
1085
  {
1015
1086
  applicationId: state.applicationId,
@@ -1023,9 +1094,9 @@ function JoinIsland(props) {
1023
1094
  ] });
1024
1095
  }
1025
1096
  if (state.step === "payment") {
1026
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1097
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
1027
1098
  header,
1028
- /* @__PURE__ */ jsx12(
1099
+ /* @__PURE__ */ jsx13(
1029
1100
  PaymentStep,
1030
1101
  {
1031
1102
  applicationId: state.applicationId,
@@ -1053,25 +1124,25 @@ function JoinIsland(props) {
1053
1124
  ] });
1054
1125
  }
1055
1126
  if (state.step === "paymentPending") {
1056
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1127
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
1057
1128
  header,
1058
- /* @__PURE__ */ jsx12("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1129
+ /* @__PURE__ */ jsx13("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1059
1130
  ] });
1060
1131
  }
1061
1132
  const submitDisabled = submitting || props.submitDisabled === true;
1062
1133
  const tierChooser = tiers.length > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null;
1063
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
1134
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
1064
1135
  header,
1065
- /* @__PURE__ */ jsxs12("form", { className: "join-form", onSubmit: (e) => void submit(e), children: [
1066
- (config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs12("fieldset", { children: [
1067
- /* @__PURE__ */ jsx12("legend", { children: copy.gift.optionsLabel }),
1068
- /* @__PURE__ */ jsx12("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => setGiftOfferId(null), children: copy.gift.chooseSelf }),
1069
- /* @__PURE__ */ jsx12(GiftOfferCards, { offers: config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: setGiftOfferId })
1136
+ /* @__PURE__ */ jsxs13("form", { className: "join-form", onSubmit: (e) => void submit(e), children: [
1137
+ (config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs13("fieldset", { children: [
1138
+ /* @__PURE__ */ jsx13("legend", { children: copy.gift.optionsLabel }),
1139
+ /* @__PURE__ */ jsx13("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => setGiftOfferId(null), children: copy.gift.chooseSelf }),
1140
+ /* @__PURE__ */ jsx13(GiftOfferCards, { offers: config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: setGiftOfferId })
1070
1141
  ] }) : null,
1071
1142
  tierChooser,
1072
1143
  children,
1073
- error ? /* @__PURE__ */ jsx12("p", { className: "join-error", children: error }) : null,
1074
- renderSubmit?.({ submitting, disabled: submitDisabled }) ?? /* @__PURE__ */ jsx12("button", { className: "submit-btn", type: "submit", disabled: submitDisabled, children: submitting ? copy.form.submitting : copy.form.submit })
1144
+ error ? /* @__PURE__ */ jsx13("p", { className: "join-error", children: error }) : null,
1145
+ renderSubmit?.({ submitting, disabled: submitDisabled }) ?? /* @__PURE__ */ jsx13("button", { className: "submit-btn", type: "submit", disabled: submitDisabled, children: submitting ? copy.form.submitting : copy.form.submit })
1075
1146
  ] })
1076
1147
  ] });
1077
1148
  }
@@ -1248,7 +1319,7 @@ function membershipPageDocument(input, options = {}) {
1248
1319
  }
1249
1320
 
1250
1321
  // src/ui/membership-cards.tsx
1251
- import { jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
1322
+ import { jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
1252
1323
  var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
1253
1324
  "--ui-membership-grid-gap": "1.4rem",
1254
1325
  "--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
@@ -1317,67 +1388,67 @@ function membershipApplicationHref(applicationPath, tierId) {
1317
1388
  }
1318
1389
  function TierAction(props) {
1319
1390
  if (props.mode === "select") {
1320
- return /* @__PURE__ */ jsxs13("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
1391
+ return /* @__PURE__ */ jsxs14("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
1321
1392
  props.label,
1322
- /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: "\u2192" })
1393
+ /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: "\u2192" })
1323
1394
  ] });
1324
1395
  }
1325
1396
  if (props.mode === "preview") {
1326
- return /* @__PURE__ */ jsxs13("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
1397
+ return /* @__PURE__ */ jsxs14("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
1327
1398
  props.label,
1328
- /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: "\u2192" })
1399
+ /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: "\u2192" })
1329
1400
  ] });
1330
1401
  }
1331
- return /* @__PURE__ */ jsxs13("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
1402
+ return /* @__PURE__ */ jsxs14("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
1332
1403
  props.label,
1333
- /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: "\u2192" })
1404
+ /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: "\u2192" })
1334
1405
  ] });
1335
1406
  }
1336
1407
  function TierCard(props) {
1337
1408
  const { tier, presentation } = props;
1338
1409
  const summary = presentation.summaryMarkdown ?? tier.blurb;
1339
1410
  const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
1340
- return /* @__PURE__ */ jsxs13("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
1341
- presentation.badge ? /* @__PURE__ */ jsx13("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
1342
- /* @__PURE__ */ jsx13("h3", { className: "chapter-membership-name", children: tier.name }),
1343
- /* @__PURE__ */ jsxs13("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
1344
- presentation.capacity ? /* @__PURE__ */ jsxs13("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
1345
- /* @__PURE__ */ jsx13("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
1346
- /* @__PURE__ */ jsx13("small", { children: presentation.capacity.label ?? "available" })
1411
+ return /* @__PURE__ */ jsxs14("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
1412
+ presentation.badge ? /* @__PURE__ */ jsx14("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
1413
+ /* @__PURE__ */ jsx14("h3", { className: "chapter-membership-name", children: tier.name }),
1414
+ /* @__PURE__ */ jsxs14("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
1415
+ presentation.capacity ? /* @__PURE__ */ jsxs14("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
1416
+ /* @__PURE__ */ jsx14("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
1417
+ /* @__PURE__ */ jsx14("small", { children: presentation.capacity.label ?? "available" })
1347
1418
  ] }) : null,
1348
- /* @__PURE__ */ jsxs13("div", { className: "chapter-membership-price-stack", children: [
1349
- presentation.priceEyebrow ? /* @__PURE__ */ jsx13("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : null,
1350
- /* @__PURE__ */ jsxs13("div", { className: "chapter-membership-price-row", children: [
1351
- presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx13("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
1352
- /* @__PURE__ */ jsx13("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.priceCents) }),
1353
- !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx13("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
1419
+ /* @__PURE__ */ jsxs14("div", { className: "chapter-membership-price-stack", children: [
1420
+ presentation.priceEyebrow ? /* @__PURE__ */ jsx14("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : null,
1421
+ /* @__PURE__ */ jsxs14("div", { className: "chapter-membership-price-row", children: [
1422
+ presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx14("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
1423
+ /* @__PURE__ */ jsx14("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.priceCents) }),
1424
+ !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx14("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
1354
1425
  ] })
1355
1426
  ] })
1356
1427
  ] }),
1357
- presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx13(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
1358
- summary ? /* @__PURE__ */ jsx13(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
1359
- presentation.benefits?.length ? /* @__PURE__ */ jsx13("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs13("li", { children: [
1360
- /* @__PURE__ */ jsx13("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
1361
- /* @__PURE__ */ jsx13(Markdown2, { className: "chapter-membership-benefit", source: benefit })
1428
+ presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx14(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
1429
+ summary ? /* @__PURE__ */ jsx14(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
1430
+ presentation.benefits?.length ? /* @__PURE__ */ jsx14("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs14("li", { children: [
1431
+ /* @__PURE__ */ jsx14("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
1432
+ /* @__PURE__ */ jsx14(Markdown2, { className: "chapter-membership-benefit", source: benefit })
1362
1433
  ] }, `${tier.id}-benefit-${index}`)) }) : null,
1363
- presentation.callout ? /* @__PURE__ */ jsxs13("aside", { className: "chapter-membership-callout", children: [
1364
- presentation.callout.label ? /* @__PURE__ */ jsx13("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
1365
- /* @__PURE__ */ jsx13(Markdown2, { source: presentation.callout.bodyMarkdown })
1434
+ presentation.callout ? /* @__PURE__ */ jsxs14("aside", { className: "chapter-membership-callout", children: [
1435
+ presentation.callout.label ? /* @__PURE__ */ jsx14("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
1436
+ /* @__PURE__ */ jsx14(Markdown2, { source: presentation.callout.bodyMarkdown })
1366
1437
  ] }) : null,
1367
- /* @__PURE__ */ jsx13(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
1438
+ /* @__PURE__ */ jsx14(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
1368
1439
  ] });
1369
1440
  }
1370
1441
  function MembershipCards(props) {
1371
1442
  const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
1372
1443
  const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
1373
1444
  const mode = props.mode ?? "link";
1374
- return /* @__PURE__ */ jsxs13("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
1375
- /* @__PURE__ */ jsx13("style", { children: MEMBERSHIP_CARDS_CSS }),
1376
- /* @__PURE__ */ jsx13("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
1445
+ return /* @__PURE__ */ jsxs14("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
1446
+ /* @__PURE__ */ jsx14("style", { children: MEMBERSHIP_CARDS_CSS }),
1447
+ /* @__PURE__ */ jsx14("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
1377
1448
  const tier = byId.get(presentation.tierId);
1378
- return /* @__PURE__ */ jsx13(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
1449
+ return /* @__PURE__ */ jsx14(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
1379
1450
  }) }),
1380
- document2.footnoteMarkdown ? /* @__PURE__ */ jsx13(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
1451
+ document2.footnoteMarkdown ? /* @__PURE__ */ jsx14(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
1381
1452
  ] });
1382
1453
  }
1383
1454
 
@@ -1393,6 +1464,7 @@ export {
1393
1464
  SlotPicker,
1394
1465
  Rescheduler,
1395
1466
  GiftOfferCards,
1467
+ GiftCodeRedeemer,
1396
1468
  PaymentStep,
1397
1469
  MemberGifts,
1398
1470
  MemberContentArea,
@@ -1406,4 +1478,4 @@ export {
1406
1478
  membershipApplicationHref,
1407
1479
  MembershipCards
1408
1480
  };
1409
- //# sourceMappingURL=chunk-E5OXQ3DC.js.map
1481
+ //# sourceMappingURL=chunk-PCRYLPMQ.js.map