@odla-ai/chapter 0.56.0 → 0.56.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -350,8 +350,23 @@ function CheckoutSeatChoice(props) {
350
350
  ] }) });
351
351
  }
352
352
 
353
+ // src/ui/checkout-seat-review.tsx
354
+ import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
355
+ function CheckoutSeatReview({ quote, label, locked, onEdit }) {
356
+ if (!quote.namedSeat) return null;
357
+ return /* @__PURE__ */ jsxs4("section", { className: "checkout-seat-review", "aria-label": label, children: [
358
+ /* @__PURE__ */ jsx4("h3", { children: label }),
359
+ /* @__PURE__ */ jsxs4("p", { children: [
360
+ quote.namedSeat.recipientName,
361
+ /* @__PURE__ */ jsx4("br", {}),
362
+ quote.namedSeat.recipientEmail
363
+ ] }),
364
+ !locked ? /* @__PURE__ */ jsx4("button", { type: "button", onClick: onEdit, children: "Edit details" }) : null
365
+ ] });
366
+ }
367
+
353
368
  // src/ui/membership-payment-step.tsx
354
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
369
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
355
370
  function MembershipPaymentStep(props) {
356
371
  const inherited = useChapterCopy();
357
372
  const copy = props.copy ?? inherited.join.payment;
@@ -360,15 +375,42 @@ function MembershipPaymentStep(props) {
360
375
  const [prefillConsumed, setPrefillConsumed] = useState4(false);
361
376
  const [error, setError] = useState4(false);
362
377
  const [revision, setRevision] = useState4(0);
378
+ useEffect(() => {
379
+ props.onNamedSeatEditingChange?.(Boolean(props.renderNamedSeatEditor && editing && !locked && quote));
380
+ }, [editing, locked, Boolean(quote), Boolean(props.renderNamedSeatEditor)]);
363
381
  useEffect(() => {
364
382
  let live = true;
365
383
  setQuote(null);
366
384
  setError(false);
367
385
  void fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, { method: "POST", cache: "no-store" }).then(async (response) => {
368
386
  if (!response.ok) throw new Error("quote unavailable");
369
- const value = await response.json();
387
+ let value = await response.json();
370
388
  value.checkoutStarted = response.headers.get("x-chapter-checkout-started") === "true";
371
389
  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");
390
+ if (!live) return;
391
+ if (props.renderNamedSeatEditor && props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer) {
392
+ const saved = await fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, {
393
+ method: "POST",
394
+ cache: "no-store",
395
+ headers: { "content-type": "application/json" },
396
+ body: JSON.stringify({ namedSeat: props.initialNamedSeat })
397
+ });
398
+ if (!saved.ok) {
399
+ if (saved.status === 409) {
400
+ if (live) setRevision((current) => current + 1);
401
+ return;
402
+ }
403
+ if (live) {
404
+ setQuote(value);
405
+ setEditing(true);
406
+ setError(true);
407
+ }
408
+ return;
409
+ }
410
+ value = await saved.json();
411
+ if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest) || !value.namedSeat) throw new Error("invalid quote");
412
+ if (live) setPrefillConsumed(true);
413
+ }
372
414
  if (live) {
373
415
  setQuote(value);
374
416
  setLocked(Boolean(value.checkoutStarted));
@@ -385,10 +427,10 @@ function MembershipPaymentStep(props) {
385
427
  setQuote(null);
386
428
  setRevision((value) => value + 1);
387
429
  };
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
430
+ if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */ jsxs5("div", { className: "join-pay", role: "status", children: [
431
+ props.merchantDisclosureText ? /* @__PURE__ */ jsx5("p", { className: "compliance-merchant", children: props.merchantDisclosureText }) : null,
432
+ /* @__PURE__ */ jsx5("p", { children: error ? copy.setupFailed : copy.preparing }),
433
+ error ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: refresh, children: "Reload payment terms" }) : null
392
434
  ] });
393
435
  const startCheckout = async () => {
394
436
  setLocked(true);
@@ -424,10 +466,33 @@ function MembershipPaymentStep(props) {
424
466
  if (value.applicationId !== props.applicationId || !/^[a-f0-9]{64}$/.test(value.digest)) throw new Error(copy.setupFailed);
425
467
  setQuote(value);
426
468
  setEditing(false);
469
+ setError(false);
427
470
  setPrefillConsumed(true);
428
471
  };
429
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
430
- quote.seatOffer ? /* @__PURE__ */ jsx4(
472
+ const pickLater = !quote.namedSeat && quote.seatOffer?.amountCents === 0;
473
+ if (props.renderNamedSeatEditor && editing && !locked && quote.seatOffer) return /* @__PURE__ */ jsxs5(Fragment3, { children: [
474
+ error ? /* @__PURE__ */ jsx5("p", { role: "alert", children: "Enter a different recipient's full name and valid email to continue." }) : null,
475
+ props.renderNamedSeatEditor({
476
+ selection: quote.namedSeat ?? (!prefillConsumed ? props.initialNamedSeat : void 0) ?? null,
477
+ offer: { ...quote.seatOffer, currency: quote.currency, interval: quote.interval },
478
+ save: changeSeat,
479
+ cancel: () => {
480
+ setEditing(false);
481
+ setError(false);
482
+ setPrefillConsumed(true);
483
+ }
484
+ })
485
+ ] });
486
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
487
+ props.renderNamedSeatEditor ? /* @__PURE__ */ jsx5(
488
+ CheckoutSeatReview,
489
+ {
490
+ quote,
491
+ label: props.namedSeatLabel ?? "Additional member",
492
+ locked,
493
+ onEdit: () => setEditing(true)
494
+ }
495
+ ) : quote.seatOffer ? /* @__PURE__ */ jsx5(
431
496
  CheckoutSeatChoice,
432
497
  {
433
498
  quote,
@@ -438,47 +503,52 @@ function MembershipPaymentStep(props) {
438
503
  },
439
504
  quote.digest
440
505
  ) : 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,
506
+ /* @__PURE__ */ jsxs5("section", { className: "payment-quote", "aria-label": "Membership price", children: [
507
+ /* @__PURE__ */ jsx5("h3", { children: quote.tierName }),
508
+ quote.founding ? /* @__PURE__ */ jsx5("p", { className: "payment-founding", role: "note", "aria-label": "Founding member", children: copy.foundingMember }) : null,
444
509
  props.renderPriceLines ? props.renderPriceLines({
445
510
  ...quote.lineItems,
446
511
  ...quote.founding ? { founding: quote.founding } : {},
512
+ ...pickLater ? { namedSeatPickLater: true } : {},
447
513
  ...quote.presentation ? { presentation: quote.presentation } : {}
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: [
514
+ }) : /* @__PURE__ */ jsxs5("dl", { children: [
515
+ quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
516
+ /* @__PURE__ */ jsx5("dt", { children: copy.standardRate }),
517
+ /* @__PURE__ */ jsxs5("dd", { children: [
452
518
  amount(quote.lineItems.standardCents),
453
519
  " per ",
454
520
  quote.interval
455
521
  ] }),
456
- /* @__PURE__ */ jsx4("dt", { children: copy.yourRate }),
457
- /* @__PURE__ */ jsxs4("dd", { children: [
522
+ /* @__PURE__ */ jsx5("dt", { children: copy.yourRate }),
523
+ /* @__PURE__ */ jsxs5("dd", { children: [
458
524
  amount(quote.lineItems.dueTodayCents - (quote.lineItems.namedSeatCents ?? 0)),
459
525
  " per ",
460
526
  quote.interval
461
527
  ] })
462
- ] }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
463
- /* @__PURE__ */ jsx4("dt", { children: "Membership price" }),
464
- /* @__PURE__ */ jsxs4("dd", { children: [
528
+ ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
529
+ /* @__PURE__ */ jsx5("dt", { children: "Membership price" }),
530
+ /* @__PURE__ */ jsxs5("dd", { children: [
465
531
  amount(quote.lineItems.standardCents),
466
532
  " per ",
467
533
  quote.interval
468
534
  ] }),
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) })
535
+ quote.lineItems.discountCents > 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
536
+ /* @__PURE__ */ jsx5("dt", { children: quote.founding ? copy.foundingDiscount : "Discount" }),
537
+ /* @__PURE__ */ jsx5("dd", { children: amount(quote.lineItems.discountCents) })
472
538
  ] }) : null
473
539
  ] }),
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) })
540
+ quote.namedSeat ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
541
+ /* @__PURE__ */ jsx5("dt", { children: "Additional member" }),
542
+ /* @__PURE__ */ jsx5("dd", { children: quote.lineItems.namedSeatCents === 0 ? "Included" : amount(quote.lineItems.namedSeatCents) })
477
543
  ] }) : null,
478
- /* @__PURE__ */ jsx4("dt", { children: "Due today" }),
479
- /* @__PURE__ */ jsx4("dd", { children: amount(quote.lineItems.dueTodayCents) })
544
+ pickLater ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
545
+ /* @__PURE__ */ jsx5("dt", { children: "Additional member" }),
546
+ /* @__PURE__ */ jsx5("dd", { children: "Pick later" })
547
+ ] }) : null,
548
+ /* @__PURE__ */ jsx5("dt", { children: "Due today" }),
549
+ /* @__PURE__ */ jsx5("dd", { children: amount(quote.lineItems.dueTodayCents) })
480
550
  ] }),
481
- quote.namedSeat ? /* @__PURE__ */ jsxs4("p", { children: [
551
+ quote.namedSeat && !props.renderNamedSeatEditor ? /* @__PURE__ */ jsxs5("p", { children: [
482
552
  "For ",
483
553
  quote.namedSeat.recipientName,
484
554
  " \xB7 ",
@@ -486,8 +556,8 @@ function MembershipPaymentStep(props) {
486
556
  ".",
487
557
  props.renderPriceLines ? ` Additional member: ${quote.lineItems.namedSeatCents === 0 ? "included" : amount(quote.lineItems.namedSeatCents)} in the total above.` : ""
488
558
  ] }) : null,
489
- quote.commercial ? /* @__PURE__ */ jsxs4("div", { role: "note", "aria-label": "Renewal terms", children: [
490
- quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs4("p", { children: [
559
+ quote.commercial ? /* @__PURE__ */ jsxs5("div", { role: "note", "aria-label": "Renewal terms", children: [
560
+ quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs5("p", { children: [
491
561
  "First renewal: ",
492
562
  new Intl.DateTimeFormat("en-US", {
493
563
  dateStyle: "long",
@@ -495,19 +565,23 @@ function MembershipPaymentStep(props) {
495
565
  }).format(quote.commercial.initialTermEndsAt),
496
566
  "."
497
567
  ] }) : null,
498
- /* @__PURE__ */ jsxs4("p", { children: [
568
+ /* @__PURE__ */ jsxs5("p", { children: [
499
569
  "Renews automatically at ",
500
570
  amount(quote.commercial.renewalCents),
501
571
  " per ",
502
572
  quote.interval,
503
573
  " unless canceled before renewal."
504
574
  ] }),
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
575
+ quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */ jsx5("p", { children: "The discount applies to your first paid term only." }) : null,
576
+ quote.commercial.discountDuration === "while_active" ? /* @__PURE__ */ jsx5("p", { children: "The discounted rate continues while this membership stays active." }) : null
507
577
  ] }) : null,
508
- quote.trustCopy ? /* @__PURE__ */ jsx4("p", { className: "pay-trust", children: quote.trustCopy }) : null
578
+ quote.trustCopy ? /* @__PURE__ */ jsx5("p", { className: "pay-trust", children: quote.trustCopy }) : null
509
579
  ] }),
510
- !editing ? /* @__PURE__ */ jsx4(
580
+ quote.namedSeat && props.renderNamedSeatEditor ? /* @__PURE__ */ jsxs5("details", { className: "checkout-seat-terms", children: [
581
+ /* @__PURE__ */ jsx5("summary", { children: "Additional-member terms" }),
582
+ /* @__PURE__ */ jsx5("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
583
+ ] }) : null,
584
+ !editing ? /* @__PURE__ */ jsx5(
511
585
  PaymentStep,
512
586
  {
513
587
  ...props,
@@ -518,12 +592,12 @@ function MembershipPaymentStep(props) {
518
592
  startCheckout
519
593
  },
520
594
  quote.digest
521
- ) : /* @__PURE__ */ jsx4("p", { role: "status", children: "Save your member selection to continue to payment." })
595
+ ) : /* @__PURE__ */ jsx5("p", { role: "status", children: "Save your member selection to continue to payment." })
522
596
  ] });
523
597
  }
524
598
 
525
599
  // src/ui/journey-frame.tsx
526
- import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
600
+ import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
527
601
  var styles = `
528
602
  .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}
529
603
  .chapter-journey *{box-sizing:border-box}
@@ -531,7 +605,7 @@ var styles = `
531
605
  .chapter-journey :where(h2,h3){font-family:var(--ui-font-display,inherit);line-height:1.2;letter-spacing:-.025em;text-transform:none}
532
606
  .chapter-journey h2{font-size:clamp(1.6rem,3vw,2.15rem)}
533
607
  .chapter-journey h3{font-size:1.3rem}
534
- .chapter-journey :where(.card,.join-form,.payment-quote,.join-book){padding:clamp(1.25rem,4vw,2.4rem);border:1px solid var(--ui-border,#dfe3df);border-radius:var(--ui-radius-lg,16px);background:var(--ui-surface,#fff);margin-block:1.2rem}
608
+ .chapter-journey :where(.card,.join-form,.payment-quote,.join-book,.checkout-seat-review){padding:clamp(1.25rem,4vw,2.4rem);border:1px solid var(--ui-border,#dfe3df);border-radius:var(--ui-radius-lg,16px);background:var(--ui-surface,#fff);margin-block:1.2rem}
535
609
  .chapter-journey :where(.card-label,.journey-eyebrow){font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ui-text-muted,#536360);margin-bottom:.7rem;font-weight:600}
536
610
  .chapter-journey :where(form,.journey-fields){display:grid;gap:1.25rem}
537
611
  .chapter-journey :where(label){display:block;font-size:.95rem;font-weight:500;letter-spacing:normal;text-transform:none;line-height:1.55}
@@ -555,17 +629,19 @@ var styles = `
555
629
  .chapter-journey :where(.pay-status,.meeting-note,.slots-status){color:var(--ui-text-muted,#536360)}
556
630
  .chapter-journey .journey-actions{display:flex;gap:.75rem;flex-wrap:wrap;margin-top:1.25rem}
557
631
  .chapter-journey fieldset{min-width:0;border:0;padding:0;margin:0}
632
+ .chapter-journey .checkout-seat-terms{margin-block:1rem}
633
+ .chapter-journey .checkout-seat-terms summary{cursor:pointer}
558
634
  @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}}
559
635
  `;
560
636
  function JourneyFrame({ children }) {
561
- return /* @__PURE__ */ jsxs5("div", { className: "chapter-journey", children: [
562
- /* @__PURE__ */ jsx5("style", { children: styles }),
637
+ return /* @__PURE__ */ jsxs6("div", { className: "chapter-journey", children: [
638
+ /* @__PURE__ */ jsx6("style", { children: styles }),
563
639
  children
564
640
  ] });
565
641
  }
566
642
 
567
643
  // src/ui/member-restart.tsx
568
- import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
644
+ import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
569
645
  function MemberRestart(props) {
570
646
  const [id, setId] = useState5(props.applicationId);
571
647
  const [busy, setBusy] = useState5(false);
@@ -610,22 +686,22 @@ function MemberRestart(props) {
610
686
  setBusy(false);
611
687
  }
612
688
  };
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 })
689
+ return /* @__PURE__ */ jsx7(JourneyFrame, { children: /* @__PURE__ */ jsxs7("section", { className: "card", "aria-label": "Restart membership", children: [
690
+ /* @__PURE__ */ jsx7("p", { className: "card-label", children: "Welcome back" }),
691
+ /* @__PURE__ */ jsx7("h2", { children: "Restart your membership" }),
692
+ /* @__PURE__ */ jsx7("p", { children: "Your account is ready, and your previous approval still counts. No new application or interview is needed." }),
693
+ /* @__PURE__ */ jsxs7("dl", { className: "journey-summary", children: [
694
+ /* @__PURE__ */ jsx7("dt", { children: "Name" }),
695
+ /* @__PURE__ */ jsx7("dd", { children: [props.application.firstName, props.application.lastName].filter(Boolean).join(" ") }),
696
+ /* @__PURE__ */ jsx7("dt", { children: "Email" }),
697
+ /* @__PURE__ */ jsx7("dd", { children: props.application.email })
622
698
  ] }),
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
699
+ paid ? /* @__PURE__ */ jsxs7("div", { role: "status", children: [
700
+ /* @__PURE__ */ jsx7("h3", { children: "Confirming your membership" }),
701
+ /* @__PURE__ */ jsx7("p", { children: "We\u2019re waiting for payment confirmation. Your membership will open here as soon as it arrives." }),
702
+ !checking ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Check membership" }) : null
703
+ ] }) : id ? /* @__PURE__ */ jsx7(MembershipPaymentStep, { applicationId: id, refundPolicyText: "", onPaid: () => setPaid(true) }) : /* @__PURE__ */ jsx7("button", { type: "button", disabled: busy, onClick: () => void start(), children: busy ? "Preparing your membership\u2026" : "Review membership and payment" }),
704
+ error ? /* @__PURE__ */ jsx7("p", { role: "alert", children: error }) : null
629
705
  ] }) });
630
706
  }
631
707
 
@@ -634,7 +710,7 @@ import { useEffect as useEffect6, useState as useState10 } from "preact/hooks";
634
710
 
635
711
  // src/ui/reschedule.tsx
636
712
  import { useState as useState6 } from "preact/hooks";
637
- import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
713
+ import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
638
714
  function Rescheduler(props) {
639
715
  const inheritedCopy = useChapterCopy();
640
716
  const copy = props.copy ?? inheritedCopy.members.reschedule;
@@ -676,7 +752,7 @@ function Rescheduler(props) {
676
752
  }
677
753
  };
678
754
  if (!open) {
679
- return /* @__PURE__ */ jsx7("p", { className: "meeting-note", children: /* @__PURE__ */ jsx7(
755
+ return /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: /* @__PURE__ */ jsx8(
680
756
  "a",
681
757
  {
682
758
  href: "#",
@@ -688,8 +764,8 @@ function Rescheduler(props) {
688
764
  }
689
765
  ) });
690
766
  }
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(
767
+ return /* @__PURE__ */ jsxs8("div", { className: "msched", children: [
768
+ slots === null ? /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: copy.loading }) : slots.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: msg ?? copy.noTimes }) : /* @__PURE__ */ jsx8(
693
769
  SlotPicker,
694
770
  {
695
771
  slots,
@@ -698,9 +774,9 @@ function Rescheduler(props) {
698
774
  onPick: (s) => void pick(s)
699
775
  }
700
776
  ),
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(
777
+ busy ? /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: copy.rescheduling }) : null,
778
+ msg && slots && slots.length > 0 ? /* @__PURE__ */ jsx8("p", { className: "meeting-note error", children: msg }) : null,
779
+ /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: /* @__PURE__ */ jsx8(
704
780
  "a",
705
781
  {
706
782
  href: "#",
@@ -718,23 +794,23 @@ function Rescheduler(props) {
718
794
  import { useEffect as useEffect3, useRef as useRef2, useState as useState7 } from "preact/hooks";
719
795
 
720
796
  // src/ui/gift-offer-cards.tsx
721
- import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
797
+ import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
722
798
  var price = (cents, currency) => currency === "usd" ? fmtMoney(cents) : new Intl.NumberFormat(void 0, { style: "currency", currency: currency.toUpperCase() }).format(cents / 100);
723
799
  function GiftOfferCards(props) {
724
800
  const mode = props.mode ?? "preview";
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: [
801
+ return /* @__PURE__ */ jsx9("section", { className: "chapter-gift-offers", "aria-label": props.ariaLabel ?? "Gift options", children: props.offers.map((offer) => /* @__PURE__ */ jsxs9("article", { className: "card chapter-gift-offer", "data-offer-id": offer.id, children: [
802
+ /* @__PURE__ */ jsx9("div", { className: "card-label", children: offer.title }),
803
+ /* @__PURE__ */ jsx9("p", { children: offer.description }),
804
+ /* @__PURE__ */ jsxs9("p", { className: "meeting-date", children: [
729
805
  price(offer.priceCents, offer.currency),
730
806
  offer.billingMode === "subscription" ? " recurring" : ""
731
807
  ] }),
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 })
808
+ mode === "select" ? /* @__PURE__ */ jsx9("button", { type: "button", className: "btn secondary", "aria-pressed": props.selectedOfferId === offer.id, onClick: () => props.onSelect?.(offer.id), children: offer.ctaLabel }) : /* @__PURE__ */ jsx9("span", { className: "btn secondary", "aria-disabled": "true", children: offer.ctaLabel })
733
809
  ] }, offer.id)) });
734
810
  }
735
811
 
736
812
  // src/ui/member-gifts.tsx
737
- import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
813
+ import { jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
738
814
  function GiftPurchases(props) {
739
815
  const [data, setData] = useState7(null);
740
816
  const [selected, setSelected] = useState7(null);
@@ -757,16 +833,16 @@ function GiftPurchases(props) {
757
833
  if (!data) return null;
758
834
  if (data.offers.length === 0 && data.claims.length === 0) return null;
759
835
  const offer = data.offers.find((item) => item.id === selected);
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) => {
836
+ return /* @__PURE__ */ jsxs10("section", { className: "member-gifts", children: [
837
+ data.offers.length ? /* @__PURE__ */ jsxs10("div", { className: "card", children: [
838
+ /* @__PURE__ */ jsx10("div", { className: "card-label", children: props.copy.title }),
839
+ /* @__PURE__ */ jsx10("p", { children: props.copy.body }),
840
+ /* @__PURE__ */ jsx10(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
765
841
  setSelected(id);
766
842
  setCode("");
767
843
  purchaseId.current = crypto.randomUUID();
768
844
  } }),
769
- offer ? /* @__PURE__ */ jsx9(
845
+ offer ? /* @__PURE__ */ jsx10(
770
846
  PaymentStep,
771
847
  {
772
848
  applicationId: purchaseId.current,
@@ -786,19 +862,19 @@ function GiftPurchases(props) {
786
862
  }
787
863
  }
788
864
  ) : null,
789
- code ? /* @__PURE__ */ jsxs9("div", { className: "gift-code-once", children: [
790
- /* @__PURE__ */ jsx9("output", { children: code }),
791
- /* @__PURE__ */ jsx9("p", { children: props.copy.saveCode })
865
+ code ? /* @__PURE__ */ jsxs10("div", { className: "gift-code-once", children: [
866
+ /* @__PURE__ */ jsx10("output", { children: code }),
867
+ /* @__PURE__ */ jsx10("p", { children: props.copy.saveCode })
792
868
  ] }) : null
793
869
  ] }) : 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
870
+ /* @__PURE__ */ jsxs10("div", { className: "card", children: [
871
+ /* @__PURE__ */ jsx10("div", { className: "card-label", children: props.copy.purchases }),
872
+ data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs10("div", { className: "member-row", children: [
873
+ /* @__PURE__ */ jsx10("span", { children: claim.offerId }),
874
+ /* @__PURE__ */ jsx10("span", { children: props.copy[claim.status] }),
875
+ claim.status === "pending" ? /* @__PURE__ */ jsx10("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
876
+ ] }, claim.id)) : /* @__PURE__ */ jsx10("p", { children: props.copy.noPurchases }),
877
+ message ? /* @__PURE__ */ jsx10("p", { role: "status", children: message }) : null
802
878
  ] })
803
879
  ] });
804
880
  }
@@ -806,7 +882,7 @@ var MemberGifts = GiftPurchases;
806
882
 
807
883
  // src/ui/member-named-seat.tsx
808
884
  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";
885
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
810
886
  var NAMED_SEAT_RECIPIENT_WORDS = {
811
887
  payment_pending: "payment in progress",
812
888
  invited: "invited, waiting for them to accept",
@@ -819,7 +895,7 @@ var NAMED_SEAT_RECIPIENT_WORDS = {
819
895
  var day = (at) => new Date(at).toLocaleDateString("en-US", { timeZone: "UTC" });
820
896
  function NamedSeatRecipientLine({ seat }) {
821
897
  const words = NAMED_SEAT_RECIPIENT_WORDS[seat.recipientState] ?? seat.status.replaceAll("_", " ");
822
- return /* @__PURE__ */ jsxs10("p", { className: "member-named-seat-recipient", children: [
898
+ return /* @__PURE__ */ jsxs11("p", { className: "member-named-seat-recipient", children: [
823
899
  seat.recipientName,
824
900
  " \xB7 ",
825
901
  seat.recipientEmail,
@@ -868,13 +944,13 @@ function NamedSeatPurchase({ api }) {
868
944
  }
869
945
  };
870
946
  const money = data ? new Intl.NumberFormat("en-US", { style: "currency", currency: data.currency }).format(data.amountCents / 100) : "";
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: [
947
+ return /* @__PURE__ */ jsx11(JourneyFrame, { children: /* @__PURE__ */ jsxs11("section", { className: "card member-named-seat", "aria-label": "Named additional seat", children: [
948
+ /* @__PURE__ */ jsx11("h2", { children: "Named additional seat" }),
949
+ error ? /* @__PURE__ */ jsx11("p", { role: "alert", children: error }) : null,
950
+ data ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
951
+ data.seat ? /* @__PURE__ */ jsx11(NamedSeatRecipientLine, { seat: data.seat }) : null,
952
+ data.eligible ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
953
+ /* @__PURE__ */ jsxs11("p", { children: [
878
954
  data.included ? "Included with your membership at no charge." : `${money} paid in full now.`,
879
955
  " This seat ",
880
956
  data.autoRenew ? "renews with your primary membership" : "ends with your primary membership",
@@ -885,39 +961,39 @@ function NamedSeatPurchase({ api }) {
885
961
  " ",
886
962
  "It belongs to one named person and cannot be reassigned."
887
963
  ] }),
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) => {
964
+ /* @__PURE__ */ jsx11("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." }),
965
+ !reviewing ? /* @__PURE__ */ jsxs11("form", { onSubmit: (event) => {
890
966
  event.preventDefault();
891
967
  setReviewing(true);
892
968
  setTerms(false);
893
969
  }, children: [
894
- /* @__PURE__ */ jsxs10("label", { children: [
970
+ /* @__PURE__ */ jsxs11("label", { children: [
895
971
  "Recipient name",
896
- /* @__PURE__ */ jsx10("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
972
+ /* @__PURE__ */ jsx11("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
897
973
  ] }),
898
- /* @__PURE__ */ jsxs10("label", { children: [
974
+ /* @__PURE__ */ jsxs11("label", { children: [
899
975
  "Recipient email",
900
- /* @__PURE__ */ jsx10("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
976
+ /* @__PURE__ */ jsx11("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
901
977
  ] }),
902
- /* @__PURE__ */ jsx10("button", { className: "btn primary", type: "submit", children: "Review named seat" })
903
- ] }) : /* @__PURE__ */ jsxs10(Fragment4, { children: [
904
- /* @__PURE__ */ jsxs10("p", { children: [
978
+ /* @__PURE__ */ jsx11("button", { className: "btn primary", type: "submit", children: "Review named seat" })
979
+ ] }) : /* @__PURE__ */ jsxs11(Fragment4, { children: [
980
+ /* @__PURE__ */ jsxs11("p", { children: [
905
981
  "For ",
906
982
  name,
907
983
  " \xB7 ",
908
984
  email
909
985
  ] }),
910
- /* @__PURE__ */ jsx10("button", { className: "btn secondary", type: "button", onClick: () => {
986
+ /* @__PURE__ */ jsx11("button", { className: "btn secondary", type: "button", onClick: () => {
911
987
  setReviewing(false);
912
988
  setTerms(false);
913
989
  void load();
914
990
  }, children: "Back to recipient" }),
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." })
991
+ /* @__PURE__ */ jsxs11("label", { className: "journey-consent", children: [
992
+ /* @__PURE__ */ jsx11("input", { type: "checkbox", checked: terms, onChange: (event) => setTerms(event.currentTarget.checked) }),
993
+ /* @__PURE__ */ jsx11("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." })
918
994
  ] }),
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(
995
+ terms && data.included ? /* @__PURE__ */ jsx11("button", { className: "btn primary", type: "button", disabled: granting, onClick: () => void grant(), children: granting ? "Sending the invitation\u2026" : "Send the invitation" }) : null,
996
+ terms && !data.included ? /* @__PURE__ */ jsx11(
921
997
  PaymentStep,
922
998
  {
923
999
  applicationId: data.membershipId,
@@ -932,17 +1008,17 @@ function NamedSeatPurchase({ api }) {
932
1008
  }
933
1009
  ) : null
934
1010
  ] })
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" })
1011
+ ] }) : !data.seat ? /* @__PURE__ */ jsx11("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,
1012
+ pending ? /* @__PURE__ */ jsx11("p", { role: "status", children: "Payment confirmation is being reconciled. The recipient\u2019s access begins only after their own acceptance and approval." }) : null
1013
+ ] }) : !error ? /* @__PURE__ */ jsx11("p", { children: "Loading your seat terms\u2026" }) : null,
1014
+ /* @__PURE__ */ jsx11("button", { className: "btn secondary", onClick: () => void load(), children: "Refresh seat status" })
939
1015
  ] }) });
940
1016
  }
941
1017
 
942
1018
  // src/ui/member-content.tsx
943
1019
  import { useEffect as useEffect5, useMemo as useMemo2, useState as useState9 } from "preact/hooks";
944
1020
  import { Markdown } from "@odla-ai/ui/components";
945
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
1021
+ import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
946
1022
  var pageLabel = (page) => `${page.title}${page.access === "locked" ? " \xB7 Locked" : ""}`;
947
1023
  function MemberContentArea(props) {
948
1024
  const {
@@ -950,8 +1026,8 @@ function MemberContentArea(props) {
950
1026
  path = "/api/member-content",
951
1027
  upsellHref,
952
1028
  onUpsell,
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." })
1029
+ loadingContent = /* @__PURE__ */ jsx12("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
1030
+ emptyContent = /* @__PURE__ */ jsx12("p", { className: "meeting-note", children: "No member pages have been published yet." })
955
1031
  } = props;
956
1032
  const [data, setData] = useState9(props.initialData ?? null);
957
1033
  const [error, setError] = useState9(null);
@@ -980,18 +1056,18 @@ function MemberContentArea(props) {
980
1056
  }
981
1057
  return [...result.entries()];
982
1058
  }, [data]);
983
- if (error) return /* @__PURE__ */ jsxs11("p", { className: "meeting-note", role: "alert", children: [
1059
+ if (error) return /* @__PURE__ */ jsxs12("p", { className: "meeting-note", role: "alert", children: [
984
1060
  "Member pages could not be loaded: ",
985
1061
  error
986
1062
  ] });
987
- if (!data) return /* @__PURE__ */ jsx11(Fragment5, { children: loadingContent });
988
- if (data.pages.length === 0) return /* @__PURE__ */ jsx11(Fragment5, { children: emptyContent });
1063
+ if (!data) return /* @__PURE__ */ jsx12(Fragment5, { children: loadingContent });
1064
+ if (data.pages.length === 0) return /* @__PURE__ */ jsx12(Fragment5, { children: emptyContent });
989
1065
  const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
990
1066
  const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
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(
1067
+ return /* @__PURE__ */ jsxs12("div", { className: "chapter-member-content", "data-member-content": true, children: [
1068
+ /* @__PURE__ */ jsx12("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs12("section", { className: "chapter-member-content-section", children: [
1069
+ /* @__PURE__ */ jsx12("h2", { children: section }),
1070
+ /* @__PURE__ */ jsx12("ul", { children: pages.map((page) => /* @__PURE__ */ jsx12("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx12(
995
1071
  "button",
996
1072
  {
997
1073
  type: "button",
@@ -1001,23 +1077,23 @@ function MemberContentArea(props) {
1001
1077
  }
1002
1078
  ) }, page.id)) })
1003
1079
  ] }, section)) }),
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: [
1080
+ /* @__PURE__ */ jsxs12("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
1081
+ /* @__PURE__ */ jsxs12("header", { children: [
1082
+ /* @__PURE__ */ jsxs12("div", { className: "card-label", children: [
1007
1083
  selected.source.type === "parent" ? "Parent" : "Chapter",
1008
1084
  " \xB7 ",
1009
1085
  selected.access
1010
1086
  ] }),
1011
- /* @__PURE__ */ jsx11("h1", { children: selected.title }),
1012
- selected.summary ? /* @__PURE__ */ jsx11("p", { children: selected.summary }) : null
1087
+ /* @__PURE__ */ jsx12("h1", { children: selected.title }),
1088
+ selected.summary ? /* @__PURE__ */ jsx12("p", { children: selected.summary }) : null
1013
1089
  ] }),
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
1090
+ selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx12(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs12("div", { className: "chapter-member-content-locked", children: [
1091
+ selected.teaserMarkdown ? /* @__PURE__ */ jsx12(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx12("p", { children: "This page is not included in your current membership." }),
1092
+ selected.upsell ? /* @__PURE__ */ jsxs12("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
1093
+ /* @__PURE__ */ jsx12("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
1094
+ /* @__PURE__ */ jsx12("p", { children: fmtMoney(selected.upsell.priceCents) }),
1095
+ selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx12(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
1096
+ href ? /* @__PURE__ */ jsx12("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx12("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
1021
1097
  ] }) : null
1022
1098
  ] })
1023
1099
  ] })
@@ -1025,12 +1101,12 @@ function MemberContentArea(props) {
1025
1101
  }
1026
1102
 
1027
1103
  // src/ui/members.tsx
1028
- import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
1104
+ import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
1029
1105
  function card(copy, kicker, body) {
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 }),
1106
+ return /* @__PURE__ */ jsxs13("div", { className: "card", children: [
1107
+ /* @__PURE__ */ jsx13("div", { className: "card-label", children: copy.provisional.cardLabel }),
1108
+ /* @__PURE__ */ jsxs13("div", { className: "meeting-block", children: [
1109
+ /* @__PURE__ */ jsx13("div", { className: "meeting-kicker", children: kicker }),
1034
1110
  body
1035
1111
  ] })
1036
1112
  ] });
@@ -1041,9 +1117,9 @@ function ProvisionalCard(props) {
1041
1117
  return card(
1042
1118
  copy,
1043
1119
  copy.provisional.applicationNeeded,
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 })
1120
+ /* @__PURE__ */ jsxs13(Fragment6, { children: [
1121
+ /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
1122
+ /* @__PURE__ */ jsx13("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
1047
1123
  ] })
1048
1124
  );
1049
1125
  }
@@ -1051,19 +1127,19 @@ function ProvisionalCard(props) {
1051
1127
  return card(
1052
1128
  copy,
1053
1129
  copy.provisional.refunded,
1054
- /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1130
+ /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1055
1131
  );
1056
1132
  }
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;
1133
+ const membership = application.paid ? /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
1058
1134
  if (application.meetingAt) {
1059
1135
  return card(
1060
1136
  copy,
1061
1137
  copy.provisional.introductionCall,
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(
1138
+ /* @__PURE__ */ jsxs13(Fragment6, { children: [
1139
+ /* @__PURE__ */ jsx13("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
1140
+ /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
1141
+ application.meetUrl ? /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: /* @__PURE__ */ jsx13("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
1142
+ /* @__PURE__ */ jsx13(
1067
1143
  Rescheduler,
1068
1144
  {
1069
1145
  api,
@@ -1080,9 +1156,9 @@ function ProvisionalCard(props) {
1080
1156
  return card(
1081
1157
  copy,
1082
1158
  copy.provisional.bookCall,
1083
- /* @__PURE__ */ jsxs12(Fragment6, { children: [
1084
- /* @__PURE__ */ jsx12("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
1085
- /* @__PURE__ */ jsx12(
1159
+ /* @__PURE__ */ jsxs13(Fragment6, { children: [
1160
+ /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
1161
+ /* @__PURE__ */ jsx13(
1086
1162
  Rescheduler,
1087
1163
  {
1088
1164
  api,
@@ -1121,22 +1197,22 @@ function MembersArea(props) {
1121
1197
  useEffect6(() => {
1122
1198
  void reload();
1123
1199
  }, []);
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 });
1200
+ if (error) return /* @__PURE__ */ jsx13("p", { className: "meeting-note", children: copy.loadFailed });
1201
+ if (!me) return /* @__PURE__ */ jsx13("p", { className: "meeting-note", children: inheritedCopy.common.loading });
1126
1202
  const role = me.role || "provisional";
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 })
1203
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
1204
+ /* @__PURE__ */ jsxs13("div", { className: "card", children: [
1205
+ /* @__PURE__ */ jsxs13("div", { className: "member-row", children: [
1206
+ /* @__PURE__ */ jsx13("span", { className: "member-email", children: me.email }),
1207
+ /* @__PURE__ */ jsx13("span", { className: "role-badge " + role, children: role })
1132
1208
  ] }),
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
1209
+ /* @__PURE__ */ jsxs13("div", { className: "account-actions", children: [
1210
+ /* @__PURE__ */ jsx13("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
1211
+ me.authorized || me.superAdmin ? /* @__PURE__ */ jsx13("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
1136
1212
  ] })
1137
1213
  ] }),
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(
1214
+ me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx13(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
1215
+ const defaultContent = /* @__PURE__ */ jsx13(
1140
1216
  ProvisionalCard,
1141
1217
  {
1142
1218
  api,
@@ -1153,15 +1229,15 @@ function MembersArea(props) {
1153
1229
  reload,
1154
1230
  defaultContent
1155
1231
  }) ?? defaultContent;
1156
- })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx12(
1232
+ })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx13(
1157
1233
  MemberContentArea,
1158
1234
  {
1159
1235
  api,
1160
1236
  ...memberPages === true ? {} : memberPages
1161
1237
  }
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
1238
+ ) : /* @__PURE__ */ jsx13("div", { className: "card", children: /* @__PURE__ */ jsx13("div", { className: "card-label", children: copy.full.welcome }) })),
1239
+ /* @__PURE__ */ jsx13(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
1240
+ me.namedSeatsEnabled ? /* @__PURE__ */ jsx13(NamedSeatPurchase, { api }) : null
1165
1241
  ] });
1166
1242
  }
1167
1243
 
@@ -1170,7 +1246,7 @@ import { useEffect as useEffect11, useRef as useRef3, useState as useState18 } f
1170
1246
 
1171
1247
  // src/ui/join-booking.tsx
1172
1248
  import { useEffect as useEffect7, useState as useState11 } from "preact/hooks";
1173
- import { jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
1249
+ import { jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
1174
1250
  function JoinBooking(props) {
1175
1251
  const { applicationId, copy, onBooked, simulation } = props;
1176
1252
  const [state, setState] = useState11(null);
@@ -1233,11 +1309,11 @@ function JoinBooking(props) {
1233
1309
  setBusy(false);
1234
1310
  }
1235
1311
  };
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(
1312
+ if (!state) return /* @__PURE__ */ jsx14("p", { className: "slots-status", children: msg ?? copy.loading });
1313
+ return /* @__PURE__ */ jsxs14("div", { className: "join-book", children: [
1314
+ /* @__PURE__ */ jsx14("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
1315
+ /* @__PURE__ */ jsx14("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
1316
+ /* @__PURE__ */ jsx14(
1241
1317
  SlotPicker,
1242
1318
  {
1243
1319
  slots: state.slots,
@@ -1247,26 +1323,26 @@ function JoinBooking(props) {
1247
1323
  onDayChange: () => setSelected(null)
1248
1324
  }
1249
1325
  ),
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
1326
+ /* @__PURE__ */ jsxs14("div", { className: "slot-confirm", hidden: !selected, children: [
1327
+ /* @__PURE__ */ jsx14("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
1328
+ msg ? /* @__PURE__ */ jsx14("p", { className: "step2-note", children: msg }) : null
1253
1329
  ] })
1254
1330
  ] });
1255
1331
  }
1256
1332
 
1257
1333
  // src/ui/join-accepted.tsx
1258
- import { jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
1334
+ import { jsx as jsx15, jsxs as jsxs15 } from "preact/jsx-runtime";
1259
1335
  function JoinAccepted(props) {
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 })
1336
+ return /* @__PURE__ */ jsxs15("div", { className: "join-done card", children: [
1337
+ /* @__PURE__ */ jsx15("div", { className: "card-label", children: props.copy.accepted.label }),
1338
+ /* @__PURE__ */ jsx15("p", { className: "meeting-note", children: props.copy.accepted.body }),
1339
+ /* @__PURE__ */ jsx15("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
1264
1340
  ] });
1265
1341
  }
1266
1342
 
1267
1343
  // src/ui/gift-claim-card.tsx
1268
1344
  import { useState as useState12 } from "preact/hooks";
1269
- import { Fragment as Fragment7, jsx as jsx15, jsxs as jsxs15 } from "preact/jsx-runtime";
1345
+ import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs16 } from "preact/jsx-runtime";
1270
1346
  function GiftClaimCard(props) {
1271
1347
  const [code, setCode] = useState12(props.initialCode ?? "");
1272
1348
  const [error, setError] = useState12(false);
@@ -1282,21 +1358,21 @@ function GiftClaimCard(props) {
1282
1358
  if (response.ok && body.code) setCode(body.code);
1283
1359
  else setError(true);
1284
1360
  };
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 })
1361
+ return /* @__PURE__ */ jsxs16("div", { className: "join-done card", children: [
1362
+ /* @__PURE__ */ jsx16("div", { className: "card-label", children: props.copy.label }),
1363
+ /* @__PURE__ */ jsx16("p", { className: "meeting-note", children: props.copy.body }),
1364
+ code ? /* @__PURE__ */ jsxs16(Fragment7, { children: [
1365
+ /* @__PURE__ */ jsx16("output", { className: "gift-code", children: code }),
1366
+ /* @__PURE__ */ jsx16("p", { children: props.copy.save })
1291
1367
  ] }) : 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
1368
+ !code && props.claimId ? /* @__PURE__ */ jsx16("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
1369
+ error ? /* @__PURE__ */ jsx16("p", { role: "alert", children: props.copy.rotateFailed }) : null
1294
1370
  ] });
1295
1371
  }
1296
1372
 
1297
1373
  // src/ui/join-tiers.tsx
1298
1374
  import { useState as useState13 } from "preact/hooks";
1299
- import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs16 } from "preact/jsx-runtime";
1375
+ import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs17 } from "preact/jsx-runtime";
1300
1376
  var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
1301
1377
  function useTierSelection(tiers, initialTierId) {
1302
1378
  const [selectedTierId, setSelectedTierId] = useState13(() => {
@@ -1314,10 +1390,10 @@ function useTierSelection(tiers, initialTierId) {
1314
1390
  };
1315
1391
  }
1316
1392
  function TierPlaceholder(context) {
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(
1393
+ return /* @__PURE__ */ jsxs17("fieldset", { "data-chapter-placeholder": "tiers", children: [
1394
+ /* @__PURE__ */ jsx17("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
1395
+ context.tiers.map((tier) => /* @__PURE__ */ jsxs17("label", { children: [
1396
+ /* @__PURE__ */ jsx17(
1321
1397
  "input",
1322
1398
  {
1323
1399
  type: "radio",
@@ -1328,13 +1404,13 @@ function TierPlaceholder(context) {
1328
1404
  }
1329
1405
  ),
1330
1406
  tier.name,
1331
- tier.founding ? /* @__PURE__ */ jsxs16(Fragment8, { children: [
1407
+ tier.founding ? /* @__PURE__ */ jsxs17(Fragment8, { children: [
1332
1408
  " \u2014 ",
1333
1409
  joinTierMoney(tier.founding.dueTodayCents),
1334
1410
  " founding member rate (list ",
1335
1411
  joinTierMoney(tier.priceCents),
1336
1412
  ")"
1337
- ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs16(Fragment8, { children: [
1413
+ ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs17(Fragment8, { children: [
1338
1414
  " \u2014 ",
1339
1415
  joinTierMoney(tier.priceCents)
1340
1416
  ] })
@@ -1346,19 +1422,19 @@ function tierNeedsPayment(selected, paymentsReady) {
1346
1422
  }
1347
1423
 
1348
1424
  // src/ui/join-application-form.tsx
1349
- import { jsx as jsx17, jsxs as jsxs17 } from "preact/jsx-runtime";
1425
+ import { jsx as jsx18, jsxs as jsxs18 } from "preact/jsx-runtime";
1350
1426
  function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
1351
1427
  const disabled = submitting || props.submitDisabled === true;
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 })
1428
+ return /* @__PURE__ */ jsxs18("form", { className: "join-form", onSubmit: (event) => void submit(event), children: [
1429
+ !requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs18("fieldset", { children: [
1430
+ /* @__PURE__ */ jsx18("legend", { children: copy.gift.optionsLabel }),
1431
+ /* @__PURE__ */ jsx18("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
1432
+ /* @__PURE__ */ jsx18(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
1357
1433
  ] }) : null,
1358
1434
  !requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
1359
1435
  typeof props.children === "function" ? props.children({ invitation }) : props.children,
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 })
1436
+ error ? /* @__PURE__ */ jsx18("p", { className: "join-error", role: "alert", children: error }) : null,
1437
+ props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx18("button", { className: "submit-btn", type: "submit", disabled, children: submitting ? copy.form.submitting : copy.form.submit })
1362
1438
  ] });
1363
1439
  }
1364
1440
 
@@ -1384,7 +1460,7 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
1384
1460
  // src/ui/gift-code-redeemer.tsx
1385
1461
  import { InlineActionField } from "@odla-ai/ui/components";
1386
1462
  import { useState as useState14 } from "preact/hooks";
1387
- import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs18 } from "preact/jsx-runtime";
1463
+ import { Fragment as Fragment9, jsx as jsx19, jsxs as jsxs19 } from "preact/jsx-runtime";
1388
1464
  var GIFT_CODE_REDEEMER_CSS = `
1389
1465
  .gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
1390
1466
  .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}
@@ -1429,9 +1505,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1429
1505
  setLoading(false);
1430
1506
  }
1431
1507
  };
1432
- return /* @__PURE__ */ jsxs18(Fragment9, { children: [
1433
- /* @__PURE__ */ jsx18("style", { children: GIFT_CODE_REDEEMER_CSS }),
1434
- /* @__PURE__ */ jsx18(
1508
+ return /* @__PURE__ */ jsxs19(Fragment9, { children: [
1509
+ /* @__PURE__ */ jsx19("style", { children: GIFT_CODE_REDEEMER_CSS }),
1510
+ /* @__PURE__ */ jsx19(
1435
1511
  InlineActionField,
1436
1512
  {
1437
1513
  id,
@@ -1487,12 +1563,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
1487
1563
  }
1488
1564
 
1489
1565
  // src/ui/join-gift-claim.tsx
1490
- import { jsx as jsx19, jsxs as jsxs19 } from "preact/jsx-runtime";
1566
+ import { jsx as jsx20, jsxs as jsxs20 } from "preact/jsx-runtime";
1491
1567
  function JoinGiftClaim(props) {
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(
1568
+ return /* @__PURE__ */ jsxs20("section", { className: "join-gift-claim card", children: [
1569
+ /* @__PURE__ */ jsx20("div", { className: "card-label", children: props.copy.claimTitle }),
1570
+ /* @__PURE__ */ jsx20("p", { children: props.copy.claimBody }),
1571
+ /* @__PURE__ */ jsx20(
1496
1572
  GiftCodeRedeemer,
1497
1573
  {
1498
1574
  api: props.api,
@@ -1517,20 +1593,20 @@ function JoinGiftClaim(props) {
1517
1593
 
1518
1594
  // src/ui/join-named-seat.tsx
1519
1595
  import { useState as useState15 } from "preact/hooks";
1520
- import { jsx as jsx20, jsxs as jsxs20 } from "preact/jsx-runtime";
1596
+ import { jsx as jsx21, jsxs as jsxs21 } from "preact/jsx-runtime";
1521
1597
  function JoinNamedSeat(props) {
1522
1598
  const seatId = props.seatId ?? "";
1523
1599
  const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
1524
1600
  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 })
1601
+ return /* @__PURE__ */ jsxs21("section", { className: "join-named-seat card", children: [
1602
+ /* @__PURE__ */ jsx21("h2", { children: copy.title }),
1603
+ /* @__PURE__ */ jsx21("p", { children: copy.body }),
1604
+ /* @__PURE__ */ jsxs21("label", { className: "journey-consent", children: [
1605
+ /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
1606
+ /* @__PURE__ */ jsx21("span", { children: copy.consent })
1531
1607
  ] }),
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 () => {
1608
+ error ? /* @__PURE__ */ jsx21("p", { role: "alert", children: error }) : null,
1609
+ /* @__PURE__ */ jsx21("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
1534
1610
  setBusy(true);
1535
1611
  setError("");
1536
1612
  try {
@@ -1551,7 +1627,7 @@ function JoinNamedSeat(props) {
1551
1627
 
1552
1628
  // src/ui/join-invitation.tsx
1553
1629
  import { useEffect as useEffect8, useState as useState16 } from "preact/hooks";
1554
- import { jsx as jsx21, jsxs as jsxs21 } from "preact/jsx-runtime";
1630
+ import { jsx as jsx22, jsxs as jsxs22 } from "preact/jsx-runtime";
1555
1631
  function useJoinInvitation(seatId, api, fallback) {
1556
1632
  const [invitation, setInvitation] = useState16(null);
1557
1633
  const [error, setError] = useState16("");
@@ -1578,12 +1654,22 @@ function useJoinInvitation(seatId, api, fallback) {
1578
1654
  return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
1579
1655
  }
1580
1656
  function JoinInvitationNotice(props) {
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 }) })
1657
+ return /* @__PURE__ */ jsxs22("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
1658
+ /* @__PURE__ */ jsx22("p", { children: /* @__PURE__ */ jsx22("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
1659
+ /* @__PURE__ */ jsx22("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
1584
1660
  ] });
1585
1661
  }
1586
1662
 
1663
+ // src/ui/join-simulation.ts
1664
+ function joinSimulationPayment(simulation, priceCents) {
1665
+ if (!simulation) return void 0;
1666
+ return simulation.payment ?? { lineItems: {
1667
+ standardCents: priceCents,
1668
+ discountCents: 0,
1669
+ dueTodayCents: priceCents
1670
+ } };
1671
+ }
1672
+
1587
1673
  // src/ui/join-pending.ts
1588
1674
  import { useEffect as useEffect9 } from "preact/hooks";
1589
1675
  function useJoinPending(state, loadResume, setState) {
@@ -1611,7 +1697,7 @@ function useJoinPending(state, loadResume, setState) {
1611
1697
 
1612
1698
  // src/ui/payment-receipt.tsx
1613
1699
  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";
1700
+ import { Fragment as Fragment10, jsx as jsx23, jsxs as jsxs23 } from "preact/jsx-runtime";
1615
1701
  function PaymentReceiptCard({ applicationId }) {
1616
1702
  const [receipt, setReceipt] = useState17(null);
1617
1703
  const [error, setError] = useState17("");
@@ -1645,9 +1731,9 @@ function PaymentReceiptCard({ applicationId }) {
1645
1731
  if (timer) clearTimeout(timer);
1646
1732
  };
1647
1733
  }, [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" })
1734
+ if (!receipt) return error ? /* @__PURE__ */ jsxs23("section", { "aria-label": "Payment receipt", children: [
1735
+ /* @__PURE__ */ jsx23("p", { role: "status", children: error }),
1736
+ /* @__PURE__ */ jsx23("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
1651
1737
  ] }) : null;
1652
1738
  const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
1653
1739
  const email = async () => {
@@ -1664,38 +1750,45 @@ function PaymentReceiptCard({ applicationId }) {
1664
1750
  setError("We could not confirm email delivery. You can print or save your receipt.");
1665
1751
  }
1666
1752
  };
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: [
1753
+ return /* @__PURE__ */ jsxs23("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
1754
+ /* @__PURE__ */ jsx23("h2", { children: "Payment received" }),
1755
+ /* @__PURE__ */ jsx23("p", { children: receipt.tierName }),
1756
+ /* @__PURE__ */ jsxs23("dl", { className: "journey-summary", children: [
1757
+ /* @__PURE__ */ jsx23("dt", { children: "Membership" }),
1758
+ /* @__PURE__ */ jsx23("dd", { children: money(receipt.membershipCents) }),
1759
+ receipt.namedSeat ? /* @__PURE__ */ jsxs23(Fragment10, { children: [
1760
+ /* @__PURE__ */ jsxs23("dt", { children: [
1675
1761
  "Additional member \u2014 ",
1676
1762
  receipt.namedSeat.recipientName
1677
1763
  ] }),
1678
- /* @__PURE__ */ jsxs22("dd", { children: [
1764
+ /* @__PURE__ */ jsxs23("dd", { children: [
1679
1765
  receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
1680
1766
  money(receipt.namedSeat.amountCents)
1681
1767
  ] })
1682
1768
  ] }) : null,
1683
- /* @__PURE__ */ jsx22("dt", { children: "Total paid" }),
1684
- /* @__PURE__ */ jsx22("dd", { children: money(receipt.totalCents) })
1769
+ /* @__PURE__ */ jsx23("dt", { children: "Total paid" }),
1770
+ /* @__PURE__ */ jsx23("dd", { children: money(receipt.totalCents) })
1685
1771
  ] }),
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" })
1772
+ /* @__PURE__ */ jsxs23("div", { className: "journey-actions", children: [
1773
+ /* @__PURE__ */ jsx23("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
1774
+ /* @__PURE__ */ jsx23("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
1689
1775
  ] }),
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
1776
+ emailState === "sent" ? /* @__PURE__ */ jsx23("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
1777
+ error ? /* @__PURE__ */ jsx23("p", { role: "alert", children: error }) : null
1692
1778
  ] });
1693
1779
  }
1694
1780
 
1781
+ // src/ui/join-recipient.ts
1782
+ function validJoinRecipient(recipient) {
1783
+ if (!recipient) return true;
1784
+ const name = recipient.recipientName.trim(), email = recipient.recipientEmail.trim();
1785
+ return name.length >= 2 && name.length <= 160 && !/[\u0000-\u001f\u007f]/.test(name) && email.length <= 254 && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
1786
+ }
1787
+
1695
1788
  // src/ui/join.tsx
1696
- import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs23 } from "preact/jsx-runtime";
1789
+ import { Fragment as Fragment11, jsx as jsx24, jsxs as jsxs24 } from "preact/jsx-runtime";
1697
1790
  function JoinIsland(props) {
1698
- return /* @__PURE__ */ jsx23(JourneyFrame, { children: /* @__PURE__ */ jsx23(JoinFlow, { ...props }) });
1791
+ return /* @__PURE__ */ jsx24(JourneyFrame, { children: /* @__PURE__ */ jsx24(JoinFlow, { ...props }) });
1699
1792
  }
1700
1793
  function JoinFlow(props) {
1701
1794
  const inheritedCopy = useChapterCopy();
@@ -1719,14 +1812,9 @@ function JoinFlow(props) {
1719
1812
  const [state, setState] = useState18(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1720
1813
  const [error, setError] = useState18(null);
1721
1814
  const [submitting, setSubmitting] = useState18(false);
1815
+ const [editingNamedSeat, setEditingNamedSeat] = useState18(false);
1722
1816
  const [giftOfferId, setGiftOfferId] = useState18(props.initialGiftOfferId ?? null);
1723
- const simulatedPayment = props.simulation ? props.simulation.payment ?? {
1724
- lineItems: {
1725
- standardCents: selectedTier?.priceCents ?? 0,
1726
- discountCents: 0,
1727
- dueTodayCents: selectedTier?.priceCents ?? 0
1728
- }
1729
- } : void 0;
1817
+ const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
1730
1818
  const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
1731
1819
  const submissionId = useRef3(null);
1732
1820
  useEffect11(() => {
@@ -1750,6 +1838,10 @@ function JoinFlow(props) {
1750
1838
  const submit = async (e) => {
1751
1839
  e.preventDefault();
1752
1840
  if (submitting || props.submitDisabled === true || requestedSeat && !invitation) return;
1841
+ if (!validJoinRecipient(props.payment?.initialNamedSeat)) {
1842
+ setError("Enter your family member's full name and valid email before continuing.");
1843
+ return;
1844
+ }
1753
1845
  setSubmitting(true);
1754
1846
  setError(null);
1755
1847
  try {
@@ -1798,13 +1890,13 @@ function JoinFlow(props) {
1798
1890
  setSubmitting(false);
1799
1891
  }
1800
1892
  };
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
1893
+ if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs24("section", { className: "card", "aria-live": "polite", children: [
1894
+ /* @__PURE__ */ jsx24("h2", { children: seatCopy.title }),
1895
+ /* @__PURE__ */ jsx24("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
1896
+ invitationState.error ? /* @__PURE__ */ jsx24("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
1805
1897
  ] });
1806
- const header = /* @__PURE__ */ jsxs23(Fragment11, { children: [
1807
- invitation ? /* @__PURE__ */ jsx23(
1898
+ const header = /* @__PURE__ */ jsxs24(Fragment11, { children: [
1899
+ invitation ? /* @__PURE__ */ jsx24(
1808
1900
  JoinInvitationNotice,
1809
1901
  {
1810
1902
  invitation,
@@ -1814,51 +1906,52 @@ function JoinFlow(props) {
1814
1906
  ) : null,
1815
1907
  renderStepHeader?.({
1816
1908
  state,
1909
+ editingNamedSeat: state.step === "payment" && editingNamedSeat,
1817
1910
  ...invitation ? { invitation } : {},
1818
1911
  ..."applicationId" in state ? { applicationId: state.applicationId } : {}
1819
1912
  }),
1820
- !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx23(PaymentReceiptCard, { applicationId: state.applicationId }) : null
1913
+ !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx24(PaymentReceiptCard, { applicationId: state.applicationId }) : null
1821
1914
  ] });
1822
1915
  if (state.step === "closed") {
1823
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1916
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1824
1917
  header,
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 })
1918
+ /* @__PURE__ */ jsxs24("section", { className: "card", "aria-label": "Application closed", children: [
1919
+ /* @__PURE__ */ jsx24("h2", { children: "This application is closed" }),
1920
+ /* @__PURE__ */ jsx24("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
1921
+ /* @__PURE__ */ jsx24("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1829
1922
  ] })
1830
1923
  ] });
1831
1924
  }
1832
1925
  if (state.step === "done") {
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 })
1926
+ const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs24("div", { className: "join-done card", children: [
1927
+ /* @__PURE__ */ jsx24("div", { className: "card-label", children: copy.done.label }),
1928
+ /* @__PURE__ */ jsx24("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
1929
+ /* @__PURE__ */ jsx24("p", { className: "meeting-note", children: copy.done.calendarInvite }),
1930
+ /* @__PURE__ */ jsx24("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1838
1931
  ] });
1839
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1932
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1840
1933
  header,
1841
1934
  body
1842
1935
  ] });
1843
1936
  }
1844
1937
  if (state.step === "accepted") {
1845
- const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx23(JoinAccepted, { copy, membersHref });
1846
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1938
+ const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx24(JoinAccepted, { copy, membersHref });
1939
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1847
1940
  header,
1848
1941
  body
1849
1942
  ] });
1850
1943
  }
1851
1944
  if (state.step === "gift") {
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: [
1945
+ const body = renderGift?.(state) ?? /* @__PURE__ */ jsx24(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
1946
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1854
1947
  header,
1855
1948
  body
1856
1949
  ] });
1857
1950
  }
1858
1951
  if (state.step === "booking") {
1859
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1952
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1860
1953
  header,
1861
- /* @__PURE__ */ jsx23(
1954
+ /* @__PURE__ */ jsx24(
1862
1955
  JoinBooking,
1863
1956
  {
1864
1957
  applicationId: state.applicationId,
@@ -1873,9 +1966,9 @@ function JoinFlow(props) {
1873
1966
  }
1874
1967
  if (state.step === "payment") {
1875
1968
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
1876
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1969
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1877
1970
  header,
1878
- /* @__PURE__ */ jsx23(
1971
+ /* @__PURE__ */ jsx24(
1879
1972
  JoinNamedSeat,
1880
1973
  {
1881
1974
  api: props.namedSeatClaimApi,
@@ -1888,9 +1981,9 @@ function JoinFlow(props) {
1888
1981
  ] });
1889
1982
  }
1890
1983
  const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
1891
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
1984
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1892
1985
  header,
1893
- props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx23(
1986
+ props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx24(
1894
1987
  JoinGiftClaim,
1895
1988
  {
1896
1989
  api: props.giftClaimApi,
@@ -1901,17 +1994,15 @@ function JoinFlow(props) {
1901
1994
  onError: () => setError(copy.form.unexpectedFailure)
1902
1995
  }
1903
1996
  ) : null,
1904
- /* @__PURE__ */ jsx23(
1997
+ /* @__PURE__ */ jsx24(
1905
1998
  Payment,
1906
1999
  {
1907
2000
  applicationId: state.applicationId,
1908
2001
  refundPolicyText: config.refundPolicyText ?? "",
1909
2002
  merchantDisclosureText: config.merchantDisclosureText,
1910
2003
  copy: copy.payment,
1911
- appearance: props.payment?.appearance,
1912
- initialNamedSeat: props.payment?.initialNamedSeat,
1913
- fonts: props.payment?.fonts,
1914
- renderPriceLines: props.payment?.renderPriceLines,
2004
+ ...props.payment,
2005
+ onNamedSeatEditingChange: setEditingNamedSeat,
1915
2006
  simulation: simulatedPayment,
1916
2007
  onPaid: (result) => {
1917
2008
  if (props.simulation) {
@@ -1931,9 +2022,9 @@ function JoinFlow(props) {
1931
2022
  }
1932
2023
  if (state.step === "paymentPending") {
1933
2024
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
1934
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
2025
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1935
2026
  header,
1936
- /* @__PURE__ */ jsx23(
2027
+ /* @__PURE__ */ jsx24(
1937
2028
  JoinNamedSeat,
1938
2029
  {
1939
2030
  api: props.namedSeatClaimApi,
@@ -1945,14 +2036,14 @@ function JoinFlow(props) {
1945
2036
  )
1946
2037
  ] });
1947
2038
  }
1948
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
2039
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1949
2040
  header,
1950
- /* @__PURE__ */ jsx23("p", { className: "pay-status", role: "status", children: copy.payment.pending })
2041
+ /* @__PURE__ */ jsx24("p", { className: "pay-status", role: "status", children: copy.payment.pending })
1951
2042
  ] });
1952
2043
  }
1953
- return /* @__PURE__ */ jsxs23(Fragment11, { children: [
2044
+ return /* @__PURE__ */ jsxs24(Fragment11, { children: [
1954
2045
  header,
1955
- /* @__PURE__ */ jsx23(
2046
+ /* @__PURE__ */ jsx24(
1956
2047
  JoinApplicationForm,
1957
2048
  {
1958
2049
  props,
@@ -2142,7 +2233,7 @@ function membershipPageDocument(input, options = {}) {
2142
2233
  }
2143
2234
 
2144
2235
  // src/ui/membership-cards.tsx
2145
- import { jsx as jsx24, jsxs as jsxs24 } from "preact/jsx-runtime";
2236
+ import { jsx as jsx25, jsxs as jsxs25 } from "preact/jsx-runtime";
2146
2237
  var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
2147
2238
  "--ui-membership-grid-gap": "1.4rem",
2148
2239
  "--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
@@ -2211,67 +2302,67 @@ function membershipApplicationHref(applicationPath, tierId) {
2211
2302
  }
2212
2303
  function TierAction(props) {
2213
2304
  if (props.mode === "select") {
2214
- return /* @__PURE__ */ jsxs24("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2305
+ return /* @__PURE__ */ jsxs25("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2215
2306
  props.label,
2216
- /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2307
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u2192" })
2217
2308
  ] });
2218
2309
  }
2219
2310
  if (props.mode === "preview") {
2220
- return /* @__PURE__ */ jsxs24("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2311
+ return /* @__PURE__ */ jsxs25("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2221
2312
  props.label,
2222
- /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2313
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u2192" })
2223
2314
  ] });
2224
2315
  }
2225
- return /* @__PURE__ */ jsxs24("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2316
+ return /* @__PURE__ */ jsxs25("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2226
2317
  props.label,
2227
- /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: "\u2192" })
2318
+ /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u2192" })
2228
2319
  ] });
2229
2320
  }
2230
2321
  function TierCard(props) {
2231
2322
  const { tier, presentation } = props;
2232
2323
  const summary = presentation.summaryMarkdown ?? tier.blurb;
2233
2324
  const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
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" })
2325
+ return /* @__PURE__ */ jsxs25("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2326
+ presentation.badge ? /* @__PURE__ */ jsx25("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2327
+ /* @__PURE__ */ jsx25("h3", { className: "chapter-membership-name", children: tier.name }),
2328
+ /* @__PURE__ */ jsxs25("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2329
+ presentation.capacity ? /* @__PURE__ */ jsxs25("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2330
+ /* @__PURE__ */ jsx25("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2331
+ /* @__PURE__ */ jsx25("small", { children: presentation.capacity.label ?? "available" })
2241
2332
  ] }) : 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
2333
+ /* @__PURE__ */ jsxs25("div", { className: "chapter-membership-price-stack", children: [
2334
+ presentation.priceEyebrow ? /* @__PURE__ */ jsx25("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx25("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2335
+ /* @__PURE__ */ jsxs25("div", { className: "chapter-membership-price-row", children: [
2336
+ tier.founding ? /* @__PURE__ */ jsx25("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx25("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2337
+ /* @__PURE__ */ jsx25("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2338
+ !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx25("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2248
2339
  ] })
2249
2340
  ] })
2250
2341
  ] }),
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 })
2342
+ presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx25(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2343
+ summary ? /* @__PURE__ */ jsx25(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2344
+ presentation.benefits?.length ? /* @__PURE__ */ jsx25("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs25("li", { children: [
2345
+ /* @__PURE__ */ jsx25("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2346
+ /* @__PURE__ */ jsx25(Markdown2, { className: "chapter-membership-benefit", source: benefit })
2256
2347
  ] }, `${tier.id}-benefit-${index}`)) }) : null,
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 })
2348
+ presentation.callout ? /* @__PURE__ */ jsxs25("aside", { className: "chapter-membership-callout", children: [
2349
+ presentation.callout.label ? /* @__PURE__ */ jsx25("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2350
+ /* @__PURE__ */ jsx25(Markdown2, { source: presentation.callout.bodyMarkdown })
2260
2351
  ] }) : null,
2261
- /* @__PURE__ */ jsx24(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2352
+ /* @__PURE__ */ jsx25(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2262
2353
  ] });
2263
2354
  }
2264
2355
  function MembershipCards(props) {
2265
2356
  const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
2266
2357
  const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
2267
2358
  const mode = props.mode ?? "link";
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) => {
2359
+ return /* @__PURE__ */ jsxs25("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2360
+ /* @__PURE__ */ jsx25("style", { children: MEMBERSHIP_CARDS_CSS }),
2361
+ /* @__PURE__ */ jsx25("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2271
2362
  const tier = byId.get(presentation.tierId);
2272
- return /* @__PURE__ */ jsx24(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2363
+ return /* @__PURE__ */ jsx25(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2273
2364
  }) }),
2274
- document2.footnoteMarkdown ? /* @__PURE__ */ jsx24(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2365
+ document2.footnoteMarkdown ? /* @__PURE__ */ jsx25(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2275
2366
  ] });
2276
2367
  }
2277
2368
 
@@ -2307,4 +2398,4 @@ export {
2307
2398
  membershipApplicationHref,
2308
2399
  MembershipCards
2309
2400
  };
2310
- //# sourceMappingURL=chunk-IQZWCG42.js.map
2401
+ //# sourceMappingURL=chunk-NK267YQZ.js.map