@odla-ai/chapter 0.56.1 → 0.56.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -111,14 +111,185 @@ function SlotPicker(props) {
111
111
  }
112
112
 
113
113
  // src/ui/member-restart.tsx
114
- import { useEffect as useEffect2, useState as useState5 } from "preact/hooks";
114
+ import { useEffect as useEffect2, useState as useState7 } from "preact/hooks";
115
+
116
+ // src/ui/additional-member-editor.tsx
117
+ import { useRef as useRef2, useState as useState3 } from "preact/hooks";
118
+
119
+ // src/ui/additional-member-fields.tsx
120
+ import { useRef } from "preact/hooks";
121
+ import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
122
+ var ADDITIONAL_MEMBER_COPY = {
123
+ label: "Additional member",
124
+ includedChoice: "Include my additional member at no extra charge.",
125
+ paidChoice: "Add one additional member.",
126
+ includedHint: "Included with your membership at no extra charge.",
127
+ pendingHint: "Your additional-member rate will be confirmed at checkout.",
128
+ editTitle: "Edit additional member details"
129
+ };
130
+ function additionalMemberSelection(value) {
131
+ return value.selected ? { recipientName: value.name.trim(), recipientEmail: value.email.trim() } : null;
132
+ }
133
+ function AdditionalMemberFields({ value, onChange, offer, ...options }) {
134
+ const draft = useRef(value);
135
+ draft.current = value;
136
+ const change = (patch) => {
137
+ draft.current = { ...draft.current, ...patch };
138
+ onChange(draft.current);
139
+ };
140
+ const copy = { ...ADDITIONAL_MEMBER_COPY, ...options.copy };
141
+ const names = { selected: "additionalMemberSelected", name: "additionalMemberName", email: "additionalMemberEmail", ...options.names };
142
+ const price2 = offer && new Intl.NumberFormat("en-US", { style: "currency", currency: offer.currency ?? "USD" }).format(offer.amountCents / 100);
143
+ return /* @__PURE__ */ jsxs2("div", { className: "form-group additional-member-fields", children: [
144
+ /* @__PURE__ */ jsx2("label", { htmlFor: names.selected, children: copy.label }),
145
+ /* @__PURE__ */ jsx2("p", { className: "hint", children: offer?.amountCents === 0 ? copy.includedHint : offer ? `${price2} per ${offer.interval ?? "year"}, paid with your membership.` : copy.pendingHint }),
146
+ /* @__PURE__ */ jsxs2("label", { className: "checkbox-option journey-consent", children: [
147
+ /* @__PURE__ */ jsx2(
148
+ "input",
149
+ {
150
+ type: "checkbox",
151
+ id: names.selected,
152
+ name: names.selected,
153
+ value: "yes",
154
+ checked: value.selected,
155
+ onChange: (event) => change({ selected: event.currentTarget.checked })
156
+ }
157
+ ),
158
+ offer?.amountCents === 0 ? copy.includedChoice : copy.paidChoice
159
+ ] }),
160
+ value.selected ? /* @__PURE__ */ jsxs2("div", { className: "additional-member-details", children: [
161
+ /* @__PURE__ */ jsxs2("label", { htmlFor: names.name, children: [
162
+ "Full name ",
163
+ /* @__PURE__ */ jsx2("span", { className: "req", "aria-hidden": "true", children: "*" })
164
+ ] }),
165
+ /* @__PURE__ */ jsx2(
166
+ "input",
167
+ {
168
+ type: "text",
169
+ id: names.name,
170
+ name: names.name,
171
+ placeholder: "Full name",
172
+ required: true,
173
+ minLength: 2,
174
+ maxLength: 160,
175
+ pattern: ".*\\S.*\\S.*",
176
+ value: value.name,
177
+ onInput: (event) => change({ name: event.currentTarget.value })
178
+ }
179
+ ),
180
+ /* @__PURE__ */ jsxs2("label", { htmlFor: names.email, children: [
181
+ "Email ",
182
+ /* @__PURE__ */ jsx2("span", { className: "req", "aria-hidden": "true", children: "*" })
183
+ ] }),
184
+ /* @__PURE__ */ jsx2(
185
+ "input",
186
+ {
187
+ type: "email",
188
+ id: names.email,
189
+ name: names.email,
190
+ placeholder: "member@example.com",
191
+ required: true,
192
+ pattern: "[^\\s@]+@[^\\s@]+\\.[^\\s@]+",
193
+ maxLength: 254,
194
+ value: value.email,
195
+ onInput: (event) => change({ email: event.currentTarget.value })
196
+ }
197
+ )
198
+ ] }) : null
199
+ ] });
200
+ }
201
+
202
+ // src/ui/form-readiness.ts
203
+ import { useLayoutEffect, useState as useState2 } from "preact/hooks";
204
+ function isFormReady(form) {
205
+ return Array.from(form.elements).every((element) => {
206
+ const field = element;
207
+ return !field.willValidate || field.validity.valid && (!field.required || field.value.trim().length > 0);
208
+ });
209
+ }
210
+ function useFormReadiness(ref) {
211
+ const [ready, setReady] = useState2(false);
212
+ useLayoutEffect(() => {
213
+ const form = ref.current;
214
+ if (!form) return;
215
+ let live = true;
216
+ const update = () => {
217
+ if (live) setReady(isFormReady(form));
218
+ };
219
+ const afterInput = () => queueMicrotask(update);
220
+ update();
221
+ for (const type of ["input", "change", "focusin", "reset"]) form.addEventListener(type, afterInput);
222
+ const observer = new MutationObserver(afterInput);
223
+ observer.observe(form, {
224
+ childList: true,
225
+ subtree: true,
226
+ attributes: true,
227
+ attributeFilter: ["required", "disabled", "pattern", "minlength", "maxlength", "min", "max", "type"]
228
+ });
229
+ return () => {
230
+ live = false;
231
+ observer.disconnect();
232
+ for (const type of ["input", "change", "focusin", "reset"]) form.removeEventListener(type, afterInput);
233
+ };
234
+ });
235
+ return ready;
236
+ }
237
+
238
+ // src/ui/join-submit-button.tsx
239
+ import { jsx as jsx3 } from "preact/jsx-runtime";
240
+ function JoinSubmitButton(props) {
241
+ return /* @__PURE__ */ jsx3("button", { ...props, type: "submit", className: "submit-btn chapter-form-primary" });
242
+ }
243
+
244
+ // src/ui/join-recipient.ts
245
+ function validJoinRecipient(recipient) {
246
+ if (!recipient) return true;
247
+ const name = recipient.recipientName.trim(), email = recipient.recipientEmail.trim();
248
+ return name.length >= 2 && name.length <= 160 && !/[\u0000-\u001f\u007f]/.test(name) && email.length <= 254 && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
249
+ }
250
+
251
+ // src/ui/additional-member-editor.tsx
252
+ import { jsx as jsx4, jsxs as jsxs3 } from "preact/jsx-runtime";
253
+ function AdditionalMemberEditor({ selection, offer, save, cancel, onSaved, ...options }) {
254
+ const [value, setValue] = useState3({ selected: Boolean(selection), name: selection?.recipientName ?? "", email: selection?.recipientEmail ?? "" });
255
+ const [saving, setSaving] = useState3(false), [error, setError] = useState3("");
256
+ const form = useRef2(null), inFlight = useRef2(false);
257
+ const ready = useFormReadiness(form);
258
+ const valid = validJoinRecipient(additionalMemberSelection(value) ?? void 0);
259
+ return /* @__PURE__ */ jsxs3("form", { ref: form, className: "join-form additional-member-editor", onSubmit: async (event) => {
260
+ event.preventDefault();
261
+ if (inFlight.current || !valid || !isFormReady(event.currentTarget)) return;
262
+ inFlight.current = true;
263
+ setSaving(true);
264
+ setError("");
265
+ try {
266
+ await save(additionalMemberSelection(value));
267
+ onSaved?.(value);
268
+ } catch (failure) {
269
+ setError(failure instanceof Error ? failure.message : "Could not save your changes. Try again.");
270
+ } finally {
271
+ inFlight.current = false;
272
+ setSaving(false);
273
+ }
274
+ }, children: [
275
+ /* @__PURE__ */ jsx4("h2", { children: options.copy?.editTitle ?? ADDITIONAL_MEMBER_COPY.editTitle }),
276
+ /* @__PURE__ */ jsxs3("fieldset", { disabled: saving, children: [
277
+ /* @__PURE__ */ jsx4(AdditionalMemberFields, { ...options, value, onChange: setValue, offer }),
278
+ error ? /* @__PURE__ */ jsx4("p", { role: "alert", children: error }) : null,
279
+ /* @__PURE__ */ jsxs3("div", { className: "journey-actions additional-member-actions", children: [
280
+ /* @__PURE__ */ jsx4(JoinSubmitButton, { disabled: saving || !ready || !valid, children: saving ? "Saving\u2026" : "Save details" }),
281
+ /* @__PURE__ */ jsx4("button", { className: "journey-secondary", type: "button", onClick: cancel, children: "Cancel" })
282
+ ] })
283
+ ] })
284
+ ] });
285
+ }
115
286
 
116
287
  // src/ui/membership-payment-step.tsx
117
- import { useEffect, useState as useState4 } from "preact/hooks";
288
+ import { useEffect, useState as useState6 } from "preact/hooks";
118
289
 
119
290
  // src/ui/payment-step.tsx
120
- import { useRef, useState as useState2 } from "preact/hooks";
121
- import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
291
+ import { useRef as useRef3, useState as useState4 } from "preact/hooks";
292
+ import { jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
122
293
  var loader = null;
123
294
  function loadStripe() {
124
295
  const existing = globalThis.Stripe;
@@ -152,13 +323,13 @@ function PaymentStep(props) {
152
323
  simulation
153
324
  } = props;
154
325
  const copy = props.copy ?? inheritedCopy.join.payment;
155
- const [status, setStatus] = useState2("idle");
156
- const [error, setError] = useState2(null);
157
- const [lineItems, setLineItems] = useState2(null);
158
- const mountRef = useRef(null);
159
- const stripeRef = useRef(null);
160
- const elementsRef = useRef(null);
161
- const completionRef = useRef({ gift: false });
326
+ const [status, setStatus] = useState4("idle");
327
+ const [error, setError] = useState4(null);
328
+ const [lineItems, setLineItems] = useState4(null);
329
+ const mountRef = useRef3(null);
330
+ const stripeRef = useRef3(null);
331
+ const elementsRef = useRef3(null);
332
+ const completionRef = useRef3({ gift: false });
162
333
  const begin = async () => {
163
334
  setStatus("loading");
164
335
  setError(null);
@@ -228,12 +399,12 @@ function PaymentStep(props) {
228
399
  setStatus("ready");
229
400
  }
230
401
  };
231
- return /* @__PURE__ */ jsxs2("div", { className: "join-pay", children: [
232
- /* @__PURE__ */ jsxs2("div", { className: "compliance-box", children: [
233
- merchantDisclosureText ? /* @__PURE__ */ jsx2("p", { className: "compliance-merchant", children: merchantDisclosureText }) : null,
234
- /* @__PURE__ */ jsx2("p", { className: "compliance-policy", children: refundPolicyText }),
235
- /* @__PURE__ */ jsxs2("label", { className: "compliance-check", children: [
236
- /* @__PURE__ */ jsx2(
402
+ return /* @__PURE__ */ jsxs4("div", { className: "join-pay", children: [
403
+ /* @__PURE__ */ jsxs4("div", { className: "compliance-box", children: [
404
+ merchantDisclosureText ? /* @__PURE__ */ jsx5("p", { className: "compliance-merchant", children: merchantDisclosureText }) : null,
405
+ /* @__PURE__ */ jsx5("p", { className: "compliance-policy", children: refundPolicyText }),
406
+ /* @__PURE__ */ jsxs4("label", { className: "compliance-check", children: [
407
+ /* @__PURE__ */ jsx5(
237
408
  "input",
238
409
  {
239
410
  type: "checkbox",
@@ -243,52 +414,55 @@ function PaymentStep(props) {
243
414
  }
244
415
  }
245
416
  ),
246
- copy.consent ? /* @__PURE__ */ jsx2("span", { children: copy.consent }) : null
417
+ copy.consent ? /* @__PURE__ */ jsx5("span", { children: copy.consent }) : null
247
418
  ] })
248
419
  ] }),
249
- status === "loading" ? /* @__PURE__ */ jsx2("p", { className: "pay-status", children: copy.preparing }) : null,
420
+ status === "loading" ? /* @__PURE__ */ jsx5("p", { className: "pay-status", children: copy.preparing }) : null,
250
421
  lineItems && renderPriceLines ? renderPriceLines(lineItems) : null,
251
422
  children,
252
- simulation && (status === "ready" || status === "confirming") ? /* @__PURE__ */ jsxs2("fieldset", { className: "join-pay-simulation", children: [
253
- /* @__PURE__ */ jsx2("legend", { children: "Payment details" }),
254
- /* @__PURE__ */ jsxs2("label", { children: [
423
+ simulation && (status === "ready" || status === "confirming") ? /* @__PURE__ */ jsxs4("fieldset", { className: "join-pay-simulation", children: [
424
+ /* @__PURE__ */ jsx5("legend", { children: "Payment details" }),
425
+ /* @__PURE__ */ jsxs4("label", { children: [
255
426
  "Card number",
256
- /* @__PURE__ */ jsx2("input", { name: "simulationCardNumber", inputMode: "numeric", autoComplete: "off", defaultValue: "4242 4242 4242 4242" })
427
+ /* @__PURE__ */ jsx5("input", { name: "simulationCardNumber", inputMode: "numeric", autoComplete: "off", defaultValue: "4242 4242 4242 4242" })
257
428
  ] }),
258
- /* @__PURE__ */ jsxs2("label", { children: [
429
+ /* @__PURE__ */ jsxs4("label", { children: [
259
430
  "Expiration",
260
- /* @__PURE__ */ jsx2("input", { name: "simulationCardExpiry", inputMode: "numeric", autoComplete: "off", defaultValue: "12 / 34" })
431
+ /* @__PURE__ */ jsx5("input", { name: "simulationCardExpiry", inputMode: "numeric", autoComplete: "off", defaultValue: "12 / 34" })
261
432
  ] }),
262
- /* @__PURE__ */ jsxs2("label", { children: [
433
+ /* @__PURE__ */ jsxs4("label", { children: [
263
434
  "Security code",
264
- /* @__PURE__ */ jsx2("input", { name: "simulationCardCvc", inputMode: "numeric", autoComplete: "off", defaultValue: "123" })
435
+ /* @__PURE__ */ jsx5("input", { name: "simulationCardCvc", inputMode: "numeric", autoComplete: "off", defaultValue: "123" })
265
436
  ] }),
266
- /* @__PURE__ */ jsx2("p", { children: "This is a simulation. No card data is sent and no charge is created." })
437
+ /* @__PURE__ */ jsx5("p", { children: "This is a simulation. No card data is sent and no charge is created." })
267
438
  ] }) : null,
268
- /* @__PURE__ */ jsx2("div", { ref: mountRef, hidden: status === "idle" || status === "loading" }),
269
- status === "ready" || status === "confirming" ? /* @__PURE__ */ jsx2("button", { className: "submit-btn", disabled: status === "confirming", onClick: () => void pay(), children: status === "confirming" ? copy.processing : copy.payAndContinue }) : null,
270
- error ? /* @__PURE__ */ jsx2("p", { className: "pay-error", children: error }) : null
439
+ /* @__PURE__ */ jsx5("div", { ref: mountRef, hidden: status === "idle" || status === "loading" }),
440
+ status === "ready" || status === "confirming" ? /* @__PURE__ */ jsx5("button", { className: "submit-btn", disabled: status === "confirming", onClick: () => void pay(), children: status === "confirming" ? copy.processing : copy.payAndContinue }) : null,
441
+ error ? /* @__PURE__ */ jsx5("p", { className: "pay-error", children: error }) : null
271
442
  ] });
272
443
  }
273
444
 
274
445
  // src/ui/checkout-seat-choice.tsx
275
- import { useState as useState3 } from "preact/hooks";
276
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
446
+ import { useRef as useRef4, useState as useState5 } from "preact/hooks";
447
+ import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
277
448
  function CheckoutSeatChoice(props) {
278
449
  const saved = props.quote.namedSeat;
279
- const [selected, setSelected] = useState3(Boolean(saved || props.initial));
280
- const [name, setName] = useState3(saved?.recipientName ?? props.initial?.recipientName ?? "");
281
- const [email, setEmail] = useState3(saved?.recipientEmail ?? props.initial?.recipientEmail ?? "");
282
- const [saving, setSaving] = useState3(false), [error, setError] = useState3("");
283
- const amount = props.quote.seatOffer.amountCents;
284
- const money = new Intl.NumberFormat("en-US", { style: "currency", currency: props.quote.currency }).format(amount / 100);
450
+ const [selected, setSelected] = useState5(Boolean(saved || props.initial));
451
+ const [name, setName] = useState5(saved?.recipientName ?? props.initial?.recipientName ?? "");
452
+ const [email, setEmail] = useState5(saved?.recipientEmail ?? props.initial?.recipientEmail ?? "");
453
+ const [saving, setSaving] = useState5(false), [error, setError] = useState5("");
454
+ const form = useRef4(null), inFlight = useRef4(false);
455
+ const ready = useFormReadiness(form);
456
+ const valid = validJoinRecipient(selected ? { recipientName: name, recipientEmail: email } : void 0);
285
457
  const dirty = selected !== Boolean(saved) || selected && (name !== saved?.recipientName || email !== saved?.recipientEmail);
286
458
  const edit = (nextSelected, nextName = name, nextEmail = email) => {
287
459
  props.onEditing(nextSelected !== Boolean(saved) || nextSelected && (nextName !== saved?.recipientName || nextEmail !== saved?.recipientEmail));
288
460
  setError("");
289
461
  };
290
- return /* @__PURE__ */ jsx3("section", { className: "checkout-seat-choice", "aria-label": "Additional member", children: /* @__PURE__ */ jsxs3("form", { onSubmit: async (event) => {
462
+ return /* @__PURE__ */ jsx6("section", { className: "checkout-seat-choice", "aria-label": "Additional member", children: /* @__PURE__ */ jsxs5("form", { ref: form, onSubmit: async (event) => {
291
463
  event.preventDefault();
464
+ if (props.locked || inFlight.current || !valid || !isFormReady(event.currentTarget)) return;
465
+ inFlight.current = true;
292
466
  setSaving(true);
293
467
  setError("");
294
468
  try {
@@ -296,88 +470,60 @@ function CheckoutSeatChoice(props) {
296
470
  } catch (error2) {
297
471
  setError(error2 instanceof Error ? error2.message : "Could not save your selection. Try again.");
298
472
  } finally {
473
+ inFlight.current = false;
299
474
  setSaving(false);
300
475
  }
301
476
  }, children: [
302
- /* @__PURE__ */ jsxs3("fieldset", { disabled: props.locked || saving, children: [
303
- /* @__PURE__ */ jsx3("legend", { children: amount === 0 ? "Included additional member" : "Add an additional member" }),
304
- /* @__PURE__ */ jsx3("p", { children: amount === 0 ? "Your membership includes one additional member at no extra charge." : `Additional-member rate: ${money} per ${props.quote.interval}, paid together with your membership.` }),
305
- /* @__PURE__ */ jsxs3("label", { children: [
306
- /* @__PURE__ */ jsx3("input", { type: "checkbox", checked: selected, onChange: (event) => {
307
- setSelected(event.currentTarget.checked);
308
- edit(event.currentTarget.checked);
309
- } }),
310
- amount === 0 ? "Include my additional member" : "Add one member to my payment"
311
- ] }),
312
- selected ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
313
- /* @__PURE__ */ jsxs3("label", { children: [
314
- "Full name",
315
- /* @__PURE__ */ jsx3(
316
- "input",
317
- {
318
- required: true,
319
- minLength: 2,
320
- maxLength: 160,
321
- value: name,
322
- onInput: (event) => {
323
- setName(event.currentTarget.value);
324
- edit(selected, event.currentTarget.value);
325
- }
326
- }
327
- )
328
- ] }),
329
- /* @__PURE__ */ jsxs3("label", { children: [
330
- "Email",
331
- /* @__PURE__ */ jsx3(
332
- "input",
333
- {
334
- required: true,
335
- type: "email",
336
- maxLength: 254,
337
- value: email,
338
- onInput: (event) => {
339
- setEmail(event.currentTarget.value);
340
- edit(selected, name, event.currentTarget.value);
341
- }
342
- }
343
- )
344
- ] }),
345
- /* @__PURE__ */ jsx3("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
346
- ] }) : /* @__PURE__ */ jsx3("p", { children: "You can add someone from your member page after paying." }),
347
- dirty ? /* @__PURE__ */ jsx3("button", { type: "submit", disabled: saving, children: saving ? "Saving\u2026" : amount === 0 ? "Save member details" : "Update total" }) : null
477
+ /* @__PURE__ */ jsxs5("fieldset", { disabled: props.locked || saving, children: [
478
+ /* @__PURE__ */ jsx6(
479
+ AdditionalMemberFields,
480
+ {
481
+ value: { selected, name, email },
482
+ offer: { ...props.quote.seatOffer, currency: props.quote.currency, interval: props.quote.interval },
483
+ onChange: (value) => {
484
+ setSelected(value.selected);
485
+ setName(value.name);
486
+ setEmail(value.email);
487
+ edit(value.selected, value.name, value.email);
488
+ }
489
+ }
490
+ ),
491
+ selected ? /* @__PURE__ */ jsx6("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." }) : /* @__PURE__ */ jsx6("p", { children: "You can add someone from your member page after paying." }),
492
+ dirty ? /* @__PURE__ */ jsx6(JoinSubmitButton, { disabled: saving || !ready || !valid, children: saving ? "Saving\u2026" : "Save details" }) : null
348
493
  ] }),
349
- error ? /* @__PURE__ */ jsx3("p", { role: "alert", children: error }) : null
494
+ error ? /* @__PURE__ */ jsx6("p", { role: "alert", children: error }) : null
350
495
  ] }) });
351
496
  }
352
497
 
353
498
  // src/ui/checkout-seat-review.tsx
354
- import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
499
+ import { jsx as jsx7, jsxs as jsxs6 } from "preact/jsx-runtime";
355
500
  function CheckoutSeatReview({ quote, label, locked, onEdit }) {
356
501
  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: [
502
+ return /* @__PURE__ */ jsxs6("section", { className: "checkout-seat-review", "aria-label": label, children: [
503
+ /* @__PURE__ */ jsx7("h3", { children: label }),
504
+ /* @__PURE__ */ jsxs6("p", { children: [
360
505
  quote.namedSeat.recipientName,
361
- /* @__PURE__ */ jsx4("br", {}),
506
+ /* @__PURE__ */ jsx7("br", {}),
362
507
  quote.namedSeat.recipientEmail
363
508
  ] }),
364
- !locked ? /* @__PURE__ */ jsx4("button", { type: "button", onClick: onEdit, children: "Edit details" }) : null
509
+ !locked ? /* @__PURE__ */ jsx7("button", { type: "button", onClick: onEdit, children: "Edit details" }) : null
365
510
  ] });
366
511
  }
367
512
 
368
513
  // src/ui/membership-payment-step.tsx
369
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
514
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
370
515
  function MembershipPaymentStep(props) {
516
+ const renderEditor = props.renderNamedSeatEditor ?? (props.additionalMember ? (context) => /* @__PURE__ */ jsx8(AdditionalMemberEditor, { ...props.additionalMember, ...context }) : void 0);
371
517
  const inherited = useChapterCopy();
372
518
  const copy = props.copy ?? inherited.join.payment;
373
- const [quote, setQuote] = useState4(null);
374
- const [locked, setLocked] = useState4(false), [editing, setEditing] = useState4(Boolean(props.initialNamedSeat));
375
- const [prefillConsumed, setPrefillConsumed] = useState4(false);
376
- const [error, setError] = useState4(false);
377
- const [revision, setRevision] = useState4(0);
519
+ const [quote, setQuote] = useState6(null);
520
+ const [locked, setLocked] = useState6(false), [editing, setEditing] = useState6(Boolean(props.initialNamedSeat));
521
+ const [prefillConsumed, setPrefillConsumed] = useState6(false);
522
+ const [error, setError] = useState6(false);
523
+ const [revision, setRevision] = useState6(0);
378
524
  useEffect(() => {
379
- props.onNamedSeatEditingChange?.(Boolean(props.renderNamedSeatEditor && editing && !locked && quote));
380
- }, [editing, locked, Boolean(quote), Boolean(props.renderNamedSeatEditor)]);
525
+ props.onNamedSeatEditingChange?.(Boolean(renderEditor && editing && !locked && quote));
526
+ }, [editing, locked, Boolean(quote), Boolean(renderEditor)]);
381
527
  useEffect(() => {
382
528
  let live = true;
383
529
  setQuote(null);
@@ -388,7 +534,7 @@ function MembershipPaymentStep(props) {
388
534
  value.checkoutStarted = response.headers.get("x-chapter-checkout-started") === "true";
389
535
  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
536
  if (!live) return;
391
- if (props.renderNamedSeatEditor && props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer) {
537
+ if (renderEditor && props.initialNamedSeat && !prefillConsumed && !value.namedSeat && !value.checkoutStarted && value.seatOffer) {
392
538
  const saved = await fetch(`/api/payments/quote?application=${encodeURIComponent(props.applicationId)}`, {
393
539
  method: "POST",
394
540
  cache: "no-store",
@@ -427,10 +573,10 @@ function MembershipPaymentStep(props) {
427
573
  setQuote(null);
428
574
  setRevision((value) => value + 1);
429
575
  };
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
576
+ if (!quote || quote.applicationId !== props.applicationId) return /* @__PURE__ */ jsxs7("div", { className: "join-pay", role: "status", children: [
577
+ props.merchantDisclosureText ? /* @__PURE__ */ jsx8("p", { className: "compliance-merchant", children: props.merchantDisclosureText }) : null,
578
+ /* @__PURE__ */ jsx8("p", { children: error ? copy.setupFailed : copy.preparing }),
579
+ error ? /* @__PURE__ */ jsx8("button", { type: "button", onClick: refresh, children: "Reload payment terms" }) : null
434
580
  ] });
435
581
  const startCheckout = async () => {
436
582
  setLocked(true);
@@ -470,9 +616,9 @@ function MembershipPaymentStep(props) {
470
616
  setPrefillConsumed(true);
471
617
  };
472
618
  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({
619
+ if (renderEditor && editing && !locked && quote.seatOffer) return /* @__PURE__ */ jsxs7(Fragment2, { children: [
620
+ error ? /* @__PURE__ */ jsx8("p", { role: "alert", children: "Enter a different recipient's full name and valid email to continue." }) : null,
621
+ renderEditor({
476
622
  selection: quote.namedSeat ?? (!prefillConsumed ? props.initialNamedSeat : void 0) ?? null,
477
623
  offer: { ...quote.seatOffer, currency: quote.currency, interval: quote.interval },
478
624
  save: changeSeat,
@@ -483,8 +629,8 @@ function MembershipPaymentStep(props) {
483
629
  }
484
630
  })
485
631
  ] });
486
- return /* @__PURE__ */ jsxs5(Fragment3, { children: [
487
- props.renderNamedSeatEditor ? /* @__PURE__ */ jsx5(
632
+ return /* @__PURE__ */ jsxs7(Fragment2, { children: [
633
+ renderEditor ? /* @__PURE__ */ jsx8(
488
634
  CheckoutSeatReview,
489
635
  {
490
636
  quote,
@@ -492,7 +638,7 @@ function MembershipPaymentStep(props) {
492
638
  locked,
493
639
  onEdit: () => setEditing(true)
494
640
  }
495
- ) : quote.seatOffer ? /* @__PURE__ */ jsx5(
641
+ ) : quote.seatOffer ? /* @__PURE__ */ jsx8(
496
642
  CheckoutSeatChoice,
497
643
  {
498
644
  quote,
@@ -503,52 +649,52 @@ function MembershipPaymentStep(props) {
503
649
  },
504
650
  quote.digest
505
651
  ) : 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,
652
+ /* @__PURE__ */ jsxs7("section", { className: "payment-quote", "aria-label": "Membership price", children: [
653
+ /* @__PURE__ */ jsx8("h3", { children: quote.tierName }),
654
+ quote.founding ? /* @__PURE__ */ jsx8("p", { className: "payment-founding", role: "note", "aria-label": "Founding member", children: copy.foundingMember }) : null,
509
655
  props.renderPriceLines ? props.renderPriceLines({
510
656
  ...quote.lineItems,
511
657
  ...quote.founding ? { founding: quote.founding } : {},
512
658
  ...pickLater ? { namedSeatPickLater: true } : {},
513
659
  ...quote.presentation ? { presentation: quote.presentation } : {}
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: [
660
+ }) : /* @__PURE__ */ jsxs7("dl", { children: [
661
+ quote.lineItems.discountCents > 0 && !quote.founding && quote.presentation ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
662
+ /* @__PURE__ */ jsx8("dt", { children: copy.standardRate }),
663
+ /* @__PURE__ */ jsxs7("dd", { children: [
518
664
  amount(quote.lineItems.standardCents),
519
665
  " per ",
520
666
  quote.interval
521
667
  ] }),
522
- /* @__PURE__ */ jsx5("dt", { children: copy.yourRate }),
523
- /* @__PURE__ */ jsxs5("dd", { children: [
668
+ /* @__PURE__ */ jsx8("dt", { children: copy.yourRate }),
669
+ /* @__PURE__ */ jsxs7("dd", { children: [
524
670
  amount(quote.lineItems.dueTodayCents - (quote.lineItems.namedSeatCents ?? 0)),
525
671
  " per ",
526
672
  quote.interval
527
673
  ] })
528
- ] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
529
- /* @__PURE__ */ jsx5("dt", { children: "Membership price" }),
530
- /* @__PURE__ */ jsxs5("dd", { children: [
674
+ ] }) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
675
+ /* @__PURE__ */ jsx8("dt", { children: "Membership price" }),
676
+ /* @__PURE__ */ jsxs7("dd", { children: [
531
677
  amount(quote.lineItems.standardCents),
532
678
  " per ",
533
679
  quote.interval
534
680
  ] }),
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) })
681
+ quote.lineItems.discountCents > 0 ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
682
+ /* @__PURE__ */ jsx8("dt", { children: quote.founding ? copy.foundingDiscount : "Discount" }),
683
+ /* @__PURE__ */ jsx8("dd", { children: amount(quote.lineItems.discountCents) })
538
684
  ] }) : null
539
685
  ] }),
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) })
686
+ quote.namedSeat ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
687
+ /* @__PURE__ */ jsx8("dt", { children: "Additional member" }),
688
+ /* @__PURE__ */ jsx8("dd", { children: quote.lineItems.namedSeatCents === 0 ? "Included" : amount(quote.lineItems.namedSeatCents) })
543
689
  ] }) : null,
544
- pickLater ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
545
- /* @__PURE__ */ jsx5("dt", { children: "Additional member" }),
546
- /* @__PURE__ */ jsx5("dd", { children: "Pick later" })
690
+ pickLater ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
691
+ /* @__PURE__ */ jsx8("dt", { children: "Additional member" }),
692
+ /* @__PURE__ */ jsx8("dd", { children: "Pick later" })
547
693
  ] }) : null,
548
- /* @__PURE__ */ jsx5("dt", { children: "Due today" }),
549
- /* @__PURE__ */ jsx5("dd", { children: amount(quote.lineItems.dueTodayCents) })
694
+ /* @__PURE__ */ jsx8("dt", { children: "Due today" }),
695
+ /* @__PURE__ */ jsx8("dd", { children: amount(quote.lineItems.dueTodayCents) })
550
696
  ] }),
551
- quote.namedSeat && !props.renderNamedSeatEditor ? /* @__PURE__ */ jsxs5("p", { children: [
697
+ quote.namedSeat && !renderEditor ? /* @__PURE__ */ jsxs7("p", { children: [
552
698
  "For ",
553
699
  quote.namedSeat.recipientName,
554
700
  " \xB7 ",
@@ -556,8 +702,8 @@ function MembershipPaymentStep(props) {
556
702
  ".",
557
703
  props.renderPriceLines ? ` Additional member: ${quote.lineItems.namedSeatCents === 0 ? "included" : amount(quote.lineItems.namedSeatCents)} in the total above.` : ""
558
704
  ] }) : null,
559
- quote.commercial ? /* @__PURE__ */ jsxs5("div", { role: "note", "aria-label": "Renewal terms", children: [
560
- quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs5("p", { children: [
705
+ quote.commercial ? /* @__PURE__ */ jsxs7("div", { role: "note", "aria-label": "Renewal terms", children: [
706
+ quote.commercial.initialTermEndsAt !== void 0 ? /* @__PURE__ */ jsxs7("p", { children: [
561
707
  "First renewal: ",
562
708
  new Intl.DateTimeFormat("en-US", {
563
709
  dateStyle: "long",
@@ -565,23 +711,23 @@ function MembershipPaymentStep(props) {
565
711
  }).format(quote.commercial.initialTermEndsAt),
566
712
  "."
567
713
  ] }) : null,
568
- /* @__PURE__ */ jsxs5("p", { children: [
714
+ /* @__PURE__ */ jsxs7("p", { children: [
569
715
  "Renews automatically at ",
570
716
  amount(quote.commercial.renewalCents),
571
717
  " per ",
572
718
  quote.interval,
573
719
  " unless canceled before renewal."
574
720
  ] }),
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
721
+ quote.commercial.discountDuration === "first_term" ? /* @__PURE__ */ jsx8("p", { children: "The discount applies to your first paid term only." }) : null,
722
+ quote.commercial.discountDuration === "while_active" ? /* @__PURE__ */ jsx8("p", { children: "The discounted rate continues while this membership stays active." }) : null
577
723
  ] }) : null,
578
- quote.trustCopy ? /* @__PURE__ */ jsx5("p", { className: "pay-trust", children: quote.trustCopy }) : null
724
+ quote.trustCopy ? /* @__PURE__ */ jsx8("p", { className: "pay-trust", children: quote.trustCopy }) : null
579
725
  ] }),
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." })
726
+ quote.namedSeat && renderEditor ? /* @__PURE__ */ jsxs7("details", { className: "checkout-seat-terms", children: [
727
+ /* @__PURE__ */ jsx8("summary", { children: "Additional-member terms" }),
728
+ /* @__PURE__ */ jsx8("p", { children: "For one named person, who completes their own application and any required interview. Non-transferable; renews and ends with your membership." })
583
729
  ] }) : null,
584
- !editing ? /* @__PURE__ */ jsx5(
730
+ !editing ? /* @__PURE__ */ jsx8(
585
731
  PaymentStep,
586
732
  {
587
733
  ...props,
@@ -592,12 +738,12 @@ function MembershipPaymentStep(props) {
592
738
  startCheckout
593
739
  },
594
740
  quote.digest
595
- ) : /* @__PURE__ */ jsx5("p", { role: "status", children: "Save your member selection to continue to payment." })
741
+ ) : /* @__PURE__ */ jsx8("p", { role: "status", children: "Save your member selection to continue to payment." })
596
742
  ] });
597
743
  }
598
744
 
599
745
  // src/ui/journey-frame.tsx
600
- import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
746
+ import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
601
747
  var styles = `
602
748
  .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}
603
749
  .chapter-journey *{box-sizing:border-box}
@@ -619,6 +765,14 @@ var styles = `
619
765
  .chapter-journey :is(.slot-time,.slot-day):hover{background:var(--ui-surface-2,#f3f5f2);color:var(--ui-text,#202827);border-color:var(--ui-accent,#285c50)}
620
766
  .chapter-journey :is(.slot-time,.slot-day)[aria-pressed=true]{background:var(--ui-accent,#285c50);color:var(--ui-on-accent,#fff)}
621
767
  .chapter-journey button:disabled{opacity:.55;cursor:default}
768
+ .chapter-journey .chapter-form-primary{background:var(--ui-accent,#285c50);color:var(--ui-on-accent,#fff);width:100%;margin-top:1rem}
769
+ .chapter-journey .chapter-form-primary:hover:not(:disabled){filter:brightness(.92)}
770
+ .chapter-journey .chapter-form-primary:disabled{background:var(--ui-surface-2,#e3e8df);color:var(--ui-text-muted,#687361);opacity:1;cursor:not-allowed;transform:none;filter:none}
771
+ .chapter-journey .additional-member-details{padding:1rem;margin-top:1rem;background:var(--ui-surface-2,#f3f5f2);border:1px solid var(--ui-border,#dfe3df);border-radius:8px}
772
+ .chapter-journey .additional-member-details label:not(:first-child){margin-top:.6rem}
773
+ .chapter-journey .additional-member-actions .chapter-form-primary{width:auto;flex:1;margin-top:0}
774
+ .chapter-journey .additional-member-actions .journey-secondary{min-width:7rem}
775
+ @media(max-width:520px){.chapter-journey .additional-member-actions{flex-direction:column}}
622
776
  .chapter-journey :where(.compliance-box,.journey-note){padding:1.2rem;background:var(--ui-surface-2,#f3f5f2);border-radius:10px;margin-block:1.2rem}
623
777
  .chapter-journey :where(.compliance-box p:last-child,.journey-note p:last-child,.card p:last-child){margin-bottom:0}
624
778
  .chapter-journey .journey-invitation{padding:1.1rem 1.3rem;border-left:3px solid var(--ui-accent,#285c50);background:var(--ui-surface-2,#f3f5f2);border-radius:0 10px 10px 0;margin-block:1rem}
@@ -634,21 +788,21 @@ var styles = `
634
788
  @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}}
635
789
  `;
636
790
  function JourneyFrame({ children }) {
637
- return /* @__PURE__ */ jsxs6("div", { className: "chapter-journey", children: [
638
- /* @__PURE__ */ jsx6("style", { children: styles }),
791
+ return /* @__PURE__ */ jsxs8("div", { className: "chapter-journey", children: [
792
+ /* @__PURE__ */ jsx9("style", { children: styles }),
639
793
  children
640
794
  ] });
641
795
  }
642
796
 
643
797
  // src/ui/member-restart.tsx
644
- import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
798
+ import { jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
645
799
  function MemberRestart(props) {
646
- const [id, setId] = useState5(props.applicationId);
647
- const [busy, setBusy] = useState5(false);
648
- const [error, setError] = useState5("");
649
- const [paid, setPaid] = useState5(false);
650
- const [checking, setChecking] = useState5(false);
651
- const [revision, setRevision] = useState5(0);
800
+ const [id, setId] = useState7(props.applicationId);
801
+ const [busy, setBusy] = useState7(false);
802
+ const [error, setError] = useState7("");
803
+ const [paid, setPaid] = useState7(false);
804
+ const [checking, setChecking] = useState7(false);
805
+ const [revision, setRevision] = useState7(0);
652
806
  useEffect2(() => {
653
807
  if (!paid) return;
654
808
  let live = true, timer, attempt = 0;
@@ -686,40 +840,40 @@ function MemberRestart(props) {
686
840
  setBusy(false);
687
841
  }
688
842
  };
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 })
843
+ return /* @__PURE__ */ jsx10(JourneyFrame, { children: /* @__PURE__ */ jsxs9("section", { className: "card", "aria-label": "Restart membership", children: [
844
+ /* @__PURE__ */ jsx10("p", { className: "card-label", children: "Welcome back" }),
845
+ /* @__PURE__ */ jsx10("h2", { children: "Restart your membership" }),
846
+ /* @__PURE__ */ jsx10("p", { children: "Your account is ready, and your previous approval still counts. No new application or interview is needed." }),
847
+ /* @__PURE__ */ jsxs9("dl", { className: "journey-summary", children: [
848
+ /* @__PURE__ */ jsx10("dt", { children: "Name" }),
849
+ /* @__PURE__ */ jsx10("dd", { children: [props.application.firstName, props.application.lastName].filter(Boolean).join(" ") }),
850
+ /* @__PURE__ */ jsx10("dt", { children: "Email" }),
851
+ /* @__PURE__ */ jsx10("dd", { children: props.application.email })
698
852
  ] }),
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
853
+ paid ? /* @__PURE__ */ jsxs9("div", { role: "status", children: [
854
+ /* @__PURE__ */ jsx10("h3", { children: "Confirming your membership" }),
855
+ /* @__PURE__ */ jsx10("p", { children: "We\u2019re waiting for payment confirmation. Your membership will open here as soon as it arrives." }),
856
+ !checking ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Check membership" }) : null
857
+ ] }) : id ? /* @__PURE__ */ jsx10(MembershipPaymentStep, { applicationId: id, refundPolicyText: "", onPaid: () => setPaid(true) }) : /* @__PURE__ */ jsx10("button", { type: "button", disabled: busy, onClick: () => void start(), children: busy ? "Preparing your membership\u2026" : "Review membership and payment" }),
858
+ error ? /* @__PURE__ */ jsx10("p", { role: "alert", children: error }) : null
705
859
  ] }) });
706
860
  }
707
861
 
708
862
  // src/ui/members.tsx
709
- import { useEffect as useEffect6, useState as useState10 } from "preact/hooks";
863
+ import { useEffect as useEffect6, useState as useState12 } from "preact/hooks";
710
864
 
711
865
  // src/ui/reschedule.tsx
712
- import { useState as useState6 } from "preact/hooks";
713
- import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
866
+ import { useState as useState8 } from "preact/hooks";
867
+ import { jsx as jsx11, jsxs as jsxs10 } from "preact/jsx-runtime";
714
868
  function Rescheduler(props) {
715
869
  const inheritedCopy = useChapterCopy();
716
870
  const copy = props.copy ?? inheritedCopy.members.reschedule;
717
871
  const { api, applicationId, timezone, onRescheduled, label = copy.changeTime } = props;
718
- const [open, setOpen] = useState6(false);
719
- const [slots, setSlots] = useState6(null);
720
- const [tz, setTz] = useState6(timezone);
721
- const [busy, setBusy] = useState6(false);
722
- const [msg, setMsg] = useState6(null);
872
+ const [open, setOpen] = useState8(false);
873
+ const [slots, setSlots] = useState8(null);
874
+ const [tz, setTz] = useState8(timezone);
875
+ const [busy, setBusy] = useState8(false);
876
+ const [msg, setMsg] = useState8(null);
723
877
  const start = async () => {
724
878
  setOpen(true);
725
879
  setSlots(null);
@@ -752,7 +906,7 @@ function Rescheduler(props) {
752
906
  }
753
907
  };
754
908
  if (!open) {
755
- return /* @__PURE__ */ jsx8("p", { className: "meeting-note", children: /* @__PURE__ */ jsx8(
909
+ return /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: /* @__PURE__ */ jsx11(
756
910
  "a",
757
911
  {
758
912
  href: "#",
@@ -764,8 +918,8 @@ function Rescheduler(props) {
764
918
  }
765
919
  ) });
766
920
  }
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(
921
+ return /* @__PURE__ */ jsxs10("div", { className: "msched", children: [
922
+ slots === null ? /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: copy.loading }) : slots.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: msg ?? copy.noTimes }) : /* @__PURE__ */ jsx11(
769
923
  SlotPicker,
770
924
  {
771
925
  slots,
@@ -774,9 +928,9 @@ function Rescheduler(props) {
774
928
  onPick: (s) => void pick(s)
775
929
  }
776
930
  ),
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(
931
+ busy ? /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: copy.rescheduling }) : null,
932
+ msg && slots && slots.length > 0 ? /* @__PURE__ */ jsx11("p", { className: "meeting-note error", children: msg }) : null,
933
+ /* @__PURE__ */ jsx11("p", { className: "meeting-note", children: /* @__PURE__ */ jsx11(
780
934
  "a",
781
935
  {
782
936
  href: "#",
@@ -791,32 +945,32 @@ function Rescheduler(props) {
791
945
  }
792
946
 
793
947
  // src/ui/member-gifts.tsx
794
- import { useEffect as useEffect3, useRef as useRef2, useState as useState7 } from "preact/hooks";
948
+ import { useEffect as useEffect3, useRef as useRef5, useState as useState9 } from "preact/hooks";
795
949
 
796
950
  // src/ui/gift-offer-cards.tsx
797
- import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
951
+ import { jsx as jsx12, jsxs as jsxs11 } from "preact/jsx-runtime";
798
952
  var price = (cents, currency) => currency === "usd" ? fmtMoney(cents) : new Intl.NumberFormat(void 0, { style: "currency", currency: currency.toUpperCase() }).format(cents / 100);
799
953
  function GiftOfferCards(props) {
800
954
  const mode = props.mode ?? "preview";
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: [
955
+ return /* @__PURE__ */ jsx12("section", { className: "chapter-gift-offers", "aria-label": props.ariaLabel ?? "Gift options", children: props.offers.map((offer) => /* @__PURE__ */ jsxs11("article", { className: "card chapter-gift-offer", "data-offer-id": offer.id, children: [
956
+ /* @__PURE__ */ jsx12("div", { className: "card-label", children: offer.title }),
957
+ /* @__PURE__ */ jsx12("p", { children: offer.description }),
958
+ /* @__PURE__ */ jsxs11("p", { className: "meeting-date", children: [
805
959
  price(offer.priceCents, offer.currency),
806
960
  offer.billingMode === "subscription" ? " recurring" : ""
807
961
  ] }),
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 })
962
+ mode === "select" ? /* @__PURE__ */ jsx12("button", { type: "button", className: "btn secondary", "aria-pressed": props.selectedOfferId === offer.id, onClick: () => props.onSelect?.(offer.id), children: offer.ctaLabel }) : /* @__PURE__ */ jsx12("span", { className: "btn secondary", "aria-disabled": "true", children: offer.ctaLabel })
809
963
  ] }, offer.id)) });
810
964
  }
811
965
 
812
966
  // src/ui/member-gifts.tsx
813
- import { jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
967
+ import { jsx as jsx13, jsxs as jsxs12 } from "preact/jsx-runtime";
814
968
  function GiftPurchases(props) {
815
- const [data, setData] = useState7(null);
816
- const [selected, setSelected] = useState7(null);
817
- const [code, setCode] = useState7("");
818
- const [message, setMessage] = useState7("");
819
- const purchaseId = useRef2(crypto.randomUUID());
969
+ const [data, setData] = useState9(null);
970
+ const [selected, setSelected] = useState9(null);
971
+ const [code, setCode] = useState9("");
972
+ const [message, setMessage] = useState9("");
973
+ const purchaseId = useRef5(crypto.randomUUID());
820
974
  const load = async () => setData(await props.api("/api/gifts"));
821
975
  useEffect3(() => {
822
976
  void load().catch(() => setData({ offers: [], claims: [] }));
@@ -833,16 +987,16 @@ function GiftPurchases(props) {
833
987
  if (!data) return null;
834
988
  if (data.offers.length === 0 && data.claims.length === 0) return null;
835
989
  const offer = data.offers.find((item) => item.id === selected);
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) => {
990
+ return /* @__PURE__ */ jsxs12("section", { className: "member-gifts", children: [
991
+ data.offers.length ? /* @__PURE__ */ jsxs12("div", { className: "card", children: [
992
+ /* @__PURE__ */ jsx13("div", { className: "card-label", children: props.copy.title }),
993
+ /* @__PURE__ */ jsx13("p", { children: props.copy.body }),
994
+ /* @__PURE__ */ jsx13(GiftOfferCards, { offers: data.offers, mode: "select", selectedOfferId: selected, onSelect: (id) => {
841
995
  setSelected(id);
842
996
  setCode("");
843
997
  purchaseId.current = crypto.randomUUID();
844
998
  } }),
845
- offer ? /* @__PURE__ */ jsx10(
999
+ offer ? /* @__PURE__ */ jsx13(
846
1000
  PaymentStep,
847
1001
  {
848
1002
  applicationId: purchaseId.current,
@@ -862,27 +1016,27 @@ function GiftPurchases(props) {
862
1016
  }
863
1017
  }
864
1018
  ) : null,
865
- code ? /* @__PURE__ */ jsxs10("div", { className: "gift-code-once", children: [
866
- /* @__PURE__ */ jsx10("output", { children: code }),
867
- /* @__PURE__ */ jsx10("p", { children: props.copy.saveCode })
1019
+ code ? /* @__PURE__ */ jsxs12("div", { className: "gift-code-once", children: [
1020
+ /* @__PURE__ */ jsx13("output", { children: code }),
1021
+ /* @__PURE__ */ jsx13("p", { children: props.copy.saveCode })
868
1022
  ] }) : null
869
1023
  ] }) : 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
1024
+ /* @__PURE__ */ jsxs12("div", { className: "card", children: [
1025
+ /* @__PURE__ */ jsx13("div", { className: "card-label", children: props.copy.purchases }),
1026
+ data.claims.length ? data.claims.map((claim) => /* @__PURE__ */ jsxs12("div", { className: "member-row", children: [
1027
+ /* @__PURE__ */ jsx13("span", { children: claim.offerId }),
1028
+ /* @__PURE__ */ jsx13("span", { children: props.copy[claim.status] }),
1029
+ claim.status === "pending" ? /* @__PURE__ */ jsx13("button", { className: "btn secondary mini", onClick: () => void rotate(claim.id), children: props.copy.rotate }) : null
1030
+ ] }, claim.id)) : /* @__PURE__ */ jsx13("p", { children: props.copy.noPurchases }),
1031
+ message ? /* @__PURE__ */ jsx13("p", { role: "status", children: message }) : null
878
1032
  ] })
879
1033
  ] });
880
1034
  }
881
1035
  var MemberGifts = GiftPurchases;
882
1036
 
883
1037
  // src/ui/member-named-seat.tsx
884
- import { useEffect as useEffect4, useState as useState8 } from "preact/hooks";
885
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
1038
+ import { useEffect as useEffect4, useState as useState10 } from "preact/hooks";
1039
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs13 } from "preact/jsx-runtime";
886
1040
  var NAMED_SEAT_RECIPIENT_WORDS = {
887
1041
  payment_pending: "payment in progress",
888
1042
  invited: "invited, waiting for them to accept",
@@ -895,7 +1049,7 @@ var NAMED_SEAT_RECIPIENT_WORDS = {
895
1049
  var day = (at) => new Date(at).toLocaleDateString("en-US", { timeZone: "UTC" });
896
1050
  function NamedSeatRecipientLine({ seat }) {
897
1051
  const words = NAMED_SEAT_RECIPIENT_WORDS[seat.recipientState] ?? seat.status.replaceAll("_", " ");
898
- return /* @__PURE__ */ jsxs11("p", { className: "member-named-seat-recipient", children: [
1052
+ return /* @__PURE__ */ jsxs13("p", { className: "member-named-seat-recipient", children: [
899
1053
  seat.recipientName,
900
1054
  " \xB7 ",
901
1055
  seat.recipientEmail,
@@ -905,9 +1059,9 @@ function NamedSeatRecipientLine({ seat }) {
905
1059
  ] });
906
1060
  }
907
1061
  function NamedSeatPurchase({ api }) {
908
- const [data, setData] = useState8(null), [error, setError] = useState8("");
909
- const [name, setName] = useState8(""), [email, setEmail] = useState8(""), [reviewing, setReviewing] = useState8(false);
910
- const [terms, setTerms] = useState8(false), [pending, setPending] = useState8(false), [granting, setGranting] = useState8(false);
1062
+ const [data, setData] = useState10(null), [error, setError] = useState10("");
1063
+ const [name, setName] = useState10(""), [email, setEmail] = useState10(""), [reviewing, setReviewing] = useState10(false);
1064
+ const [terms, setTerms] = useState10(false), [pending, setPending] = useState10(false), [granting, setGranting] = useState10(false);
911
1065
  const load = async () => {
912
1066
  try {
913
1067
  const value = await api("/api/named-seat");
@@ -944,13 +1098,13 @@ function NamedSeatPurchase({ api }) {
944
1098
  }
945
1099
  };
946
1100
  const money = data ? new Intl.NumberFormat("en-US", { style: "currency", currency: data.currency }).format(data.amountCents / 100) : "";
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: [
1101
+ return /* @__PURE__ */ jsx14(JourneyFrame, { children: /* @__PURE__ */ jsxs13("section", { className: "card member-named-seat", "aria-label": "Named additional seat", children: [
1102
+ /* @__PURE__ */ jsx14("h2", { children: "Named additional seat" }),
1103
+ error ? /* @__PURE__ */ jsx14("p", { role: "alert", children: error }) : null,
1104
+ data ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
1105
+ data.seat ? /* @__PURE__ */ jsx14(NamedSeatRecipientLine, { seat: data.seat }) : null,
1106
+ data.eligible ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
1107
+ /* @__PURE__ */ jsxs13("p", { children: [
954
1108
  data.included ? "Included with your membership at no charge." : `${money} paid in full now.`,
955
1109
  " This seat ",
956
1110
  data.autoRenew ? "renews with your primary membership" : "ends with your primary membership",
@@ -961,39 +1115,39 @@ function NamedSeatPurchase({ api }) {
961
1115
  " ",
962
1116
  "It belongs to one named person and cannot be reassigned."
963
1117
  ] }),
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) => {
1118
+ /* @__PURE__ */ jsx14("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." }),
1119
+ !reviewing ? /* @__PURE__ */ jsxs13("form", { onSubmit: (event) => {
966
1120
  event.preventDefault();
967
1121
  setReviewing(true);
968
1122
  setTerms(false);
969
1123
  }, children: [
970
- /* @__PURE__ */ jsxs11("label", { children: [
1124
+ /* @__PURE__ */ jsxs13("label", { children: [
971
1125
  "Recipient name",
972
- /* @__PURE__ */ jsx11("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
1126
+ /* @__PURE__ */ jsx14("input", { required: true, maxLength: 160, value: name, disabled: Boolean(data.seat), onInput: (event) => setName(event.currentTarget.value) })
973
1127
  ] }),
974
- /* @__PURE__ */ jsxs11("label", { children: [
1128
+ /* @__PURE__ */ jsxs13("label", { children: [
975
1129
  "Recipient email",
976
- /* @__PURE__ */ jsx11("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
1130
+ /* @__PURE__ */ jsx14("input", { required: true, type: "email", maxLength: 254, value: email, disabled: Boolean(data.seat), onInput: (event) => setEmail(event.currentTarget.value) })
977
1131
  ] }),
978
- /* @__PURE__ */ jsx11("button", { className: "btn primary", type: "submit", children: "Review named seat" })
979
- ] }) : /* @__PURE__ */ jsxs11(Fragment4, { children: [
980
- /* @__PURE__ */ jsxs11("p", { children: [
1132
+ /* @__PURE__ */ jsx14("button", { className: "btn primary", type: "submit", children: "Review named seat" })
1133
+ ] }) : /* @__PURE__ */ jsxs13(Fragment3, { children: [
1134
+ /* @__PURE__ */ jsxs13("p", { children: [
981
1135
  "For ",
982
1136
  name,
983
1137
  " \xB7 ",
984
1138
  email
985
1139
  ] }),
986
- /* @__PURE__ */ jsx11("button", { className: "btn secondary", type: "button", onClick: () => {
1140
+ /* @__PURE__ */ jsx14("button", { className: "btn secondary", type: "button", onClick: () => {
987
1141
  setReviewing(false);
988
1142
  setTerms(false);
989
1143
  void load();
990
1144
  }, children: "Back to recipient" }),
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." })
1145
+ /* @__PURE__ */ jsxs13("label", { className: "journey-consent", children: [
1146
+ /* @__PURE__ */ jsx14("input", { type: "checkbox", checked: terms, onChange: (event) => setTerms(event.currentTarget.checked) }),
1147
+ /* @__PURE__ */ jsx14("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." })
994
1148
  ] }),
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(
1149
+ terms && data.included ? /* @__PURE__ */ jsx14("button", { className: "btn primary", type: "button", disabled: granting, onClick: () => void grant(), children: granting ? "Sending the invitation\u2026" : "Send the invitation" }) : null,
1150
+ terms && !data.included ? /* @__PURE__ */ jsx14(
997
1151
  PaymentStep,
998
1152
  {
999
1153
  applicationId: data.membershipId,
@@ -1008,17 +1162,17 @@ function NamedSeatPurchase({ api }) {
1008
1162
  }
1009
1163
  ) : null
1010
1164
  ] })
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" })
1165
+ ] }) : !data.seat ? /* @__PURE__ */ jsx14("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,
1166
+ pending ? /* @__PURE__ */ jsx14("p", { role: "status", children: "Payment confirmation is being reconciled. The recipient\u2019s access begins only after their own acceptance and approval." }) : null
1167
+ ] }) : !error ? /* @__PURE__ */ jsx14("p", { children: "Loading your seat terms\u2026" }) : null,
1168
+ /* @__PURE__ */ jsx14("button", { className: "btn secondary", onClick: () => void load(), children: "Refresh seat status" })
1015
1169
  ] }) });
1016
1170
  }
1017
1171
 
1018
1172
  // src/ui/member-content.tsx
1019
- import { useEffect as useEffect5, useMemo as useMemo2, useState as useState9 } from "preact/hooks";
1173
+ import { useEffect as useEffect5, useMemo as useMemo2, useState as useState11 } from "preact/hooks";
1020
1174
  import { Markdown } from "@odla-ai/ui/components";
1021
- import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
1175
+ import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs14 } from "preact/jsx-runtime";
1022
1176
  var pageLabel = (page) => `${page.title}${page.access === "locked" ? " \xB7 Locked" : ""}`;
1023
1177
  function MemberContentArea(props) {
1024
1178
  const {
@@ -1026,12 +1180,12 @@ function MemberContentArea(props) {
1026
1180
  path = "/api/member-content",
1027
1181
  upsellHref,
1028
1182
  onUpsell,
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." })
1183
+ loadingContent = /* @__PURE__ */ jsx15("p", { className: "meeting-note", children: "Loading member pages\u2026" }),
1184
+ emptyContent = /* @__PURE__ */ jsx15("p", { className: "meeting-note", children: "No member pages have been published yet." })
1031
1185
  } = props;
1032
- const [data, setData] = useState9(props.initialData ?? null);
1033
- const [error, setError] = useState9(null);
1034
- const [selectedId, setSelectedId] = useState9(
1186
+ const [data, setData] = useState11(props.initialData ?? null);
1187
+ const [error, setError] = useState11(null);
1188
+ const [selectedId, setSelectedId] = useState11(
1035
1189
  props.initialPageId ?? props.initialData?.pages[0]?.id ?? ""
1036
1190
  );
1037
1191
  useEffect5(() => {
@@ -1056,18 +1210,18 @@ function MemberContentArea(props) {
1056
1210
  }
1057
1211
  return [...result.entries()];
1058
1212
  }, [data]);
1059
- if (error) return /* @__PURE__ */ jsxs12("p", { className: "meeting-note", role: "alert", children: [
1213
+ if (error) return /* @__PURE__ */ jsxs14("p", { className: "meeting-note", role: "alert", children: [
1060
1214
  "Member pages could not be loaded: ",
1061
1215
  error
1062
1216
  ] });
1063
- if (!data) return /* @__PURE__ */ jsx12(Fragment5, { children: loadingContent });
1064
- if (data.pages.length === 0) return /* @__PURE__ */ jsx12(Fragment5, { children: emptyContent });
1217
+ if (!data) return /* @__PURE__ */ jsx15(Fragment4, { children: loadingContent });
1218
+ if (data.pages.length === 0) return /* @__PURE__ */ jsx15(Fragment4, { children: emptyContent });
1065
1219
  const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
1066
1220
  const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
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(
1221
+ return /* @__PURE__ */ jsxs14("div", { className: "chapter-member-content", "data-member-content": true, children: [
1222
+ /* @__PURE__ */ jsx15("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs14("section", { className: "chapter-member-content-section", children: [
1223
+ /* @__PURE__ */ jsx15("h2", { children: section }),
1224
+ /* @__PURE__ */ jsx15("ul", { children: pages.map((page) => /* @__PURE__ */ jsx15("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx15(
1071
1225
  "button",
1072
1226
  {
1073
1227
  type: "button",
@@ -1077,23 +1231,23 @@ function MemberContentArea(props) {
1077
1231
  }
1078
1232
  ) }, page.id)) })
1079
1233
  ] }, section)) }),
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: [
1234
+ /* @__PURE__ */ jsxs14("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
1235
+ /* @__PURE__ */ jsxs14("header", { children: [
1236
+ /* @__PURE__ */ jsxs14("div", { className: "card-label", children: [
1083
1237
  selected.source.type === "parent" ? "Parent" : "Chapter",
1084
1238
  " \xB7 ",
1085
1239
  selected.access
1086
1240
  ] }),
1087
- /* @__PURE__ */ jsx12("h1", { children: selected.title }),
1088
- selected.summary ? /* @__PURE__ */ jsx12("p", { children: selected.summary }) : null
1241
+ /* @__PURE__ */ jsx15("h1", { children: selected.title }),
1242
+ selected.summary ? /* @__PURE__ */ jsx15("p", { children: selected.summary }) : null
1089
1243
  ] }),
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
1244
+ selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx15(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs14("div", { className: "chapter-member-content-locked", children: [
1245
+ selected.teaserMarkdown ? /* @__PURE__ */ jsx15(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx15("p", { children: "This page is not included in your current membership." }),
1246
+ selected.upsell ? /* @__PURE__ */ jsxs14("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
1247
+ /* @__PURE__ */ jsx15("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
1248
+ /* @__PURE__ */ jsx15("p", { children: fmtMoney(selected.upsell.priceCents) }),
1249
+ selected.upsell.bodyMarkdown ? /* @__PURE__ */ jsx15(Markdown, { source: selected.upsell.bodyMarkdown }) : null,
1250
+ href ? /* @__PURE__ */ jsx15("a", { className: "btn primary", href, children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : onUpsell ? /* @__PURE__ */ jsx15("button", { className: "btn primary", type: "button", onClick: () => onUpsell(selected.upsell.tierId, selected), children: selected.upsell.ctaLabel ?? `Explore ${selected.upsell.tierName}` }) : null
1097
1251
  ] }) : null
1098
1252
  ] })
1099
1253
  ] })
@@ -1101,12 +1255,12 @@ function MemberContentArea(props) {
1101
1255
  }
1102
1256
 
1103
1257
  // src/ui/members.tsx
1104
- import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
1258
+ import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs15 } from "preact/jsx-runtime";
1105
1259
  function card(copy, kicker, body) {
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 }),
1260
+ return /* @__PURE__ */ jsxs15("div", { className: "card", children: [
1261
+ /* @__PURE__ */ jsx16("div", { className: "card-label", children: copy.provisional.cardLabel }),
1262
+ /* @__PURE__ */ jsxs15("div", { className: "meeting-block", children: [
1263
+ /* @__PURE__ */ jsx16("div", { className: "meeting-kicker", children: kicker }),
1110
1264
  body
1111
1265
  ] })
1112
1266
  ] });
@@ -1117,9 +1271,9 @@ function ProvisionalCard(props) {
1117
1271
  return card(
1118
1272
  copy,
1119
1273
  copy.provisional.applicationNeeded,
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 })
1274
+ /* @__PURE__ */ jsxs15(Fragment5, { children: [
1275
+ /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
1276
+ /* @__PURE__ */ jsx16("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
1123
1277
  ] })
1124
1278
  );
1125
1279
  }
@@ -1127,19 +1281,19 @@ function ProvisionalCard(props) {
1127
1281
  return card(
1128
1282
  copy,
1129
1283
  copy.provisional.refunded,
1130
- /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1284
+ /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1131
1285
  );
1132
1286
  }
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;
1287
+ const membership = application.paid ? /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
1134
1288
  if (application.meetingAt) {
1135
1289
  return card(
1136
1290
  copy,
1137
1291
  copy.provisional.introductionCall,
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(
1292
+ /* @__PURE__ */ jsxs15(Fragment5, { children: [
1293
+ /* @__PURE__ */ jsx16("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
1294
+ /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
1295
+ application.meetUrl ? /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: /* @__PURE__ */ jsx16("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
1296
+ /* @__PURE__ */ jsx16(
1143
1297
  Rescheduler,
1144
1298
  {
1145
1299
  api,
@@ -1156,9 +1310,9 @@ function ProvisionalCard(props) {
1156
1310
  return card(
1157
1311
  copy,
1158
1312
  copy.provisional.bookCall,
1159
- /* @__PURE__ */ jsxs13(Fragment6, { children: [
1160
- /* @__PURE__ */ jsx13("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
1161
- /* @__PURE__ */ jsx13(
1313
+ /* @__PURE__ */ jsxs15(Fragment5, { children: [
1314
+ /* @__PURE__ */ jsx16("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
1315
+ /* @__PURE__ */ jsx16(
1162
1316
  Rescheduler,
1163
1317
  {
1164
1318
  api,
@@ -1185,8 +1339,8 @@ function MembersArea(props) {
1185
1339
  renderProvisional
1186
1340
  } = props;
1187
1341
  const copy = props.copy ?? inheritedCopy.members;
1188
- const [me, setMe] = useState10(null);
1189
- const [error, setError] = useState10(false);
1342
+ const [me, setMe] = useState12(null);
1343
+ const [error, setError] = useState12(false);
1190
1344
  const reload = async () => {
1191
1345
  try {
1192
1346
  setMe(await api("/api/me"));
@@ -1197,22 +1351,22 @@ function MembersArea(props) {
1197
1351
  useEffect6(() => {
1198
1352
  void reload();
1199
1353
  }, []);
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 });
1354
+ if (error) return /* @__PURE__ */ jsx16("p", { className: "meeting-note", children: copy.loadFailed });
1355
+ if (!me) return /* @__PURE__ */ jsx16("p", { className: "meeting-note", children: inheritedCopy.common.loading });
1202
1356
  const role = me.role || "provisional";
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 })
1357
+ return /* @__PURE__ */ jsxs15(Fragment5, { children: [
1358
+ /* @__PURE__ */ jsxs15("div", { className: "card", children: [
1359
+ /* @__PURE__ */ jsxs15("div", { className: "member-row", children: [
1360
+ /* @__PURE__ */ jsx16("span", { className: "member-email", children: me.email }),
1361
+ /* @__PURE__ */ jsx16("span", { className: "role-badge " + role, children: role })
1208
1362
  ] }),
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
1363
+ /* @__PURE__ */ jsxs15("div", { className: "account-actions", children: [
1364
+ /* @__PURE__ */ jsx16("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
1365
+ me.authorized || me.superAdmin ? /* @__PURE__ */ jsx16("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
1212
1366
  ] })
1213
1367
  ] }),
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(
1368
+ me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx16(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
1369
+ const defaultContent = /* @__PURE__ */ jsx16(
1216
1370
  ProvisionalCard,
1217
1371
  {
1218
1372
  api,
@@ -1229,30 +1383,30 @@ function MembersArea(props) {
1229
1383
  reload,
1230
1384
  defaultContent
1231
1385
  }) ?? defaultContent;
1232
- })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx13(
1386
+ })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx16(
1233
1387
  MemberContentArea,
1234
1388
  {
1235
1389
  api,
1236
1390
  ...memberPages === true ? {} : memberPages
1237
1391
  }
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
1392
+ ) : /* @__PURE__ */ jsx16("div", { className: "card", children: /* @__PURE__ */ jsx16("div", { className: "card-label", children: copy.full.welcome }) })),
1393
+ /* @__PURE__ */ jsx16(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
1394
+ me.namedSeatsEnabled ? /* @__PURE__ */ jsx16(NamedSeatPurchase, { api }) : null
1241
1395
  ] });
1242
1396
  }
1243
1397
 
1244
1398
  // src/ui/join.tsx
1245
- import { useEffect as useEffect11, useRef as useRef3, useState as useState18 } from "preact/hooks";
1399
+ import { useEffect as useEffect11, useRef as useRef7, useState as useState20 } from "preact/hooks";
1246
1400
 
1247
1401
  // src/ui/join-booking.tsx
1248
- import { useEffect as useEffect7, useState as useState11 } from "preact/hooks";
1249
- import { jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
1402
+ import { useEffect as useEffect7, useState as useState13 } from "preact/hooks";
1403
+ import { jsx as jsx17, jsxs as jsxs16 } from "preact/jsx-runtime";
1250
1404
  function JoinBooking(props) {
1251
1405
  const { applicationId, copy, onBooked, simulation } = props;
1252
- const [state, setState] = useState11(null);
1253
- const [msg, setMsg] = useState11(null);
1254
- const [busy, setBusy] = useState11(false);
1255
- const [selected, setSelected] = useState11(null);
1406
+ const [state, setState] = useState13(null);
1407
+ const [msg, setMsg] = useState13(null);
1408
+ const [busy, setBusy] = useState13(false);
1409
+ const [selected, setSelected] = useState13(null);
1256
1410
  const load = async () => {
1257
1411
  setMsg(null);
1258
1412
  try {
@@ -1309,11 +1463,11 @@ function JoinBooking(props) {
1309
1463
  setBusy(false);
1310
1464
  }
1311
1465
  };
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(
1466
+ if (!state) return /* @__PURE__ */ jsx17("p", { className: "slots-status", children: msg ?? copy.loading });
1467
+ return /* @__PURE__ */ jsxs16("div", { className: "join-book", children: [
1468
+ /* @__PURE__ */ jsx17("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
1469
+ /* @__PURE__ */ jsx17("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
1470
+ /* @__PURE__ */ jsx17(
1317
1471
  SlotPicker,
1318
1472
  {
1319
1473
  slots: state.slots,
@@ -1323,29 +1477,29 @@ function JoinBooking(props) {
1323
1477
  onDayChange: () => setSelected(null)
1324
1478
  }
1325
1479
  ),
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
1480
+ /* @__PURE__ */ jsxs16("div", { className: "slot-confirm", hidden: !selected, children: [
1481
+ /* @__PURE__ */ jsx17("button", { className: "submit-btn", disabled: busy, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
1482
+ msg ? /* @__PURE__ */ jsx17("p", { className: "step2-note", children: msg }) : null
1329
1483
  ] })
1330
1484
  ] });
1331
1485
  }
1332
1486
 
1333
1487
  // src/ui/join-accepted.tsx
1334
- import { jsx as jsx15, jsxs as jsxs15 } from "preact/jsx-runtime";
1488
+ import { jsx as jsx18, jsxs as jsxs17 } from "preact/jsx-runtime";
1335
1489
  function JoinAccepted(props) {
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 })
1490
+ return /* @__PURE__ */ jsxs17("div", { className: "join-done card", children: [
1491
+ /* @__PURE__ */ jsx18("div", { className: "card-label", children: props.copy.accepted.label }),
1492
+ /* @__PURE__ */ jsx18("p", { className: "meeting-note", children: props.copy.accepted.body }),
1493
+ /* @__PURE__ */ jsx18("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
1340
1494
  ] });
1341
1495
  }
1342
1496
 
1343
1497
  // src/ui/gift-claim-card.tsx
1344
- import { useState as useState12 } from "preact/hooks";
1345
- import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs16 } from "preact/jsx-runtime";
1498
+ import { useState as useState14 } from "preact/hooks";
1499
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs18 } from "preact/jsx-runtime";
1346
1500
  function GiftClaimCard(props) {
1347
- const [code, setCode] = useState12(props.initialCode ?? "");
1348
- const [error, setError] = useState12(false);
1501
+ const [code, setCode] = useState14(props.initialCode ?? "");
1502
+ const [error, setError] = useState14(false);
1349
1503
  const rotate = async () => {
1350
1504
  if (!props.claimId) return;
1351
1505
  setError(false);
@@ -1358,24 +1512,27 @@ function GiftClaimCard(props) {
1358
1512
  if (response.ok && body.code) setCode(body.code);
1359
1513
  else setError(true);
1360
1514
  };
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 })
1515
+ return /* @__PURE__ */ jsxs18("div", { className: "join-done card", children: [
1516
+ /* @__PURE__ */ jsx19("div", { className: "card-label", children: props.copy.label }),
1517
+ /* @__PURE__ */ jsx19("p", { className: "meeting-note", children: props.copy.body }),
1518
+ code ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
1519
+ /* @__PURE__ */ jsx19("output", { className: "gift-code", children: code }),
1520
+ /* @__PURE__ */ jsx19("p", { children: props.copy.save })
1367
1521
  ] }) : 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
1522
+ !code && props.claimId ? /* @__PURE__ */ jsx19("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
1523
+ error ? /* @__PURE__ */ jsx19("p", { role: "alert", children: props.copy.rotateFailed }) : null
1370
1524
  ] });
1371
1525
  }
1372
1526
 
1527
+ // src/ui/join-application-form.tsx
1528
+ import { useRef as useRef6 } from "preact/hooks";
1529
+
1373
1530
  // src/ui/join-tiers.tsx
1374
- import { useState as useState13 } from "preact/hooks";
1375
- import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs17 } from "preact/jsx-runtime";
1531
+ import { useState as useState15 } from "preact/hooks";
1532
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs19 } from "preact/jsx-runtime";
1376
1533
  var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
1377
1534
  function useTierSelection(tiers, initialTierId) {
1378
- const [selectedTierId, setSelectedTierId] = useState13(() => {
1535
+ const [selectedTierId, setSelectedTierId] = useState15(() => {
1379
1536
  const preset = tiers.find((tier) => tier.id === initialTierId);
1380
1537
  if (preset) return preset.id;
1381
1538
  return tiers.length === 1 ? tiers[0].id : null;
@@ -1390,10 +1547,10 @@ function useTierSelection(tiers, initialTierId) {
1390
1547
  };
1391
1548
  }
1392
1549
  function TierPlaceholder(context) {
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(
1550
+ return /* @__PURE__ */ jsxs19("fieldset", { "data-chapter-placeholder": "tiers", children: [
1551
+ /* @__PURE__ */ jsx20("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
1552
+ context.tiers.map((tier) => /* @__PURE__ */ jsxs19("label", { children: [
1553
+ /* @__PURE__ */ jsx20(
1397
1554
  "input",
1398
1555
  {
1399
1556
  type: "radio",
@@ -1404,13 +1561,13 @@ function TierPlaceholder(context) {
1404
1561
  }
1405
1562
  ),
1406
1563
  tier.name,
1407
- tier.founding ? /* @__PURE__ */ jsxs17(Fragment8, { children: [
1564
+ tier.founding ? /* @__PURE__ */ jsxs19(Fragment7, { children: [
1408
1565
  " \u2014 ",
1409
1566
  joinTierMoney(tier.founding.dueTodayCents),
1410
1567
  " founding member rate (list ",
1411
1568
  joinTierMoney(tier.priceCents),
1412
1569
  ")"
1413
- ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs17(Fragment8, { children: [
1570
+ ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs19(Fragment7, { children: [
1414
1571
  " \u2014 ",
1415
1572
  joinTierMoney(tier.priceCents)
1416
1573
  ] })
@@ -1422,19 +1579,28 @@ function tierNeedsPayment(selected, paymentsReady) {
1422
1579
  }
1423
1580
 
1424
1581
  // src/ui/join-application-form.tsx
1425
- import { jsx as jsx18, jsxs as jsxs18 } from "preact/jsx-runtime";
1582
+ import { jsx as jsx21, jsxs as jsxs20 } from "preact/jsx-runtime";
1426
1583
  function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
1427
- const disabled = submitting || props.submitDisabled === true;
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 })
1584
+ const form = useRef6(null);
1585
+ const ready = useFormReadiness(form);
1586
+ const disabled = submitting || props.submitDisabled === true || !ready || !validJoinRecipient(props.payment?.initialNamedSeat);
1587
+ return /* @__PURE__ */ jsxs20("form", { ref: form, className: "join-form", onSubmit: (event) => {
1588
+ if (!isFormReady(event.currentTarget)) {
1589
+ event.preventDefault();
1590
+ event.currentTarget.reportValidity();
1591
+ return;
1592
+ }
1593
+ void submit(event);
1594
+ }, children: [
1595
+ !requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs20("fieldset", { children: [
1596
+ /* @__PURE__ */ jsx21("legend", { children: copy.gift.optionsLabel }),
1597
+ /* @__PURE__ */ jsx21("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
1598
+ /* @__PURE__ */ jsx21(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
1433
1599
  ] }) : null,
1434
1600
  !requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
1435
1601
  typeof props.children === "function" ? props.children({ invitation }) : props.children,
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 })
1602
+ error ? /* @__PURE__ */ jsx21("p", { className: "join-error", role: "alert", children: error }) : null,
1603
+ props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx21(JoinSubmitButton, { disabled, children: submitting ? copy.form.submitting : copy.form.submit })
1438
1604
  ] });
1439
1605
  }
1440
1606
 
@@ -1459,8 +1625,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
1459
1625
 
1460
1626
  // src/ui/gift-code-redeemer.tsx
1461
1627
  import { InlineActionField } from "@odla-ai/ui/components";
1462
- import { useState as useState14 } from "preact/hooks";
1463
- import { Fragment as Fragment9, jsx as jsx19, jsxs as jsxs19 } from "preact/jsx-runtime";
1628
+ import { useState as useState16 } from "preact/hooks";
1629
+ import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs21 } from "preact/jsx-runtime";
1464
1630
  var GIFT_CODE_REDEEMER_CSS = `
1465
1631
  .gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
1466
1632
  .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}
@@ -1475,10 +1641,10 @@ var GIFT_CODE_REDEEMER_CSS = `
1475
1641
  @container (max-width:26rem){.gift-code-redeemer .inline-action-field-row{grid-template-columns:minmax(0,1fr)}.gift-code-redeemer .inline-action-field-action{width:100%}}
1476
1642
  `;
1477
1643
  function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1478
- const [code, setCode] = useState14("");
1479
- const [loading, setLoading] = useState14(false);
1480
- const [message, setMessage] = useState14("");
1481
- const [messageTone, setMessageTone] = useState14("neutral");
1644
+ const [code, setCode] = useState16("");
1645
+ const [loading, setLoading] = useState16(false);
1646
+ const [message, setMessage] = useState16("");
1647
+ const [messageTone, setMessageTone] = useState16("neutral");
1482
1648
  const normalizedCode = code.trim();
1483
1649
  const redeem = async () => {
1484
1650
  if (!normalizedCode || loading) return;
@@ -1505,9 +1671,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1505
1671
  setLoading(false);
1506
1672
  }
1507
1673
  };
1508
- return /* @__PURE__ */ jsxs19(Fragment9, { children: [
1509
- /* @__PURE__ */ jsx19("style", { children: GIFT_CODE_REDEEMER_CSS }),
1510
- /* @__PURE__ */ jsx19(
1674
+ return /* @__PURE__ */ jsxs21(Fragment8, { children: [
1675
+ /* @__PURE__ */ jsx22("style", { children: GIFT_CODE_REDEEMER_CSS }),
1676
+ /* @__PURE__ */ jsx22(
1511
1677
  InlineActionField,
1512
1678
  {
1513
1679
  id,
@@ -1563,12 +1729,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
1563
1729
  }
1564
1730
 
1565
1731
  // src/ui/join-gift-claim.tsx
1566
- import { jsx as jsx20, jsxs as jsxs20 } from "preact/jsx-runtime";
1732
+ import { jsx as jsx23, jsxs as jsxs22 } from "preact/jsx-runtime";
1567
1733
  function JoinGiftClaim(props) {
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(
1734
+ return /* @__PURE__ */ jsxs22("section", { className: "join-gift-claim card", children: [
1735
+ /* @__PURE__ */ jsx23("div", { className: "card-label", children: props.copy.claimTitle }),
1736
+ /* @__PURE__ */ jsx23("p", { children: props.copy.claimBody }),
1737
+ /* @__PURE__ */ jsx23(
1572
1738
  GiftCodeRedeemer,
1573
1739
  {
1574
1740
  api: props.api,
@@ -1592,21 +1758,21 @@ function JoinGiftClaim(props) {
1592
1758
  }
1593
1759
 
1594
1760
  // src/ui/join-named-seat.tsx
1595
- import { useState as useState15 } from "preact/hooks";
1596
- import { jsx as jsx21, jsxs as jsxs21 } from "preact/jsx-runtime";
1761
+ import { useState as useState17 } from "preact/hooks";
1762
+ import { jsx as jsx24, jsxs as jsxs23 } from "preact/jsx-runtime";
1597
1763
  function JoinNamedSeat(props) {
1598
1764
  const seatId = props.seatId ?? "";
1599
1765
  const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
1600
- const [accepted, setAccepted] = useState15(false), [busy, setBusy] = useState15(false), [error, setError] = useState15("");
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 })
1766
+ const [accepted, setAccepted] = useState17(false), [busy, setBusy] = useState17(false), [error, setError] = useState17("");
1767
+ return /* @__PURE__ */ jsxs23("section", { className: "join-named-seat card", children: [
1768
+ /* @__PURE__ */ jsx24("h2", { children: copy.title }),
1769
+ /* @__PURE__ */ jsx24("p", { children: copy.body }),
1770
+ /* @__PURE__ */ jsxs23("label", { className: "journey-consent", children: [
1771
+ /* @__PURE__ */ jsx24("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
1772
+ /* @__PURE__ */ jsx24("span", { children: copy.consent })
1607
1773
  ] }),
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 () => {
1774
+ error ? /* @__PURE__ */ jsx24("p", { role: "alert", children: error }) : null,
1775
+ /* @__PURE__ */ jsx24("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
1610
1776
  setBusy(true);
1611
1777
  setError("");
1612
1778
  try {
@@ -1626,12 +1792,12 @@ function JoinNamedSeat(props) {
1626
1792
  }
1627
1793
 
1628
1794
  // src/ui/join-invitation.tsx
1629
- import { useEffect as useEffect8, useState as useState16 } from "preact/hooks";
1630
- import { jsx as jsx22, jsxs as jsxs22 } from "preact/jsx-runtime";
1795
+ import { useEffect as useEffect8, useState as useState18 } from "preact/hooks";
1796
+ import { jsx as jsx25, jsxs as jsxs24 } from "preact/jsx-runtime";
1631
1797
  function useJoinInvitation(seatId, api, fallback) {
1632
- const [invitation, setInvitation] = useState16(null);
1633
- const [error, setError] = useState16("");
1634
- const [revision, setRevision] = useState16(0);
1798
+ const [invitation, setInvitation] = useState18(null);
1799
+ const [error, setError] = useState18("");
1800
+ const [revision, setRevision] = useState18(0);
1635
1801
  useEffect8(() => {
1636
1802
  let live = true;
1637
1803
  setInvitation(null);
@@ -1654,9 +1820,9 @@ function useJoinInvitation(seatId, api, fallback) {
1654
1820
  return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
1655
1821
  }
1656
1822
  function JoinInvitationNotice(props) {
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 }) })
1823
+ return /* @__PURE__ */ jsxs24("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
1824
+ /* @__PURE__ */ jsx25("p", { children: /* @__PURE__ */ jsx25("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
1825
+ /* @__PURE__ */ jsx25("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
1660
1826
  ] });
1661
1827
  }
1662
1828
 
@@ -1696,14 +1862,14 @@ function useJoinPending(state, loadResume, setState) {
1696
1862
  }
1697
1863
 
1698
1864
  // src/ui/payment-receipt.tsx
1699
- import { useEffect as useEffect10, useState as useState17 } from "preact/hooks";
1700
- import { Fragment as Fragment10, jsx as jsx23, jsxs as jsxs23 } from "preact/jsx-runtime";
1865
+ import { useEffect as useEffect10, useState as useState19 } from "preact/hooks";
1866
+ import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs25 } from "preact/jsx-runtime";
1701
1867
  function PaymentReceiptCard({ applicationId }) {
1702
- const [receipt, setReceipt] = useState17(null);
1703
- const [error, setError] = useState17("");
1704
- const [revision, setRevision] = useState17(0);
1705
- const [emailState, setEmailState] = useState17("idle");
1706
- const [previewEmail, setPreviewEmail] = useState17(false);
1868
+ const [receipt, setReceipt] = useState19(null);
1869
+ const [error, setError] = useState19("");
1870
+ const [revision, setRevision] = useState19(0);
1871
+ const [emailState, setEmailState] = useState19("idle");
1872
+ const [previewEmail, setPreviewEmail] = useState19(false);
1707
1873
  const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
1708
1874
  useEffect10(() => {
1709
1875
  let live = true, timer;
@@ -1731,9 +1897,9 @@ function PaymentReceiptCard({ applicationId }) {
1731
1897
  if (timer) clearTimeout(timer);
1732
1898
  };
1733
1899
  }, [endpoint, revision]);
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" })
1900
+ if (!receipt) return error ? /* @__PURE__ */ jsxs25("section", { "aria-label": "Payment receipt", children: [
1901
+ /* @__PURE__ */ jsx26("p", { role: "status", children: error }),
1902
+ /* @__PURE__ */ jsx26("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
1737
1903
  ] }) : null;
1738
1904
  const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
1739
1905
  const email = async () => {
@@ -1750,45 +1916,38 @@ function PaymentReceiptCard({ applicationId }) {
1750
1916
  setError("We could not confirm email delivery. You can print or save your receipt.");
1751
1917
  }
1752
1918
  };
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: [
1919
+ return /* @__PURE__ */ jsxs25("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
1920
+ /* @__PURE__ */ jsx26("h2", { children: "Payment received" }),
1921
+ /* @__PURE__ */ jsx26("p", { children: receipt.tierName }),
1922
+ /* @__PURE__ */ jsxs25("dl", { className: "journey-summary", children: [
1923
+ /* @__PURE__ */ jsx26("dt", { children: "Membership" }),
1924
+ /* @__PURE__ */ jsx26("dd", { children: money(receipt.membershipCents) }),
1925
+ receipt.namedSeat ? /* @__PURE__ */ jsxs25(Fragment9, { children: [
1926
+ /* @__PURE__ */ jsxs25("dt", { children: [
1761
1927
  "Additional member \u2014 ",
1762
1928
  receipt.namedSeat.recipientName
1763
1929
  ] }),
1764
- /* @__PURE__ */ jsxs23("dd", { children: [
1930
+ /* @__PURE__ */ jsxs25("dd", { children: [
1765
1931
  receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
1766
1932
  money(receipt.namedSeat.amountCents)
1767
1933
  ] })
1768
1934
  ] }) : null,
1769
- /* @__PURE__ */ jsx23("dt", { children: "Total paid" }),
1770
- /* @__PURE__ */ jsx23("dd", { children: money(receipt.totalCents) })
1935
+ /* @__PURE__ */ jsx26("dt", { children: "Total paid" }),
1936
+ /* @__PURE__ */ jsx26("dd", { children: money(receipt.totalCents) })
1771
1937
  ] }),
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" })
1938
+ /* @__PURE__ */ jsxs25("div", { className: "journey-actions", children: [
1939
+ /* @__PURE__ */ jsx26("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
1940
+ /* @__PURE__ */ jsx26("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
1775
1941
  ] }),
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
1942
+ emailState === "sent" ? /* @__PURE__ */ jsx26("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
1943
+ error ? /* @__PURE__ */ jsx26("p", { role: "alert", children: error }) : null
1778
1944
  ] });
1779
1945
  }
1780
1946
 
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
-
1788
1947
  // src/ui/join.tsx
1789
- import { Fragment as Fragment11, jsx as jsx24, jsxs as jsxs24 } from "preact/jsx-runtime";
1948
+ import { Fragment as Fragment10, jsx as jsx27, jsxs as jsxs26 } from "preact/jsx-runtime";
1790
1949
  function JoinIsland(props) {
1791
- return /* @__PURE__ */ jsx24(JourneyFrame, { children: /* @__PURE__ */ jsx24(JoinFlow, { ...props }) });
1950
+ return /* @__PURE__ */ jsx27(JourneyFrame, { children: /* @__PURE__ */ jsx27(JoinFlow, { ...props }) });
1792
1951
  }
1793
1952
  function JoinFlow(props) {
1794
1953
  const inheritedCopy = useChapterCopy();
@@ -1809,14 +1968,14 @@ function JoinFlow(props) {
1809
1968
  const invitation = invitationState.invitation;
1810
1969
  const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
1811
1970
  const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
1812
- const [state, setState] = useState18(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1813
- const [error, setError] = useState18(null);
1814
- const [submitting, setSubmitting] = useState18(false);
1815
- const [editingNamedSeat, setEditingNamedSeat] = useState18(false);
1816
- const [giftOfferId, setGiftOfferId] = useState18(props.initialGiftOfferId ?? null);
1971
+ const [state, setState] = useState20(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
1972
+ const [error, setError] = useState20(null);
1973
+ const [submitting, setSubmitting] = useState20(false);
1974
+ const [editingNamedSeat, setEditingNamedSeat] = useState20(false);
1975
+ const [giftOfferId, setGiftOfferId] = useState20(props.initialGiftOfferId ?? null);
1817
1976
  const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
1818
1977
  const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
1819
- const submissionId = useRef3(null);
1978
+ const submissionId = useRef7(null);
1820
1979
  useEffect11(() => {
1821
1980
  if (props.simulation) return;
1822
1981
  const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
@@ -1890,13 +2049,13 @@ function JoinFlow(props) {
1890
2049
  setSubmitting(false);
1891
2050
  }
1892
2051
  };
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
2052
+ if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs26("section", { className: "card", "aria-live": "polite", children: [
2053
+ /* @__PURE__ */ jsx27("h2", { children: seatCopy.title }),
2054
+ /* @__PURE__ */ jsx27("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
2055
+ invitationState.error ? /* @__PURE__ */ jsx27("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
1897
2056
  ] });
1898
- const header = /* @__PURE__ */ jsxs24(Fragment11, { children: [
1899
- invitation ? /* @__PURE__ */ jsx24(
2057
+ const header = /* @__PURE__ */ jsxs26(Fragment10, { children: [
2058
+ invitation ? /* @__PURE__ */ jsx27(
1900
2059
  JoinInvitationNotice,
1901
2060
  {
1902
2061
  invitation,
@@ -1910,48 +2069,48 @@ function JoinFlow(props) {
1910
2069
  ...invitation ? { invitation } : {},
1911
2070
  ..."applicationId" in state ? { applicationId: state.applicationId } : {}
1912
2071
  }),
1913
- !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx24(PaymentReceiptCard, { applicationId: state.applicationId }) : null
2072
+ !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx27(PaymentReceiptCard, { applicationId: state.applicationId }) : null
1914
2073
  ] });
1915
2074
  if (state.step === "closed") {
1916
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2075
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1917
2076
  header,
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 })
2077
+ /* @__PURE__ */ jsxs26("section", { className: "card", "aria-label": "Application closed", children: [
2078
+ /* @__PURE__ */ jsx27("h2", { children: "This application is closed" }),
2079
+ /* @__PURE__ */ jsx27("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
2080
+ /* @__PURE__ */ jsx27("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1922
2081
  ] })
1923
2082
  ] });
1924
2083
  }
1925
2084
  if (state.step === "done") {
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 })
2085
+ const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs26("div", { className: "join-done card", children: [
2086
+ /* @__PURE__ */ jsx27("div", { className: "card-label", children: copy.done.label }),
2087
+ /* @__PURE__ */ jsx27("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
2088
+ /* @__PURE__ */ jsx27("p", { className: "meeting-note", children: copy.done.calendarInvite }),
2089
+ /* @__PURE__ */ jsx27("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
1931
2090
  ] });
1932
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2091
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1933
2092
  header,
1934
2093
  body
1935
2094
  ] });
1936
2095
  }
1937
2096
  if (state.step === "accepted") {
1938
- const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx24(JoinAccepted, { copy, membersHref });
1939
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2097
+ const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx27(JoinAccepted, { copy, membersHref });
2098
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1940
2099
  header,
1941
2100
  body
1942
2101
  ] });
1943
2102
  }
1944
2103
  if (state.step === "gift") {
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: [
2104
+ const body = renderGift?.(state) ?? /* @__PURE__ */ jsx27(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
2105
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1947
2106
  header,
1948
2107
  body
1949
2108
  ] });
1950
2109
  }
1951
2110
  if (state.step === "booking") {
1952
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2111
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1953
2112
  header,
1954
- /* @__PURE__ */ jsx24(
2113
+ /* @__PURE__ */ jsx27(
1955
2114
  JoinBooking,
1956
2115
  {
1957
2116
  applicationId: state.applicationId,
@@ -1966,9 +2125,9 @@ function JoinFlow(props) {
1966
2125
  }
1967
2126
  if (state.step === "payment") {
1968
2127
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
1969
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2128
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1970
2129
  header,
1971
- /* @__PURE__ */ jsx24(
2130
+ /* @__PURE__ */ jsx27(
1972
2131
  JoinNamedSeat,
1973
2132
  {
1974
2133
  api: props.namedSeatClaimApi,
@@ -1981,9 +2140,9 @@ function JoinFlow(props) {
1981
2140
  ] });
1982
2141
  }
1983
2142
  const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
1984
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2143
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
1985
2144
  header,
1986
- props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx24(
2145
+ props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx27(
1987
2146
  JoinGiftClaim,
1988
2147
  {
1989
2148
  api: props.giftClaimApi,
@@ -1994,7 +2153,7 @@ function JoinFlow(props) {
1994
2153
  onError: () => setError(copy.form.unexpectedFailure)
1995
2154
  }
1996
2155
  ) : null,
1997
- /* @__PURE__ */ jsx24(
2156
+ /* @__PURE__ */ jsx27(
1998
2157
  Payment,
1999
2158
  {
2000
2159
  applicationId: state.applicationId,
@@ -2022,9 +2181,9 @@ function JoinFlow(props) {
2022
2181
  }
2023
2182
  if (state.step === "paymentPending") {
2024
2183
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
2025
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2184
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
2026
2185
  header,
2027
- /* @__PURE__ */ jsx24(
2186
+ /* @__PURE__ */ jsx27(
2028
2187
  JoinNamedSeat,
2029
2188
  {
2030
2189
  api: props.namedSeatClaimApi,
@@ -2036,14 +2195,14 @@ function JoinFlow(props) {
2036
2195
  )
2037
2196
  ] });
2038
2197
  }
2039
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2198
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
2040
2199
  header,
2041
- /* @__PURE__ */ jsx24("p", { className: "pay-status", role: "status", children: copy.payment.pending })
2200
+ /* @__PURE__ */ jsx27("p", { className: "pay-status", role: "status", children: copy.payment.pending })
2042
2201
  ] });
2043
2202
  }
2044
- return /* @__PURE__ */ jsxs24(Fragment11, { children: [
2203
+ return /* @__PURE__ */ jsxs26(Fragment10, { children: [
2045
2204
  header,
2046
- /* @__PURE__ */ jsx24(
2205
+ /* @__PURE__ */ jsx27(
2047
2206
  JoinApplicationForm,
2048
2207
  {
2049
2208
  props,
@@ -2233,7 +2392,7 @@ function membershipPageDocument(input, options = {}) {
2233
2392
  }
2234
2393
 
2235
2394
  // src/ui/membership-cards.tsx
2236
- import { jsx as jsx25, jsxs as jsxs25 } from "preact/jsx-runtime";
2395
+ import { jsx as jsx28, jsxs as jsxs27 } from "preact/jsx-runtime";
2237
2396
  var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
2238
2397
  "--ui-membership-grid-gap": "1.4rem",
2239
2398
  "--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
@@ -2302,67 +2461,67 @@ function membershipApplicationHref(applicationPath, tierId) {
2302
2461
  }
2303
2462
  function TierAction(props) {
2304
2463
  if (props.mode === "select") {
2305
- return /* @__PURE__ */ jsxs25("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2464
+ return /* @__PURE__ */ jsxs27("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2306
2465
  props.label,
2307
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u2192" })
2466
+ /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
2308
2467
  ] });
2309
2468
  }
2310
2469
  if (props.mode === "preview") {
2311
- return /* @__PURE__ */ jsxs25("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2470
+ return /* @__PURE__ */ jsxs27("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2312
2471
  props.label,
2313
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u2192" })
2472
+ /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
2314
2473
  ] });
2315
2474
  }
2316
- return /* @__PURE__ */ jsxs25("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2475
+ return /* @__PURE__ */ jsxs27("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2317
2476
  props.label,
2318
- /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u2192" })
2477
+ /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: "\u2192" })
2319
2478
  ] });
2320
2479
  }
2321
2480
  function TierCard(props) {
2322
2481
  const { tier, presentation } = props;
2323
2482
  const summary = presentation.summaryMarkdown ?? tier.blurb;
2324
2483
  const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
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" })
2484
+ return /* @__PURE__ */ jsxs27("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2485
+ presentation.badge ? /* @__PURE__ */ jsx28("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2486
+ /* @__PURE__ */ jsx28("h3", { className: "chapter-membership-name", children: tier.name }),
2487
+ /* @__PURE__ */ jsxs27("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2488
+ presentation.capacity ? /* @__PURE__ */ jsxs27("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2489
+ /* @__PURE__ */ jsx28("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2490
+ /* @__PURE__ */ jsx28("small", { children: presentation.capacity.label ?? "available" })
2332
2491
  ] }) : 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
2492
+ /* @__PURE__ */ jsxs27("div", { className: "chapter-membership-price-stack", children: [
2493
+ presentation.priceEyebrow ? /* @__PURE__ */ jsx28("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx28("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2494
+ /* @__PURE__ */ jsxs27("div", { className: "chapter-membership-price-row", children: [
2495
+ tier.founding ? /* @__PURE__ */ jsx28("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx28("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2496
+ /* @__PURE__ */ jsx28("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2497
+ !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx28("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2339
2498
  ] })
2340
2499
  ] })
2341
2500
  ] }),
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 })
2501
+ presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2502
+ summary ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2503
+ presentation.benefits?.length ? /* @__PURE__ */ jsx28("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs27("li", { children: [
2504
+ /* @__PURE__ */ jsx28("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2505
+ /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-benefit", source: benefit })
2347
2506
  ] }, `${tier.id}-benefit-${index}`)) }) : null,
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 })
2507
+ presentation.callout ? /* @__PURE__ */ jsxs27("aside", { className: "chapter-membership-callout", children: [
2508
+ presentation.callout.label ? /* @__PURE__ */ jsx28("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2509
+ /* @__PURE__ */ jsx28(Markdown2, { source: presentation.callout.bodyMarkdown })
2351
2510
  ] }) : null,
2352
- /* @__PURE__ */ jsx25(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2511
+ /* @__PURE__ */ jsx28(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2353
2512
  ] });
2354
2513
  }
2355
2514
  function MembershipCards(props) {
2356
2515
  const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
2357
2516
  const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
2358
2517
  const mode = props.mode ?? "link";
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) => {
2518
+ return /* @__PURE__ */ jsxs27("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2519
+ /* @__PURE__ */ jsx28("style", { children: MEMBERSHIP_CARDS_CSS }),
2520
+ /* @__PURE__ */ jsx28("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2362
2521
  const tier = byId.get(presentation.tierId);
2363
- return /* @__PURE__ */ jsx25(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2522
+ return /* @__PURE__ */ jsx28(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2364
2523
  }) }),
2365
- document2.footnoteMarkdown ? /* @__PURE__ */ jsx25(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2524
+ document2.footnoteMarkdown ? /* @__PURE__ */ jsx28(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2366
2525
  ] });
2367
2526
  }
2368
2527
 
@@ -2376,6 +2535,11 @@ export {
2376
2535
  fmtDate,
2377
2536
  groupSlotsByDay,
2378
2537
  SlotPicker,
2538
+ ADDITIONAL_MEMBER_COPY,
2539
+ additionalMemberSelection,
2540
+ AdditionalMemberFields,
2541
+ JoinSubmitButton,
2542
+ AdditionalMemberEditor,
2379
2543
  PaymentStep,
2380
2544
  JourneyFrame,
2381
2545
  MemberRestart,
@@ -2398,4 +2562,4 @@ export {
2398
2562
  membershipApplicationHref,
2399
2563
  MembershipCards
2400
2564
  };
2401
- //# sourceMappingURL=chunk-NK267YQZ.js.map
2565
+ //# sourceMappingURL=chunk-E7CB5K2D.js.map