@odla-ai/chapter 0.54.2 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -111,10 +111,10 @@ function SlotPicker(props) {
111
111
  }
112
112
 
113
113
  // src/ui/member-restart.tsx
114
- import { useEffect as useEffect2, useState as useState4 } from "preact/hooks";
114
+ import { useEffect as useEffect2, useState as useState5 } from "preact/hooks";
115
115
 
116
116
  // src/ui/membership-payment-step.tsx
117
- import { useEffect, useState as useState3 } from "preact/hooks";
117
+ import { useEffect, useState as useState4 } from "preact/hooks";
118
118
 
119
119
  // src/ui/payment-step.tsx
120
120
  import { useRef, useState as useState2 } from "preact/hooks";
@@ -271,14 +271,95 @@ function PaymentStep(props) {
271
271
  ] });
272
272
  }
273
273
 
274
- // src/ui/membership-payment-step.tsx
274
+ // src/ui/checkout-seat-choice.tsx
275
+ import { useState as useState3 } from "preact/hooks";
275
276
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
277
+ function CheckoutSeatChoice(props) {
278
+ const saved = props.quote.namedSeat;
279
+ const [selected, setSelected] = useState3(Boolean(saved || props.initial));
280
+ const [name, setName] = useState3(saved?.recipientName ?? props.initial?.recipientName ?? "");
281
+ const [email, setEmail] = useState3(saved?.recipientEmail ?? props.initial?.recipientEmail ?? "");
282
+ const [saving, setSaving] = useState3(false), [error, setError] = useState3("");
283
+ const amount = props.quote.seatOffer.amountCents;
284
+ const money = new Intl.NumberFormat("en-US", { style: "currency", currency: props.quote.currency }).format(amount / 100);
285
+ const dirty = selected !== Boolean(saved) || selected && (name !== saved?.recipientName || email !== saved?.recipientEmail);
286
+ const edit = (nextSelected, nextName = name, nextEmail = email) => {
287
+ props.onEditing(nextSelected !== Boolean(saved) || nextSelected && (nextName !== saved?.recipientName || nextEmail !== saved?.recipientEmail));
288
+ setError("");
289
+ };
290
+ return /* @__PURE__ */ jsx3("section", { className: "checkout-seat-choice", "aria-label": "Additional member", children: /* @__PURE__ */ jsxs3("form", { onSubmit: async (event) => {
291
+ event.preventDefault();
292
+ setSaving(true);
293
+ setError("");
294
+ try {
295
+ await props.onChange(selected ? { recipientName: name, recipientEmail: email } : null);
296
+ } catch (error2) {
297
+ setError(error2 instanceof Error ? error2.message : "Could not save your selection. Try again.");
298
+ } finally {
299
+ setSaving(false);
300
+ }
301
+ }, children: [
302
+ /* @__PURE__ */ jsxs3("fieldset", { disabled: props.locked || saving, children: [
303
+ /* @__PURE__ */ jsx3("legend", { children: amount === 0 ? "Included additional member" : "Add an additional member" }),
304
+ /* @__PURE__ */ jsx3("p", { children: amount === 0 ? "Your membership includes one additional member at no extra charge." : `Additional-member rate: ${money} per ${props.quote.interval}, paid together with your membership.` }),
305
+ /* @__PURE__ */ jsxs3("label", { children: [
306
+ /* @__PURE__ */ jsx3("input", { type: "checkbox", checked: selected, onChange: (event) => {
307
+ setSelected(event.currentTarget.checked);
308
+ edit(event.currentTarget.checked);
309
+ } }),
310
+ amount === 0 ? "Include my additional member" : "Add one member to my payment"
311
+ ] }),
312
+ selected ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
313
+ /* @__PURE__ */ jsxs3("label", { children: [
314
+ "Full name",
315
+ /* @__PURE__ */ jsx3(
316
+ "input",
317
+ {
318
+ required: true,
319
+ minLength: 2,
320
+ maxLength: 160,
321
+ value: name,
322
+ onInput: (event) => {
323
+ setName(event.currentTarget.value);
324
+ edit(selected, event.currentTarget.value);
325
+ }
326
+ }
327
+ )
328
+ ] }),
329
+ /* @__PURE__ */ jsxs3("label", { children: [
330
+ "Email",
331
+ /* @__PURE__ */ jsx3(
332
+ "input",
333
+ {
334
+ required: true,
335
+ type: "email",
336
+ maxLength: 254,
337
+ value: email,
338
+ onInput: (event) => {
339
+ setEmail(event.currentTarget.value);
340
+ edit(selected, name, event.currentTarget.value);
341
+ }
342
+ }
343
+ )
344
+ ] }),
345
+ /* @__PURE__ */ jsx3("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
346
+ ] }) : /* @__PURE__ */ jsx3("p", { children: "You can add someone from your member page after paying." }),
347
+ dirty ? /* @__PURE__ */ jsx3("button", { type: "submit", disabled: saving, children: saving ? "Saving\u2026" : amount === 0 ? "Save member details" : "Update total" }) : null
348
+ ] }),
349
+ error ? /* @__PURE__ */ jsx3("p", { role: "alert", children: error }) : null
350
+ ] }) });
351
+ }
352
+
353
+ // src/ui/membership-payment-step.tsx
354
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
276
355
  function MembershipPaymentStep(props) {
277
356
  const inherited = useChapterCopy();
278
357
  const copy = props.copy ?? inherited.join.payment;
279
- const [quote, setQuote] = useState3(null);
280
- const [error, setError] = useState3(false);
281
- const [revision, setRevision] = useState3(0);
358
+ const [quote, setQuote] = useState4(null);
359
+ const [locked, setLocked] = useState4(false), [editing, setEditing] = useState4(Boolean(props.initialNamedSeat));
360
+ const [prefillConsumed, setPrefillConsumed] = useState4(false);
361
+ const [error, setError] = useState4(false);
362
+ const [revision, setRevision] = useState4(0);
282
363
  useEffect(() => {
283
364
  let live = true;
284
365
  setQuote(null);
@@ -286,8 +367,13 @@ function MembershipPaymentStep(props) {
286
367
  void fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, { method: "POST", cache: "no-store" }).then(async (response) => {
287
368
  if (!response.ok) throw new Error("quote unavailable");
288
369
  const value = await response.json();
370
+ value.checkoutStarted = response.headers.get("x-chapter-checkout-started") === "true";
289
371
  if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest) || !/^[a-z]{3}$/.test(value.currency) || !Number.isSafeInteger(value.lineItems?.dueTodayCents) || value.lineItems.dueTodayCents <= 0 || typeof value.refundPolicyText !== "string") throw new Error("invalid quote");
290
- if (live) setQuote(value);
372
+ if (live) {
373
+ setQuote(value);
374
+ setLocked(Boolean(value.checkoutStarted));
375
+ setEditing(Boolean(props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer));
376
+ }
291
377
  }).catch(() => {
292
378
  if (live) setError(true);
293
379
  });
@@ -299,16 +385,22 @@ function MembershipPaymentStep(props) {
299
385
  setQuote(null);
300
386
  setRevision((value) => value + 1);
301
387
  };
302
- if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */ jsxs3("div", { className: "join-pay", role: "status", children: [
303
- props.merchantDisclosureText ? /* @__PURE__ */ jsx3("p", { className: "compliance-merchant", children: props.merchantDisclosureText }) : null,
304
- /* @__PURE__ */ jsx3("p", { children: error ? copy.setupFailed : copy.preparing }),
305
- error ? /* @__PURE__ */ jsx3("button", { type: "button", onClick: refresh, children: "Reload payment terms" }) : null
388
+ if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */ jsxs4("div", { className: "join-pay", role: "status", children: [
389
+ props.merchantDisclosureText ? /* @__PURE__ */ jsx4("p", { className: "compliance-merchant", children: props.merchantDisclosureText }) : null,
390
+ /* @__PURE__ */ jsx4("p", { children: error ? copy.setupFailed : copy.preparing }),
391
+ error ? /* @__PURE__ */ jsx4("button", { type: "button", onClick: refresh, children: "Reload payment terms" }) : null
306
392
  ] });
307
393
  const startCheckout = async () => {
394
+ setLocked(true);
308
395
  const response = await fetch("/api/payments/subscription", {
309
396
  method: "POST",
310
397
  headers: { "content-type": "application/json" },
311
- body: JSON.stringify({ applicationId: props.applicationId, refundPolicyAck: true, quoteDigest: quote.digest })
398
+ body: JSON.stringify({
399
+ applicationId: props.applicationId,
400
+ refundPolicyAck: true,
401
+ quoteDigest: quote.digest,
402
+ ...quote.namedSeat ? { seatTermsAck: true } : {}
403
+ })
312
404
  });
313
405
  if (!response.ok) {
314
406
  if (response.status === 409) refresh();
@@ -317,45 +409,85 @@ function MembershipPaymentStep(props) {
317
409
  return response.json();
318
410
  };
319
411
  const amount = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: quote.currency }).format(cents / 100);
320
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
321
- /* @__PURE__ */ jsxs3("section", { className: "payment-quote", "aria-label": "Membership price", children: [
322
- /* @__PURE__ */ jsx3("h3", { children: quote.tierName }),
323
- quote.founding ? /* @__PURE__ */ jsx3("p", { className: "payment-founding", role: "note", "aria-label": "Founding member", children: copy.foundingMember }) : null,
412
+ const changeSeat = async (namedSeat) => {
413
+ const response = await fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, {
414
+ method: "POST",
415
+ cache: "no-store",
416
+ headers: { "content-type": "application/json" },
417
+ body: JSON.stringify({ namedSeat })
418
+ });
419
+ if (!response.ok) {
420
+ if (response.status === 409) refresh();
421
+ throw new Error(response.status === 400 ? "Enter a different recipient's name and valid email." : "Could not save your selection. Reload payment terms and try again.");
422
+ }
423
+ const value = await response.json();
424
+ if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest)) throw new Error(copy.setupFailed);
425
+ setQuote(value);
426
+ setEditing(false);
427
+ setPrefillConsumed(true);
428
+ };
429
+ return /* @__PURE__ */ jsxs4(Fragment3, { children: [
430
+ quote.seatOffer ? /* @__PURE__ */ jsx4(
431
+ CheckoutSeatChoice,
432
+ {
433
+ quote,
434
+ locked,
435
+ onChange: changeSeat,
436
+ initial: quote.namedSeat || locked || prefillConsumed ? void 0 : props.initialNamedSeat,
437
+ onEditing: setEditing
438
+ },
439
+ quote.digest
440
+ ) : null,
441
+ /* @__PURE__ */ jsxs4("section", { className: "payment-quote", "aria-label": "Membership price", children: [
442
+ /* @__PURE__ */ jsx4("h3", { children: quote.tierName }),
443
+ quote.founding ? /* @__PURE__ */ jsx4("p", { className: "payment-founding", role: "note", "aria-label": "Founding member", children: copy.foundingMember }) : null,
324
444
  props.renderPriceLines ? props.renderPriceLines({
325
445
  ...quote.lineItems,
326
446
  ...quote.founding ? { founding: quote.founding } : {},
327
447
  ...quote.presentation ? { presentation: quote.presentation } : {}
328
- }) : /* @__PURE__ */ jsxs3("dl", { children: [
329
- quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
330
- /* @__PURE__ */ jsx3("dt", { children: copy.standardRate }),
331
- /* @__PURE__ */ jsxs3("dd", { children: [
448
+ }) : /* @__PURE__ */ jsxs4("dl", { children: [
449
+ quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
450
+ /* @__PURE__ */ jsx4("dt", { children: copy.standardRate }),
451
+ /* @__PURE__ */ jsxs4("dd", { children: [
332
452
  amount(quote.lineItems.standardCents),
333
453
  " per ",
334
454
  quote.interval
335
455
  ] }),
336
- /* @__PURE__ */ jsx3("dt", { children: copy.yourRate }),
337
- /* @__PURE__ */ jsxs3("dd", { children: [
338
- amount(quote.lineItems.dueTodayCents),
456
+ /* @__PURE__ */ jsx4("dt", { children: copy.yourRate }),
457
+ /* @__PURE__ */ jsxs4("dd", { children: [
458
+ amount(quote.lineItems.dueTodayCents - (quote.lineItems.namedSeatCents ?? 0)),
339
459
  " per ",
340
460
  quote.interval
341
461
  ] })
342
- ] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
343
- /* @__PURE__ */ jsx3("dt", { children: "Membership price" }),
344
- /* @__PURE__ */ jsxs3("dd", { children: [
462
+ ] }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
463
+ /* @__PURE__ */ jsx4("dt", { children: "Membership price" }),
464
+ /* @__PURE__ */ jsxs4("dd", { children: [
345
465
  amount(quote.lineItems.standardCents),
346
466
  " per ",
347
467
  quote.interval
348
468
  ] }),
349
- quote.lineItems.discountCents > 0 ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
350
- /* @__PURE__ */ jsx3("dt", { children: quote.founding ? copy.foundingDiscount : "Discount" }),
351
- /* @__PURE__ */ jsx3("dd", { children: amount(quote.lineItems.discountCents) })
469
+ quote.lineItems.discountCents > 0 ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
470
+ /* @__PURE__ */ jsx4("dt", { children: quote.founding ? copy.foundingDiscount : "Discount" }),
471
+ /* @__PURE__ */ jsx4("dd", { children: amount(quote.lineItems.discountCents) })
352
472
  ] }) : null
353
473
  ] }),
354
- /* @__PURE__ */ jsx3("dt", { children: "Due today" }),
355
- /* @__PURE__ */ jsx3("dd", { children: amount(quote.lineItems.dueTodayCents) })
474
+ quote.namedSeat ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
475
+ /* @__PURE__ */ jsx4("dt", { children: "Additional member" }),
476
+ /* @__PURE__ */ jsx4("dd", { children: quote.lineItems.namedSeatCents === 0 ? "Included" : amount(quote.lineItems.namedSeatCents) })
477
+ ] }) : null,
478
+ /* @__PURE__ */ jsx4("dt", { children: "Due today" }),
479
+ /* @__PURE__ */ jsx4("dd", { children: amount(quote.lineItems.dueTodayCents) })
356
480
  ] }),
357
- quote.commercial ? /* @__PURE__ */ jsxs3("div", { role: "note", "aria-label": "Renewal terms", children: [
358
- quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs3("p", { children: [
481
+ quote.namedSeat ? /* @__PURE__ */ jsxs4("p", { children: [
482
+ "For ",
483
+ quote.namedSeat.recipientName,
484
+ " \xB7 ",
485
+ quote.namedSeat.recipientEmail,
486
+ ".",
487
+ props.renderPriceLines ? ` Additional member: ${quote.lineItems.namedSeatCents === 0 ? "included" : amount(quote.lineItems.namedSeatCents)} in the total above.` : ""
488
+ ] }) : null,
489
+ quote.commercial ? /* @__PURE__ */ jsxs4("div", { role: "note", "aria-label": "Renewal terms", children: [
490
+ quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs4("p", { children: [
359
491
  "First renewal: ",
360
492
  new Intl.DateTimeFormat("en-US", {
361
493
  dateStyle: "long",
@@ -363,33 +495,35 @@ function MembershipPaymentStep(props) {
363
495
  }).format(quote.commercial.initialTermEndsAt),
364
496
  "."
365
497
  ] }) : null,
366
- /* @__PURE__ */ jsxs3("p", { children: [
498
+ /* @__PURE__ */ jsxs4("p", { children: [
367
499
  "Renews automatically at ",
368
500
  amount(quote.commercial.renewalCents),
369
501
  " per ",
370
502
  quote.interval,
371
503
  " unless canceled before renewal."
372
504
  ] }),
373
- quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */ jsx3("p", { children: "The discount applies to your first paid term only." }) : null,
374
- quote.commercial.discountDuration === "while_active" ? /* @__PURE__ */ jsx3("p", { children: "The discounted rate continues while this membership stays active." }) : null
505
+ quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */ jsx4("p", { children: "The discount applies to your first paid term only." }) : null,
506
+ quote.commercial.discountDuration === "while_active" ? /* @__PURE__ */ jsx4("p", { children: "The discounted rate continues while this membership stays active." }) : null
375
507
  ] }) : null,
376
- quote.trustCopy ? /* @__PURE__ */ jsx3("p", { className: "pay-trust", children: quote.trustCopy }) : null
508
+ quote.trustCopy ? /* @__PURE__ */ jsx4("p", { className: "pay-trust", children: quote.trustCopy }) : null
377
509
  ] }),
378
- /* @__PURE__ */ jsx3(
510
+ !editing ? /* @__PURE__ */ jsx4(
379
511
  PaymentStep,
380
512
  {
381
513
  ...props,
382
514
  refundPolicyText: quote.refundPolicyText,
383
515
  merchantDisclosureText: quote.merchantDisclosureText,
516
+ copy: { ...copy, consent: quote.namedSeat ? "I agree to the refund policy, renewal terms, and additional-member terms above." : "I agree to the refund policy and renewal terms above." },
384
517
  renderPriceLines: void 0,
385
518
  startCheckout
386
- }
387
- )
519
+ },
520
+ quote.digest
521
+ ) : /* @__PURE__ */ jsx4("p", { role: "status", children: "Save your member selection to continue to payment." })
388
522
  ] });
389
523
  }
390
524
 
391
525
  // src/ui/journey-frame.tsx
392
- import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
526
+ import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
393
527
  var styles = `
394
528
  .chapter-journey{color:var(--ui-text,#202827);font-family:var(--ui-font-sans,inherit);line-height:1.65;max-width:46rem;margin-inline:auto;min-width:0}
395
529
  .chapter-journey *{box-sizing:border-box}
@@ -424,21 +558,21 @@ var styles = `
424
558
  @media(max-width:520px){.chapter-journey .journey-actions>*{width:100%}.chapter-journey .journey-summary{grid-template-columns:1fr}.chapter-journey .journey-summary dd{text-align:left}.chapter-journey :where(.card,.join-form,.payment-quote,.join-book){padding:1.25rem}}
425
559
  `;
426
560
  function JourneyFrame({ children }) {
427
- return /* @__PURE__ */ jsxs4("div", { className: "chapter-journey", children: [
428
- /* @__PURE__ */ jsx4("style", { children: styles }),
561
+ return /* @__PURE__ */ jsxs5("div", { className: "chapter-journey", children: [
562
+ /* @__PURE__ */ jsx5("style", { children: styles }),
429
563
  children
430
564
  ] });
431
565
  }
432
566
 
433
567
  // src/ui/member-restart.tsx
434
- import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
568
+ import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
435
569
  function MemberRestart(props) {
436
- const [id, setId] = useState4(props.applicationId);
437
- const [busy, setBusy] = useState4(false);
438
- const [error, setError] = useState4("");
439
- const [paid, setPaid] = useState4(false);
440
- const [checking, setChecking] = useState4(false);
441
- const [revision, setRevision] = useState4(0);
570
+ const [id, setId] = useState5(props.applicationId);
571
+ const [busy, setBusy] = useState5(false);
572
+ const [error, setError] = useState5("");
573
+ const [paid, setPaid] = useState5(false);
574
+ const [checking, setChecking] = useState5(false);
575
+ const [revision, setRevision] = useState5(0);
442
576
  useEffect2(() => {
443
577
  if (!paid) return;
444
578
  let live = true, timer, attempt = 0;
@@ -476,40 +610,40 @@ function MemberRestart(props) {
476
610
  setBusy(false);
477
611
  }
478
612
  };
479
- return /* @__PURE__ */ jsx5(JourneyFrame, { children: /* @__PURE__ */ jsxs5("section", { className: "card", "aria-label": "Restart membership", children: [
480
- /* @__PURE__ */ jsx5("p", { className: "card-label", children: "Welcome back" }),
481
- /* @__PURE__ */ jsx5("h2", { children: "Restart your membership" }),
482
- /* @__PURE__ */ jsx5("p", { children: "Your account is ready, and your previous approval still counts. No new application or interview is needed." }),
483
- /* @__PURE__ */ jsxs5("dl", { className: "journey-summary", children: [
484
- /* @__PURE__ */ jsx5("dt", { children: "Name" }),
485
- /* @__PURE__ */ jsx5("dd", { children: [props.application.firstName, props.application.lastName].filter(Boolean).join(" ") }),
486
- /* @__PURE__ */ jsx5("dt", { children: "Email" }),
487
- /* @__PURE__ */ jsx5("dd", { children: props.application.email })
613
+ return /* @__PURE__ */ jsx6(JourneyFrame, { children: /* @__PURE__ */ jsxs6("section", { className: "card", "aria-label": "Restart membership", children: [
614
+ /* @__PURE__ */ jsx6("p", { className: "card-label", children: "Welcome back" }),
615
+ /* @__PURE__ */ jsx6("h2", { children: "Restart your membership" }),
616
+ /* @__PURE__ */ jsx6("p", { children: "Your account is ready, and your previous approval still counts. No new application or interview is needed." }),
617
+ /* @__PURE__ */ jsxs6("dl", { className: "journey-summary", children: [
618
+ /* @__PURE__ */ jsx6("dt", { children: "Name" }),
619
+ /* @__PURE__ */ jsx6("dd", { children: [props.application.firstName, props.application.lastName].filter(Boolean).join(" ") }),
620
+ /* @__PURE__ */ jsx6("dt", { children: "Email" }),
621
+ /* @__PURE__ */ jsx6("dd", { children: props.application.email })
488
622
  ] }),
489
- paid ? /* @__PURE__ */ jsxs5("div", { role: "status", children: [
490
- /* @__PURE__ */ jsx5("h3", { children: "Confirming your membership" }),
491
- /* @__PURE__ */ jsx5("p", { children: "We\u2019re waiting for payment confirmation. Your membership will open here as soon as it arrives." }),
492
- !checking ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Check membership" }) : null
493
- ] }) : id ? /* @__PURE__ */ jsx5(MembershipPaymentStep, { applicationId: id, refundPolicyText: "", onPaid: () => setPaid(true) }) : /* @__PURE__ */ jsx5("button", { type: "button", disabled: busy, onClick: () => void start(), children: busy ? "Preparing your membership\u2026" : "Review membership and payment" }),
494
- error ? /* @__PURE__ */ jsx5("p", { role: "alert", children: error }) : null
623
+ paid ? /* @__PURE__ */ jsxs6("div", { role: "status", children: [
624
+ /* @__PURE__ */ jsx6("h3", { children: "Confirming your membership" }),
625
+ /* @__PURE__ */ jsx6("p", { children: "We\u2019re waiting for payment confirmation. Your membership will open here as soon as it arrives." }),
626
+ !checking ? /* @__PURE__ */ jsx6("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Check membership" }) : null
627
+ ] }) : id ? /* @__PURE__ */ jsx6(MembershipPaymentStep, { applicationId: id, refundPolicyText: "", onPaid: () => setPaid(true) }) : /* @__PURE__ */ jsx6("button", { type: "button", disabled: busy, onClick: () => void start(), children: busy ? "Preparing your membership\u2026" : "Review membership and payment" }),
628
+ error ? /* @__PURE__ */ jsx6("p", { role: "alert", children: error }) : null
495
629
  ] }) });
496
630
  }
497
631
 
498
632
  // src/ui/members.tsx
499
- import { useEffect as useEffect6, useState as useState9 } from "preact/hooks";
633
+ import { useEffect as useEffect6, useState as useState10 } from "preact/hooks";
500
634
 
501
635
  // src/ui/reschedule.tsx
502
- import { useState as useState5 } from "preact/hooks";
503
- import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
636
+ import { useState as useState6 } from "preact/hooks";
637
+ import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
504
638
  function Rescheduler(props) {
505
639
  const inheritedCopy = useChapterCopy();
506
640
  const copy = props.copy ?? inheritedCopy.members.reschedule;
507
641
  const { api, applicationId, timezone, onRescheduled, label = copy.changeTime } = props;
508
- const [open, setOpen] = useState5(false);
509
- const [slots, setSlots] = useState5(null);
510
- const [tz, setTz] = useState5(timezone);
511
- const [busy, setBusy] = useState5(false);
512
- const [msg, setMsg] = useState5(null);
642
+ const [open, setOpen] = useState6(false);
643
+ const [slots, setSlots] = useState6(null);
644
+ const [tz, setTz] = useState6(timezone);
645
+ const [busy, setBusy] = useState6(false);
646
+ const [msg, setMsg] = useState6(null);
513
647
  const start = async () => {
514
648
  setOpen(true);
515
649
  setSlots(null);
@@ -542,7 +676,7 @@ function Rescheduler(props) {
542
676
  }
543
677
  };
544
678
  if (!open) {
545
- return /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: /* @__PURE__ */ jsx6(
679
+ return /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: /* @__PURE__ */ jsx7(
546
680
  "a",
547
681
  {
548
682
  href: "#",
@@ -554,8 +688,8 @@ function Rescheduler(props) {
554
688
  }
555
689
  ) });
556
690
  }
557
- return /* @__PURE__ */ jsxs6("div", { className: "msched", children: [
558
- slots === null ? /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: copy.loading }) : slots.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: msg ?? copy.noTimes }) : /* @__PURE__ */ jsx6(
691
+ return /* @__PURE__ */ jsxs7("div", { className: "msched", children: [
692
+ slots === null ? /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: copy.loading }) : slots.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: msg ?? copy.noTimes }) : /* @__PURE__ */ jsx7(
559
693
  SlotPicker,
560
694
  {
561
695
  slots,
@@ -564,9 +698,9 @@ function Rescheduler(props) {
564
698
  onPick: (s) => void pick(s)
565
699
  }
566
700
  ),
567
- busy ? /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: copy.rescheduling }) : null,
568
- msg && slots && slots.length > 0 ? /* @__PURE__ */ jsx6("p", { className: "meeting-note error", children: msg }) : null,
569
- /* @__PURE__ */ jsx6("p", { className: "meeting-note", children: /* @__PURE__ */ jsx6(
701
+ busy ? /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: copy.rescheduling }) : null,
702
+ msg && slots && slots.length > 0 ? /* @__PURE__ */ jsx7("p", { className: "meeting-note error", children: msg }) : null,
703
+ /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: /* @__PURE__ */ jsx7(
570
704
  "a",
571
705
  {
572
706
  href: "#",
@@ -581,31 +715,31 @@ function Rescheduler(props) {
581
715
  }
582
716
 
583
717
  // src/ui/member-gifts.tsx
584
- import { useEffect as useEffect3, useRef as useRef2, useState as useState6 } from "preact/hooks";
718
+ import { useEffect as useEffect3, useRef as useRef2, useState as useState7 } from "preact/hooks";
585
719
 
586
720
  // src/ui/gift-offer-cards.tsx
587
- import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
721
+ import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
588
722
  var price = (cents, currency) => currency === "usd" ? fmtMoney(cents) : new Intl.NumberFormat(void 0, { style: "currency", currency: currency.toUpperCase() }).format(cents / 100);
589
723
  function GiftOfferCards(props) {
590
724
  const mode = props.mode ?? "preview";
591
- return /* @__PURE__ */ jsx7("section", { className: "chapter-gift-offers", "aria-label": props.ariaLabel ?? "Gift options", children: props.offers.map((offer) => /* @__PURE__ */ jsxs7("article", { className: "card chapter-gift-offer", "data-offer-id": offer.id, children: [
592
- /* @__PURE__ */ jsx7("div", { className: "card-label", children: offer.title }),
593
- /* @__PURE__ */ jsx7("p", { children: offer.description }),
594
- /* @__PURE__ */ jsxs7("p", { className: "meeting-date", children: [
725
+ return /* @__PURE__ */ jsx8("section", { className: "chapter-gift-offers", "aria-label": props.ariaLabel ?? "Gift options", children: props.offers.map((offer) => /* @__PURE__ */ jsxs8("article", { className: "card chapter-gift-offer", "data-offer-id": offer.id, children: [
726
+ /* @__PURE__ */ jsx8("div", { className: "card-label", children: offer.title }),
727
+ /* @__PURE__ */ jsx8("p", { children: offer.description }),
728
+ /* @__PURE__ */ jsxs8("p", { className: "meeting-date", children: [
595
729
  price(offer.priceCents, offer.currency),
596
730
  offer.billingMode === "subscription" ? " recurring" : ""
597
731
  ] }),
598
- mode === "select" ? /* @__PURE__ */ jsx7("button", { type: "button", className: "btn secondary", "aria-pressed": props.selectedOfferId === offer.id, onClick: () => props.onSelect?.(offer.id), children: offer.ctaLabel }) : /* @__PURE__ */ jsx7("span", { className: "btn secondary", "aria-disabled": "true", children: offer.ctaLabel })
732
+ mode === "select" ? /* @__PURE__ */ jsx8("button", { type: "button", className: "btn secondary", "aria-pressed": props.selectedOfferId === offer.id, onClick: () => props.onSelect?.(offer.id), children: offer.ctaLabel }) : /* @__PURE__ */ jsx8("span", { className: "btn secondary", "aria-disabled": "true", children: offer.ctaLabel })
599
733
  ] }, offer.id)) });
600
734
  }
601
735
 
602
736
  // src/ui/member-gifts.tsx
603
- import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
737
+ import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
604
738
  function GiftPurchases(props) {
605
- const [data, setData] = useState6(null);
606
- const [selected, setSelected] = useState6(null);
607
- const [code, setCode] = useState6("");
608
- const [message, setMessage] = useState6("");
739
+ const [data, setData] = useState7(null);
740
+ const [selected, setSelected] = useState7(null);
741
+ const [code, setCode] = useState7("");
742
+ const [message, setMessage] = useState7("");
609
743
  const purchaseId = useRef2(crypto.randomUUID());
610
744
  const load = async () => setData(await props.api("/api/gifts"));
611
745
  useEffect3(() => {
@@ -623,16 +757,16 @@ function GiftPurchases(props) {
623
757
  if (!data) return null;
624
758
  if (data.offers.length === 0 && data.claims.length === 0) return null;
625
759
  const offer = data.offers.find((item) => item.id === selected);
626
- return /* @__PURE__ */ jsxs8("section", { className: "member-gifts", children: [
627
- data.offers.length ? /* @__PURE__ */ jsxs8("div", { className: "card", children: [
628
- /* @__PURE__ */ jsx8("div", { className: "card-label", children: props.copy.title }),
629
- /* @__PURE__ */ jsx8("p", { children: props.copy.body }),
630
- /* @__PURE__ */ jsx8(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
760
+ return /* @__PURE__ */ jsxs9("section", { className: "member-gifts", children: [
761
+ data.offers.length ? /* @__PURE__ */ jsxs9("div", { className: "card", children: [
762
+ /* @__PURE__ */ jsx9("div", { className: "card-label", children: props.copy.title }),
763
+ /* @__PURE__ */ jsx9("p", { children: props.copy.body }),
764
+ /* @__PURE__ */ jsx9(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
631
765
  setSelected(id);
632
766
  setCode("");
633
767
  purchaseId.current = crypto.randomUUID();
634
768
  } }),
635
- offer ? /* @__PURE__ */ jsx8(
769
+ offer ? /* @__PURE__ */ jsx9(
636
770
  PaymentStep,
637
771
  {
638
772
  applicationId: purchaseId.current,
@@ -652,27 +786,27 @@ function GiftPurchases(props) {
652
786
  }
653
787
  }
654
788
  ) : null,
655
- code ? /* @__PURE__ */ jsxs8("div", { className: "gift-code-once", children: [
656
- /* @__PURE__ */ jsx8("output", { children: code }),
657
- /* @__PURE__ */ jsx8("p", { children: props.copy.saveCode })
789
+ code ? /* @__PURE__ */ jsxs9("div", { className: "gift-code-once", children: [
790
+ /* @__PURE__ */ jsx9("output", { children: code }),
791
+ /* @__PURE__ */ jsx9("p", { children: props.copy.saveCode })
658
792
  ] }) : null
659
793
  ] }) : null,
660
- /* @__PURE__ */ jsxs8("div", { className: "card", children: [
661
- /* @__PURE__ */ jsx8("div", { className: "card-label", children: props.copy.purchases }),
662
- data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs8("div", { className: "member-row", children: [
663
- /* @__PURE__ */ jsx8("span", { children: claim.offerId }),
664
- /* @__PURE__ */ jsx8("span", { children: props.copy[claim.status] }),
665
- claim.status === "pending" ? /* @__PURE__ */ jsx8("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
666
- ] }, claim.id)) : /* @__PURE__ */ jsx8("p", { children: props.copy.noPurchases }),
667
- message ? /* @__PURE__ */ jsx8("p", { role: "status", children: message }) : null
794
+ /* @__PURE__ */ jsxs9("div", { className: "card", children: [
795
+ /* @__PURE__ */ jsx9("div", { className: "card-label", children: props.copy.purchases }),
796
+ data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs9("div", { className: "member-row", children: [
797
+ /* @__PURE__ */ jsx9("span", { children: claim.offerId }),
798
+ /* @__PURE__ */ jsx9("span", { children: props.copy[claim.status] }),
799
+ claim.status === "pending" ? /* @__PURE__ */ jsx9("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
800
+ ] }, claim.id)) : /* @__PURE__ */ jsx9("p", { children: props.copy.noPurchases }),
801
+ message ? /* @__PURE__ */ jsx9("p", { role: "status", children: message }) : null
668
802
  ] })
669
803
  ] });
670
804
  }
671
805
  var MemberGifts = GiftPurchases;
672
806
 
673
807
  // src/ui/member-named-seat.tsx
674
- import { useEffect as useEffect4, useState as useState7 } from "preact/hooks";
675
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
808
+ import { useEffect as useEffect4, useState as useState8 } from "preact/hooks";
809
+ import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
676
810
  var NAMED_SEAT_RECIPIENT_WORDS = {
677
811
  payment_pending: "payment in progress",
678
812
  invited: "invited, waiting for them to accept",
@@ -685,7 +819,7 @@ var NAMED_SEAT_RECIPIENT_WORDS = {
685
819
  var day = (at) => new Date(at).toLocaleDateString("en-US", { timeZone: "UTC" });
686
820
  function NamedSeatRecipientLine({ seat }) {
687
821
  const words = NAMED_SEAT_RECIPIENT_WORDS[seat.recipientState] ?? seat.status.replaceAll("_", " ");
688
- return /* @__PURE__ */ jsxs9("p", { className: "member-named-seat-recipient", children: [
822
+ return /* @__PURE__ */ jsxs10("p", { className: "member-named-seat-recipient", children: [
689
823
  seat.recipientName,
690
824
  " \xB7 ",
691
825
  seat.recipientEmail,
@@ -695,9 +829,9 @@ function NamedSeatRecipientLine({ seat }) {
695
829
  ] });
696
830
  }
697
831
  function NamedSeatPurchase({ api }) {
698
- const [data, setData] = useState7(null), [error, setError] = useState7("");
699
- const [name, setName] = useState7(""), [email, setEmail] = useState7(""), [reviewing, setReviewing] = useState7(false);
700
- const [terms, setTerms] = useState7(false), [pending, setPending] = useState7(false), [granting, setGranting] = useState7(false);
832
+ const [data, setData] = useState8(null), [error, setError] = useState8("");
833
+ const [name, setName] = useState8(""), [email, setEmail] = useState8(""), [reviewing, setReviewing] = useState8(false);
834
+ const [terms, setTerms] = useState8(false), [pending, setPending] = useState8(false), [granting, setGranting] = useState8(false);
701
835
  const load = async () => {
702
836
  try {
703
837
  const value = await api("/api/named-seat");
@@ -734,13 +868,13 @@ function NamedSeatPurchase({ api }) {
734
868
  }
735
869
  };
736
870
  const money = data ? new Intl.NumberFormat("en-US", { style: "currency", currency: data.currency }).format(data.amountCents / 100) : "";
737
- return /* @__PURE__ */ jsx9(JourneyFrame, { children: /* @__PURE__ */ jsxs9("section", { className: "card member-named-seat", "aria-label": "Named additional seat", children: [
738
- /* @__PURE__ */ jsx9("h2", { children: "Named additional seat" }),
739
- error ? /* @__PURE__ */ jsx9("p", { role: "alert", children: error }) : null,
740
- data ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
741
- data.seat ? /* @__PURE__ */ jsx9(NamedSeatRecipientLine, { seat: data.seat }) : null,
742
- data.eligible ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
743
- /* @__PURE__ */ jsxs9("p", { children: [
871
+ return /* @__PURE__ */ jsx10(JourneyFrame, { children: /* @__PURE__ */ jsxs10("section", { className: "card member-named-seat", "aria-label": "Named additional seat", children: [
872
+ /* @__PURE__ */ jsx10("h2", { children: "Named additional seat" }),
873
+ error ? /* @__PURE__ */ jsx10("p", { role: "alert", children: error }) : null,
874
+ data ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
875
+ data.seat ? /* @__PURE__ */ jsx10(NamedSeatRecipientLine, { seat: data.seat }) : null,
876
+ data.eligible ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
877
+ /* @__PURE__ */ jsxs10("p", { children: [
744
878
  data.included ? "Included with your membership at no charge." : `${money} paid in full now.`,
745
879
  " This seat ",
746
880
  data.autoRenew ? "renews with your primary membership" : "ends with your primary membership",
@@ -751,39 +885,39 @@ function NamedSeatPurchase({ api }) {
751
885
  " ",
752
886
  "It belongs to one named person and cannot be reassigned."
753
887
  ] }),
754
- /* @__PURE__ */ jsx9("p", { children: "The recipient must accept and complete their own application and any required interview. The seat stays open for them while your membership is paid; it is not refunded automatically. Contact the chapter if you need a refund." }),
755
- !reviewing ? /* @__PURE__ */ jsxs9("form", { onSubmit: (event) => {
888
+ /* @__PURE__ */ jsx10("p", { children: "The recipient must accept and complete their own application and any required interview. The seat stays open for them while your membership is paid; it is not refunded automatically. Contact the chapter if you need a refund." }),
889
+ !reviewing ? /* @__PURE__ */ jsxs10("form", { onSubmit: (event) => {
756
890
  event.preventDefault();
757
891
  setReviewing(true);
758
892
  setTerms(false);
759
893
  }, children: [
760
- /* @__PURE__ */ jsxs9("label", { children: [
894
+ /* @__PURE__ */ jsxs10("label", { children: [
761
895
  "Recipient name",
762
- /* @__PURE__ */ jsx9("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
896
+ /* @__PURE__ */ jsx10("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
763
897
  ] }),
764
- /* @__PURE__ */ jsxs9("label", { children: [
898
+ /* @__PURE__ */ jsxs10("label", { children: [
765
899
  "Recipient email",
766
- /* @__PURE__ */ jsx9("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
900
+ /* @__PURE__ */ jsx10("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
767
901
  ] }),
768
- /* @__PURE__ */ jsx9("button", { className: "btn primary", type: "submit", children: "Review named seat" })
769
- ] }) : /* @__PURE__ */ jsxs9(Fragment3, { children: [
770
- /* @__PURE__ */ jsxs9("p", { children: [
902
+ /* @__PURE__ */ jsx10("button", { className: "btn primary", type: "submit", children: "Review named seat" })
903
+ ] }) : /* @__PURE__ */ jsxs10(Fragment4, { children: [
904
+ /* @__PURE__ */ jsxs10("p", { children: [
771
905
  "For ",
772
906
  name,
773
907
  " \xB7 ",
774
908
  email
775
909
  ] }),
776
- /* @__PURE__ */ jsx9("button", { className: "btn secondary", type: "button", onClick: () => {
910
+ /* @__PURE__ */ jsx10("button", { className: "btn secondary", type: "button", onClick: () => {
777
911
  setReviewing(false);
778
912
  setTerms(false);
779
913
  void load();
780
914
  }, children: "Back to recipient" }),
781
- /* @__PURE__ */ jsxs9("label", { className: "journey-consent", children: [
782
- /* @__PURE__ */ jsx9("input", { type: "checkbox", checked: terms, onChange: (event) => setTerms(event.currentTarget.checked) }),
783
- /* @__PURE__ */ jsx9("span", { children: data.included ? "I agree to the seat terms and the refund policy; the seat is included with my membership and follows its renewal." : data.autoRenew ? "I agree to the full initial payment and automatic renewal with my membership; I can cancel renewal." : "I agree to the full initial payment and the displayed end date, with no automatic renewal while my membership renewal is canceled." })
915
+ /* @__PURE__ */ jsxs10("label", { className: "journey-consent", children: [
916
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", checked: terms, onChange: (event) => setTerms(event.currentTarget.checked) }),
917
+ /* @__PURE__ */ jsx10("span", { children: data.included ? "I agree to the seat terms and the refund policy; the seat is included with my membership and follows its renewal." : data.autoRenew ? "I agree to the full initial payment and automatic renewal with my membership; I can cancel renewal." : "I agree to the full initial payment and the displayed end date, with no automatic renewal while my membership renewal is canceled." })
784
918
  ] }),
785
- terms && data.included ? /* @__PURE__ */ jsx9("button", { className: "btn primary", type: "button", disabled: granting, onClick: () => void grant(), children: granting ? "Sending the invitation\u2026" : "Send the invitation" }) : null,
786
- terms && !data.included ? /* @__PURE__ */ jsx9(
919
+ terms && data.included ? /* @__PURE__ */ jsx10("button", { className: "btn primary", type: "button", disabled: granting, onClick: () => void grant(), children: granting ? "Sending the invitation\u2026" : "Send the invitation" }) : null,
920
+ terms && !data.included ? /* @__PURE__ */ jsx10(
787
921
  PaymentStep,
788
922
  {
789
923
  applicationId: data.membershipId,
@@ -798,17 +932,17 @@ function NamedSeatPurchase({ api }) {
798
932
  }
799
933
  ) : null
800
934
  ] })
801
- ] }) : !data.seat ? /* @__PURE__ */ jsx9("p", { children: data.purchaseWindowed === false ? "An additional seat can be purchased for as long as your membership stays paid." : `Additional seats can be purchased until ${day(data.purchaseEndsAt)}.` }) : null,
802
- pending ? /* @__PURE__ */ jsx9("p", { role: "status", children: "Payment confirmation is being reconciled. The recipient\u2019s access begins only after their own acceptance and approval." }) : null
803
- ] }) : !error ? /* @__PURE__ */ jsx9("p", { children: "Loading your seat terms\u2026" }) : null,
804
- /* @__PURE__ */ jsx9("button", { className: "btn secondary", onClick: () => void load(), children: "Refresh seat status" })
935
+ ] }) : !data.seat ? /* @__PURE__ */ jsx10("p", { children: data.purchaseWindowed === false ? "An additional seat can be purchased for as long as your membership stays paid." : `Additional seats can be purchased until ${day(data.purchaseEndsAt)}.` }) : null,
936
+ pending ? /* @__PURE__ */ jsx10("p", { role: "status", children: "Payment confirmation is being reconciled. The recipient\u2019s access begins only after their own acceptance and approval." }) : null
937
+ ] }) : !error ? /* @__PURE__ */ jsx10("p", { children: "Loading your seat terms\u2026" }) : null,
938
+ /* @__PURE__ */ jsx10("button", { className: "btn secondary", onClick: () => void load(), children: "Refresh seat status" })
805
939
  ] }) });
806
940
  }
807
941
 
808
942
  // src/ui/member-content.tsx
809
- import { useEffect as useEffect5, useMemo as useMemo2, useState as useState8 } from "preact/hooks";
943
+ import { useEffect as useEffect5, useMemo as useMemo2, useState as useState9 } from "preact/hooks";
810
944
  import { Markdown } from "@odla-ai/ui/components";
811
- import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
945
+ import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
812
946
  var pageLabel = (page) => `${page.title}${page.access === "locked" ? " \xB7 Locked" : ""}`;
813
947
  function MemberContentArea(props) {
814
948
  const {
@@ -816,12 +950,12 @@ function MemberContentArea(props) {
816
950
  path = "/api/member-content",
817
951
  upsellHref,
818
952
  onUpsell,
819
- loadingContent = /* @__PURE__ */ jsx10("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
820
- emptyContent = /* @__PURE__ */ jsx10("p", { className: "meeting-note", children: "No member pages have been published yet." })
953
+ loadingContent = /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
954
+ emptyContent = /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: "No member pages have been published yet." })
821
955
  } = props;
822
- const [data, setData] = useState8(props.initialData ?? null);
823
- const [error, setError] = useState8(null);
824
- const [selectedId, setSelectedId] = useState8(
956
+ const [data, setData] = useState9(props.initialData ?? null);
957
+ const [error, setError] = useState9(null);
958
+ const [selectedId, setSelectedId] = useState9(
825
959
  props.initialPageId ?? props.initialData?.pages[0]?.id ?? ""
826
960
  );
827
961
  useEffect5(() => {
@@ -846,18 +980,18 @@ function MemberContentArea(props) {
846
980
  }
847
981
  return [...result.entries()];
848
982
  }, [data]);
849
- if (error) return /* @__PURE__ */ jsxs10("p", { className: "meeting-note", role: "alert", children: [
983
+ if (error) return /* @__PURE__ */ jsxs11("p", { className: "meeting-note", role: "alert", children: [
850
984
  "Member pages could not be loaded: ",
851
985
  error
852
986
  ] });
853
- if (!data) return /* @__PURE__ */ jsx10(Fragment4, { children: loadingContent });
854
- if (data.pages.length === 0) return /* @__PURE__ */ jsx10(Fragment4, { children: emptyContent });
987
+ if (!data) return /* @__PURE__ */ jsx11(Fragment5, { children: loadingContent });
988
+ if (data.pages.length === 0) return /* @__PURE__ */ jsx11(Fragment5, { children: emptyContent });
855
989
  const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
856
990
  const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
857
- return /* @__PURE__ */ jsxs10("div", { className: "chapter-member-content", "data-member-content": true, children: [
858
- /* @__PURE__ */ jsx10("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs10("section", { className: "chapter-member-content-section", children: [
859
- /* @__PURE__ */ jsx10("h2", { children: section }),
860
- /* @__PURE__ */ jsx10("ul", { children: pages.map((page) => /* @__PURE__ */ jsx10("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx10(
991
+ return /* @__PURE__ */ jsxs11("div", { className: "chapter-member-content", "data-member-content": true, children: [
992
+ /* @__PURE__ */ jsx11("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs11("section", { className: "chapter-member-content-section", children: [
993
+ /* @__PURE__ */ jsx11("h2", { children: section }),
994
+ /* @__PURE__ */ jsx11("ul", { children: pages.map((page) => /* @__PURE__ */ jsx11("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx11(
861
995
  "button",
862
996
  {
863
997
  type: "button",
@@ -867,23 +1001,23 @@ function MemberContentArea(props) {
867
1001
  }
868
1002
  ) }, page.id)) })
869
1003
  ] }, section)) }),
870
- /* @__PURE__ */ jsxs10("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
871
- /* @__PURE__ */ jsxs10("header", { children: [
872
- /* @__PURE__ */ jsxs10("div", { className: "card-label", children: [
1004
+ /* @__PURE__ */ jsxs11("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
1005
+ /* @__PURE__ */ jsxs11("header", { children: [
1006
+ /* @__PURE__ */ jsxs11("div", { className: "card-label", children: [
873
1007
  selected.source.type === "parent" ? "Parent" : "Chapter",
874
1008
  " \xB7 ",
875
1009
  selected.access
876
1010
  ] }),
877
- /* @__PURE__ */ jsx10("h1", { children: selected.title }),
878
- selected.summary ? /* @__PURE__ */ jsx10("p", { children: selected.summary }) : null
1011
+ /* @__PURE__ */ jsx11("h1", { children: selected.title }),
1012
+ selected.summary ? /* @__PURE__ */ jsx11("p", { children: selected.summary }) : null
879
1013
  ] }),
880
- selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx10(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs10("div", { className: "chapter-member-content-locked", children: [
881
- selected.teaserMarkdown ? /* @__PURE__ */ jsx10(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx10("p", { children: "This page is not included in your current membership." }),
882
- selected.upsell ? /* @__PURE__ */ jsxs10("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
883
- /* @__PURE__ */ jsx10("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
884
- /* @__PURE__ */ jsx10("p", { children: fmtMoney(selected.upsell.priceCents) }),
885
- selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx10(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
886
- href ? /* @__PURE__ */ jsx10("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx10("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
1014
+ selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx11(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs11("div", { className: "chapter-member-content-locked", children: [
1015
+ selected.teaserMarkdown ? /* @__PURE__ */ jsx11(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx11("p", { children: "This page is not included in your current membership." }),
1016
+ selected.upsell ? /* @__PURE__ */ jsxs11("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
1017
+ /* @__PURE__ */ jsx11("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
1018
+ /* @__PURE__ */ jsx11("p", { children: fmtMoney(selected.upsell.priceCents) }),
1019
+ selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx11(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
1020
+ href ? /* @__PURE__ */ jsx11("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx11("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
887
1021
  ] }) : null
888
1022
  ] })
889
1023
  ] })
@@ -891,12 +1025,12 @@ function MemberContentArea(props) {
891
1025
  }
892
1026
 
893
1027
  // src/ui/members.tsx
894
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
1028
+ import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
895
1029
  function card(copy, kicker, body) {
896
- return /* @__PURE__ */ jsxs11("div", { className: "card", children: [
897
- /* @__PURE__ */ jsx11("div", { className: "card-label", children: copy.provisional.cardLabel }),
898
- /* @__PURE__ */ jsxs11("div", { className: "meeting-block", children: [
899
- /* @__PURE__ */ jsx11("div", { className: "meeting-kicker", children: kicker }),
1030
+ return /* @__PURE__ */ jsxs12("div", { className: "card", children: [
1031
+ /* @__PURE__ */ jsx12("div", { className: "card-label", children: copy.provisional.cardLabel }),
1032
+ /* @__PURE__ */ jsxs12("div", { className: "meeting-block", children: [
1033
+ /* @__PURE__ */ jsx12("div", { className: "meeting-kicker", children: kicker }),
900
1034
  body
901
1035
  ] })
902
1036
  ] });
@@ -907,9 +1041,9 @@ function ProvisionalCard(props) {
907
1041
  return card(
908
1042
  copy,
909
1043
  copy.provisional.applicationNeeded,
910
- /* @__PURE__ */ jsxs11(Fragment5, { children: [
911
- /* @__PURE__ */ jsx11("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
912
- /* @__PURE__ */ jsx11("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
1044
+ /* @__PURE__ */ jsxs12(Fragment6, { children: [
1045
+ /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
1046
+ /* @__PURE__ */ jsx12("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
913
1047
  ] })
914
1048
  );
915
1049
  }
@@ -917,19 +1051,19 @@ function ProvisionalCard(props) {
917
1051
  return card(
918
1052
  copy,
919
1053
  copy.provisional.refunded,
920
- /* @__PURE__ */ jsx11("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1054
+ /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: copy.provisional.refundedBody })
921
1055
  );
922
1056
  }
923
- const membership = application.paid ? /* @__PURE__ */ jsx11("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
1057
+ const membership = application.paid ? /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
924
1058
  if (application.meetingAt) {
925
1059
  return card(
926
1060
  copy,
927
1061
  copy.provisional.introductionCall,
928
- /* @__PURE__ */ jsxs11(Fragment5, { children: [
929
- /* @__PURE__ */ jsx11("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
930
- /* @__PURE__ */ jsx11("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
931
- application.meetUrl ? /* @__PURE__ */ jsx11("div", { className: "meeting-note", children: /* @__PURE__ */ jsx11("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
932
- /* @__PURE__ */ jsx11(
1062
+ /* @__PURE__ */ jsxs12(Fragment6, { children: [
1063
+ /* @__PURE__ */ jsx12("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
1064
+ /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
1065
+ application.meetUrl ? /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: /* @__PURE__ */ jsx12("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
1066
+ /* @__PURE__ */ jsx12(
933
1067
  Rescheduler,
934
1068
  {
935
1069
  api,
@@ -946,9 +1080,9 @@ function ProvisionalCard(props) {
946
1080
  return card(
947
1081
  copy,
948
1082
  copy.provisional.bookCall,
949
- /* @__PURE__ */ jsxs11(Fragment5, { children: [
950
- /* @__PURE__ */ jsx11("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
951
- /* @__PURE__ */ jsx11(
1083
+ /* @__PURE__ */ jsxs12(Fragment6, { children: [
1084
+ /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
1085
+ /* @__PURE__ */ jsx12(
952
1086
  Rescheduler,
953
1087
  {
954
1088
  api,
@@ -975,8 +1109,8 @@ function MembersArea(props) {
975
1109
  renderProvisional
976
1110
  } = props;
977
1111
  const copy = props.copy ?? inheritedCopy.members;
978
- const [me, setMe] = useState9(null);
979
- const [error, setError] = useState9(false);
1112
+ const [me, setMe] = useState10(null);
1113
+ const [error, setError] = useState10(false);
980
1114
  const reload = async () => {
981
1115
  try {
982
1116
  setMe(await api("/api/me"));
@@ -987,22 +1121,22 @@ function MembersArea(props) {
987
1121
  useEffect6(() => {
988
1122
  void reload();
989
1123
  }, []);
990
- if (error) return /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: copy.loadFailed });
991
- if (!me) return /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: inheritedCopy.common.loading });
1124
+ if (error) return /* @__PURE__ */ jsx12("p", { className: "meeting-note", children: copy.loadFailed });
1125
+ if (!me) return /* @__PURE__ */ jsx12("p", { className: "meeting-note", children: inheritedCopy.common.loading });
992
1126
  const role = me.role || "provisional";
993
- return /* @__PURE__ */ jsxs11(Fragment5, { children: [
994
- /* @__PURE__ */ jsxs11("div", { className: "card", children: [
995
- /* @__PURE__ */ jsxs11("div", { className: "member-row", children: [
996
- /* @__PURE__ */ jsx11("span", { className: "member-email", children: me.email }),
997
- /* @__PURE__ */ jsx11("span", { className: "role-badge " + role, children: role })
1127
+ return /* @__PURE__ */ jsxs12(Fragment6, { children: [
1128
+ /* @__PURE__ */ jsxs12("div", { className: "card", children: [
1129
+ /* @__PURE__ */ jsxs12("div", { className: "member-row", children: [
1130
+ /* @__PURE__ */ jsx12("span", { className: "member-email", children: me.email }),
1131
+ /* @__PURE__ */ jsx12("span", { className: "role-badge " + role, children: role })
998
1132
  ] }),
999
- /* @__PURE__ */ jsxs11("div", { className: "account-actions", children: [
1000
- /* @__PURE__ */ jsx11("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
1001
- me.authorized || me.superAdmin ? /* @__PURE__ */ jsx11("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
1133
+ /* @__PURE__ */ jsxs12("div", { className: "account-actions", children: [
1134
+ /* @__PURE__ */ jsx12("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
1135
+ me.authorized || me.superAdmin ? /* @__PURE__ */ jsx12("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
1002
1136
  ] })
1003
1137
  ] }),
1004
- me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx11(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
1005
- const defaultContent = /* @__PURE__ */ jsx11(
1138
+ me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx12(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
1139
+ const defaultContent = /* @__PURE__ */ jsx12(
1006
1140
  ProvisionalCard,
1007
1141
  {
1008
1142
  api,
@@ -1019,30 +1153,30 @@ function MembersArea(props) {
1019
1153
  reload,
1020
1154
  defaultContent
1021
1155
  }) ?? defaultContent;
1022
- })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx11(
1156
+ })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx12(
1023
1157
  MemberContentArea,
1024
1158
  {
1025
1159
  api,
1026
1160
  ...memberPages === true ? {} : memberPages
1027
1161
  }
1028
- ) : /* @__PURE__ */ jsx11("div", { className: "card", children: /* @__PURE__ */ jsx11("div", { className: "card-label", children: copy.full.welcome }) })),
1029
- /* @__PURE__ */ jsx11(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
1030
- me.namedSeatsEnabled ? /* @__PURE__ */ jsx11(NamedSeatPurchase, { api }) : null
1162
+ ) : /* @__PURE__ */ jsx12("div", { className: "card", children: /* @__PURE__ */ jsx12("div", { className: "card-label", children: copy.full.welcome }) })),
1163
+ /* @__PURE__ */ jsx12(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
1164
+ me.namedSeatsEnabled ? /* @__PURE__ */ jsx12(NamedSeatPurchase, { api }) : null
1031
1165
  ] });
1032
1166
  }
1033
1167
 
1034
1168
  // src/ui/join.tsx
1035
- import { useEffect as useEffect10, useRef as useRef3, useState as useState16 } from "preact/hooks";
1169
+ import { useEffect as useEffect11, useRef as useRef3, useState as useState18 } from "preact/hooks";
1036
1170
 
1037
1171
  // src/ui/join-booking.tsx
1038
- import { useEffect as useEffect7, useState as useState10 } from "preact/hooks";
1039
- import { jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
1172
+ import { useEffect as useEffect7, useState as useState11 } from "preact/hooks";
1173
+ import { jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
1040
1174
  function JoinBooking(props) {
1041
1175
  const { applicationId, copy, onBooked, simulation } = props;
1042
- const [state, setState] = useState10(null);
1043
- const [msg, setMsg] = useState10(null);
1044
- const [busy, setBusy] = useState10(false);
1045
- const [selected, setSelected] = useState10(null);
1176
+ const [state, setState] = useState11(null);
1177
+ const [msg, setMsg] = useState11(null);
1178
+ const [busy, setBusy] = useState11(false);
1179
+ const [selected, setSelected] = useState11(null);
1046
1180
  const load = async () => {
1047
1181
  setMsg(null);
1048
1182
  try {
@@ -1099,11 +1233,11 @@ function JoinBooking(props) {
1099
1233
  setBusy(false);
1100
1234
  }
1101
1235
  };
1102
- if (!state) return /* @__PURE__ */ jsx12("p", { className: "slots-status", children: msg ?? copy.loading });
1103
- return /* @__PURE__ */ jsxs12("div", { className: "join-book", children: [
1104
- /* @__PURE__ */ jsx12("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
1105
- /* @__PURE__ */ jsx12("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
1106
- /* @__PURE__ */ jsx12(
1236
+ if (!state) return /* @__PURE__ */ jsx13("p", { className: "slots-status", children: msg ?? copy.loading });
1237
+ return /* @__PURE__ */ jsxs13("div", { className: "join-book", children: [
1238
+ /* @__PURE__ */ jsx13("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
1239
+ /* @__PURE__ */ jsx13("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
1240
+ /* @__PURE__ */ jsx13(
1107
1241
  SlotPicker,
1108
1242
  {
1109
1243
  slots: state.slots,
@@ -1113,29 +1247,29 @@ function JoinBooking(props) {
1113
1247
  onDayChange: () => setSelected(null)
1114
1248
  }
1115
1249
  ),
1116
- /* @__PURE__ */ jsxs12("div", { className: "slot-confirm", hidden: !selected, children: [
1117
- /* @__PURE__ */ jsx12("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
1118
- msg ? /* @__PURE__ */ jsx12("p", { className: "step2-note", children: msg }) : null
1250
+ /* @__PURE__ */ jsxs13("div", { className: "slot-confirm", hidden: !selected, children: [
1251
+ /* @__PURE__ */ jsx13("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
1252
+ msg ? /* @__PURE__ */ jsx13("p", { className: "step2-note", children: msg }) : null
1119
1253
  ] })
1120
1254
  ] });
1121
1255
  }
1122
1256
 
1123
1257
  // src/ui/join-accepted.tsx
1124
- import { jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
1258
+ import { jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
1125
1259
  function JoinAccepted(props) {
1126
- return /* @__PURE__ */ jsxs13("div", { className: "join-done card", children: [
1127
- /* @__PURE__ */ jsx13("div", { className: "card-label", children: props.copy.accepted.label }),
1128
- /* @__PURE__ */ jsx13("p", { className: "meeting-note", children: props.copy.accepted.body }),
1129
- /* @__PURE__ */ jsx13("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
1260
+ return /* @__PURE__ */ jsxs14("div", { className: "join-done card", children: [
1261
+ /* @__PURE__ */ jsx14("div", { className: "card-label", children: props.copy.accepted.label }),
1262
+ /* @__PURE__ */ jsx14("p", { className: "meeting-note", children: props.copy.accepted.body }),
1263
+ /* @__PURE__ */ jsx14("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
1130
1264
  ] });
1131
1265
  }
1132
1266
 
1133
1267
  // src/ui/gift-claim-card.tsx
1134
- import { useState as useState11 } from "preact/hooks";
1135
- import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
1268
+ import { useState as useState12 } from "preact/hooks";
1269
+ import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs15 } from "preact/jsx-runtime";
1136
1270
  function GiftClaimCard(props) {
1137
- const [code, setCode] = useState11(props.initialCode ?? "");
1138
- const [error, setError] = useState11(false);
1271
+ const [code, setCode] = useState12(props.initialCode ?? "");
1272
+ const [error, setError] = useState12(false);
1139
1273
  const rotate = async () => {
1140
1274
  if (!props.claimId) return;
1141
1275
  setError(false);
@@ -1148,30 +1282,30 @@ function GiftClaimCard(props) {
1148
1282
  if (response.ok && body.code) setCode(body.code);
1149
1283
  else setError(true);
1150
1284
  };
1151
- return /* @__PURE__ */ jsxs14("div", { className: "join-done card", children: [
1152
- /* @__PURE__ */ jsx14("div", { className: "card-label", children: props.copy.label }),
1153
- /* @__PURE__ */ jsx14("p", { className: "meeting-note", children: props.copy.body }),
1154
- code ? /* @__PURE__ */ jsxs14(Fragment6, { children: [
1155
- /* @__PURE__ */ jsx14("output", { className: "gift-code", children: code }),
1156
- /* @__PURE__ */ jsx14("p", { children: props.copy.save })
1285
+ return /* @__PURE__ */ jsxs15("div", { className: "join-done card", children: [
1286
+ /* @__PURE__ */ jsx15("div", { className: "card-label", children: props.copy.label }),
1287
+ /* @__PURE__ */ jsx15("p", { className: "meeting-note", children: props.copy.body }),
1288
+ code ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
1289
+ /* @__PURE__ */ jsx15("output", { className: "gift-code", children: code }),
1290
+ /* @__PURE__ */ jsx15("p", { children: props.copy.save })
1157
1291
  ] }) : null,
1158
- !code && props.claimId ? /* @__PURE__ */ jsx14("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
1159
- error ? /* @__PURE__ */ jsx14("p", { role: "alert", children: props.copy.rotateFailed }) : null
1292
+ !code && props.claimId ? /* @__PURE__ */ jsx15("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
1293
+ error ? /* @__PURE__ */ jsx15("p", { role: "alert", children: props.copy.rotateFailed }) : null
1160
1294
  ] });
1161
1295
  }
1162
1296
 
1163
1297
  // src/ui/join-tiers.tsx
1164
- import { useState as useState12 } from "preact/hooks";
1165
- import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs15 } from "preact/jsx-runtime";
1298
+ import { useState as useState13 } from "preact/hooks";
1299
+ import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs16 } from "preact/jsx-runtime";
1166
1300
  var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
1167
1301
  function useTierSelection(tiers, initialTierId) {
1168
- const [selectedTierId, setSelectedTierId] = useState12(() => {
1302
+ const [selectedTierId, setSelectedTierId] = useState13(() => {
1169
1303
  const preset = tiers.find((tier) => tier.id === initialTierId);
1170
1304
  if (preset) return preset.id;
1171
1305
  return tiers.length === 1 ? tiers[0].id : null;
1172
1306
  });
1173
1307
  return {
1174
- tiers,
1308
+ tiers: [...tiers].sort((a, b) => Number(b.id === selectedTierId) - Number(a.id === selectedTierId)),
1175
1309
  selected: tiers.find((tier) => tier.id === selectedTierId) ?? null,
1176
1310
  selectedTierId,
1177
1311
  selectTier: (tierId) => {
@@ -1180,10 +1314,10 @@ function useTierSelection(tiers, initialTierId) {
1180
1314
  };
1181
1315
  }
1182
1316
  function TierPlaceholder(context) {
1183
- return /* @__PURE__ */ jsxs15("fieldset", { "data-chapter-placeholder": "tiers", children: [
1184
- /* @__PURE__ */ jsx15("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
1185
- context.tiers.map((tier) => /* @__PURE__ */ jsxs15("label", { children: [
1186
- /* @__PURE__ */ jsx15(
1317
+ return /* @__PURE__ */ jsxs16("fieldset", { "data-chapter-placeholder": "tiers", children: [
1318
+ /* @__PURE__ */ jsx16("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
1319
+ context.tiers.map((tier) => /* @__PURE__ */ jsxs16("label", { children: [
1320
+ /* @__PURE__ */ jsx16(
1187
1321
  "input",
1188
1322
  {
1189
1323
  type: "radio",
@@ -1194,13 +1328,13 @@ function TierPlaceholder(context) {
1194
1328
  }
1195
1329
  ),
1196
1330
  tier.name,
1197
- tier.founding ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
1331
+ tier.founding ? /* @__PURE__ */ jsxs16(Fragment8, { children: [
1198
1332
  " \u2014 ",
1199
1333
  joinTierMoney(tier.founding.dueTodayCents),
1200
1334
  " founding member rate (list ",
1201
1335
  joinTierMoney(tier.priceCents),
1202
1336
  ")"
1203
- ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs15(Fragment7, { children: [
1337
+ ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs16(Fragment8, { children: [
1204
1338
  " \u2014 ",
1205
1339
  joinTierMoney(tier.priceCents)
1206
1340
  ] })
@@ -1212,19 +1346,19 @@ function tierNeedsPayment(selected, paymentsReady) {
1212
1346
  }
1213
1347
 
1214
1348
  // src/ui/join-application-form.tsx
1215
- import { jsx as jsx16, jsxs as jsxs16 } from "preact/jsx-runtime";
1349
+ import { jsx as jsx17, jsxs as jsxs17 } from "preact/jsx-runtime";
1216
1350
  function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
1217
1351
  const disabled = submitting || props.submitDisabled === true;
1218
- return /* @__PURE__ */ jsxs16("form", { className: "join-form", onSubmit: (event) => void submit(event), children: [
1219
- !requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs16("fieldset", { children: [
1220
- /* @__PURE__ */ jsx16("legend", { children: copy.gift.optionsLabel }),
1221
- /* @__PURE__ */ jsx16("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
1222
- /* @__PURE__ */ jsx16(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
1352
+ return /* @__PURE__ */ jsxs17("form", { className: "join-form", onSubmit: (event) => void submit(event), children: [
1353
+ !requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs17("fieldset", { children: [
1354
+ /* @__PURE__ */ jsx17("legend", { children: copy.gift.optionsLabel }),
1355
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
1356
+ /* @__PURE__ */ jsx17(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
1223
1357
  ] }) : null,
1224
1358
  !requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
1225
1359
  typeof props.children === "function" ? props.children({ invitation }) : props.children,
1226
- error ? /* @__PURE__ */ jsx16("p", { className: "join-error", role: "alert", children: error }) : null,
1227
- props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx16("button", { className: "submit-btn", type: "submit", disabled, children: submitting ? copy.form.submitting : copy.form.submit })
1360
+ error ? /* @__PURE__ */ jsx17("p", { className: "join-error", role: "alert", children: error }) : null,
1361
+ props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx17("button", { className: "submit-btn", type: "submit", disabled, children: submitting ? copy.form.submitting : copy.form.submit })
1228
1362
  ] });
1229
1363
  }
1230
1364
 
@@ -1249,8 +1383,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
1249
1383
 
1250
1384
  // src/ui/gift-code-redeemer.tsx
1251
1385
  import { InlineActionField } from "@odla-ai/ui/components";
1252
- import { useState as useState13 } from "preact/hooks";
1253
- import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs17 } from "preact/jsx-runtime";
1386
+ import { useState as useState14 } from "preact/hooks";
1387
+ import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs18 } from "preact/jsx-runtime";
1254
1388
  var GIFT_CODE_REDEEMER_CSS = `
1255
1389
  .gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
1256
1390
  .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}
@@ -1265,10 +1399,10 @@ var GIFT_CODE_REDEEMER_CSS = `
1265
1399
  @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%}}
1266
1400
  `;
1267
1401
  function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1268
- const [code, setCode] = useState13("");
1269
- const [loading, setLoading] = useState13(false);
1270
- const [message, setMessage] = useState13("");
1271
- const [messageTone, setMessageTone] = useState13("neutral");
1402
+ const [code, setCode] = useState14("");
1403
+ const [loading, setLoading] = useState14(false);
1404
+ const [message, setMessage] = useState14("");
1405
+ const [messageTone, setMessageTone] = useState14("neutral");
1272
1406
  const normalizedCode = code.trim();
1273
1407
  const redeem = async () => {
1274
1408
  if (!normalizedCode || loading) return;
@@ -1295,9 +1429,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1295
1429
  setLoading(false);
1296
1430
  }
1297
1431
  };
1298
- return /* @__PURE__ */ jsxs17(Fragment8, { children: [
1299
- /* @__PURE__ */ jsx17("style", { children: GIFT_CODE_REDEEMER_CSS }),
1300
- /* @__PURE__ */ jsx17(
1432
+ return /* @__PURE__ */ jsxs18(Fragment9, { children: [
1433
+ /* @__PURE__ */ jsx18("style", { children: GIFT_CODE_REDEEMER_CSS }),
1434
+ /* @__PURE__ */ jsx18(
1301
1435
  InlineActionField,
1302
1436
  {
1303
1437
  id,
@@ -1353,12 +1487,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
1353
1487
  }
1354
1488
 
1355
1489
  // src/ui/join-gift-claim.tsx
1356
- import { jsx as jsx18, jsxs as jsxs18 } from "preact/jsx-runtime";
1490
+ import { jsx as jsx19, jsxs as jsxs19 } from "preact/jsx-runtime";
1357
1491
  function JoinGiftClaim(props) {
1358
- return /* @__PURE__ */ jsxs18("section", { className: "join-gift-claim card", children: [
1359
- /* @__PURE__ */ jsx18("div", { className: "card-label", children: props.copy.claimTitle }),
1360
- /* @__PURE__ */ jsx18("p", { children: props.copy.claimBody }),
1361
- /* @__PURE__ */ jsx18(
1492
+ return /* @__PURE__ */ jsxs19("section", { className: "join-gift-claim card", children: [
1493
+ /* @__PURE__ */ jsx19("div", { className: "card-label", children: props.copy.claimTitle }),
1494
+ /* @__PURE__ */ jsx19("p", { children: props.copy.claimBody }),
1495
+ /* @__PURE__ */ jsx19(
1362
1496
  GiftCodeRedeemer,
1363
1497
  {
1364
1498
  api: props.api,
@@ -1382,21 +1516,21 @@ function JoinGiftClaim(props) {
1382
1516
  }
1383
1517
 
1384
1518
  // src/ui/join-named-seat.tsx
1385
- import { useState as useState14 } from "preact/hooks";
1386
- import { jsx as jsx19, jsxs as jsxs19 } from "preact/jsx-runtime";
1519
+ import { useState as useState15 } from "preact/hooks";
1520
+ import { jsx as jsx20, jsxs as jsxs20 } from "preact/jsx-runtime";
1387
1521
  function JoinNamedSeat(props) {
1388
1522
  const seatId = props.seatId ?? "";
1389
1523
  const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
1390
- const [accepted, setAccepted] = useState14(false), [busy, setBusy] = useState14(false), [error, setError] = useState14("");
1391
- return /* @__PURE__ */ jsxs19("section", { className: "join-named-seat card", children: [
1392
- /* @__PURE__ */ jsx19("h2", { children: copy.title }),
1393
- /* @__PURE__ */ jsx19("p", { children: copy.body }),
1394
- /* @__PURE__ */ jsxs19("label", { className: "journey-consent", children: [
1395
- /* @__PURE__ */ jsx19("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
1396
- /* @__PURE__ */ jsx19("span", { children: copy.consent })
1524
+ const [accepted, setAccepted] = useState15(false), [busy, setBusy] = useState15(false), [error, setError] = useState15("");
1525
+ return /* @__PURE__ */ jsxs20("section", { className: "join-named-seat card", children: [
1526
+ /* @__PURE__ */ jsx20("h2", { children: copy.title }),
1527
+ /* @__PURE__ */ jsx20("p", { children: copy.body }),
1528
+ /* @__PURE__ */ jsxs20("label", { className: "journey-consent", children: [
1529
+ /* @__PURE__ */ jsx20("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
1530
+ /* @__PURE__ */ jsx20("span", { children: copy.consent })
1397
1531
  ] }),
1398
- error ? /* @__PURE__ */ jsx19("p", { role: "alert", children: error }) : null,
1399
- /* @__PURE__ */ jsx19("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
1532
+ error ? /* @__PURE__ */ jsx20("p", { role: "alert", children: error }) : null,
1533
+ /* @__PURE__ */ jsx20("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
1400
1534
  setBusy(true);
1401
1535
  setError("");
1402
1536
  try {
@@ -1416,12 +1550,12 @@ function JoinNamedSeat(props) {
1416
1550
  }
1417
1551
 
1418
1552
  // src/ui/join-invitation.tsx
1419
- import { useEffect as useEffect8, useState as useState15 } from "preact/hooks";
1420
- import { jsx as jsx20, jsxs as jsxs20 } from "preact/jsx-runtime";
1553
+ import { useEffect as useEffect8, useState as useState16 } from "preact/hooks";
1554
+ import { jsx as jsx21, jsxs as jsxs21 } from "preact/jsx-runtime";
1421
1555
  function useJoinInvitation(seatId, api, fallback) {
1422
- const [invitation, setInvitation] = useState15(null);
1423
- const [error, setError] = useState15("");
1424
- const [revision, setRevision] = useState15(0);
1556
+ const [invitation, setInvitation] = useState16(null);
1557
+ const [error, setError] = useState16("");
1558
+ const [revision, setRevision] = useState16(0);
1425
1559
  useEffect8(() => {
1426
1560
  let live = true;
1427
1561
  setInvitation(null);
@@ -1444,9 +1578,9 @@ function useJoinInvitation(seatId, api, fallback) {
1444
1578
  return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
1445
1579
  }
1446
1580
  function JoinInvitationNotice(props) {
1447
- return /* @__PURE__ */ jsxs20("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
1448
- /* @__PURE__ */ jsx20("p", { children: /* @__PURE__ */ jsx20("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
1449
- /* @__PURE__ */ jsx20("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
1581
+ return /* @__PURE__ */ jsxs21("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
1582
+ /* @__PURE__ */ jsx21("p", { children: /* @__PURE__ */ jsx21("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
1583
+ /* @__PURE__ */ jsx21("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
1450
1584
  ] });
1451
1585
  }
1452
1586
 
@@ -1475,10 +1609,93 @@ function useJoinPending(state, loadResume, setState) {
1475
1609
  }, [state, loadResume]);
1476
1610
  }
1477
1611
 
1612
+ // src/ui/payment-receipt.tsx
1613
+ import { useEffect as useEffect10, useState as useState17 } from "preact/hooks";
1614
+ import { Fragment as Fragment10, jsx as jsx22, jsxs as jsxs22 } from "preact/jsx-runtime";
1615
+ function PaymentReceiptCard({ applicationId }) {
1616
+ const [receipt, setReceipt] = useState17(null);
1617
+ const [error, setError] = useState17("");
1618
+ const [revision, setRevision] = useState17(0);
1619
+ const [emailState, setEmailState] = useState17("idle");
1620
+ const [previewEmail, setPreviewEmail] = useState17(false);
1621
+ const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
1622
+ useEffect10(() => {
1623
+ let live = true, timer;
1624
+ setReceipt(null);
1625
+ setError("");
1626
+ setEmailState("idle");
1627
+ const read = async () => {
1628
+ try {
1629
+ const response = await fetch(endpoint, { cache: "no-store" });
1630
+ if (!live || response.status === 404) return;
1631
+ if (response.status === 202) {
1632
+ timer = setTimeout(() => void read(), 2e3);
1633
+ return;
1634
+ }
1635
+ if (!response.ok) throw new Error();
1636
+ const data = await response.json();
1637
+ if (live) setReceipt(data.receipt);
1638
+ } catch {
1639
+ if (live) setError("Your receipt is temporarily unavailable.");
1640
+ }
1641
+ };
1642
+ void read();
1643
+ return () => {
1644
+ live = false;
1645
+ if (timer) clearTimeout(timer);
1646
+ };
1647
+ }, [endpoint, revision]);
1648
+ if (!receipt) return error ? /* @__PURE__ */ jsxs22("section", { "aria-label": "Payment receipt", children: [
1649
+ /* @__PURE__ */ jsx22("p", { role: "status", children: error }),
1650
+ /* @__PURE__ */ jsx22("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
1651
+ ] }) : null;
1652
+ const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
1653
+ const email = async () => {
1654
+ setEmailState("sending");
1655
+ setError("");
1656
+ try {
1657
+ const response = await fetch(endpoint, { method: "POST" });
1658
+ if (!response.ok) throw new Error();
1659
+ const result = await response.json();
1660
+ setPreviewEmail(result.preview === true);
1661
+ setEmailState("sent");
1662
+ } catch {
1663
+ setEmailState("idle");
1664
+ setError("We could not confirm email delivery. You can print or save your receipt.");
1665
+ }
1666
+ };
1667
+ return /* @__PURE__ */ jsxs22("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
1668
+ /* @__PURE__ */ jsx22("h2", { children: "Payment received" }),
1669
+ /* @__PURE__ */ jsx22("p", { children: receipt.tierName }),
1670
+ /* @__PURE__ */ jsxs22("dl", { className: "journey-summary", children: [
1671
+ /* @__PURE__ */ jsx22("dt", { children: "Membership" }),
1672
+ /* @__PURE__ */ jsx22("dd", { children: money(receipt.membershipCents) }),
1673
+ receipt.namedSeat ? /* @__PURE__ */ jsxs22(Fragment10, { children: [
1674
+ /* @__PURE__ */ jsxs22("dt", { children: [
1675
+ "Additional member \u2014 ",
1676
+ receipt.namedSeat.recipientName
1677
+ ] }),
1678
+ /* @__PURE__ */ jsxs22("dd", { children: [
1679
+ receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
1680
+ money(receipt.namedSeat.amountCents)
1681
+ ] })
1682
+ ] }) : null,
1683
+ /* @__PURE__ */ jsx22("dt", { children: "Total paid" }),
1684
+ /* @__PURE__ */ jsx22("dd", { children: money(receipt.totalCents) })
1685
+ ] }),
1686
+ /* @__PURE__ */ jsxs22("div", { className: "journey-actions", children: [
1687
+ /* @__PURE__ */ jsx22("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
1688
+ /* @__PURE__ */ jsx22("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
1689
+ ] }),
1690
+ emailState === "sent" ? /* @__PURE__ */ jsx22("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
1691
+ error ? /* @__PURE__ */ jsx22("p", { role: "alert", children: error }) : null
1692
+ ] });
1693
+ }
1694
+
1478
1695
  // src/ui/join.tsx
1479
- import { Fragment as Fragment9, jsx as jsx21, jsxs as jsxs21 } from "preact/jsx-runtime";
1696
+ import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs23 } from "preact/jsx-runtime";
1480
1697
  function JoinIsland(props) {
1481
- return /* @__PURE__ */ jsx21(JourneyFrame, { children: /* @__PURE__ */ jsx21(JoinFlow, { ...props }) });
1698
+ return /* @__PURE__ */ jsx23(JourneyFrame, { children: /* @__PURE__ */ jsx23(JoinFlow, { ...props }) });
1482
1699
  }
1483
1700
  function JoinFlow(props) {
1484
1701
  const inheritedCopy = useChapterCopy();
@@ -1499,10 +1716,10 @@ function JoinFlow(props) {
1499
1716
  const invitation = invitationState.invitation;
1500
1717
  const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
1501
1718
  const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
1502
- const [state, setState] = useState16(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1503
- const [error, setError] = useState16(null);
1504
- const [submitting, setSubmitting] = useState16(false);
1505
- const [giftOfferId, setGiftOfferId] = useState16(props.initialGiftOfferId ?? null);
1719
+ const [state, setState] = useState18(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1720
+ const [error, setError] = useState18(null);
1721
+ const [submitting, setSubmitting] = useState18(false);
1722
+ const [giftOfferId, setGiftOfferId] = useState18(props.initialGiftOfferId ?? null);
1506
1723
  const simulatedPayment = props.simulation ? props.simulation.payment ?? {
1507
1724
  lineItems: {
1508
1725
  standardCents: selectedTier?.priceCents ?? 0,
@@ -1512,7 +1729,7 @@ function JoinFlow(props) {
1512
1729
  } : void 0;
1513
1730
  const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
1514
1731
  const submissionId = useRef3(null);
1515
- useEffect10(() => {
1732
+ useEffect11(() => {
1516
1733
  if (props.simulation) return;
1517
1734
  const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
1518
1735
  if (typeof window === "undefined") return Promise.resolve(null);
@@ -1581,13 +1798,13 @@ function JoinFlow(props) {
1581
1798
  setSubmitting(false);
1582
1799
  }
1583
1800
  };
1584
- if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs21("section", { className: "card", "aria-live": "polite", children: [
1585
- /* @__PURE__ */ jsx21("h2", { children: seatCopy.title }),
1586
- /* @__PURE__ */ jsx21("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
1587
- invitationState.error ? /* @__PURE__ */ jsx21("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
1801
+ if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs23("section", { className: "card", "aria-live": "polite", children: [
1802
+ /* @__PURE__ */ jsx23("h2", { children: seatCopy.title }),
1803
+ /* @__PURE__ */ jsx23("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
1804
+ invitationState.error ? /* @__PURE__ */ jsx23("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
1588
1805
  ] });
1589
- const header = /* @__PURE__ */ jsxs21(Fragment9, { children: [
1590
- invitation ? /* @__PURE__ */ jsx21(
1806
+ const header = /* @__PURE__ */ jsxs23(Fragment11, { children: [
1807
+ invitation ? /* @__PURE__ */ jsx23(
1591
1808
  JoinInvitationNotice,
1592
1809
  {
1593
1810
  invitation,
@@ -1599,48 +1816,49 @@ function JoinFlow(props) {
1599
1816
  state,
1600
1817
  ...invitation ? { invitation } : {},
1601
1818
  ..."applicationId" in state ? { applicationId: state.applicationId } : {}
1602
- })
1819
+ }),
1820
+ !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx23(PaymentReceiptCard, { applicationId: state.applicationId }) : null
1603
1821
  ] });
1604
1822
  if (state.step === "closed") {
1605
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1823
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1606
1824
  header,
1607
- /* @__PURE__ */ jsxs21("section", { className: "card", "aria-label": "Application closed", children: [
1608
- /* @__PURE__ */ jsx21("h2", { children: "This application is closed" }),
1609
- /* @__PURE__ */ jsx21("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
1610
- /* @__PURE__ */ jsx21("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1825
+ /* @__PURE__ */ jsxs23("section", { className: "card", "aria-label": "Application closed", children: [
1826
+ /* @__PURE__ */ jsx23("h2", { children: "This application is closed" }),
1827
+ /* @__PURE__ */ jsx23("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
1828
+ /* @__PURE__ */ jsx23("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1611
1829
  ] })
1612
1830
  ] });
1613
1831
  }
1614
1832
  if (state.step === "done") {
1615
- const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs21("div", { className: "join-done card", children: [
1616
- /* @__PURE__ */ jsx21("div", { className: "card-label", children: copy.done.label }),
1617
- /* @__PURE__ */ jsx21("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
1618
- /* @__PURE__ */ jsx21("p", { className: "meeting-note", children: copy.done.calendarInvite }),
1619
- /* @__PURE__ */ jsx21("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1833
+ const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs23("div", { className: "join-done card", children: [
1834
+ /* @__PURE__ */ jsx23("div", { className: "card-label", children: copy.done.label }),
1835
+ /* @__PURE__ */ jsx23("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
1836
+ /* @__PURE__ */ jsx23("p", { className: "meeting-note", children: copy.done.calendarInvite }),
1837
+ /* @__PURE__ */ jsx23("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1620
1838
  ] });
1621
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1839
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1622
1840
  header,
1623
1841
  body
1624
1842
  ] });
1625
1843
  }
1626
1844
  if (state.step === "accepted") {
1627
- const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx21(JoinAccepted, { copy, membersHref });
1628
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1845
+ const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx23(JoinAccepted, { copy, membersHref });
1846
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1629
1847
  header,
1630
1848
  body
1631
1849
  ] });
1632
1850
  }
1633
1851
  if (state.step === "gift") {
1634
- const body = renderGift?.(state) ?? /* @__PURE__ */ jsx21(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1635
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1852
+ const body = renderGift?.(state) ?? /* @__PURE__ */ jsx23(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1853
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1636
1854
  header,
1637
1855
  body
1638
1856
  ] });
1639
1857
  }
1640
1858
  if (state.step === "booking") {
1641
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1859
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1642
1860
  header,
1643
- /* @__PURE__ */ jsx21(
1861
+ /* @__PURE__ */ jsx23(
1644
1862
  JoinBooking,
1645
1863
  {
1646
1864
  applicationId: state.applicationId,
@@ -1655,9 +1873,9 @@ function JoinFlow(props) {
1655
1873
  }
1656
1874
  if (state.step === "payment") {
1657
1875
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
1658
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1876
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1659
1877
  header,
1660
- /* @__PURE__ */ jsx21(
1878
+ /* @__PURE__ */ jsx23(
1661
1879
  JoinNamedSeat,
1662
1880
  {
1663
1881
  api: props.namedSeatClaimApi,
@@ -1670,9 +1888,9 @@ function JoinFlow(props) {
1670
1888
  ] });
1671
1889
  }
1672
1890
  const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
1673
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1891
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1674
1892
  header,
1675
- props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx21(
1893
+ props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx23(
1676
1894
  JoinGiftClaim,
1677
1895
  {
1678
1896
  api: props.giftClaimApi,
@@ -1683,7 +1901,7 @@ function JoinFlow(props) {
1683
1901
  onError: () => setError(copy.form.unexpectedFailure)
1684
1902
  }
1685
1903
  ) : null,
1686
- /* @__PURE__ */ jsx21(
1904
+ /* @__PURE__ */ jsx23(
1687
1905
  Payment,
1688
1906
  {
1689
1907
  applicationId: state.applicationId,
@@ -1691,6 +1909,7 @@ function JoinFlow(props) {
1691
1909
  merchantDisclosureText: config.merchantDisclosureText,
1692
1910
  copy: copy.payment,
1693
1911
  appearance: props.payment?.appearance,
1912
+ initialNamedSeat: props.payment?.initialNamedSeat,
1694
1913
  fonts: props.payment?.fonts,
1695
1914
  renderPriceLines: props.payment?.renderPriceLines,
1696
1915
  simulation: simulatedPayment,
@@ -1712,9 +1931,9 @@ function JoinFlow(props) {
1712
1931
  }
1713
1932
  if (state.step === "paymentPending") {
1714
1933
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
1715
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1934
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1716
1935
  header,
1717
- /* @__PURE__ */ jsx21(
1936
+ /* @__PURE__ */ jsx23(
1718
1937
  JoinNamedSeat,
1719
1938
  {
1720
1939
  api: props.namedSeatClaimApi,
@@ -1726,14 +1945,14 @@ function JoinFlow(props) {
1726
1945
  )
1727
1946
  ] });
1728
1947
  }
1729
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1948
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1730
1949
  header,
1731
- /* @__PURE__ */ jsx21("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1950
+ /* @__PURE__ */ jsx23("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1732
1951
  ] });
1733
1952
  }
1734
- return /* @__PURE__ */ jsxs21(Fragment9, { children: [
1953
+ return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1735
1954
  header,
1736
- /* @__PURE__ */ jsx21(
1955
+ /* @__PURE__ */ jsx23(
1737
1956
  JoinApplicationForm,
1738
1957
  {
1739
1958
  props,
@@ -1923,7 +2142,7 @@ function membershipPageDocument(input, options = {}) {
1923
2142
  }
1924
2143
 
1925
2144
  // src/ui/membership-cards.tsx
1926
- import { jsx as jsx22, jsxs as jsxs22 } from "preact/jsx-runtime";
2145
+ import { jsx as jsx24, jsxs as jsxs24 } from "preact/jsx-runtime";
1927
2146
  var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
1928
2147
  "--ui-membership-grid-gap": "1.4rem",
1929
2148
  "--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
@@ -1992,67 +2211,67 @@ function membershipApplicationHref(applicationPath, tierId) {
1992
2211
  }
1993
2212
  function TierAction(props) {
1994
2213
  if (props.mode === "select") {
1995
- return /* @__PURE__ */ jsxs22("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2214
+ return /* @__PURE__ */ jsxs24("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
1996
2215
  props.label,
1997
- /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", children: "\u2192" })
2216
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
1998
2217
  ] });
1999
2218
  }
2000
2219
  if (props.mode === "preview") {
2001
- return /* @__PURE__ */ jsxs22("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2220
+ return /* @__PURE__ */ jsxs24("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2002
2221
  props.label,
2003
- /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", children: "\u2192" })
2222
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2004
2223
  ] });
2005
2224
  }
2006
- return /* @__PURE__ */ jsxs22("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2225
+ return /* @__PURE__ */ jsxs24("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2007
2226
  props.label,
2008
- /* @__PURE__ */ jsx22("span", { "aria-hidden": "true", children: "\u2192" })
2227
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2009
2228
  ] });
2010
2229
  }
2011
2230
  function TierCard(props) {
2012
2231
  const { tier, presentation } = props;
2013
2232
  const summary = presentation.summaryMarkdown ?? tier.blurb;
2014
2233
  const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
2015
- return /* @__PURE__ */ jsxs22("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2016
- presentation.badge ? /* @__PURE__ */ jsx22("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2017
- /* @__PURE__ */ jsx22("h3", { className: "chapter-membership-name", children: tier.name }),
2018
- /* @__PURE__ */ jsxs22("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2019
- presentation.capacity ? /* @__PURE__ */ jsxs22("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2020
- /* @__PURE__ */ jsx22("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2021
- /* @__PURE__ */ jsx22("small", { children: presentation.capacity.label ?? "available" })
2234
+ return /* @__PURE__ */ jsxs24("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2235
+ presentation.badge ? /* @__PURE__ */ jsx24("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2236
+ /* @__PURE__ */ jsx24("h3", { className: "chapter-membership-name", children: tier.name }),
2237
+ /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2238
+ presentation.capacity ? /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2239
+ /* @__PURE__ */ jsx24("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2240
+ /* @__PURE__ */ jsx24("small", { children: presentation.capacity.label ?? "available" })
2022
2241
  ] }) : null,
2023
- /* @__PURE__ */ jsxs22("div", { className: "chapter-membership-price-stack", children: [
2024
- presentation.priceEyebrow ? /* @__PURE__ */ jsx22("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx22("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2025
- /* @__PURE__ */ jsxs22("div", { className: "chapter-membership-price-row", children: [
2026
- tier.founding ? /* @__PURE__ */ jsx22("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx22("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2027
- /* @__PURE__ */ jsx22("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2028
- !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx22("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2242
+ /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-price-stack", children: [
2243
+ presentation.priceEyebrow ? /* @__PURE__ */ jsx24("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx24("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2244
+ /* @__PURE__ */ jsxs24("div", { className: "chapter-membership-price-row", children: [
2245
+ tier.founding ? /* @__PURE__ */ jsx24("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx24("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2246
+ /* @__PURE__ */ jsx24("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2247
+ !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx24("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2029
2248
  ] })
2030
2249
  ] })
2031
2250
  ] }),
2032
- presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx22(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2033
- summary ? /* @__PURE__ */ jsx22(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2034
- presentation.benefits?.length ? /* @__PURE__ */ jsx22("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs22("li", { children: [
2035
- /* @__PURE__ */ jsx22("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2036
- /* @__PURE__ */ jsx22(Markdown2, { className: "chapter-membership-benefit", source: benefit })
2251
+ presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2252
+ summary ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2253
+ presentation.benefits?.length ? /* @__PURE__ */ jsx24("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs24("li", { children: [
2254
+ /* @__PURE__ */ jsx24("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2255
+ /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-benefit", source: benefit })
2037
2256
  ] }, `${tier.id}-benefit-${index}`)) }) : null,
2038
- presentation.callout ? /* @__PURE__ */ jsxs22("aside", { className: "chapter-membership-callout", children: [
2039
- presentation.callout.label ? /* @__PURE__ */ jsx22("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2040
- /* @__PURE__ */ jsx22(Markdown2, { source: presentation.callout.bodyMarkdown })
2257
+ presentation.callout ? /* @__PURE__ */ jsxs24("aside", { className: "chapter-membership-callout", children: [
2258
+ presentation.callout.label ? /* @__PURE__ */ jsx24("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2259
+ /* @__PURE__ */ jsx24(Markdown2, { source: presentation.callout.bodyMarkdown })
2041
2260
  ] }) : null,
2042
- /* @__PURE__ */ jsx22(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2261
+ /* @__PURE__ */ jsx24(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2043
2262
  ] });
2044
2263
  }
2045
2264
  function MembershipCards(props) {
2046
2265
  const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
2047
2266
  const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
2048
2267
  const mode = props.mode ?? "link";
2049
- return /* @__PURE__ */ jsxs22("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2050
- /* @__PURE__ */ jsx22("style", { children: MEMBERSHIP_CARDS_CSS }),
2051
- /* @__PURE__ */ jsx22("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2268
+ return /* @__PURE__ */ jsxs24("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2269
+ /* @__PURE__ */ jsx24("style", { children: MEMBERSHIP_CARDS_CSS }),
2270
+ /* @__PURE__ */ jsx24("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2052
2271
  const tier = byId.get(presentation.tierId);
2053
- return /* @__PURE__ */ jsx22(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2272
+ return /* @__PURE__ */ jsx24(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2054
2273
  }) }),
2055
- document2.footnoteMarkdown ? /* @__PURE__ */ jsx22(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2274
+ document2.footnoteMarkdown ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2056
2275
  ] });
2057
2276
  }
2058
2277
 
@@ -2088,4 +2307,4 @@ export {
2088
2307
  membershipApplicationHref,
2089
2308
  MembershipCards
2090
2309
  };
2091
- //# sourceMappingURL=chunk-SPEL4OGE.js.map
2310
+ //# sourceMappingURL=chunk-IQZWCG42.js.map