@odla-ai/chapter 0.61.0 → 0.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import {
2
2
  DEFAULT_JOIN_COPY,
3
3
  formatChapterCopy,
4
4
  useChapterCopy
5
- } from "./chunk-PKVHXKGJ.js";
5
+ } from "./chunk-7CVP6VSO.js";
6
6
  import {
7
7
  collectFormFields
8
8
  } from "./chunk-IVXVECKR.js";
@@ -867,7 +867,7 @@ function MemberRestart(props) {
867
867
  }
868
868
 
869
869
  // src/ui/members.tsx
870
- import { useEffect as useEffect6, useState as useState13 } from "preact/hooks";
870
+ import { useEffect as useEffect8, useState as useState15 } from "preact/hooks";
871
871
 
872
872
  // src/ui/reschedule.tsx
873
873
  import { useState as useState8 } from "preact/hooks";
@@ -1316,7 +1316,8 @@ function MemberContentArea(props) {
1316
1316
  list.push(page);
1317
1317
  result.set(page.navigation.section, list);
1318
1318
  }
1319
- return [...result.entries()];
1319
+ const declared = data?.sections ?? [...result.keys()].map((id) => ({ id, label: id }));
1320
+ return declared.filter((section) => result.has(section.id)).map((section) => [section.label ?? "", result.get(section.id)]);
1320
1321
  }, [data]);
1321
1322
  if (error) return /* @__PURE__ */ jsxs15("p", { className: "meeting-note", role: "alert", children: [
1322
1323
  "Member pages could not be loaded: ",
@@ -1327,8 +1328,8 @@ function MemberContentArea(props) {
1327
1328
  const selected = data.pages.find((page) => page.id === selectedId) ?? data.pages[0];
1328
1329
  const href = selected.upsell && upsellHref ? upsellHref(selected.upsell.tierId, selected) : void 0;
1329
1330
  return /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content", "data-member-content": true, children: [
1330
- /* @__PURE__ */ jsx16("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages]) => /* @__PURE__ */ jsxs15("section", { className: "chapter-member-content-section", children: [
1331
- /* @__PURE__ */ jsx16("h2", { children: section }),
1331
+ /* @__PURE__ */ jsx16("nav", { className: "chapter-member-content-nav", "aria-label": "Member pages", children: sections.map(([section, pages], index) => /* @__PURE__ */ jsxs15("section", { className: "chapter-member-content-section", children: [
1332
+ section ? /* @__PURE__ */ jsx16("h2", { children: section }) : null,
1332
1333
  /* @__PURE__ */ jsx16("ul", { children: pages.map((page) => /* @__PURE__ */ jsx16("li", { "data-parent-page": page.navigation.parentId ?? void 0, children: /* @__PURE__ */ jsx16(
1333
1334
  "button",
1334
1335
  {
@@ -1338,7 +1339,7 @@ function MemberContentArea(props) {
1338
1339
  children: pageLabel(page)
1339
1340
  }
1340
1341
  ) }, page.id)) })
1341
- ] }, section)) }),
1342
+ ] }, `${index}:${section}`)) }),
1342
1343
  /* @__PURE__ */ jsxs15("article", { className: "chapter-member-content-page", "data-access": selected.access, children: [
1343
1344
  /* @__PURE__ */ jsxs15("header", { children: [
1344
1345
  /* @__PURE__ */ jsxs15("div", { className: "card-label", children: [
@@ -1349,7 +1350,7 @@ function MemberContentArea(props) {
1349
1350
  /* @__PURE__ */ jsx16("h1", { children: selected.title }),
1350
1351
  selected.summary ? /* @__PURE__ */ jsx16("p", { children: selected.summary }) : null
1351
1352
  ] }),
1352
- selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content-locked", children: [
1353
+ selected.access === "allowed" && selected.kind === "feature" ? /* @__PURE__ */ jsx16(Fragment4, { children: props.renderFeature?.(selected) ?? null }) : selected.access === "allowed" && selected.kind === "placeholder" ? /* @__PURE__ */ jsx16(MemberPlaceholderBody, { page: selected }) : selected.access === "allowed" && selected.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.bodyMarkdown }) : /* @__PURE__ */ jsxs15("div", { className: "chapter-member-content-locked", children: [
1353
1354
  selected.teaserMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: selected.teaserMarkdown }) : /* @__PURE__ */ jsx16("p", { children: "This page is not included in your current membership." }),
1354
1355
  selected.upsell ? /* @__PURE__ */ jsxs15("aside", { className: "chapter-member-content-upsell", "aria-label": selected.upsell.label ?? "Membership option", children: [
1355
1356
  /* @__PURE__ */ jsx16("h2", { children: selected.upsell.label ?? selected.upsell.tierName }),
@@ -1361,14 +1362,598 @@ function MemberContentArea(props) {
1361
1362
  ] })
1362
1363
  ] });
1363
1364
  }
1365
+ var placeholderBadge = (page) => page.placeholder?.badge ?? (page.placeholder?.availableYear ? `Coming in ${page.placeholder.availableYear}` : "Coming soon");
1366
+ function MemberPlaceholderBody({ page }) {
1367
+ return /* @__PURE__ */ jsxs15("div", { className: "chapter-member-placeholder", "data-placeholder": true, children: [
1368
+ /* @__PURE__ */ jsx16("span", { className: "pill", children: placeholderBadge(page) }),
1369
+ page.bodyMarkdown ? /* @__PURE__ */ jsx16(Markdown, { source: page.bodyMarkdown }) : null,
1370
+ page.placeholder?.actionLabel ? /* @__PURE__ */ jsx16("button", { className: "btn", type: "button", disabled: true, children: page.placeholder.actionLabel }) : null
1371
+ ] });
1372
+ }
1373
+
1374
+ // src/ui/member-portal.tsx
1375
+ import { useEffect as useEffect7, useMemo as useMemo3, useState as useState14 } from "preact/hooks";
1376
+
1377
+ // src/ui/member-portal-nav.tsx
1378
+ import { ThemeScope } from "@odla-ai/ui/components";
1379
+
1380
+ // src/ui/member-portal-icons.tsx
1381
+ import { jsx as jsx17 } from "preact/jsx-runtime";
1382
+ var PATHS = {
1383
+ home: ["M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z"],
1384
+ course: ["M22 10 12 5 2 10l10 5 10-5z", "M6 12v5c3 2 9 2 12 0v-5"],
1385
+ library: ["M4 19.5V4.5A1.5 1.5 0 0 1 5.5 3H20v18H5.5A1.5 1.5 0 0 1 4 19.5z", "M8 7h8"],
1386
+ deals: ["M3 17l6-6 4 4 8-8", "M14 7h7v7"],
1387
+ training: ["M9 11l3 3 8-8", "M20 12v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9"],
1388
+ events: ["M5 4h14a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z", "M16 2v4M8 2v4M3 10h18"],
1389
+ members: ["M9 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8z", "M2 21a7 7 0 0 1 14 0", "M16 4a4 4 0 0 1 0 8", "M22 21a7 7 0 0 0-4-6.3"],
1390
+ share: ["M12 3v12", "m7 8 5-5 5 5", "M5 14v5a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-5"],
1391
+ profile: ["M12 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8z", "M4 21a8 8 0 0 1 16 0"],
1392
+ document: ["M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z", "M14 3v6h6", "M8 13h8M8 17h5"],
1393
+ calendar: ["M5 4h14a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z", "M16 2v4M8 2v4M3 10h18"],
1394
+ chat: ["M21 12a8 8 0 0 1-11.6 7.1L3 21l1.9-6.4A8 8 0 1 1 21 12z"],
1395
+ star: ["m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2L12 17.3l-5.6 2.9 1.1-6.2L3 9.6l6.2-.9z"],
1396
+ lock: ["M6 11h12a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2z", "M8 11V7a4 4 0 0 1 8 0v4"],
1397
+ menu: ["M4 7h16M4 12h16M4 17h16"],
1398
+ close: ["M6 6l12 12M18 6 6 18"]
1399
+ };
1400
+ function PortalIcon({ name, size = 18, label }) {
1401
+ return /* @__PURE__ */ jsx17(
1402
+ "svg",
1403
+ {
1404
+ width: size,
1405
+ height: size,
1406
+ viewBox: "0 0 24 24",
1407
+ fill: "none",
1408
+ stroke: "currentColor",
1409
+ "stroke-width": "1.8",
1410
+ "stroke-linecap": "round",
1411
+ "stroke-linejoin": "round",
1412
+ "aria-hidden": label ? void 0 : "true",
1413
+ "aria-label": label,
1414
+ role: label ? "img" : void 0,
1415
+ focusable: "false",
1416
+ children: PATHS[name].map((d) => /* @__PURE__ */ jsx17("path", { d }, d))
1417
+ }
1418
+ );
1419
+ }
1420
+
1421
+ // src/ui/member-portal-routing.ts
1422
+ var PROFILE_SEGMENT = "profile";
1423
+ var trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
1424
+ function routeFromLocation(location, routing) {
1425
+ let segment = "";
1426
+ if (routing.mode === "hash") segment = trimSlashes(decodeURIComponent(location.hash.replace(/^#/, "")));
1427
+ else {
1428
+ const base = `/${trimSlashes(routing.basePath)}`;
1429
+ const path = location.pathname;
1430
+ if (path === base || path.startsWith(`${base}/`)) segment = trimSlashes(decodeURIComponent(path.slice(base.length)));
1431
+ }
1432
+ if (!segment) return { kind: "home" };
1433
+ if (segment === PROFILE_SEGMENT) return { kind: "profile" };
1434
+ return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(segment) ? { kind: "page", slug: segment } : { kind: "home" };
1435
+ }
1436
+ function hrefFor(route, routing) {
1437
+ const base = `/${trimSlashes(routing.basePath)}`.replace(/^\/$/, "");
1438
+ const segment = route.kind === "home" ? "" : route.kind === "profile" ? PROFILE_SEGMENT : route.slug;
1439
+ if (routing.mode === "hash") return segment ? `${base}/#${segment}` : `${base}/`;
1440
+ return segment ? `${base}/${segment}` : `${base}/`;
1441
+ }
1442
+ var sameRoute = (a, b) => a.kind === b.kind && (a.kind !== "page" || a.slug === b.slug);
1443
+
1444
+ // src/ui/member-portal-nav.tsx
1445
+ import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs16 } from "preact/jsx-runtime";
1446
+ function PortalAvatar({ me, className }) {
1447
+ return /* @__PURE__ */ jsx18("span", { className: `chapter-portal-avatar${className ? ` ${className}` : ""}`, children: me.photoUrl ? /* @__PURE__ */ jsx18("img", { src: me.photoUrl, alt: "" }) : me.initials });
1448
+ }
1449
+ function navTag(page, copy) {
1450
+ if (page.access === "locked") return { kind: "lock", text: copy.shell.locked };
1451
+ if (page.navigation.tag === "new") return { kind: "new", text: copy.pages.tagNew };
1452
+ if (page.kind === "placeholder") {
1453
+ const year = page.placeholder?.availableYear;
1454
+ return { kind: "soon", text: year ? String(year) : copy.pages.tagSoon };
1455
+ }
1456
+ return null;
1457
+ }
1458
+ function Groups({ content, route, copy, onNavigate }) {
1459
+ const sections = content.sections ?? [...new Set(content.pages.map((page) => page.navigation.section))].map((id) => ({ id, label: id }));
1460
+ const item = (target, icon, label, tag) => /* @__PURE__ */ jsxs16("button", { type: "button", className: "chapter-portal-nav-item", "aria-current": sameRoute(route, target) ? "page" : void 0, onClick: () => onNavigate(target), children: [
1461
+ /* @__PURE__ */ jsx18(PortalIcon, { name: icon }),
1462
+ /* @__PURE__ */ jsx18("span", { children: label }),
1463
+ tag?.kind === "lock" ? /* @__PURE__ */ jsx18("span", { className: "chapter-portal-tag", "data-tag": "lock", title: tag.text, children: /* @__PURE__ */ jsx18(PortalIcon, { name: "lock", size: 12, label: tag.text }) }) : tag ? /* @__PURE__ */ jsx18("span", { className: "chapter-portal-tag", "data-tag": tag.kind, children: tag.text }) : null
1464
+ ] });
1465
+ return /* @__PURE__ */ jsxs16(Fragment5, { children: [
1466
+ /* @__PURE__ */ jsx18("div", { children: item({ kind: "home" }, "home", copy.shell.home) }),
1467
+ sections.map((section) => {
1468
+ const pages = content.pages.filter((page) => page.navigation.section === section.id && !page.navigation.parentId);
1469
+ if (!pages.length) return null;
1470
+ return /* @__PURE__ */ jsxs16("div", { children: [
1471
+ section.label ? /* @__PURE__ */ jsx18("div", { className: "chapter-portal-group-label", children: section.label }) : null,
1472
+ pages.map((page) => /* @__PURE__ */ jsx18("div", { children: item({ kind: "page", slug: page.slug }, page.navigation.icon ?? "document", page.title, navTag(page, copy)) }, page.id))
1473
+ ] }, section.id);
1474
+ })
1475
+ ] });
1476
+ }
1477
+ function Account(props) {
1478
+ const { me, email, route, copy, adminHref, onNavigate, onSignOut } = props;
1479
+ return /* @__PURE__ */ jsxs16("div", { className: "chapter-portal-account", children: [
1480
+ /* @__PURE__ */ jsxs16("button", { type: "button", className: "chapter-portal-nav-item", "aria-current": route.kind === "profile" ? "page" : void 0, onClick: () => onNavigate({ kind: "profile" }), children: [
1481
+ /* @__PURE__ */ jsx18(PortalAvatar, { me }),
1482
+ /* @__PURE__ */ jsx18("span", { children: copy.shell.yourProfile })
1483
+ ] }),
1484
+ /* @__PURE__ */ jsx18("div", { children: copy.shell.signedInAs }),
1485
+ /* @__PURE__ */ jsx18("div", { children: email }),
1486
+ /* @__PURE__ */ jsxs16("div", { style: { marginTop: ".5rem", display: "flex", gap: "1rem", flexWrap: "wrap" }, children: [
1487
+ /* @__PURE__ */ jsx18("button", { type: "button", className: "chapter-portal-link", onClick: onSignOut, children: copy.shell.signOut }),
1488
+ adminHref ? /* @__PURE__ */ jsx18("a", { href: adminHref, children: copy.shell.adminConsole }) : null
1489
+ ] })
1490
+ ] });
1491
+ }
1492
+ function PortalNav(props) {
1493
+ const island = props.sidebarTokens ? void 0 : "ui-invert";
1494
+ return /* @__PURE__ */ jsxs16(Fragment5, { children: [
1495
+ /* @__PURE__ */ jsxs16(ThemeScope, { tokens: props.sidebarTokens, className: `chapter-portal-side ${island ?? ""}`, role: "complementary", "aria-label": props.copy.shell.navLabel, children: [
1496
+ /* @__PURE__ */ jsx18("div", { className: "chapter-portal-brand", children: props.brand }),
1497
+ /* @__PURE__ */ jsx18(Groups, { ...props }),
1498
+ /* @__PURE__ */ jsx18(Account, { ...props })
1499
+ ] }),
1500
+ /* @__PURE__ */ jsxs16(ThemeScope, { tokens: props.sidebarTokens, className: `chapter-portal-mobile ${island ?? ""}`, children: [
1501
+ /* @__PURE__ */ jsxs16("div", { className: "chapter-portal-mobile-bar", children: [
1502
+ /* @__PURE__ */ jsx18("div", { className: "chapter-portal-brand", children: props.brand }),
1503
+ /* @__PURE__ */ jsx18(
1504
+ "button",
1505
+ {
1506
+ type: "button",
1507
+ className: "chapter-portal-burger",
1508
+ "aria-expanded": props.menuOpen,
1509
+ "aria-label": props.menuOpen ? props.copy.shell.closeMenu : props.copy.shell.openMenu,
1510
+ onClick: props.onToggleMenu,
1511
+ children: /* @__PURE__ */ jsx18(PortalIcon, { name: props.menuOpen ? "close" : "menu", size: 22 })
1512
+ }
1513
+ )
1514
+ ] }),
1515
+ props.menuOpen ? /* @__PURE__ */ jsxs16("nav", { className: "chapter-portal-mobile-menu", "aria-label": props.copy.shell.navLabel, children: [
1516
+ /* @__PURE__ */ jsx18(Groups, { ...props }),
1517
+ /* @__PURE__ */ jsx18(Account, { ...props })
1518
+ ] }) : null
1519
+ ] })
1520
+ ] });
1521
+ }
1522
+
1523
+ // src/ui/member-portal-pages.tsx
1524
+ import { Markdown as Markdown2 } from "@odla-ai/ui/components";
1525
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs17 } from "preact/jsx-runtime";
1526
+ var upsellOf = (page, ctx) => {
1527
+ const tierName = page.upsell?.tierName;
1528
+ const href = page.upsell && ctx.upsellHref ? ctx.upsellHref(page.upsell.tierId, page) : void 0;
1529
+ return { tierName, href, cta: page.upsell?.ctaLabel ?? ctx.copy.pages.upgrade };
1530
+ };
1531
+ function LockedPill({ page, ctx }) {
1532
+ const { tierName } = upsellOf(page, ctx);
1533
+ return /* @__PURE__ */ jsxs17("span", { className: "chapter-portal-pill", children: [
1534
+ /* @__PURE__ */ jsx19(PortalIcon, { name: "lock", size: 12 }),
1535
+ tierName ? formatChapterCopy(ctx.copy.pages.includedWith, { tierName }) : ctx.copy.shell.locked
1536
+ ] });
1537
+ }
1538
+ function UpgradeLink({ page, ctx, variant }) {
1539
+ const { href, cta } = upsellOf(page, ctx);
1540
+ return href ? /* @__PURE__ */ jsx19("a", { className: "chapter-portal-btn", "data-variant": variant, href, target: "_blank", rel: "noopener", children: cta }) : null;
1541
+ }
1542
+ function LockedScreen({ page, ctx }) {
1543
+ return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-soon", "data-access": "locked", children: [
1544
+ /* @__PURE__ */ jsx19(LockedPill, { page, ctx }),
1545
+ /* @__PURE__ */ jsx19("h2", { children: page.title }),
1546
+ page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
1547
+ page.teaserMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.teaserMarkdown }) : null,
1548
+ page.upsell?.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.upsell.bodyMarkdown }) : null,
1549
+ /* @__PURE__ */ jsx19("div", { className: "chapter-portal-btns", style: { justifyContent: "center", marginTop: "1.25rem" }, children: /* @__PURE__ */ jsx19(UpgradeLink, { page, ctx }) })
1550
+ ] });
1551
+ }
1552
+ function PlaceholderScreen({ page }) {
1553
+ return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-soon", "data-placeholder": true, children: [
1554
+ /* @__PURE__ */ jsx19("span", { className: "chapter-portal-pill", children: placeholderBadge(page) }),
1555
+ /* @__PURE__ */ jsx19("h2", { children: page.title }),
1556
+ page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
1557
+ page.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.bodyMarkdown }) : null,
1558
+ page.placeholder?.actionLabel ? /* @__PURE__ */ jsx19("div", { className: "chapter-portal-btns", style: { justifyContent: "center", marginTop: "1.25rem" }, children: /* @__PURE__ */ jsx19("button", { className: "chapter-portal-btn", type: "button", disabled: true, children: page.placeholder.actionLabel }) }) : null
1559
+ ] });
1560
+ }
1561
+ function PortalPage({ page, ctx, features }) {
1562
+ if (page.access === "locked") return /* @__PURE__ */ jsx19(LockedScreen, { page, ctx });
1563
+ if (page.kind === "placeholder") return /* @__PURE__ */ jsx19(PlaceholderScreen, { page });
1564
+ if (page.kind === "feature" && page.feature) {
1565
+ const feature = features[page.feature.name];
1566
+ if (feature) return /* @__PURE__ */ jsx19(Fragment6, { children: feature.page(page, ctx) });
1567
+ }
1568
+ return /* @__PURE__ */ jsxs17("article", { className: "chapter-portal-card", children: [
1569
+ /* @__PURE__ */ jsx19("h2", { children: page.title }),
1570
+ page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
1571
+ page.bodyMarkdown ? /* @__PURE__ */ jsx19(Markdown2, { source: page.bodyMarkdown }) : null
1572
+ ] });
1573
+ }
1574
+ function PortalTile({ page, ctx }) {
1575
+ return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card chapter-portal-tile", "data-access": page.access, children: [
1576
+ /* @__PURE__ */ jsx19(PortalIcon, { name: page.navigation.icon ?? "document", size: 22 }),
1577
+ /* @__PURE__ */ jsx19("h3", { children: page.title }),
1578
+ page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
1579
+ page.access === "locked" ? /* @__PURE__ */ jsx19(LockedPill, { page, ctx }) : /* @__PURE__ */ jsx19("span", { className: "chapter-portal-pill", style: { alignSelf: "flex-start" }, children: placeholderBadge(page) })
1580
+ ] });
1581
+ }
1582
+ function DefaultHome({ ctx, features, slots }) {
1583
+ const panels = ctx.content.pages.filter((page) => page.kind === "feature" && page.feature && features[page.feature.name]?.home);
1584
+ const soon = ctx.content.pages.filter((page) => page.kind === "placeholder");
1585
+ return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-stack", children: [
1586
+ slots.top?.(ctx) ?? null,
1587
+ panels.map((page) => {
1588
+ const panel = features[page.feature.name].home(page, ctx);
1589
+ if (page.access !== "locked") return /* @__PURE__ */ jsx19("div", { children: panel }, page.id);
1590
+ return /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-locked-wrap", style: { position: "relative" }, children: [
1591
+ /* @__PURE__ */ jsx19("div", { "aria-hidden": "true", inert: true, style: { opacity: 0.35, filter: "grayscale(1)", pointerEvents: "none" }, children: panel }),
1592
+ /* @__PURE__ */ jsx19("div", { style: { position: "absolute", inset: 0, display: "grid", placeItems: "center", padding: "1rem" }, children: /* @__PURE__ */ jsxs17("div", { className: "chapter-portal-card", style: { maxWidth: "26rem", textAlign: "center" }, children: [
1593
+ /* @__PURE__ */ jsx19(LockedPill, { page, ctx }),
1594
+ /* @__PURE__ */ jsx19("h3", { children: page.title }),
1595
+ page.summary ? /* @__PURE__ */ jsx19("p", { children: page.summary }) : null,
1596
+ /* @__PURE__ */ jsx19(UpgradeLink, { page, ctx })
1597
+ ] }) })
1598
+ ] }, page.id);
1599
+ }),
1600
+ slots.middle?.(ctx) ?? null,
1601
+ soon.length ? /* @__PURE__ */ jsxs17("section", { children: [
1602
+ /* @__PURE__ */ jsx19("h2", { style: { fontFamily: "var(--ui-font-display,inherit)", fontWeight: 400 }, children: ctx.copy.pages.comingToPortal }),
1603
+ /* @__PURE__ */ jsx19("div", { className: "chapter-portal-tiles", children: soon.map((page) => /* @__PURE__ */ jsx19("div", { children: slots.tile?.(page, ctx) ?? /* @__PURE__ */ jsx19(PortalTile, { page, ctx }) }, page.id)) })
1604
+ ] }) : null
1605
+ ] });
1606
+ }
1607
+
1608
+ // src/ui/member-profile-page.tsx
1609
+ import { useEffect as useEffect6, useState as useState13 } from "preact/hooks";
1610
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs18 } from "preact/jsx-runtime";
1611
+ var memberMonth = (at) => new Date(at).toLocaleString("en-US", { month: "long", year: "numeric", timeZone: "UTC" });
1612
+ var startingPrompts = (view) => view.profile.prompts.length ? view.profile.prompts : view.promptChoices.slice(0, view.maxPrompts).map((prompt) => ({ prompt, answer: "" }));
1613
+ function choosePrompt(prompts, prompt, max) {
1614
+ if (prompts.some((entry) => entry.prompt === prompt) || max === 0) return prompts;
1615
+ return prompts.length < max ? [...prompts, { prompt, answer: "" }] : [...prompts.slice(0, max - 1), { prompt, answer: "" }];
1616
+ }
1617
+ async function resizePhoto(file) {
1618
+ const bitmap = await createImageBitmap(file);
1619
+ const side = Math.min(bitmap.width, bitmap.height);
1620
+ const canvas = document.createElement("canvas");
1621
+ canvas.width = canvas.height = 400;
1622
+ canvas.getContext("2d").drawImage(bitmap, (bitmap.width - side) / 2, (bitmap.height - side) / 2, side, side, 0, 0, 400, 400);
1623
+ return new Promise((resolve, reject) => canvas.toBlob((blob) => blob ? resolve(blob) : reject(new Error("encode failed")), "image/jpeg", 0.9));
1624
+ }
1625
+ function MemberProfilePage({ ctx, middle, extras }) {
1626
+ const copy = ctx.copy.profile;
1627
+ const [view, setView] = useState13(null);
1628
+ const [draft, setDraft] = useState13(null);
1629
+ const [status, setStatus] = useState13(null);
1630
+ const [busy, setBusy] = useState13(false);
1631
+ const load = async () => {
1632
+ try {
1633
+ setView(await ctx.api("/api/member/profile"));
1634
+ } catch {
1635
+ setStatus(ctx.copy.shell.loadFailed);
1636
+ }
1637
+ };
1638
+ useEffect6(() => {
1639
+ void load();
1640
+ }, []);
1641
+ if (!view) return /* @__PURE__ */ jsx20("p", { children: status ?? ctx.copy.shell.loading });
1642
+ const prompts = draft?.prompts ?? startingPrompts(view);
1643
+ const edit = () => setDraft({
1644
+ preferredName: view.profile.preferredName ?? ctx.me.displayName,
1645
+ location: view.profile.location ?? "",
1646
+ introducedByText: view.profile.introducedByText ?? "",
1647
+ prompts: startingPrompts(view)
1648
+ });
1649
+ const save = async () => {
1650
+ if (!draft) return;
1651
+ setBusy(true);
1652
+ try {
1653
+ const next = await ctx.api("/api/member/profile", { method: "PUT", headers: { "content-type": "application/json" }, body: JSON.stringify({
1654
+ expectedRevision: view.revision,
1655
+ preferredName: draft.preferredName,
1656
+ location: draft.location,
1657
+ introducedByText: draft.introducedByText,
1658
+ prompts: draft.prompts
1659
+ }) });
1660
+ setView(next);
1661
+ setDraft(null);
1662
+ setStatus(copy.saved);
1663
+ await ctx.reloadMe();
1664
+ } catch (error) {
1665
+ setStatus(String(error).includes("409") ? copy.conflict : copy.saveFailed);
1666
+ } finally {
1667
+ setBusy(false);
1668
+ }
1669
+ };
1670
+ const upload = async (file) => {
1671
+ if (!file) return;
1672
+ setBusy(true);
1673
+ setStatus(copy.photoUploading);
1674
+ try {
1675
+ if (file.size > 10 * 1024 * 1024) throw new Error("too large");
1676
+ await ctx.api("/api/member/profile/photo", { method: "POST", headers: { "content-type": "image/jpeg" }, body: await resizePhoto(file) });
1677
+ setStatus(null);
1678
+ await ctx.reloadMe();
1679
+ } catch {
1680
+ setStatus(copy.photoFailed);
1681
+ } finally {
1682
+ setBusy(false);
1683
+ }
1684
+ };
1685
+ const remaining = view.promptChoices.filter((choice) => !prompts.some((entry) => entry.prompt === choice));
1686
+ return /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-stack", "data-portal-profile": true, children: [
1687
+ /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", style: { display: "flex", gap: "1.25rem", alignItems: "center", flexWrap: "wrap" }, children: [
1688
+ /* @__PURE__ */ jsxs18("div", { style: { textAlign: "center" }, children: [
1689
+ /* @__PURE__ */ jsx20(PortalAvatar, { me: ctx.me, className: "chapter-portal-profile-photo" }),
1690
+ view.photos ? /* @__PURE__ */ jsxs18("label", { className: "chapter-portal-btn", "data-variant": "ghost", style: { marginTop: ".6rem", padding: ".35rem .8rem", fontSize: ".78rem" }, children: [
1691
+ ctx.me.photoUrl ? copy.changePhoto : copy.uploadPhoto,
1692
+ /* @__PURE__ */ jsx20("input", { type: "file", accept: "image/jpeg,image/png", hidden: true, disabled: busy, onChange: (event) => void upload(event.currentTarget.files?.[0]) })
1693
+ ] }) : null
1694
+ ] }),
1695
+ /* @__PURE__ */ jsxs18("div", { style: { flex: 1, minWidth: "12rem" }, children: [
1696
+ /* @__PURE__ */ jsx20("div", { className: "chapter-portal-group-label", style: { padding: 0 }, children: copy.eyebrow }),
1697
+ draft ? /* @__PURE__ */ jsx20(
1698
+ "input",
1699
+ {
1700
+ "aria-label": copy.namePlaceholder,
1701
+ placeholder: copy.namePlaceholder,
1702
+ value: draft.preferredName,
1703
+ maxLength: 80,
1704
+ onInput: (event) => setDraft({ ...draft, preferredName: event.currentTarget.value })
1705
+ }
1706
+ ) : /* @__PURE__ */ jsx20("h2", { style: { margin: ".2rem 0" }, children: ctx.me.displayName }),
1707
+ /* @__PURE__ */ jsxs18("p", { style: { margin: 0, color: "var(--ui-text-muted)" }, children: [
1708
+ ctx.me.tier && ctx.me.memberSince ? formatChapterCopy(copy.memberSince, { tierName: ctx.me.tier.name, month: memberMonth(ctx.me.memberSince) }) : null,
1709
+ draft ? /* @__PURE__ */ jsx20(
1710
+ "input",
1711
+ {
1712
+ "aria-label": copy.locationPlaceholder,
1713
+ placeholder: copy.locationPlaceholder,
1714
+ value: draft.location,
1715
+ maxLength: 80,
1716
+ onInput: (event) => setDraft({ ...draft, location: event.currentTarget.value })
1717
+ }
1718
+ ) : ctx.me.location ? /* @__PURE__ */ jsxs18(Fragment7, { children: [
1719
+ " \xB7 ",
1720
+ ctx.me.location
1721
+ ] }) : null
1722
+ ] })
1723
+ ] }),
1724
+ /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-btns", children: [
1725
+ draft ? /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", disabled: busy, onClick: () => void save(), children: busy ? copy.saving : copy.saveProfile }) : /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", onClick: edit, children: copy.editProfile }),
1726
+ draft ? /* @__PURE__ */ jsx20("button", { type: "button", className: "chapter-portal-btn", "data-variant": "ghost", disabled: busy, onClick: () => setDraft(null), children: copy.cancel }) : null
1727
+ ] })
1728
+ ] }),
1729
+ status ? /* @__PURE__ */ jsx20("p", { role: "status", children: status }) : null,
1730
+ view.maxPrompts > 0 && view.promptChoices.length ? /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
1731
+ /* @__PURE__ */ jsx20("h2", { children: copy.promptsTitle }),
1732
+ /* @__PURE__ */ jsx20("p", { style: { color: "var(--ui-text-muted)" }, children: formatChapterCopy(copy.promptsNote, { count: String(view.maxPrompts) }) }),
1733
+ /* @__PURE__ */ jsx20("div", { className: "chapter-portal-tiles", children: prompts.map((entry, index) => /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
1734
+ /* @__PURE__ */ jsx20("q", { children: entry.prompt }),
1735
+ draft ? /* @__PURE__ */ jsx20(
1736
+ "textarea",
1737
+ {
1738
+ "aria-label": entry.prompt,
1739
+ maxLength: 280,
1740
+ rows: 3,
1741
+ value: entry.answer,
1742
+ onInput: (event) => setDraft({ ...draft, prompts: draft.prompts.map((p, i) => i === index ? { ...p, answer: event.currentTarget.value } : p) })
1743
+ }
1744
+ ) : /* @__PURE__ */ jsx20("p", { children: entry.answer || /* @__PURE__ */ jsx20("span", { style: { color: "var(--ui-text-muted)" }, children: copy.answerEmpty }) })
1745
+ ] }, entry.prompt)) }),
1746
+ /* @__PURE__ */ jsx20("div", { className: "chapter-portal-btns", style: { marginTop: "1rem" }, children: remaining.map((choice) => /* @__PURE__ */ jsx20(
1747
+ "button",
1748
+ {
1749
+ type: "button",
1750
+ className: "chapter-portal-pill",
1751
+ style: { cursor: "pointer", background: "transparent" },
1752
+ onClick: () => {
1753
+ const base = draft ?? { preferredName: view.profile.preferredName ?? ctx.me.displayName, location: view.profile.location ?? "", introducedByText: view.profile.introducedByText ?? "", prompts };
1754
+ setDraft({ ...base, prompts: choosePrompt(base.prompts, choice, view.maxPrompts) });
1755
+ },
1756
+ children: formatChapterCopy(copy.addPrompt, { prompt: choice })
1757
+ },
1758
+ choice
1759
+ )) })
1760
+ ] }) : null,
1761
+ middle,
1762
+ /* @__PURE__ */ jsxs18("div", { className: "chapter-portal-card", children: [
1763
+ /* @__PURE__ */ jsx20("h2", { children: copy.howYouFoundUs }),
1764
+ view.referredBy ? /* @__PURE__ */ jsxs18("p", { children: [
1765
+ /* @__PURE__ */ jsx20("strong", { children: copy.referredBy }),
1766
+ " \xB7 ",
1767
+ /* @__PURE__ */ jsx20("strong", { children: view.referredBy.name }),
1768
+ " ",
1769
+ /* @__PURE__ */ jsxs18("span", { style: { color: "var(--ui-text-muted)" }, children: [
1770
+ "\xB7 ",
1771
+ copy.referredByNote
1772
+ ] })
1773
+ ] }) : null,
1774
+ /* @__PURE__ */ jsxs18("label", { style: { display: "block" }, children: [
1775
+ /* @__PURE__ */ jsx20("span", { children: copy.introducedBy }),
1776
+ draft ? /* @__PURE__ */ jsx20(
1777
+ "input",
1778
+ {
1779
+ placeholder: copy.introducedByPlaceholder,
1780
+ value: draft.introducedByText,
1781
+ maxLength: 120,
1782
+ onInput: (event) => setDraft({ ...draft, introducedByText: event.currentTarget.value })
1783
+ }
1784
+ ) : /* @__PURE__ */ jsx20("p", { children: view.profile.introducedByText || /* @__PURE__ */ jsx20("span", { style: { color: "var(--ui-text-muted)" }, children: copy.introducedByPlaceholder }) })
1785
+ ] })
1786
+ ] }),
1787
+ extras
1788
+ ] });
1789
+ }
1790
+
1791
+ // src/ui/member-portal-styles.ts
1792
+ var MEMBER_PORTAL_CSS = `
1793
+ .chapter-portal{display:grid;grid-template-columns:clamp(232px,22vw,272px) minmax(0,1fr);min-height:100vh;background:var(--ui-bg,#f4efe6);color:var(--ui-text,#2f3e34);font-family:var(--ui-font-sans,inherit);line-height:1.55;overflow-x:clip}
1794
+ .chapter-portal *,.chapter-portal *::before,.chapter-portal *::after{box-sizing:border-box}
1795
+ .chapter-portal-side{position:sticky;top:0;height:100vh;overflow-y:auto;display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem 1rem;background:var(--ui-surface,#2f3e34);color:var(--ui-text,#fbf8f2)}
1796
+ .chapter-portal-brand{display:flex;align-items:center;gap:.65rem;padding:0 .5rem;font-family:var(--ui-font-display,inherit);font-size:1.35rem;line-height:1.1;white-space:nowrap}
1797
+ .chapter-portal-brand :where(img,svg){width:30px;height:30px;flex:none}
1798
+ .chapter-portal-group-label{padding:0 .75rem;margin-bottom:.35rem;font-size:.68rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--ui-text-muted,#b8c4bb)}
1799
+ .chapter-portal-nav-item{display:flex;align-items:center;gap:.7rem;width:100%;padding:.55rem .75rem;border:0;border-radius:var(--ui-radius-sm,8px);background:transparent;color:inherit;font:inherit;font-size:.95rem;text-align:left;text-decoration:none;cursor:pointer}
1800
+ .chapter-portal-nav-item:hover{background:color-mix(in srgb,var(--ui-text,#fff) 8%,transparent)}
1801
+ .chapter-portal-nav-item[aria-current=page]{background:color-mix(in srgb,var(--ui-text,#fff) 14%,transparent);font-weight:600}
1802
+ .chapter-portal-nav-item>span:first-of-type{flex:1;min-width:0}
1803
+ .chapter-portal-tag{border:1px solid var(--ui-border,rgba(255,255,255,.2));border-radius:999px;padding:.05rem .5rem;font-size:.62rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ui-text-muted,#b8c4bb)}
1804
+ .chapter-portal-tag[data-tag=new]{border-color:transparent;background:var(--ui-accent,#7cb83f);color:var(--ui-on-accent,#2f3e34)}
1805
+ .chapter-portal-account{margin-top:auto;padding:.75rem;border-top:1px solid var(--ui-border,rgba(255,255,255,.15));font-size:.85rem;color:var(--ui-text-muted,#b8c4bb);overflow-wrap:anywhere}
1806
+ .chapter-portal-account .chapter-portal-nav-item{margin:0 -.75rem .75rem;width:calc(100% + 1.5rem);color:var(--ui-text,#fff)}
1807
+ .chapter-portal-account button.chapter-portal-link,.chapter-portal-account a{display:inline;padding:0;border:0;background:none;color:var(--ui-text,#fff);font:inherit;text-decoration:underline;cursor:pointer}
1808
+ .chapter-portal-avatar{display:inline-grid;place-items:center;flex:none;width:28px;height:28px;border-radius:50%;overflow:hidden;background:var(--ui-accent-soft,rgba(124,184,63,.2));color:var(--ui-text,inherit);font-size:.72rem;font-weight:700;letter-spacing:.04em}
1809
+ .chapter-portal-avatar img{width:100%;height:100%;object-fit:cover}
1810
+ .chapter-portal-main{min-width:0;padding:clamp(1rem,3vw,2.5rem);display:flex;flex-direction:column;gap:1.5rem}
1811
+ .chapter-portal-top{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
1812
+ .chapter-portal-top h1{margin:0;font-family:var(--ui-font-display,inherit);font-weight:400;font-size:clamp(1.8rem,4vw,2.4rem);line-height:1.1}
1813
+ .chapter-portal-back{padding:0;border:0;background:none;color:var(--ui-text,inherit);font:inherit;font-weight:600;cursor:pointer}
1814
+ .chapter-portal-top-right{display:flex;align-items:center;gap:.75rem;margin-left:auto}
1815
+ .chapter-portal-pill{display:inline-flex;align-items:center;gap:.35rem;border:1px solid var(--ui-border,#e2dccf);border-radius:999px;padding:.2rem .7rem;font-size:.66rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ui-text-muted,#7e8e84);white-space:nowrap}
1816
+ .chapter-portal-me{padding:0;border:0;background:none;cursor:pointer;border-radius:50%}
1817
+ .chapter-portal-me .chapter-portal-avatar{width:40px;height:40px;font-size:.85rem}
1818
+ .chapter-portal-card{background:var(--ui-surface,#fbf8f2);border:1px solid var(--ui-border,#e2dccf);border-radius:var(--ui-radius-lg,14px);padding:clamp(1.1rem,3vw,1.6rem);min-width:0}
1819
+ .chapter-portal-card h2{margin:.4rem 0 .5rem;font-family:var(--ui-font-display,inherit);font-weight:400;font-size:1.6rem;line-height:1.15}
1820
+ .chapter-portal-stack{display:flex;flex-direction:column;gap:1.25rem}
1821
+ .chapter-portal-soon{text-align:center;padding:clamp(2rem,6vw,3.5rem) 1.5rem}
1822
+ .chapter-portal-soon p{max-width:36rem;margin:.5rem auto 0;color:var(--ui-text-muted,#7e8e84)}
1823
+ .chapter-portal-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:1rem}
1824
+ .chapter-portal-tile{display:flex;flex-direction:column;gap:.5rem}
1825
+ .chapter-portal-tile h3{margin:0;font-size:1.05rem}
1826
+ .chapter-portal-tile p{margin:0;color:var(--ui-text-muted,#7e8e84);font-size:.92rem;flex:1}
1827
+ .chapter-portal-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:42px;padding:.6rem 1.2rem;border:1px solid var(--ui-text,#2f3e34);border-radius:999px;background:var(--ui-text,#2f3e34);color:var(--ui-bg,#fbf8f2);font:inherit;font-size:.92rem;font-weight:600;text-decoration:none;cursor:pointer}
1828
+ .chapter-portal-btn[data-variant=ghost]{background:transparent;color:var(--ui-text,#2f3e34)}
1829
+ .chapter-portal-btn[data-variant=accent]{background:var(--ui-accent,#7cb83f);border-color:var(--ui-accent,#7cb83f);color:var(--ui-on-accent,#2f3e34)}
1830
+ .chapter-portal-btn:disabled{opacity:.5;cursor:not-allowed}
1831
+ .chapter-portal-btns{display:flex;flex-wrap:wrap;gap:.6rem}
1832
+ .chapter-portal :where(button,a,input,textarea,select):focus-visible{outline:3px solid var(--ui-focus,var(--ui-accent,#7cb83f));outline-offset:2px}
1833
+ .chapter-portal-mobile{display:none}
1834
+ @media (max-width:860px){
1835
+ .chapter-portal{grid-template-columns:minmax(0,1fr)}
1836
+ .chapter-portal-side{display:none}
1837
+ .chapter-portal-mobile{display:block;margin:calc(-1*clamp(1rem,3vw,2.5rem)) calc(-1*clamp(1rem,3vw,2.5rem)) 0;background:var(--ui-surface,#2f3e34);color:var(--ui-text,#fbf8f2)}
1838
+ .chapter-portal-mobile-bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.8rem 1rem}
1839
+ .chapter-portal-burger{display:inline-grid;place-items:center;width:44px;height:44px;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer}
1840
+ .chapter-portal-mobile-menu{display:flex;flex-direction:column;gap:1rem;padding:0 1rem 1.25rem}
1841
+ .chapter-portal-mobile .chapter-portal-brand{font-size:1.15rem;padding:0}
1842
+ }
1843
+ `;
1844
+
1845
+ // src/ui/member-portal-features.tsx
1846
+ var PACKAGED_PORTAL_FEATURES = {};
1847
+
1848
+ // src/ui/member-portal.tsx
1849
+ import { jsx as jsx21, jsxs as jsxs19 } from "preact/jsx-runtime";
1850
+ var EMPTY = { pages: [], sections: [], viewer: { tierId: null, admin: false }, revisions: { parent: null, chapter: null } };
1851
+ function MemberPortal(props) {
1852
+ const inherited = useChapterCopy();
1853
+ const copy = props.copy ?? inherited.portal;
1854
+ const routing = { mode: props.routing?.mode ?? "hash", basePath: props.routing?.basePath ?? "/members" };
1855
+ const [content, setContent] = useState14(props.initialContent ?? null);
1856
+ const [route, setRoute] = useState14(props.initialRoute ?? { kind: "home" });
1857
+ const [menuOpen, setMenuOpen] = useState14(false);
1858
+ useEffect7(() => {
1859
+ if (props.initialContent) return;
1860
+ let live = true;
1861
+ void props.api("/api/member-content").then((value) => live && setContent(value)).catch(() => live && setContent(EMPTY));
1862
+ return () => {
1863
+ live = false;
1864
+ };
1865
+ }, [props.api, props.initialContent]);
1866
+ useEffect7(() => {
1867
+ if (typeof window === "undefined" || props.initialRoute) return;
1868
+ const sync = () => setRoute(routeFromLocation(window.location, routing));
1869
+ sync();
1870
+ window.addEventListener("popstate", sync);
1871
+ window.addEventListener("hashchange", sync);
1872
+ return () => {
1873
+ window.removeEventListener("popstate", sync);
1874
+ window.removeEventListener("hashchange", sync);
1875
+ };
1876
+ }, [routing.mode, routing.basePath]);
1877
+ const navigate = (next) => {
1878
+ setRoute(next);
1879
+ setMenuOpen(false);
1880
+ if (typeof window !== "undefined") {
1881
+ window.history.pushState(null, "", hrefFor(next, routing));
1882
+ window.scrollTo?.(0, 0);
1883
+ }
1884
+ };
1885
+ const features = useMemo3(() => ({ ...PACKAGED_PORTAL_FEATURES, ...props.features }), [props.features]);
1886
+ if (!content) return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal", children: [
1887
+ /* @__PURE__ */ jsx21("style", { children: MEMBER_PORTAL_CSS }),
1888
+ /* @__PURE__ */ jsx21("p", { children: copy.shell.loading })
1889
+ ] });
1890
+ const ctx = {
1891
+ api: props.api,
1892
+ me: props.me.portal,
1893
+ email: props.me.email,
1894
+ content,
1895
+ copy,
1896
+ navigate,
1897
+ hrefFor: (target) => hrefFor(target, routing),
1898
+ upsellHref: props.upsellHref,
1899
+ reloadMe: props.reloadMe ?? (async () => {
1900
+ })
1901
+ };
1902
+ const page = route.kind === "page" ? content.pages.find((candidate) => candidate.slug === route.slug) : void 0;
1903
+ const slots = typeof props.home === "function" ? {} : props.home ?? {};
1904
+ const home = /* @__PURE__ */ jsx21(DefaultHome, { ctx, features, slots });
1905
+ const body = route.kind === "home" ? typeof props.home === "function" ? props.home(ctx, home) : home : route.kind === "profile" ? /* @__PURE__ */ jsx21(MemberProfilePage, { ctx, middle: props.profile?.middle?.(ctx), extras: props.profile?.extras }) : page ? /* @__PURE__ */ jsx21(PortalPage, { page, ctx, features }) : /* @__PURE__ */ jsx21("div", { className: "chapter-portal-card", children: copy.shell.notFound });
1906
+ const admin = props.me.authorized || props.me.superAdmin ? props.adminHref ?? "/admin/" : void 0;
1907
+ return /* @__PURE__ */ jsxs19("div", { className: "chapter-portal", "data-member-portal": true, "data-route": route.kind, children: [
1908
+ /* @__PURE__ */ jsx21("style", { children: MEMBER_PORTAL_CSS }),
1909
+ /* @__PURE__ */ jsx21(
1910
+ PortalNav,
1911
+ {
1912
+ content,
1913
+ me: ctx.me,
1914
+ email: props.me.email,
1915
+ route,
1916
+ copy,
1917
+ adminHref: admin,
1918
+ onNavigate: navigate,
1919
+ onSignOut: props.signOut,
1920
+ brand: props.brand,
1921
+ sidebarTokens: props.sidebarTokens,
1922
+ menuOpen,
1923
+ onToggleMenu: () => setMenuOpen(!menuOpen)
1924
+ }
1925
+ ),
1926
+ /* @__PURE__ */ jsxs19("main", { className: "chapter-portal-main", children: [
1927
+ /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-top", children: [
1928
+ route.kind === "home" ? /* @__PURE__ */ jsx21("h1", { children: copy.shell.welcomeBack }) : /* @__PURE__ */ jsx21("button", { type: "button", className: "chapter-portal-back", onClick: () => navigate({ kind: "home" }), children: copy.shell.backHome }),
1929
+ /* @__PURE__ */ jsxs19("div", { className: "chapter-portal-top-right", children: [
1930
+ ctx.me.tier ? /* @__PURE__ */ jsx21("span", { className: "chapter-portal-pill", children: ctx.me.tier.name }) : null,
1931
+ /* @__PURE__ */ jsx21(
1932
+ "button",
1933
+ {
1934
+ type: "button",
1935
+ className: "chapter-portal-me",
1936
+ "aria-label": copy.shell.yourProfile,
1937
+ title: copy.shell.yourProfile,
1938
+ "aria-current": route.kind === "profile" ? "page" : void 0,
1939
+ onClick: () => navigate({ kind: "profile" }),
1940
+ children: /* @__PURE__ */ jsx21(PortalAvatar, { me: ctx.me })
1941
+ }
1942
+ )
1943
+ ] })
1944
+ ] }),
1945
+ body
1946
+ ] })
1947
+ ] });
1948
+ }
1364
1949
 
1365
1950
  // src/ui/members.tsx
1366
- import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs16 } from "preact/jsx-runtime";
1951
+ import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs20 } from "preact/jsx-runtime";
1367
1952
  function card(copy, kicker, body) {
1368
- return /* @__PURE__ */ jsxs16("div", { className: "card", children: [
1369
- /* @__PURE__ */ jsx17("div", { className: "card-label", children: copy.provisional.cardLabel }),
1370
- /* @__PURE__ */ jsxs16("div", { className: "meeting-block", children: [
1371
- /* @__PURE__ */ jsx17("div", { className: "meeting-kicker", children: kicker }),
1953
+ return /* @__PURE__ */ jsxs20("div", { className: "card", children: [
1954
+ /* @__PURE__ */ jsx22("div", { className: "card-label", children: copy.provisional.cardLabel }),
1955
+ /* @__PURE__ */ jsxs20("div", { className: "meeting-block", children: [
1956
+ /* @__PURE__ */ jsx22("div", { className: "meeting-kicker", children: kicker }),
1372
1957
  body
1373
1958
  ] })
1374
1959
  ] });
@@ -1379,29 +1964,32 @@ function ProvisionalCard(props) {
1379
1964
  return card(
1380
1965
  copy,
1381
1966
  copy.provisional.applicationNeeded,
1382
- /* @__PURE__ */ jsxs16(Fragment5, { children: [
1383
- /* @__PURE__ */ jsx17("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
1384
- /* @__PURE__ */ jsx17("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
1967
+ /* @__PURE__ */ jsxs20(Fragment8, { children: [
1968
+ /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.applicationNeededBody }),
1969
+ /* @__PURE__ */ jsx22("a", { className: "apply-link", href: applyHref, children: copy.provisional.apply })
1385
1970
  ] })
1386
1971
  );
1387
1972
  }
1973
+ if (application.status === "declined") {
1974
+ return card(copy, copy.provisional.declined, /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.declinedBody }));
1975
+ }
1388
1976
  if (application.status === "refunded") {
1389
1977
  return card(
1390
1978
  copy,
1391
1979
  copy.provisional.refunded,
1392
- /* @__PURE__ */ jsx17("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1980
+ /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.refundedBody })
1393
1981
  );
1394
1982
  }
1395
- const membership = application.paid ? /* @__PURE__ */ jsx17("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
1983
+ const membership = application.paid ? /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: application.renewalAt ? formatChapterCopy(copy.provisional.renews, { date: fmtDate(application.renewalAt) }) : copy.provisional.active }) : null;
1396
1984
  if (application.meetingAt) {
1397
1985
  return card(
1398
1986
  copy,
1399
1987
  copy.provisional.introductionCall,
1400
- /* @__PURE__ */ jsxs16(Fragment5, { children: [
1401
- /* @__PURE__ */ jsx17("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
1402
- /* @__PURE__ */ jsx17("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
1403
- application.meetUrl ? /* @__PURE__ */ jsx17("div", { className: "meeting-note", children: /* @__PURE__ */ jsx17("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
1404
- /* @__PURE__ */ jsx17(
1988
+ /* @__PURE__ */ jsxs20(Fragment8, { children: [
1989
+ /* @__PURE__ */ jsx22("div", { className: "meeting-date", children: fullLabel(application.meetingAt, application.timezone) }),
1990
+ /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.calendarInvite }),
1991
+ application.meetUrl ? /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: /* @__PURE__ */ jsx22("a", { href: application.meetUrl, target: "_blank", rel: "noopener", children: copy.provisional.joinCall }) }) : null,
1992
+ /* @__PURE__ */ jsx22(
1405
1993
  Rescheduler,
1406
1994
  {
1407
1995
  api,
@@ -1418,9 +2006,9 @@ function ProvisionalCard(props) {
1418
2006
  return card(
1419
2007
  copy,
1420
2008
  copy.provisional.bookCall,
1421
- /* @__PURE__ */ jsxs16(Fragment5, { children: [
1422
- /* @__PURE__ */ jsx17("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
1423
- /* @__PURE__ */ jsx17(
2009
+ /* @__PURE__ */ jsxs20(Fragment8, { children: [
2010
+ /* @__PURE__ */ jsx22("div", { className: "meeting-note", children: copy.provisional.bookCallBody }),
2011
+ /* @__PURE__ */ jsx22(
1424
2012
  Rescheduler,
1425
2013
  {
1426
2014
  api,
@@ -1447,8 +2035,8 @@ function MembersArea(props) {
1447
2035
  renderProvisional
1448
2036
  } = props;
1449
2037
  const copy = props.copy ?? inheritedCopy.members;
1450
- const [me, setMe] = useState13(null);
1451
- const [error, setError] = useState13(false);
2038
+ const [me, setMe] = useState15(null);
2039
+ const [error, setError] = useState15(false);
1452
2040
  const reload = async () => {
1453
2041
  try {
1454
2042
  setMe(await api("/api/me"));
@@ -1456,25 +2044,44 @@ function MembersArea(props) {
1456
2044
  setError(true);
1457
2045
  }
1458
2046
  };
1459
- useEffect6(() => {
2047
+ useEffect8(() => {
1460
2048
  void reload();
1461
2049
  }, []);
1462
- if (error) return /* @__PURE__ */ jsx17("p", { className: "meeting-note", children: copy.loadFailed });
1463
- if (!me) return /* @__PURE__ */ jsx17("p", { className: "meeting-note", children: inheritedCopy.common.loading });
2050
+ if (error) return /* @__PURE__ */ jsx22("p", { className: "meeting-note", children: copy.loadFailed });
2051
+ if (!me) return /* @__PURE__ */ jsx22("p", { className: "meeting-note", children: inheritedCopy.common.loading });
2052
+ if (props.portal && me.memberAccess === true && me.portal) {
2053
+ const gifts = /* @__PURE__ */ jsx22(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment });
2054
+ return /* @__PURE__ */ jsx22(
2055
+ MemberPortal,
2056
+ {
2057
+ ...props.portal,
2058
+ api,
2059
+ me: { ...me, portal: me.portal },
2060
+ signOut,
2061
+ reloadMe: reload,
2062
+ adminHref: props.portal.adminHref ?? adminHref,
2063
+ profile: { ...props.portal.profile, extras: /* @__PURE__ */ jsxs20(Fragment8, { children: [
2064
+ props.portal.profile?.extras,
2065
+ gifts,
2066
+ me.namedSeatsEnabled ? /* @__PURE__ */ jsx22(NamedSeatPurchase, { api }) : null
2067
+ ] }) }
2068
+ }
2069
+ );
2070
+ }
1464
2071
  const role = me.role || "provisional";
1465
- return /* @__PURE__ */ jsxs16(Fragment5, { children: [
1466
- /* @__PURE__ */ jsxs16("div", { className: "card", children: [
1467
- /* @__PURE__ */ jsxs16("div", { className: "member-row", children: [
1468
- /* @__PURE__ */ jsx17("span", { className: "member-email", children: me.email }),
1469
- /* @__PURE__ */ jsx17("span", { className: "role-badge " + role, children: role })
2072
+ return /* @__PURE__ */ jsxs20(Fragment8, { children: [
2073
+ /* @__PURE__ */ jsxs20("div", { className: "card", children: [
2074
+ /* @__PURE__ */ jsxs20("div", { className: "member-row", children: [
2075
+ /* @__PURE__ */ jsx22("span", { className: "member-email", children: me.email }),
2076
+ /* @__PURE__ */ jsx22("span", { className: "role-badge " + role, children: role })
1470
2077
  ] }),
1471
- /* @__PURE__ */ jsxs16("div", { className: "account-actions", children: [
1472
- /* @__PURE__ */ jsx17("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
1473
- me.authorized || me.superAdmin ? /* @__PURE__ */ jsx17("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
2078
+ /* @__PURE__ */ jsxs20("div", { className: "account-actions", children: [
2079
+ /* @__PURE__ */ jsx22("button", { className: "btn secondary mini", onClick: signOut, children: copy.account.signOut }),
2080
+ me.authorized || me.superAdmin ? /* @__PURE__ */ jsx22("a", { className: "admin-console-link", href: adminHref, children: copy.account.adminConsole }) : null
1474
2081
  ] })
1475
2082
  ] }),
1476
- me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx17(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
1477
- const defaultContent = /* @__PURE__ */ jsx17(
2083
+ me.memberAccess !== true && me.membershipRestart?.eligible && me.application ? /* @__PURE__ */ jsx22(MemberRestart, { api, application: me.application, applicationId: me.membershipRestart.applicationId, onComplete: reload }) : me.memberAccess !== true ? (() => {
2084
+ const defaultContent = /* @__PURE__ */ jsx22(
1478
2085
  ProvisionalCard,
1479
2086
  {
1480
2087
  api,
@@ -1491,27 +2098,27 @@ function MembersArea(props) {
1491
2098
  reload,
1492
2099
  defaultContent
1493
2100
  }) ?? defaultContent;
1494
- })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx17(
2101
+ })() : memberContent ?? (memberPages ? /* @__PURE__ */ jsx22(
1495
2102
  MemberContentArea,
1496
2103
  {
1497
2104
  api,
1498
2105
  ...memberPages === true ? {} : memberPages
1499
2106
  }
1500
- ) : /* @__PURE__ */ jsx17("div", { className: "card", children: /* @__PURE__ */ jsx17("div", { className: "card-label", children: copy.full.welcome }) })),
1501
- /* @__PURE__ */ jsx17(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
1502
- me.namedSeatsEnabled ? /* @__PURE__ */ jsx17(NamedSeatPurchase, { api }) : null
2107
+ ) : /* @__PURE__ */ jsx22("div", { className: "card", children: /* @__PURE__ */ jsx22("div", { className: "card-label", children: copy.full.welcome }) })),
2108
+ /* @__PURE__ */ jsx22(GiftPurchases, { api, copy: copy.gifts, paymentCopy: inheritedCopy.join.payment }),
2109
+ me.namedSeatsEnabled ? /* @__PURE__ */ jsx22(NamedSeatPurchase, { api }) : null
1503
2110
  ] });
1504
2111
  }
1505
2112
 
1506
2113
  // src/ui/join.tsx
1507
- import { useEffect as useEffect11, useRef as useRef8, useState as useState21 } from "preact/hooks";
2114
+ import { useEffect as useEffect13, useRef as useRef8, useState as useState23 } from "preact/hooks";
1508
2115
 
1509
2116
  // src/ui/join-booking.tsx
1510
- import { useEffect as useEffect7, useRef as useRef6, useState as useState14 } from "preact/hooks";
1511
- import { jsx as jsx18, jsxs as jsxs17 } from "preact/jsx-runtime";
2117
+ import { useEffect as useEffect9, useRef as useRef6, useState as useState16 } from "preact/hooks";
2118
+ import { jsx as jsx23, jsxs as jsxs21 } from "preact/jsx-runtime";
1512
2119
  function useJoinSlotsPreload(active) {
1513
2120
  const preload = useRef6(null);
1514
- useEffect7(() => {
2121
+ useEffect9(() => {
1515
2122
  if (!active || preload.current) return;
1516
2123
  preload.current = Promise.resolve().then(() => fetch("/api/schedule/slots"));
1517
2124
  preload.current.catch(() => {
@@ -1522,11 +2129,11 @@ function useJoinSlotsPreload(active) {
1522
2129
  }
1523
2130
  function JoinBooking(props) {
1524
2131
  const { applicationId, copy, onBooked, simulation } = props;
1525
- const [state, setState] = useState14(null);
1526
- const [msg, setMsg] = useState14(null);
1527
- const [busy, setBusy] = useState14(false);
1528
- const [day2, setDay] = useState14(null);
1529
- const [selected, setSelected] = useState14(null);
2132
+ const [state, setState] = useState16(null);
2133
+ const [msg, setMsg] = useState16(null);
2134
+ const [busy, setBusy] = useState16(false);
2135
+ const [day2, setDay] = useState16(null);
2136
+ const [selected, setSelected] = useState16(null);
1530
2137
  const load = async (preloaded) => {
1531
2138
  setMsg(null);
1532
2139
  try {
@@ -1551,7 +2158,7 @@ function JoinBooking(props) {
1551
2158
  setMsg(copy.loadFailed);
1552
2159
  }
1553
2160
  };
1554
- useEffect7(() => {
2161
+ useEffect9(() => {
1555
2162
  void load(props.preload);
1556
2163
  }, [simulation]);
1557
2164
  const book = async () => {
@@ -1583,17 +2190,17 @@ function JoinBooking(props) {
1583
2190
  setBusy(false);
1584
2191
  }
1585
2192
  };
1586
- if (!state) return /* @__PURE__ */ jsx18("p", { className: "slots-status", children: msg ?? copy.loading });
2193
+ if (!state) return /* @__PURE__ */ jsx23("p", { className: "slots-status", children: msg ?? copy.loading });
1587
2194
  const hint = !day2 ? copy.pickDate ?? DEFAULT_JOIN_COPY.booking.pickDate : !selected ? copy.pickTime ?? DEFAULT_JOIN_COPY.booking.pickTime : null;
1588
- return /* @__PURE__ */ jsxs17("div", { className: "join-book", children: [
1589
- /* @__PURE__ */ jsx18("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
1590
- /* @__PURE__ */ jsx18("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
1591
- /* @__PURE__ */ jsxs17("div", { className: "slot-confirm", children: [
1592
- /* @__PURE__ */ jsx18("button", { className: "submit-btn", type: "button", disabled: busy || !selected, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
1593
- hint ? /* @__PURE__ */ jsx18("p", { className: "slot-hint", role: "status", children: hint }) : null,
1594
- msg ? /* @__PURE__ */ jsx18("p", { className: "step2-note", role: "alert", children: msg }) : null
2195
+ return /* @__PURE__ */ jsxs21("div", { className: "join-book", children: [
2196
+ /* @__PURE__ */ jsx23("h2", { children: copy.title ?? DEFAULT_JOIN_COPY.booking.title }),
2197
+ /* @__PURE__ */ jsx23("p", { children: copy.intro ?? DEFAULT_JOIN_COPY.booking.intro }),
2198
+ /* @__PURE__ */ jsxs21("div", { className: "slot-confirm", children: [
2199
+ /* @__PURE__ */ jsx23("button", { className: "submit-btn", type: "button", disabled: busy || !selected, onClick: () => void book(), children: busy ? copy.booking : copy.book }),
2200
+ hint ? /* @__PURE__ */ jsx23("p", { className: "slot-hint", role: "status", children: hint }) : null,
2201
+ msg ? /* @__PURE__ */ jsx23("p", { className: "step2-note", role: "alert", children: msg }) : null
1595
2202
  ] }),
1596
- /* @__PURE__ */ jsx18(
2203
+ /* @__PURE__ */ jsx23(
1597
2204
  SlotPicker,
1598
2205
  {
1599
2206
  slots: state.slots,
@@ -1611,21 +2218,21 @@ function JoinBooking(props) {
1611
2218
  }
1612
2219
 
1613
2220
  // src/ui/join-accepted.tsx
1614
- import { jsx as jsx19, jsxs as jsxs18 } from "preact/jsx-runtime";
2221
+ import { jsx as jsx24, jsxs as jsxs22 } from "preact/jsx-runtime";
1615
2222
  function JoinAccepted(props) {
1616
- return /* @__PURE__ */ jsxs18("div", { className: "join-done card", children: [
1617
- /* @__PURE__ */ jsx19("div", { className: "card-label", children: props.copy.accepted.label }),
1618
- /* @__PURE__ */ jsx19("p", { className: "meeting-note", children: props.copy.accepted.body }),
1619
- /* @__PURE__ */ jsx19("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
2223
+ return /* @__PURE__ */ jsxs22("div", { className: "join-done card", children: [
2224
+ /* @__PURE__ */ jsx24("div", { className: "card-label", children: props.copy.accepted.label }),
2225
+ /* @__PURE__ */ jsx24("p", { className: "meeting-note", children: props.copy.accepted.body }),
2226
+ /* @__PURE__ */ jsx24("a", { className: "apply-link", href: props.membersHref, children: props.copy.done.memberArea })
1620
2227
  ] });
1621
2228
  }
1622
2229
 
1623
2230
  // src/ui/gift-claim-card.tsx
1624
- import { useState as useState15 } from "preact/hooks";
1625
- import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs19 } from "preact/jsx-runtime";
2231
+ import { useState as useState17 } from "preact/hooks";
2232
+ import { Fragment as Fragment9, jsx as jsx25, jsxs as jsxs23 } from "preact/jsx-runtime";
1626
2233
  function GiftClaimCard(props) {
1627
- const [code, setCode] = useState15(props.initialCode ?? "");
1628
- const [error, setError] = useState15(false);
2234
+ const [code, setCode] = useState17(props.initialCode ?? "");
2235
+ const [error, setError] = useState17(false);
1629
2236
  const rotate = async () => {
1630
2237
  if (!props.claimId) return;
1631
2238
  setError(false);
@@ -1638,15 +2245,15 @@ function GiftClaimCard(props) {
1638
2245
  if (response.ok && body.code) setCode(body.code);
1639
2246
  else setError(true);
1640
2247
  };
1641
- return /* @__PURE__ */ jsxs19("div", { className: "join-done card", children: [
1642
- /* @__PURE__ */ jsx20("div", { className: "card-label", children: props.copy.label }),
1643
- /* @__PURE__ */ jsx20("p", { className: "meeting-note", children: props.copy.body }),
1644
- code ? /* @__PURE__ */ jsxs19(Fragment6, { children: [
1645
- /* @__PURE__ */ jsx20("output", { className: "gift-code", children: code }),
1646
- /* @__PURE__ */ jsx20("p", { children: props.copy.save })
2248
+ return /* @__PURE__ */ jsxs23("div", { className: "join-done card", children: [
2249
+ /* @__PURE__ */ jsx25("div", { className: "card-label", children: props.copy.label }),
2250
+ /* @__PURE__ */ jsx25("p", { className: "meeting-note", children: props.copy.body }),
2251
+ code ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
2252
+ /* @__PURE__ */ jsx25("output", { className: "gift-code", children: code }),
2253
+ /* @__PURE__ */ jsx25("p", { children: props.copy.save })
1647
2254
  ] }) : null,
1648
- !code && props.claimId ? /* @__PURE__ */ jsx20("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
1649
- error ? /* @__PURE__ */ jsx20("p", { role: "alert", children: props.copy.rotateFailed }) : null
2255
+ !code && props.claimId ? /* @__PURE__ */ jsx25("button", { type: "button", className: "btn secondary", onClick: () => void rotate(), children: props.copy.rotate }) : null,
2256
+ error ? /* @__PURE__ */ jsx25("p", { role: "alert", children: props.copy.rotateFailed }) : null
1650
2257
  ] });
1651
2258
  }
1652
2259
 
@@ -1654,11 +2261,11 @@ function GiftClaimCard(props) {
1654
2261
  import { useRef as useRef7 } from "preact/hooks";
1655
2262
 
1656
2263
  // src/ui/join-tiers.tsx
1657
- import { useState as useState16 } from "preact/hooks";
1658
- import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs20 } from "preact/jsx-runtime";
2264
+ import { useState as useState18 } from "preact/hooks";
2265
+ import { Fragment as Fragment10, jsx as jsx26, jsxs as jsxs24 } from "preact/jsx-runtime";
1659
2266
  var joinTierMoney = (cents, currency = "usd") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(cents / 100);
1660
2267
  function useTierSelection(tiers, initialTierId) {
1661
- const [selectedTierId, setSelectedTierId] = useState16(() => {
2268
+ const [selectedTierId, setSelectedTierId] = useState18(() => {
1662
2269
  const preset = tiers.find((tier) => tier.id === initialTierId);
1663
2270
  if (preset) return preset.id;
1664
2271
  return tiers.length === 1 ? tiers[0].id : null;
@@ -1673,10 +2280,10 @@ function useTierSelection(tiers, initialTierId) {
1673
2280
  };
1674
2281
  }
1675
2282
  function TierPlaceholder(context) {
1676
- return /* @__PURE__ */ jsxs20("fieldset", { "data-chapter-placeholder": "tiers", children: [
1677
- /* @__PURE__ */ jsx21("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
1678
- context.tiers.map((tier) => /* @__PURE__ */ jsxs20("label", { children: [
1679
- /* @__PURE__ */ jsx21(
2283
+ return /* @__PURE__ */ jsxs24("fieldset", { "data-chapter-placeholder": "tiers", children: [
2284
+ /* @__PURE__ */ jsx26("legend", { children: "Membership (placeholder \u2014 pass renderTiers to style this)" }),
2285
+ context.tiers.map((tier) => /* @__PURE__ */ jsxs24("label", { children: [
2286
+ /* @__PURE__ */ jsx26(
1680
2287
  "input",
1681
2288
  {
1682
2289
  type: "radio",
@@ -1687,13 +2294,13 @@ function TierPlaceholder(context) {
1687
2294
  }
1688
2295
  ),
1689
2296
  tier.name,
1690
- tier.founding ? /* @__PURE__ */ jsxs20(Fragment7, { children: [
2297
+ tier.founding ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
1691
2298
  " \u2014 ",
1692
2299
  joinTierMoney(tier.founding.dueTodayCents),
1693
2300
  " founding member rate (list ",
1694
2301
  joinTierMoney(tier.priceCents),
1695
2302
  ")"
1696
- ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs20(Fragment7, { children: [
2303
+ ] }) : tier.free ? " \u2014 free" : /* @__PURE__ */ jsxs24(Fragment10, { children: [
1697
2304
  " \u2014 ",
1698
2305
  joinTierMoney(tier.priceCents)
1699
2306
  ] })
@@ -1705,12 +2312,12 @@ function tierNeedsPayment(selected, paymentsReady) {
1705
2312
  }
1706
2313
 
1707
2314
  // src/ui/join-application-form.tsx
1708
- import { jsx as jsx22, jsxs as jsxs21 } from "preact/jsx-runtime";
2315
+ import { jsx as jsx27, jsxs as jsxs25 } from "preact/jsx-runtime";
1709
2316
  function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelection, giftOfferId, selectGift, submitting, error, submit }) {
1710
2317
  const form = useRef7(null);
1711
2318
  const ready = useFormReadiness(form);
1712
2319
  const disabled = submitting || props.submitDisabled === true || !ready || !validJoinRecipient(props.payment?.initialNamedSeat);
1713
- return /* @__PURE__ */ jsxs21("form", { ref: form, className: "join-form", onSubmit: (event) => {
2320
+ return /* @__PURE__ */ jsxs25("form", { ref: form, className: "join-form", onSubmit: (event) => {
1714
2321
  if (!isFormReady(event.currentTarget)) {
1715
2322
  event.preventDefault();
1716
2323
  event.currentTarget.reportValidity();
@@ -1718,15 +2325,15 @@ function JoinApplicationForm({ props, copy, invitation, requestedSeat, tierSelec
1718
2325
  }
1719
2326
  void submit(event);
1720
2327
  }, children: [
1721
- !requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs21("fieldset", { children: [
1722
- /* @__PURE__ */ jsx22("legend", { children: copy.gift.optionsLabel }),
1723
- /* @__PURE__ */ jsx22("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
1724
- /* @__PURE__ */ jsx22(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
2328
+ !requestedSeat && (props.config.giftOffers?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs25("fieldset", { children: [
2329
+ /* @__PURE__ */ jsx27("legend", { children: copy.gift.optionsLabel }),
2330
+ /* @__PURE__ */ jsx27("button", { type: "button", className: "btn secondary", "aria-pressed": !giftOfferId, onClick: () => selectGift(null), children: copy.gift.chooseSelf }),
2331
+ /* @__PURE__ */ jsx27(GiftOfferCards, { offers: props.config.giftOffers ?? [], mode: "select", selectedOfferId: giftOfferId, onSelect: selectGift })
1725
2332
  ] }) : null,
1726
2333
  !requestedSeat && (props.config.tiers?.length ?? 0) > 1 ? props.renderTiers?.(tierSelection) ?? TierPlaceholder(tierSelection) : null,
1727
2334
  typeof props.children === "function" ? props.children({ invitation }) : props.children,
1728
- error ? /* @__PURE__ */ jsx22("p", { className: "join-error", role: "alert", children: error }) : null,
1729
- props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx22(JoinSubmitButton, { disabled, children: submitting ? copy.form.submitting : copy.form.submit })
2335
+ error ? /* @__PURE__ */ jsx27("p", { className: "join-error", role: "alert", children: error }) : null,
2336
+ props.renderSubmit?.({ submitting, disabled }) ?? /* @__PURE__ */ jsx27(JoinSubmitButton, { disabled, children: submitting ? copy.form.submitting : copy.form.submit })
1730
2337
  ] });
1731
2338
  }
1732
2339
 
@@ -1751,8 +2358,8 @@ function joinStateFromApplicationResponse(data, fallbackNeedsPayment, submittedG
1751
2358
 
1752
2359
  // src/ui/gift-code-redeemer.tsx
1753
2360
  import { InlineActionField } from "@odla-ai/ui/components";
1754
- import { useState as useState17 } from "preact/hooks";
1755
- import { Fragment as Fragment8, jsx as jsx23, jsxs as jsxs22 } from "preact/jsx-runtime";
2361
+ import { useState as useState19 } from "preact/hooks";
2362
+ import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs26 } from "preact/jsx-runtime";
1756
2363
  var GIFT_CODE_REDEEMER_CSS = `
1757
2364
  .gift-code-redeemer{container-type:inline-size;display:grid;gap:var(--ui-space-1,.35rem);margin:0}
1758
2365
  .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}
@@ -1767,10 +2374,10 @@ var GIFT_CODE_REDEEMER_CSS = `
1767
2374
  @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%}}
1768
2375
  `;
1769
2376
  function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1770
- const [code, setCode] = useState17("");
1771
- const [loading, setLoading] = useState17(false);
1772
- const [message, setMessage] = useState17("");
1773
- const [messageTone, setMessageTone] = useState17("neutral");
2377
+ const [code, setCode] = useState19("");
2378
+ const [loading, setLoading] = useState19(false);
2379
+ const [message, setMessage] = useState19("");
2380
+ const [messageTone, setMessageTone] = useState19("neutral");
1774
2381
  const normalizedCode = code.trim();
1775
2382
  const redeem = async () => {
1776
2383
  if (!normalizedCode || loading) return;
@@ -1797,9 +2404,9 @@ function GiftCodeRedeemer({ api, applicationId, copy, id, onRedeemed }) {
1797
2404
  setLoading(false);
1798
2405
  }
1799
2406
  };
1800
- return /* @__PURE__ */ jsxs22(Fragment8, { children: [
1801
- /* @__PURE__ */ jsx23("style", { children: GIFT_CODE_REDEEMER_CSS }),
1802
- /* @__PURE__ */ jsx23(
2407
+ return /* @__PURE__ */ jsxs26(Fragment11, { children: [
2408
+ /* @__PURE__ */ jsx28("style", { children: GIFT_CODE_REDEEMER_CSS }),
2409
+ /* @__PURE__ */ jsx28(
1803
2410
  InlineActionField,
1804
2411
  {
1805
2412
  id,
@@ -1855,12 +2462,12 @@ async function loadJoinResume(applicationId, fetcher = fetch) {
1855
2462
  }
1856
2463
 
1857
2464
  // src/ui/join-gift-claim.tsx
1858
- import { jsx as jsx24, jsxs as jsxs23 } from "preact/jsx-runtime";
2465
+ import { jsx as jsx29, jsxs as jsxs27 } from "preact/jsx-runtime";
1859
2466
  function JoinGiftClaim(props) {
1860
- return /* @__PURE__ */ jsxs23("section", { className: "join-gift-claim card", children: [
1861
- /* @__PURE__ */ jsx24("div", { className: "card-label", children: props.copy.claimTitle }),
1862
- /* @__PURE__ */ jsx24("p", { children: props.copy.claimBody }),
1863
- /* @__PURE__ */ jsx24(
2467
+ return /* @__PURE__ */ jsxs27("section", { className: "join-gift-claim card", children: [
2468
+ /* @__PURE__ */ jsx29("div", { className: "card-label", children: props.copy.claimTitle }),
2469
+ /* @__PURE__ */ jsx29("p", { children: props.copy.claimBody }),
2470
+ /* @__PURE__ */ jsx29(
1864
2471
  GiftCodeRedeemer,
1865
2472
  {
1866
2473
  api: props.api,
@@ -1884,21 +2491,21 @@ function JoinGiftClaim(props) {
1884
2491
  }
1885
2492
 
1886
2493
  // src/ui/join-named-seat.tsx
1887
- import { useState as useState18 } from "preact/hooks";
1888
- import { jsx as jsx25, jsxs as jsxs24 } from "preact/jsx-runtime";
2494
+ import { useState as useState20 } from "preact/hooks";
2495
+ import { jsx as jsx30, jsxs as jsxs28 } from "preact/jsx-runtime";
1889
2496
  function JoinNamedSeat(props) {
1890
2497
  const seatId = props.seatId ?? "";
1891
2498
  const inherited = useChapterCopy(), copy = props.copy ?? inherited.join.namedSeat;
1892
- const [accepted, setAccepted] = useState18(false), [busy, setBusy] = useState18(false), [error, setError] = useState18("");
1893
- return /* @__PURE__ */ jsxs24("section", { className: "join-named-seat card", children: [
1894
- /* @__PURE__ */ jsx25("h2", { children: copy.title }),
1895
- /* @__PURE__ */ jsx25("p", { children: copy.body }),
1896
- /* @__PURE__ */ jsxs24("label", { className: "journey-consent", children: [
1897
- /* @__PURE__ */ jsx25("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
1898
- /* @__PURE__ */ jsx25("span", { children: copy.consent })
2499
+ const [accepted, setAccepted] = useState20(false), [busy, setBusy] = useState20(false), [error, setError] = useState20("");
2500
+ return /* @__PURE__ */ jsxs28("section", { className: "join-named-seat card", children: [
2501
+ /* @__PURE__ */ jsx30("h2", { children: copy.title }),
2502
+ /* @__PURE__ */ jsx30("p", { children: copy.body }),
2503
+ /* @__PURE__ */ jsxs28("label", { className: "journey-consent", children: [
2504
+ /* @__PURE__ */ jsx30("input", { type: "checkbox", checked: accepted, disabled: busy, onChange: (event) => setAccepted(event.currentTarget.checked) }),
2505
+ /* @__PURE__ */ jsx30("span", { children: copy.consent })
1899
2506
  ] }),
1900
- error ? /* @__PURE__ */ jsx25("p", { role: "alert", children: error }) : null,
1901
- /* @__PURE__ */ jsx25("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
2507
+ error ? /* @__PURE__ */ jsx30("p", { role: "alert", children: error }) : null,
2508
+ /* @__PURE__ */ jsx30("button", { type: "button", className: "btn btn-primary", disabled: busy || !accepted || !seatId.trim(), onClick: async () => {
1902
2509
  setBusy(true);
1903
2510
  setError("");
1904
2511
  try {
@@ -1918,13 +2525,13 @@ function JoinNamedSeat(props) {
1918
2525
  }
1919
2526
 
1920
2527
  // src/ui/join-invitation.tsx
1921
- import { useEffect as useEffect8, useState as useState19 } from "preact/hooks";
1922
- import { jsx as jsx26, jsxs as jsxs25 } from "preact/jsx-runtime";
2528
+ import { useEffect as useEffect10, useState as useState21 } from "preact/hooks";
2529
+ import { jsx as jsx31, jsxs as jsxs29 } from "preact/jsx-runtime";
1923
2530
  function useJoinInvitation(seatId, api, fallback) {
1924
- const [invitation, setInvitation] = useState19(null);
1925
- const [error, setError] = useState19("");
1926
- const [revision, setRevision] = useState19(0);
1927
- useEffect8(() => {
2531
+ const [invitation, setInvitation] = useState21(null);
2532
+ const [error, setError] = useState21("");
2533
+ const [revision, setRevision] = useState21(0);
2534
+ useEffect10(() => {
1928
2535
  let live = true;
1929
2536
  setInvitation(null);
1930
2537
  setError("");
@@ -1946,9 +2553,9 @@ function useJoinInvitation(seatId, api, fallback) {
1946
2553
  return { invitation: invitation?.seatId === seatId ? invitation : null, error, retry: () => setRevision((value) => value + 1) };
1947
2554
  }
1948
2555
  function JoinInvitationNotice(props) {
1949
- return /* @__PURE__ */ jsxs25("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
1950
- /* @__PURE__ */ jsx26("p", { children: /* @__PURE__ */ jsx26("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
1951
- /* @__PURE__ */ jsx26("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
2556
+ return /* @__PURE__ */ jsxs29("aside", { className: "journey-invitation", "aria-label": props.copy.title, children: [
2557
+ /* @__PURE__ */ jsx31("p", { children: /* @__PURE__ */ jsx31("strong", { children: formatChapterCopy(props.copy.from, { purchaserName: props.invitation.purchaserName }) }) }),
2558
+ /* @__PURE__ */ jsx31("p", { children: formatChapterCopy(props.copy.prepaid, { tierName: props.tierName }) })
1952
2559
  ] });
1953
2560
  }
1954
2561
 
@@ -1963,9 +2570,9 @@ function joinSimulationPayment(simulation, priceCents) {
1963
2570
  }
1964
2571
 
1965
2572
  // src/ui/join-pending.ts
1966
- import { useEffect as useEffect9 } from "preact/hooks";
2573
+ import { useEffect as useEffect11 } from "preact/hooks";
1967
2574
  function useJoinPending(state, loadResume, setState) {
1968
- useEffect9(() => {
2575
+ useEffect11(() => {
1969
2576
  if (state.step !== "paymentPending") return;
1970
2577
  let live = true;
1971
2578
  let timer;
@@ -1988,16 +2595,16 @@ function useJoinPending(state, loadResume, setState) {
1988
2595
  }
1989
2596
 
1990
2597
  // src/ui/payment-receipt.tsx
1991
- import { useEffect as useEffect10, useState as useState20 } from "preact/hooks";
1992
- import { Fragment as Fragment9, jsx as jsx27, jsxs as jsxs26 } from "preact/jsx-runtime";
2598
+ import { useEffect as useEffect12, useState as useState22 } from "preact/hooks";
2599
+ import { Fragment as Fragment12, jsx as jsx32, jsxs as jsxs30 } from "preact/jsx-runtime";
1993
2600
  function PaymentReceiptCard({ applicationId }) {
1994
- const [receipt, setReceipt] = useState20(null);
1995
- const [error, setError] = useState20("");
1996
- const [revision, setRevision] = useState20(0);
1997
- const [emailState, setEmailState] = useState20("idle");
1998
- const [previewEmail, setPreviewEmail] = useState20(false);
2601
+ const [receipt, setReceipt] = useState22(null);
2602
+ const [error, setError] = useState22("");
2603
+ const [revision, setRevision] = useState22(0);
2604
+ const [emailState, setEmailState] = useState22("idle");
2605
+ const [previewEmail, setPreviewEmail] = useState22(false);
1999
2606
  const endpoint = `/api/payments/receipt?application=${encodeURIComponent(applicationId)}`;
2000
- useEffect10(() => {
2607
+ useEffect12(() => {
2001
2608
  let live = true, timer;
2002
2609
  setReceipt(null);
2003
2610
  setError("");
@@ -2023,9 +2630,9 @@ function PaymentReceiptCard({ applicationId }) {
2023
2630
  if (timer) clearTimeout(timer);
2024
2631
  };
2025
2632
  }, [endpoint, revision]);
2026
- if (!receipt) return error ? /* @__PURE__ */ jsxs26("section", { "aria-label": "Payment receipt", children: [
2027
- /* @__PURE__ */ jsx27("p", { role: "status", children: error }),
2028
- /* @__PURE__ */ jsx27("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
2633
+ if (!receipt) return error ? /* @__PURE__ */ jsxs30("section", { "aria-label": "Payment receipt", children: [
2634
+ /* @__PURE__ */ jsx32("p", { role: "status", children: error }),
2635
+ /* @__PURE__ */ jsx32("button", { type: "button", onClick: () => setRevision((value) => value + 1), children: "Reload receipt" })
2029
2636
  ] }) : null;
2030
2637
  const money = (cents) => new Intl.NumberFormat("en-US", { style: "currency", currency: receipt.currency }).format(cents / 100);
2031
2638
  const email = async () => {
@@ -2042,38 +2649,38 @@ function PaymentReceiptCard({ applicationId }) {
2042
2649
  setError("We could not confirm email delivery. You can print or save your receipt.");
2043
2650
  }
2044
2651
  };
2045
- return /* @__PURE__ */ jsxs26("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
2046
- /* @__PURE__ */ jsx27("h2", { children: "Payment received" }),
2047
- /* @__PURE__ */ jsx27("p", { children: receipt.tierName }),
2048
- /* @__PURE__ */ jsxs26("dl", { className: "journey-summary", children: [
2049
- /* @__PURE__ */ jsx27("dt", { children: "Membership" }),
2050
- /* @__PURE__ */ jsx27("dd", { children: money(receipt.membershipCents) }),
2051
- receipt.namedSeat ? /* @__PURE__ */ jsxs26(Fragment9, { children: [
2052
- /* @__PURE__ */ jsxs26("dt", { children: [
2652
+ return /* @__PURE__ */ jsxs30("section", { className: "payment-receipt card", "aria-label": "Payment receipt", children: [
2653
+ /* @__PURE__ */ jsx32("h2", { children: "Payment received" }),
2654
+ /* @__PURE__ */ jsx32("p", { children: receipt.tierName }),
2655
+ /* @__PURE__ */ jsxs30("dl", { className: "journey-summary", children: [
2656
+ /* @__PURE__ */ jsx32("dt", { children: "Membership" }),
2657
+ /* @__PURE__ */ jsx32("dd", { children: money(receipt.membershipCents) }),
2658
+ receipt.namedSeat ? /* @__PURE__ */ jsxs30(Fragment12, { children: [
2659
+ /* @__PURE__ */ jsxs30("dt", { children: [
2053
2660
  "Additional member \u2014 ",
2054
2661
  receipt.namedSeat.recipientName
2055
2662
  ] }),
2056
- /* @__PURE__ */ jsxs26("dd", { children: [
2663
+ /* @__PURE__ */ jsxs30("dd", { children: [
2057
2664
  receipt.namedSeat.amountCents === 0 ? "Included \u2014 " : "",
2058
2665
  money(receipt.namedSeat.amountCents)
2059
2666
  ] })
2060
2667
  ] }) : null,
2061
- /* @__PURE__ */ jsx27("dt", { children: "Total paid" }),
2062
- /* @__PURE__ */ jsx27("dd", { children: money(receipt.totalCents) })
2668
+ /* @__PURE__ */ jsx32("dt", { children: "Total paid" }),
2669
+ /* @__PURE__ */ jsx32("dd", { children: money(receipt.totalCents) })
2063
2670
  ] }),
2064
- /* @__PURE__ */ jsxs26("div", { className: "journey-actions", children: [
2065
- /* @__PURE__ */ jsx27("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
2066
- /* @__PURE__ */ jsx27("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
2671
+ /* @__PURE__ */ jsxs30("div", { className: "journey-actions", children: [
2672
+ /* @__PURE__ */ jsx32("a", { className: "apply-link journey-secondary", href: `${endpoint}&format=html`, target: "_blank", rel: "noopener noreferrer", children: "Print / save receipt" }),
2673
+ /* @__PURE__ */ jsx32("button", { type: "button", disabled: emailState !== "idle", onClick: () => void email(), children: emailState === "sending" ? "Sending\u2026" : emailState === "sent" ? "Receipt emailed" : "Email me my receipt" })
2067
2674
  ] }),
2068
- emailState === "sent" ? /* @__PURE__ */ jsx27("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
2069
- error ? /* @__PURE__ */ jsx27("p", { role: "alert", children: error }) : null
2675
+ emailState === "sent" ? /* @__PURE__ */ jsx32("p", { role: "status", children: previewEmail ? "Test receipt sent to the configured test inbox." : "Sent to the email used for your payment." }) : null,
2676
+ error ? /* @__PURE__ */ jsx32("p", { role: "alert", children: error }) : null
2070
2677
  ] });
2071
2678
  }
2072
2679
 
2073
2680
  // src/ui/join.tsx
2074
- import { Fragment as Fragment10, jsx as jsx28, jsxs as jsxs27 } from "preact/jsx-runtime";
2681
+ import { Fragment as Fragment13, jsx as jsx33, jsxs as jsxs31 } from "preact/jsx-runtime";
2075
2682
  function JoinIsland(props) {
2076
- return /* @__PURE__ */ jsx28(JourneyFrame, { children: /* @__PURE__ */ jsx28(JoinFlow, { ...props }) });
2683
+ return /* @__PURE__ */ jsx33(JourneyFrame, { children: /* @__PURE__ */ jsx33(JoinFlow, { ...props }) });
2077
2684
  }
2078
2685
  function JoinFlow(props) {
2079
2686
  const inheritedCopy = useChapterCopy();
@@ -2094,16 +2701,16 @@ function JoinFlow(props) {
2094
2701
  const invitation = invitationState.invitation;
2095
2702
  const selectedTierId = invitation?.skuId ?? tierSelection.selectedTierId;
2096
2703
  const selectedTier = tiers.find((tier) => tier.id === selectedTierId) ?? tierSelection.selected;
2097
- const [state, setState] = useState21(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
2098
- const [error, setError] = useState21(null);
2099
- const [submitting, setSubmitting] = useState21(false);
2100
- const [editingNamedSeat, setEditingNamedSeat] = useState21(false);
2101
- const [giftOfferId, setGiftOfferId] = useState21(props.initialGiftOfferId ?? null);
2704
+ const [state, setState] = useState23(requestedSeat ? { step: "form" } : props.initialState ?? { step: "form" });
2705
+ const [error, setError] = useState23(null);
2706
+ const [submitting, setSubmitting] = useState23(false);
2707
+ const [editingNamedSeat, setEditingNamedSeat] = useState23(false);
2708
+ const [giftOfferId, setGiftOfferId] = useState23(props.initialGiftOfferId ?? null);
2102
2709
  const simulatedPayment = joinSimulationPayment(props.simulation, selectedTier?.priceCents ?? 0);
2103
2710
  const simulatedBooking = props.simulation ? props.simulation.booking ?? { slots: [], timezone: "UTC" } : void 0;
2104
2711
  const submissionId = useRef8(null);
2105
2712
  const slotsPreload = useJoinSlotsPreload(!props.simulation && ["payment", "paymentPending"].includes(state.step));
2106
- useEffect11(() => {
2713
+ useEffect13(() => {
2107
2714
  if (props.simulation) return;
2108
2715
  const resolver = requestedSeat ? () => invitation?.applicationId ? loadJoinResume(invitation.applicationId) : Promise.resolve(null) : props.loadResume ?? (() => {
2109
2716
  if (typeof window === "undefined") return Promise.resolve(null);
@@ -2176,13 +2783,13 @@ function JoinFlow(props) {
2176
2783
  setSubmitting(false);
2177
2784
  }
2178
2785
  };
2179
- if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs27("section", { className: "card", "aria-live": "polite", children: [
2180
- /* @__PURE__ */ jsx28("h2", { children: seatCopy.title }),
2181
- /* @__PURE__ */ jsx28("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
2182
- invitationState.error ? /* @__PURE__ */ jsx28("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
2786
+ if (requestedSeat && !invitation) return /* @__PURE__ */ jsxs31("section", { className: "card", "aria-live": "polite", children: [
2787
+ /* @__PURE__ */ jsx33("h2", { children: seatCopy.title }),
2788
+ /* @__PURE__ */ jsx33("p", { role: invitationState.error ? "alert" : "status", children: invitationState.error || seatCopy.loading }),
2789
+ invitationState.error ? /* @__PURE__ */ jsx33("button", { type: "button", onClick: invitationState.retry, children: seatCopy.retry }) : null
2183
2790
  ] });
2184
- const header = /* @__PURE__ */ jsxs27(Fragment10, { children: [
2185
- invitation ? /* @__PURE__ */ jsx28(
2791
+ const header = /* @__PURE__ */ jsxs31(Fragment13, { children: [
2792
+ invitation ? /* @__PURE__ */ jsx33(
2186
2793
  JoinInvitationNotice,
2187
2794
  {
2188
2795
  invitation,
@@ -2197,49 +2804,49 @@ function JoinFlow(props) {
2197
2804
  ..."applicationId" in state ? { applicationId: state.applicationId } : {}
2198
2805
  })
2199
2806
  ] });
2200
- const receipt = !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx28(PaymentReceiptCard, { applicationId: state.applicationId }) : null;
2807
+ const receipt = !props.simulation && !requestedSeat && ["paymentPending", "booking", "accepted", "done"].includes(state.step) && "applicationId" in state ? /* @__PURE__ */ jsx33(PaymentReceiptCard, { applicationId: state.applicationId }) : null;
2201
2808
  if (state.step === "closed") {
2202
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2809
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2203
2810
  header,
2204
- /* @__PURE__ */ jsxs27("section", { className: "card", "aria-label": "Application closed", children: [
2205
- /* @__PURE__ */ jsx28("h2", { children: "This application is closed" }),
2206
- /* @__PURE__ */ jsx28("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
2207
- /* @__PURE__ */ jsx28("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
2811
+ /* @__PURE__ */ jsxs31("section", { className: "card", "aria-label": "Application closed", children: [
2812
+ /* @__PURE__ */ jsx33("h2", { children: "This application is closed" }),
2813
+ /* @__PURE__ */ jsx33("p", { children: "This link cannot resume payment or booking. Sign in to view your application status, or contact the chapter if you need help." }),
2814
+ /* @__PURE__ */ jsx33("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
2208
2815
  ] })
2209
2816
  ] });
2210
2817
  }
2211
2818
  if (state.step === "done") {
2212
- const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs27("div", { className: "join-done card", children: [
2213
- /* @__PURE__ */ jsx28("div", { className: "card-label", children: copy.done.label }),
2214
- /* @__PURE__ */ jsx28("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
2215
- /* @__PURE__ */ jsx28("p", { className: "meeting-note", children: copy.done.calendarInvite }),
2216
- /* @__PURE__ */ jsx28("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
2819
+ const body = renderDone?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsxs31("div", { className: "join-done card", children: [
2820
+ /* @__PURE__ */ jsx33("div", { className: "card-label", children: copy.done.label }),
2821
+ /* @__PURE__ */ jsx33("p", { className: "meeting-date", children: fullLabel(state.booked.startAt, state.booked.timezone) }),
2822
+ /* @__PURE__ */ jsx33("p", { className: "meeting-note", children: copy.done.calendarInvite }),
2823
+ /* @__PURE__ */ jsx33("a", { className: "apply-link", href: membersHref, children: copy.done.memberArea })
2217
2824
  ] });
2218
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2825
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2219
2826
  header,
2220
2827
  body,
2221
2828
  receipt
2222
2829
  ] });
2223
2830
  }
2224
2831
  if (state.step === "accepted") {
2225
- const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx28(JoinAccepted, { copy, membersHref });
2226
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2832
+ const body = renderAccepted?.({ ...state, membersHref }) ?? /* @__PURE__ */ jsx33(JoinAccepted, { copy, membersHref });
2833
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2227
2834
  header,
2228
2835
  body,
2229
2836
  receipt
2230
2837
  ] });
2231
2838
  }
2232
2839
  if (state.step === "gift") {
2233
- const body = renderGift?.(state) ?? /* @__PURE__ */ jsx28(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
2234
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2840
+ const body = renderGift?.(state) ?? /* @__PURE__ */ jsx33(GiftClaimCard, { applicationId: state.applicationId, claimId: state.claimId, initialCode: state.code, copy: copy.gift });
2841
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2235
2842
  header,
2236
2843
  body
2237
2844
  ] });
2238
2845
  }
2239
2846
  if (state.step === "booking") {
2240
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2847
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2241
2848
  header,
2242
- /* @__PURE__ */ jsx28(
2849
+ /* @__PURE__ */ jsx33(
2243
2850
  JoinBooking,
2244
2851
  {
2245
2852
  applicationId: state.applicationId,
@@ -2256,9 +2863,9 @@ function JoinFlow(props) {
2256
2863
  }
2257
2864
  if (state.step === "payment") {
2258
2865
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation && !state.giftPurchase) {
2259
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2866
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2260
2867
  header,
2261
- /* @__PURE__ */ jsx28(
2868
+ /* @__PURE__ */ jsx33(
2262
2869
  JoinNamedSeat,
2263
2870
  {
2264
2871
  api: props.namedSeatClaimApi,
@@ -2271,9 +2878,9 @@ function JoinFlow(props) {
2271
2878
  ] });
2272
2879
  }
2273
2880
  const Payment = state.giftPurchase || props.simulation ? PaymentStep : MembershipPaymentStep;
2274
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2881
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2275
2882
  header,
2276
- props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx28(
2883
+ props.giftClaimApi && !state.giftPurchase ? /* @__PURE__ */ jsx33(
2277
2884
  JoinGiftClaim,
2278
2885
  {
2279
2886
  api: props.giftClaimApi,
@@ -2284,7 +2891,7 @@ function JoinFlow(props) {
2284
2891
  onError: () => setError(copy.form.unexpectedFailure)
2285
2892
  }
2286
2893
  ) : null,
2287
- /* @__PURE__ */ jsx28(
2894
+ /* @__PURE__ */ jsx33(
2288
2895
  Payment,
2289
2896
  {
2290
2897
  applicationId: state.applicationId,
@@ -2312,9 +2919,9 @@ function JoinFlow(props) {
2312
2919
  }
2313
2920
  if (state.step === "paymentPending") {
2314
2921
  if (props.namedSeatClaimApi && props.initialNamedSeatId && !props.simulation) {
2315
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2922
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2316
2923
  header,
2317
- /* @__PURE__ */ jsx28(
2924
+ /* @__PURE__ */ jsx33(
2318
2925
  JoinNamedSeat,
2319
2926
  {
2320
2927
  api: props.namedSeatClaimApi,
@@ -2326,15 +2933,15 @@ function JoinFlow(props) {
2326
2933
  )
2327
2934
  ] });
2328
2935
  }
2329
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2936
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2330
2937
  header,
2331
- /* @__PURE__ */ jsx28("p", { className: "pay-status", role: "status", children: copy.payment.pending }),
2938
+ /* @__PURE__ */ jsx33("p", { className: "pay-status", role: "status", children: copy.payment.pending }),
2332
2939
  receipt
2333
2940
  ] });
2334
2941
  }
2335
- return /* @__PURE__ */ jsxs27(Fragment10, { children: [
2942
+ return /* @__PURE__ */ jsxs31(Fragment13, { children: [
2336
2943
  header,
2337
- /* @__PURE__ */ jsx28(
2944
+ /* @__PURE__ */ jsx33(
2338
2945
  JoinApplicationForm,
2339
2946
  {
2340
2947
  props,
@@ -2353,7 +2960,7 @@ function JoinFlow(props) {
2353
2960
  }
2354
2961
 
2355
2962
  // src/ui/membership-cards.tsx
2356
- import { Markdown as Markdown2 } from "@odla-ai/ui/components";
2963
+ import { Markdown as Markdown3 } from "@odla-ai/ui/components";
2357
2964
 
2358
2965
  // src/membership-page.ts
2359
2966
  var MEMBERSHIP_PAGE_RENDERER = "membership-cards-v1";
@@ -2524,7 +3131,7 @@ function membershipPageDocument(input, options = {}) {
2524
3131
  }
2525
3132
 
2526
3133
  // src/ui/membership-cards.tsx
2527
- import { jsx as jsx29, jsxs as jsxs28 } from "preact/jsx-runtime";
3134
+ import { jsx as jsx34, jsxs as jsxs32 } from "preact/jsx-runtime";
2528
3135
  var MEMBERSHIP_CARD_TOKEN_DEFAULTS = Object.freeze({
2529
3136
  "--ui-membership-grid-gap": "1.4rem",
2530
3137
  "--ui-membership-card-padding": "2rem 1.7rem 1.8rem",
@@ -2593,67 +3200,67 @@ function membershipApplicationHref(applicationPath, tierId) {
2593
3200
  }
2594
3201
  function TierAction(props) {
2595
3202
  if (props.mode === "select") {
2596
- return /* @__PURE__ */ jsxs28("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
3203
+ return /* @__PURE__ */ jsxs32("button", { type: "button", className: "chapter-membership-action", "aria-current": props.selected ? "true" : void 0, onClick: () => props.onSelectTier?.(props.tierId), children: [
2597
3204
  props.label,
2598
- /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", children: "\u2192" })
3205
+ /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", children: "\u2192" })
2599
3206
  ] });
2600
3207
  }
2601
3208
  if (props.mode === "preview") {
2602
- return /* @__PURE__ */ jsxs28("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
3209
+ return /* @__PURE__ */ jsxs32("span", { className: "chapter-membership-action", "aria-disabled": "true", children: [
2603
3210
  props.label,
2604
- /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", children: "\u2192" })
3211
+ /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", children: "\u2192" })
2605
3212
  ] });
2606
3213
  }
2607
- return /* @__PURE__ */ jsxs28("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
3214
+ return /* @__PURE__ */ jsxs32("a", { className: "chapter-membership-action", href: membershipApplicationHref(props.applicationPath, props.tierId), children: [
2608
3215
  props.label,
2609
- /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", children: "\u2192" })
3216
+ /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", children: "\u2192" })
2610
3217
  ] });
2611
3218
  }
2612
3219
  function TierCard(props) {
2613
3220
  const { tier, presentation } = props;
2614
3221
  const summary = presentation.summaryMarkdown ?? tier.blurb;
2615
3222
  const action = presentation.ctaLabel ?? (tier.free ? "Join for free" : `Choose ${tier.name}`);
2616
- return /* @__PURE__ */ jsxs28("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
2617
- presentation.badge ? /* @__PURE__ */ jsx29("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
2618
- /* @__PURE__ */ jsx29("h3", { className: "chapter-membership-name", children: tier.name }),
2619
- /* @__PURE__ */ jsxs28("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
2620
- presentation.capacity ? /* @__PURE__ */ jsxs28("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
2621
- /* @__PURE__ */ jsx29("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
2622
- /* @__PURE__ */ jsx29("small", { children: presentation.capacity.label ?? "available" })
3223
+ return /* @__PURE__ */ jsxs32("article", { className: "chapter-membership-card", "data-tier-id": tier.id, "data-variant": presentation.variant ?? "standard", children: [
3224
+ presentation.badge ? /* @__PURE__ */ jsx34("div", { className: "chapter-membership-badge", children: presentation.badge }) : null,
3225
+ /* @__PURE__ */ jsx34("h3", { className: "chapter-membership-name", children: tier.name }),
3226
+ /* @__PURE__ */ jsxs32("div", { className: "chapter-membership-offer", "data-with-capacity": presentation.capacity ? "true" : void 0, children: [
3227
+ presentation.capacity ? /* @__PURE__ */ jsxs32("div", { className: "chapter-membership-capacity", "aria-label": `${presentation.capacity.total} ${presentation.capacity.label ?? "available"}`, children: [
3228
+ /* @__PURE__ */ jsx34("strong", { children: presentation.capacity.total.toLocaleString("en-US") }),
3229
+ /* @__PURE__ */ jsx34("small", { children: presentation.capacity.label ?? "available" })
2623
3230
  ] }) : null,
2624
- /* @__PURE__ */ jsxs28("div", { className: "chapter-membership-price-stack", children: [
2625
- presentation.priceEyebrow ? /* @__PURE__ */ jsx29("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx29("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
2626
- /* @__PURE__ */ jsxs28("div", { className: "chapter-membership-price-row", children: [
2627
- tier.founding ? /* @__PURE__ */ jsx29("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx29("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
2628
- /* @__PURE__ */ jsx29("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
2629
- !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx29("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
3231
+ /* @__PURE__ */ jsxs32("div", { className: "chapter-membership-price-stack", children: [
3232
+ presentation.priceEyebrow ? /* @__PURE__ */ jsx34("p", { className: "chapter-membership-price-eyebrow", children: presentation.priceEyebrow }) : tier.founding ? /* @__PURE__ */ jsx34("p", { className: "chapter-membership-price-eyebrow", children: "Founding member rate" }) : null,
3233
+ /* @__PURE__ */ jsxs32("div", { className: "chapter-membership-price-row", children: [
3234
+ tier.founding ? /* @__PURE__ */ jsx34("span", { className: "chapter-membership-compare", children: fmtMoney(tier.priceCents) }) : presentation.compareAtPriceCents !== void 0 ? /* @__PURE__ */ jsx34("span", { className: "chapter-membership-compare", children: fmtMoney(presentation.compareAtPriceCents) }) : null,
3235
+ /* @__PURE__ */ jsx34("span", { className: "chapter-membership-price", children: tier.free ? "Free" : fmtMoney(tier.founding ? tier.founding.dueTodayCents : tier.priceCents) }),
3236
+ !tier.free && presentation.billingLabel ? /* @__PURE__ */ jsx34("span", { className: "chapter-membership-billing", children: presentation.billingLabel }) : null
2630
3237
  ] })
2631
3238
  ] })
2632
3239
  ] }),
2633
- presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx29(Markdown2, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
2634
- summary ? /* @__PURE__ */ jsx29(Markdown2, { className: "chapter-membership-summary", source: summary }) : null,
2635
- presentation.benefits?.length ? /* @__PURE__ */ jsx29("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs28("li", { children: [
2636
- /* @__PURE__ */ jsx29("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
2637
- /* @__PURE__ */ jsx29(Markdown2, { className: "chapter-membership-benefit", source: benefit })
3240
+ presentation.priceNoteMarkdown ? /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-price-note", source: presentation.priceNoteMarkdown }) : null,
3241
+ summary ? /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-summary", source: summary }) : null,
3242
+ presentation.benefits?.length ? /* @__PURE__ */ jsx34("ul", { className: "chapter-membership-benefits", children: presentation.benefits.map((benefit, index) => /* @__PURE__ */ jsxs32("li", { children: [
3243
+ /* @__PURE__ */ jsx34("span", { className: "chapter-membership-check", "aria-hidden": "true", children: "\u2713" }),
3244
+ /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-benefit", source: benefit })
2638
3245
  ] }, `${tier.id}-benefit-${index}`)) }) : null,
2639
- presentation.callout ? /* @__PURE__ */ jsxs28("aside", { className: "chapter-membership-callout", children: [
2640
- presentation.callout.label ? /* @__PURE__ */ jsx29("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
2641
- /* @__PURE__ */ jsx29(Markdown2, { source: presentation.callout.bodyMarkdown })
3246
+ presentation.callout ? /* @__PURE__ */ jsxs32("aside", { className: "chapter-membership-callout", children: [
3247
+ presentation.callout.label ? /* @__PURE__ */ jsx34("p", { className: "chapter-membership-callout-label", children: presentation.callout.label }) : null,
3248
+ /* @__PURE__ */ jsx34(Markdown3, { source: presentation.callout.bodyMarkdown })
2642
3249
  ] }) : null,
2643
- /* @__PURE__ */ jsx29(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
3250
+ /* @__PURE__ */ jsx34(TierAction, { tierId: tier.id, label: action, mode: props.mode, selected: props.selected, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier })
2644
3251
  ] });
2645
3252
  }
2646
3253
  function MembershipCards(props) {
2647
3254
  const document2 = membershipPageDocument(props.document, { tiers: props.tiers });
2648
3255
  const byId = new Map(props.tiers.map((tier) => [tier.id, tier]));
2649
3256
  const mode = props.mode ?? "link";
2650
- return /* @__PURE__ */ jsxs28("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
2651
- /* @__PURE__ */ jsx29("style", { children: MEMBERSHIP_CARDS_CSS }),
2652
- /* @__PURE__ */ jsx29("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
3257
+ return /* @__PURE__ */ jsxs32("section", { className: ["chapter-membership", props.className].filter(Boolean).join(" "), "data-chapter-membership": MEMBERSHIP_PAGE_RENDERER, "aria-label": props.ariaLabel ?? "Membership options", children: [
3258
+ /* @__PURE__ */ jsx34("style", { children: MEMBERSHIP_CARDS_CSS }),
3259
+ /* @__PURE__ */ jsx34("div", { className: "chapter-membership-grid", style: { "--chapter-membership-columns": String(Math.min(document2.tiers.length, 3)) }, children: document2.tiers.map((presentation) => {
2653
3260
  const tier = byId.get(presentation.tierId);
2654
- return /* @__PURE__ */ jsx29(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
3261
+ return /* @__PURE__ */ jsx34(TierCard, { tier, presentation, mode, selected: props.selectedTierId === tier.id, applicationPath: props.applicationPath, onSelectTier: props.onSelectTier }, tier.id);
2655
3262
  }) }),
2656
- document2.footnoteMarkdown ? /* @__PURE__ */ jsx29(Markdown2, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
3263
+ document2.footnoteMarkdown ? /* @__PURE__ */ jsx34(Markdown3, { className: "chapter-membership-footnote", source: document2.footnoteMarkdown }) : null
2657
3264
  ] });
2658
3265
  }
2659
3266
 
@@ -2687,6 +3294,29 @@ export {
2687
3294
  NamedSeatRecipientLine,
2688
3295
  NamedSeatPurchase,
2689
3296
  MemberContentArea,
3297
+ placeholderBadge,
3298
+ MemberPlaceholderBody,
3299
+ PortalIcon,
3300
+ PROFILE_SEGMENT,
3301
+ routeFromLocation,
3302
+ hrefFor,
3303
+ sameRoute,
3304
+ PortalAvatar,
3305
+ navTag,
3306
+ PortalNav,
3307
+ LockedPill,
3308
+ UpgradeLink,
3309
+ LockedScreen,
3310
+ PlaceholderScreen,
3311
+ PortalPage,
3312
+ PortalTile,
3313
+ DefaultHome,
3314
+ memberMonth,
3315
+ startingPrompts,
3316
+ choosePrompt,
3317
+ MemberProfilePage,
3318
+ PACKAGED_PORTAL_FEATURES,
3319
+ MemberPortal,
2690
3320
  MembersArea,
2691
3321
  useTierSelection,
2692
3322
  TierPlaceholder,
@@ -2698,4 +3328,4 @@ export {
2698
3328
  membershipApplicationHref,
2699
3329
  MembershipCards
2700
3330
  };
2701
- //# sourceMappingURL=chunk-RTJKUOFE.js.map
3331
+ //# sourceMappingURL=chunk-ZIYK3OV2.js.map