@the-portland-company/shell 0.97.1 → 0.99.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.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-SHcw15A4.cjs';
2
- export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as Card, c as CommsNotification, d as CommsNotificationKind, F as FormColumn, H as HeaderTabBar, e as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, f as NotificationsAdapter, g as NotificationsFeed, R as RowMenu, h as RowMenuItem, i as RowMenuPlacement, T as TabGlyphComponent, j as aiCreditsWalletUrl, k as createCommsNotificationsAdapter, l as emptyNotificationsFeed, n as normalizeNotificationsFeed, r as resolveTabGlyph, m as rowMenuPosition } from './index-SHcw15A4.cjs';
1
+ import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-DhrhpBVm.cjs';
2
+ export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as CONTACTS_ORIGIN, c as Card, d as CommsNotification, e as CommsNotificationKind, f as ContactSlideIn, g as ContactSlideInProps, F as FormColumn, H as HeaderTabBar, h as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, i as NotificationsAdapter, j as NotificationsFeed, R as RowMenu, k as RowMenuItem, l as RowMenuPlacement, T as TabGlyphComponent, V as VRM_TIER_LABELS, m as VRM_VERIFIED_TOOLTIP, n as VrmVerifiedBadge, o as VrmVerifiedBadgeProps, p as VrmVerifiedTier, q as aiCreditsWalletUrl, r as contactEmbedUrl, s as contactPageUrl, t as createCommsNotificationsAdapter, u as emptyNotificationsFeed, v as normalizeNotificationsFeed, w as resolveTabGlyph, x as rowMenuPosition, y as useContactSlideIn } from './index-DhrhpBVm.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
5
  import { ReactNode, CSSProperties } from 'react';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-smsLP_tM.js';
2
- export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as Card, c as CommsNotification, d as CommsNotificationKind, F as FormColumn, H as HeaderTabBar, e as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, f as NotificationsAdapter, g as NotificationsFeed, R as RowMenu, h as RowMenuItem, i as RowMenuPlacement, T as TabGlyphComponent, j as aiCreditsWalletUrl, k as createCommsNotificationsAdapter, l as emptyNotificationsFeed, n as normalizeNotificationsFeed, r as resolveTabGlyph, m as rowMenuPosition } from './index-smsLP_tM.js';
1
+ import { P as PageHeaderProps, B as BreadcrumbBarProps, N as NavItem } from './index-Di9AyVsU.js';
2
+ export { A as AI_CREDITS_STATE_TITLES, a as AiCreditsState, b as AiCreditsStateKind, C as CONTACTS_ORIGIN, c as Card, d as CommsNotification, e as CommsNotificationKind, f as ContactSlideIn, g as ContactSlideInProps, F as FormColumn, H as HeaderTabBar, h as HeaderTabBarItem, K as KNOWN_TAB_GLYPHS, i as NotificationsAdapter, j as NotificationsFeed, R as RowMenu, k as RowMenuItem, l as RowMenuPlacement, T as TabGlyphComponent, V as VRM_TIER_LABELS, m as VRM_VERIFIED_TOOLTIP, n as VrmVerifiedBadge, o as VrmVerifiedBadgeProps, p as VrmVerifiedTier, q as aiCreditsWalletUrl, r as contactEmbedUrl, s as contactPageUrl, t as createCommsNotificationsAdapter, u as emptyNotificationsFeed, v as normalizeNotificationsFeed, w as resolveTabGlyph, x as rowMenuPosition, y as useContactSlideIn } from './index-Di9AyVsU.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
5
  import { ReactNode, CSSProperties } from 'react';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { PageHeaderView, warnDeprecated, BreadcrumbBarView } from './chunk-XPTC47TY.js';
2
- export { AI_CREDITS_STATE_TITLES, AiCreditsState, Card, FormColumn, HeaderTabBar, KNOWN_TAB_GLYPHS, RowMenu, RowMenuItem, SpeculationRulesScript, aiCreditsWalletUrl, buildNavSpeculationRules, buildSpeculationRules, collectSiblingAppUrls, createCommsNotificationsAdapter, emptyNotificationsFeed, normalizeNotificationsFeed, resolveTabGlyph, rowMenuPosition } from './chunk-XPTC47TY.js';
1
+ import { PageHeaderView, warnDeprecated, BreadcrumbBarView } from './chunk-PQQLCUNO.js';
2
+ export { AI_CREDITS_STATE_TITLES, AiCreditsState, CONTACTS_ORIGIN, Card, ContactSlideIn, FormColumn, HeaderTabBar, KNOWN_TAB_GLYPHS, RowMenu, RowMenuItem, SpeculationRulesScript, VRM_TIER_LABELS, VRM_VERIFIED_TOOLTIP, VrmVerifiedBadge, aiCreditsWalletUrl, buildNavSpeculationRules, buildSpeculationRules, collectSiblingAppUrls, contactEmbedUrl, contactPageUrl, createCommsNotificationsAdapter, emptyNotificationsFeed, normalizeNotificationsFeed, resolveTabGlyph, rowMenuPosition, useContactSlideIn } from './chunk-PQQLCUNO.js';
3
3
  import { readResolvedTheme } from './chunk-BHRVZPZ7.js';
4
- export { BRAND_APPLE_ICON_LINK_ID, BRAND_FAVICON_LINK_ID, BrandFavicon, applyBrandFavicon, watchBrandFavicon } from './chunk-BMR5WAWH.js';
4
+ export { BRAND_APPLE_ICON_LINK_ID, BRAND_FAVICON_LINK_ID, BrandFavicon, applyBrandFavicon, watchBrandFavicon } from './chunk-Q5DTPY5N.js';
5
5
  import { extendTheme, ChakraProvider, useColorMode } from '@chakra-ui/react';
6
6
  import { jsx, jsxs } from 'react/jsx-runtime';
7
7
  import clsx from 'clsx';
package/dist/native.cjs CHANGED
@@ -2430,6 +2430,30 @@ function readBrandAsset(kind) {
2430
2430
  return null;
2431
2431
  }
2432
2432
  }
2433
+ var RETRY_MS = [0, 250, 1e3, 3e3];
2434
+ function useBrandAsset(kind) {
2435
+ const [url, setUrl] = react.useState(null);
2436
+ react.useEffect(() => {
2437
+ let done = false;
2438
+ const read = () => {
2439
+ if (done) return;
2440
+ const next = readBrandAsset(kind);
2441
+ setUrl((prev) => prev === next ? prev : next);
2442
+ };
2443
+ const links = Array.from(
2444
+ document.querySelectorAll('link[rel="stylesheet"][href*="api/tokens"]')
2445
+ );
2446
+ links.forEach((l) => l.addEventListener("load", read));
2447
+ const timers = RETRY_MS.map((ms) => window.setTimeout(read, ms));
2448
+ read();
2449
+ return () => {
2450
+ done = true;
2451
+ links.forEach((l) => l.removeEventListener("load", read));
2452
+ timers.forEach((t) => window.clearTimeout(t));
2453
+ };
2454
+ }, [kind]);
2455
+ return url;
2456
+ }
2433
2457
 
2434
2458
  // src/lib/brandFavicon.ts
2435
2459
  var BRAND_FAVICON_LINK_ID = "politogy-brand-favicon";
@@ -2454,7 +2478,7 @@ function applyBrandFavicon() {
2454
2478
  if (apple) upsertLink(BRAND_APPLE_ICON_LINK_ID, "apple-touch-icon", apple);
2455
2479
  return true;
2456
2480
  }
2457
- var RETRY_MS = [0, 250, 1e3, 3e3];
2481
+ var RETRY_MS2 = [0, 250, 1e3, 3e3];
2458
2482
  function watchBrandFavicon() {
2459
2483
  if (typeof document === "undefined") return () => {
2460
2484
  };
@@ -2471,7 +2495,7 @@ function watchBrandFavicon() {
2471
2495
  });
2472
2496
  };
2473
2497
  listen();
2474
- const timers = RETRY_MS.map((ms) => window.setTimeout(apply, ms));
2498
+ const timers = RETRY_MS2.map((ms) => window.setTimeout(apply, ms));
2475
2499
  const observer = typeof MutationObserver === "undefined" ? null : new MutationObserver(() => {
2476
2500
  listen();
2477
2501
  apply();
@@ -3013,6 +3037,257 @@ function RowMenuItem({
3013
3037
  }
3014
3038
  );
3015
3039
  }
3040
+ var VRM_VERIFIED_TOOLTIP = "Politogy has confirmed this is a real, registered voter.";
3041
+ var VRM_TIER_LABELS = {
3042
+ verified: "VRM Verified",
3043
+ identified: "Identified",
3044
+ anonymous: "Anonymous",
3045
+ stale: "Stale",
3046
+ inactive: "Inactive"
3047
+ };
3048
+ var TIER_TOOLTIPS = {
3049
+ verified: VRM_VERIFIED_TOOLTIP,
3050
+ identified: "Identified: we know who this is, but Politogy has not verified them.",
3051
+ anonymous: "Anonymous: nothing identifying has been captured yet.",
3052
+ stale: "Stale: was VRM Verified, but the proof is more than 12 months old.",
3053
+ inactive: "Inactive: the voter file marks this registration inactive or canceled."
3054
+ };
3055
+ var DOT_FALLBACK = {
3056
+ verified: "#00A651",
3057
+ identified: "#a855f7",
3058
+ anonymous: "var(--color-graphite, #2b2b2b)",
3059
+ stale: "#eab308",
3060
+ inactive: "var(--muted, #8a8a8a)"
3061
+ };
3062
+ function VrmVerifiedBadge({ tier, variant = "pill", size, showLabel = true, className, style }) {
3063
+ const known = tier && tier in VRM_TIER_LABELS ? tier : null;
3064
+ if (variant === "icon") {
3065
+ return known === "verified" ? /* @__PURE__ */ jsxRuntime.jsx(VerifiedIcon, { size: size ?? 16, className, style }) : null;
3066
+ }
3067
+ const label = known ? VRM_TIER_LABELS[known] : "Not yet computed";
3068
+ const title = known ? TIER_TOOLTIPS[known] : "The VRM Verified tier has not been worked out yet.";
3069
+ const dotSize = size ?? 8;
3070
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3071
+ "span",
3072
+ {
3073
+ "data-vrm-tier": known ?? "none",
3074
+ title,
3075
+ "aria-label": showLabel ? void 0 : label,
3076
+ role: showLabel ? void 0 : "img",
3077
+ className,
3078
+ style: {
3079
+ display: "inline-flex",
3080
+ alignItems: "center",
3081
+ gap: 6,
3082
+ borderRadius: 9999,
3083
+ border: "1px solid var(--line, #e5e5e5)",
3084
+ padding: "2px 10px",
3085
+ fontSize: 12,
3086
+ fontWeight: 600,
3087
+ lineHeight: 1.4,
3088
+ whiteSpace: "nowrap",
3089
+ ...style
3090
+ },
3091
+ children: [
3092
+ /* @__PURE__ */ jsxRuntime.jsx(
3093
+ "span",
3094
+ {
3095
+ "aria-hidden": true,
3096
+ "data-vrm-dot": true,
3097
+ style: {
3098
+ display: "inline-block",
3099
+ width: dotSize,
3100
+ height: dotSize,
3101
+ borderRadius: 9999,
3102
+ flexShrink: 0,
3103
+ background: known ? `var(--vrm-tier-${known}, ${DOT_FALLBACK[known]})` : "transparent",
3104
+ border: known ? void 0 : "1px dashed var(--muted, #8a8a8a)"
3105
+ }
3106
+ }
3107
+ ),
3108
+ showLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
3109
+ ]
3110
+ }
3111
+ );
3112
+ }
3113
+ function VerifiedIcon({ size, className, style }) {
3114
+ const icon = useBrandAsset("verified-icon");
3115
+ return (
3116
+ // The box is reserved while the Brand sheet loads; nothing stands in.
3117
+ /* @__PURE__ */ jsxRuntime.jsx(
3118
+ "span",
3119
+ {
3120
+ "data-vrm-tier": "verified",
3121
+ "data-vrm-variant": "icon",
3122
+ role: "img",
3123
+ "aria-label": VRM_TIER_LABELS.verified,
3124
+ title: VRM_VERIFIED_TOOLTIP,
3125
+ className,
3126
+ style: { display: "inline-block", width: size, height: size, flexShrink: 0, verticalAlign: "middle", ...style },
3127
+ children: icon ? /* @__PURE__ */ jsxRuntime.jsx(
3128
+ "img",
3129
+ {
3130
+ src: icon,
3131
+ alt: "",
3132
+ width: size,
3133
+ height: size,
3134
+ draggable: false,
3135
+ "data-testid": "vrm-verified-icon",
3136
+ style: { display: "block", width: size, height: size }
3137
+ }
3138
+ ) : null
3139
+ }
3140
+ )
3141
+ );
3142
+ }
3143
+ var CONTACTS_ORIGIN = "https://contacts.politogyvrm.com";
3144
+ function withOrg(path, orgId) {
3145
+ return orgId ? `${path}?org=${encodeURIComponent(orgId)}` : path;
3146
+ }
3147
+ function contactEmbedUrl(contactId, orgId, origin = CONTACTS_ORIGIN) {
3148
+ return withOrg(`${origin}/contacts/embed/${encodeURIComponent(contactId)}`, orgId);
3149
+ }
3150
+ function contactPageUrl(contactId, orgId, origin = CONTACTS_ORIGIN) {
3151
+ return withOrg(`${origin}/contacts/${encodeURIComponent(contactId)}`, orgId);
3152
+ }
3153
+ function prefersReducedMotion() {
3154
+ try {
3155
+ return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
3156
+ } catch {
3157
+ return false;
3158
+ }
3159
+ }
3160
+ var iconButton = {
3161
+ display: "inline-flex",
3162
+ alignItems: "center",
3163
+ justifyContent: "center",
3164
+ borderRadius: 9999,
3165
+ border: "1px solid var(--line, #d7dadf)",
3166
+ padding: 6,
3167
+ background: "transparent",
3168
+ color: "var(--muted, #5c6b80)",
3169
+ cursor: "pointer"
3170
+ };
3171
+ function ContactSlideIn({ contactId, orgId, onClose, contactsOrigin = CONTACTS_ORIGIN }) {
3172
+ const [shown, setShown] = react.useState(false);
3173
+ react.useEffect(() => {
3174
+ if (!contactId) {
3175
+ setShown(false);
3176
+ return;
3177
+ }
3178
+ if (prefersReducedMotion()) {
3179
+ setShown(true);
3180
+ return;
3181
+ }
3182
+ const id = requestAnimationFrame(() => setShown(true));
3183
+ return () => cancelAnimationFrame(id);
3184
+ }, [contactId]);
3185
+ react.useEffect(() => {
3186
+ if (!contactId) return;
3187
+ const onKey = (event) => {
3188
+ if (event.key === "Escape") onClose();
3189
+ };
3190
+ document.addEventListener("keydown", onKey);
3191
+ return () => document.removeEventListener("keydown", onKey);
3192
+ }, [contactId, onClose]);
3193
+ if (!contactId) return null;
3194
+ return /* @__PURE__ */ jsxRuntime.jsx(
3195
+ "div",
3196
+ {
3197
+ "data-testid": "contact-slide-in-overlay",
3198
+ onClick: onClose,
3199
+ style: { position: "fixed", inset: 0, zIndex: 60, background: "rgba(0, 0, 0, 0.4)" },
3200
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
3201
+ "aside",
3202
+ {
3203
+ role: "dialog",
3204
+ "aria-modal": "true",
3205
+ "aria-label": "Contact card",
3206
+ "data-testid": "contact-slide-in",
3207
+ onClick: (event) => event.stopPropagation(),
3208
+ style: {
3209
+ position: "absolute",
3210
+ top: 0,
3211
+ right: 0,
3212
+ bottom: 0,
3213
+ width: "100%",
3214
+ maxWidth: 672,
3215
+ display: "flex",
3216
+ flexDirection: "column",
3217
+ background: "var(--panel, #ffffff)",
3218
+ color: "var(--foreground, #2f3136)",
3219
+ borderLeft: "1px solid var(--line, #d7dadf)",
3220
+ boxShadow: "var(--shadow-soft, 0 10px 28px rgba(27, 28, 32, 0.14))",
3221
+ transform: shown ? "translateX(0)" : "translateX(100%)",
3222
+ transition: "transform 220ms cubic-bezier(0.16, 1, 0.3, 1)"
3223
+ },
3224
+ children: [
3225
+ /* @__PURE__ */ jsxRuntime.jsxs(
3226
+ "div",
3227
+ {
3228
+ style: {
3229
+ display: "flex",
3230
+ alignItems: "center",
3231
+ justifyContent: "space-between",
3232
+ gap: 12,
3233
+ borderBottom: "1px solid var(--line, #d7dadf)",
3234
+ padding: "12px 24px"
3235
+ },
3236
+ children: [
3237
+ /* @__PURE__ */ jsxRuntime.jsx(
3238
+ "p",
3239
+ {
3240
+ style: {
3241
+ margin: 0,
3242
+ fontSize: 12,
3243
+ fontWeight: 600,
3244
+ letterSpacing: "0.18em",
3245
+ textTransform: "uppercase",
3246
+ color: "var(--muted, #5c6b80)"
3247
+ },
3248
+ children: "Contact Card"
3249
+ }
3250
+ ),
3251
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
3252
+ /* @__PURE__ */ jsxRuntime.jsx(
3253
+ "a",
3254
+ {
3255
+ href: contactPageUrl(contactId, orgId, contactsOrigin),
3256
+ target: "_top",
3257
+ style: { fontSize: 13, fontWeight: 600, color: "var(--color-race-blue-500, #007bff)", textDecoration: "none" },
3258
+ children: "Open in Contacts"
3259
+ }
3260
+ ),
3261
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Close contact card", title: "Close", onClick: onClose, style: iconButton, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": true, width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
3262
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
3263
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
3264
+ ] }) })
3265
+ ] })
3266
+ ]
3267
+ }
3268
+ ),
3269
+ /* @__PURE__ */ jsxRuntime.jsx(
3270
+ "iframe",
3271
+ {
3272
+ title: "Contact card",
3273
+ src: contactEmbedUrl(contactId, orgId, contactsOrigin),
3274
+ "data-testid": "contact-slide-in-frame",
3275
+ style: { flex: 1, minHeight: 0, width: "100%", border: 0, background: "var(--panel, #ffffff)" }
3276
+ },
3277
+ contactId
3278
+ )
3279
+ ]
3280
+ }
3281
+ )
3282
+ }
3283
+ );
3284
+ }
3285
+ function useContactSlideIn() {
3286
+ const [contactId, setContactId] = react.useState(null);
3287
+ const open = react.useCallback((id) => setContactId(id), []);
3288
+ const close = react.useCallback(() => setContactId(null), []);
3289
+ return { contactId, open, close };
3290
+ }
3016
3291
  var standardNavIcons = {
3017
3292
  home: lu.LuHouse,
3018
3293
  users: lu.LuUsers,
@@ -3168,14 +3443,14 @@ var APP_SIGNS_CHILDREN = [
3168
3443
  function standardPolitogyNav(opts) {
3169
3444
  const icon = (key) => opts.icons?.[key] ?? standardNavIcons[key];
3170
3445
  const orgParam = opts.activeOrgId ? `org=${opts.activeOrgId}` : "";
3171
- const withOrg = (url) => orgParam ? `${url}${url.includes("?") ? "&" : "?"}${orgParam}` : url;
3446
+ const withOrg2 = (url) => orgParam ? `${url}${url.includes("?") ? "&" : "?"}${orgParam}` : url;
3172
3447
  const leaves = (origin, children) => appLeaves(origin, children);
3173
3448
  const branches = (origin, children) => {
3174
3449
  const o = origin.replace(/\/+$/, "");
3175
3450
  return children.map((c) => ({
3176
3451
  label: c.label,
3177
3452
  icon: icon(c.icon),
3178
- href: withOrg(`${o}/${c.path}`),
3453
+ href: withOrg2(`${o}/${c.path}`),
3179
3454
  children: c.children ? leaves(origin, c.children) : void 0
3180
3455
  }));
3181
3456
  };
@@ -3184,21 +3459,21 @@ function standardPolitogyNav(opts) {
3184
3459
  return children.map((c) => {
3185
3460
  const url = c.path ? `${base}/${c.path}` : `${base}/`;
3186
3461
  const withMode = modeParam ? `${url}${url.includes("?") ? "&" : "?"}mode=${modeParam}` : url;
3187
- return { label: c.label, icon: icon(c.icon), href: withOrg(withMode) };
3462
+ return { label: c.label, icon: icon(c.icon), href: withOrg2(withMode) };
3188
3463
  });
3189
3464
  };
3190
3465
  const accountRows = () => [
3191
3466
  { kind: "section", label: "Account", railHidden: true },
3192
3467
  // My Profile moved to the Politogy ID account app (auth.politogyvrm.com)
3193
3468
  // with the retirement of app.politogyvrm.com.
3194
- { label: "My profile", icon: icon("circleUser"), href: withOrg(`${AUTH_ORIGIN}my-profile`), railHidden: true },
3469
+ { label: "My profile", icon: icon("circleUser"), href: withOrg2(`${AUTH_ORIGIN}my-profile`), railHidden: true },
3195
3470
  {
3196
3471
  label: "Organization settings",
3197
3472
  icon: icon("settings"),
3198
3473
  railHidden: true,
3199
3474
  // Organization settings moved to the standalone Settings app
3200
3475
  // (settings.politogyvrm.com, Specs/Organization-Settings v12).
3201
- href: withOrg(`${SETTINGS_ORIGIN2}organization-settings`),
3476
+ href: withOrg2(`${SETTINGS_ORIGIN2}organization-settings`),
3202
3477
  children: branches(SETTINGS_ORIGIN2, ORG_SETTINGS_CHILDREN)
3203
3478
  }
3204
3479
  ];
@@ -3212,11 +3487,11 @@ function standardPolitogyNav(opts) {
3212
3487
  } : {
3213
3488
  label: "Contacts",
3214
3489
  icon: icon("usersRound"),
3215
- href: withOrg(`${CONTACTS_APP}/`),
3490
+ href: withOrg2(`${CONTACTS_APP}/`),
3216
3491
  children: APP_CONTACTS_CHILDREN.map((c) => ({
3217
3492
  label: c.label,
3218
3493
  icon: icon(c.icon),
3219
- href: withOrg(c.href)
3494
+ href: withOrg2(c.href)
3220
3495
  }))
3221
3496
  };
3222
3497
  return [
@@ -3228,13 +3503,13 @@ function standardPolitogyNav(opts) {
3228
3503
  // target as active on `/` alone, so a root link left the Dashboard row
3229
3504
  // without its active marker on the Dashboard (Left-Navigation §8.1,
3230
3505
  // §11.3 "exactly one row is active").
3231
- { label: "Dashboard", icon: icon("layoutDashboard"), href: withOrg(`${DASHBOARD_ORIGIN}dashboard`) },
3506
+ { label: "Dashboard", icon: icon("layoutDashboard"), href: withOrg2(`${DASHBOARD_ORIGIN}dashboard`) },
3232
3507
  contacts,
3233
3508
  {
3234
3509
  label: "Email broadcast",
3235
3510
  icon: icon("mail"),
3236
- href: withOrg(`${EMAIL_APP}/dashboard`),
3237
- children: APP_EMAIL_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
3511
+ href: withOrg2(`${EMAIL_APP}/dashboard`),
3512
+ children: APP_EMAIL_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg2(c.href) }))
3238
3513
  },
3239
3514
  {
3240
3515
  // SMS/MMS Blast is the a2p app entered in RELATIONSHIP mode (a2p is
@@ -3243,7 +3518,7 @@ function standardPolitogyNav(opts) {
3243
3518
  // lights up on arrival.
3244
3519
  label: "SMS/MMS blast",
3245
3520
  icon: icon("messageSquare"),
3246
- href: withOrg(`${A2P_ORIGIN}?mode=relationship`),
3521
+ href: withOrg2(`${A2P_ORIGIN}?mode=relationship`),
3247
3522
  children: appLeaves(A2P_ORIGIN, APP_A2P_CHILDREN, "relationship")
3248
3523
  },
3249
3524
  { kind: "section", label: "Collect" },
@@ -3252,20 +3527,20 @@ function standardPolitogyNav(opts) {
3252
3527
  {
3253
3528
  label: "Calls to action",
3254
3529
  icon: icon("mousePointerClick"),
3255
- href: withOrg("https://ctas.politogyvrm.com/"),
3256
- children: APP_CTAS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
3530
+ href: withOrg2("https://ctas.politogyvrm.com/"),
3531
+ children: APP_CTAS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg2(c.href) }))
3257
3532
  },
3258
3533
  {
3259
3534
  label: "Forms",
3260
3535
  icon: icon("fileText"),
3261
- href: withOrg("https://forms.politogyvrm.com/"),
3262
- children: APP_FORMS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
3536
+ href: withOrg2("https://forms.politogyvrm.com/"),
3537
+ children: APP_FORMS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg2(c.href) }))
3263
3538
  },
3264
3539
  {
3265
3540
  label: "Surveys",
3266
3541
  icon: icon("clipboardList"),
3267
- href: withOrg("https://surveys.politogyvrm.com/surveys"),
3268
- children: APP_SURVEYS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
3542
+ href: withOrg2("https://surveys.politogyvrm.com/surveys"),
3543
+ children: APP_SURVEYS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg2(c.href) }))
3269
3544
  },
3270
3545
  // No Polls row here: Polling is a Campaign Mode feature only
3271
3546
  // (Specs/Left-Navigation §9.1 "Polls is not a Relationship row"). Its
@@ -3286,48 +3561,48 @@ function standardPolitogyNav(opts) {
3286
3561
  { kind: "section", label: "Race data" },
3287
3562
  // Battleground is the Campaign Mode landing page, its own app on its own
3288
3563
  // host (registry key `battleground`; Specs/Left-Navigation §9.2, §13, §14).
3289
- { label: "Battleground", icon: icon("crosshair"), href: withOrg(`${BATTLEGROUND_ORIGIN}battleground`) },
3564
+ { label: "Battleground", icon: icon("crosshair"), href: withOrg2(`${BATTLEGROUND_ORIGIN}battleground`) },
3290
3565
  // District Data is its own Campaign Mode app on its own host (registry key `districts`).
3291
- { label: "District data", icon: icon("landmark"), href: withOrg(`${DISTRICTS_ORIGIN}districts`) },
3566
+ { label: "District data", icon: icon("landmark"), href: withOrg2(`${DISTRICTS_ORIGIN}districts`) },
3292
3567
  // Campaign Tribes (Specs/Tribes §2.3–§2.4, Left-Navigation §9.2; decided
3293
3568
  // 2026-10-16, Ben): a page of the Battleground app at /tribes, so it is
3294
3569
  // the only active row there (Battleground's /battleground prefix does
3295
3570
  // not match it). Relationship Tribes stay inside Contacts.
3296
- { label: "Tribes", icon: icon("usersRound"), href: withOrg(`${BATTLEGROUND_ORIGIN}tribes`) },
3571
+ { label: "Tribes", icon: icon("usersRound"), href: withOrg2(`${BATTLEGROUND_ORIGIN}tribes`) },
3297
3572
  { kind: "section", label: "Research" },
3298
3573
  {
3299
3574
  label: "Polling",
3300
3575
  icon: icon("chartNoAxes"),
3301
- href: withOrg(POLLS_ORIGIN),
3302
- children: APP_POLLS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) })),
3576
+ href: withOrg2(POLLS_ORIGIN),
3577
+ children: APP_POLLS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg2(c.href) })),
3303
3578
  flag: "polling"
3304
3579
  },
3305
3580
  { kind: "section", label: "GOTV" },
3306
3581
  {
3307
3582
  label: "Field canvassing",
3308
3583
  icon: icon("doorOpen"),
3309
- href: withOrg(CANVASS_ORIGIN),
3584
+ href: withOrg2(CANVASS_ORIGIN),
3310
3585
  children: appLeaves(CANVASS_ORIGIN, APP_CANVASS_CHILDREN),
3311
3586
  flag: "canvass"
3312
3587
  },
3313
3588
  {
3314
3589
  label: "Phone banking",
3315
3590
  icon: icon("phone"),
3316
- href: withOrg(PHONEBANK_ORIGIN),
3591
+ href: withOrg2(PHONEBANK_ORIGIN),
3317
3592
  children: appLeaves(PHONEBANK_ORIGIN, APP_PHONEBANK_CHILDREN),
3318
3593
  flag: "phonebank"
3319
3594
  },
3320
3595
  {
3321
3596
  label: "A2P texting",
3322
3597
  icon: icon("messageSquare"),
3323
- href: withOrg(A2P_ORIGIN),
3598
+ href: withOrg2(A2P_ORIGIN),
3324
3599
  children: appLeaves(A2P_ORIGIN, APP_A2P_CHILDREN),
3325
3600
  flag: "a2p"
3326
3601
  },
3327
3602
  {
3328
3603
  label: "Sign mapping",
3329
3604
  icon: icon("signpost"),
3330
- href: withOrg(SIGNS_ORIGIN),
3605
+ href: withOrg2(SIGNS_ORIGIN),
3331
3606
  children: appLeaves(SIGNS_ORIGIN, APP_SIGNS_CHILDREN),
3332
3607
  flag: "signs"
3333
3608
  },
@@ -3344,9 +3619,9 @@ function standardPolitogyNav(opts) {
3344
3619
  opts.petitionsItem ? {
3345
3620
  label: "Dashboard",
3346
3621
  icon: icon("home"),
3347
- href: opts.petitionsItem.href ?? withOrg(PETITION_MODE_ORIGIN),
3622
+ href: opts.petitionsItem.href ?? withOrg2(PETITION_MODE_ORIGIN),
3348
3623
  children: opts.petitionsItem.children
3349
- } : { label: "Dashboard", icon: icon("home"), href: withOrg(PETITION_MODE_ORIGIN) }
3624
+ } : { label: "Dashboard", icon: icon("home"), href: withOrg2(PETITION_MODE_ORIGIN) }
3350
3625
  ];
3351
3626
  const mode = opts.mode ?? "relationship";
3352
3627
  const built = mode === "campaign" ? buildCampaign() : mode === "petition" ? buildPetition() : buildRelationship();
@@ -4986,11 +5261,13 @@ exports.BETA_BANNER_DISMISS_KEY = BETA_BANNER_DISMISS_KEY;
4986
5261
  exports.BrandFavicon = BrandFavicon;
4987
5262
  exports.BreadcrumbBar = BreadcrumbBar;
4988
5263
  exports.CAMPAIGN_FEATURE_AVAILABILITY = CAMPAIGN_FEATURE_AVAILABILITY;
5264
+ exports.CONTACTS_ORIGIN = CONTACTS_ORIGIN;
4989
5265
  exports.CORE_APP_ORIGIN = CORE_APP_ORIGIN;
4990
5266
  exports.CORE_BILLING_PATH = CORE_BILLING_PATH;
4991
5267
  exports.CREDIT_TYPE_LABELS = CREDIT_TYPE_LABELS;
4992
5268
  exports.CREDIT_TYPE_ORDER = CREDIT_TYPE_ORDER;
4993
5269
  exports.Card = Card;
5270
+ exports.ContactSlideIn = ContactSlideIn;
4994
5271
  exports.CreditsAction = CreditsAction;
4995
5272
  exports.FormColumn = FormColumn;
4996
5273
  exports.FuelAction = FuelAction;
@@ -5019,10 +5296,15 @@ exports.TopBarPanelArrow = TopBarPanelArrow;
5019
5296
  exports.TopBarPopover = TopBarPopover;
5020
5297
  exports.TopBarTooltip = TopBarTooltip;
5021
5298
  exports.TopBarWidgetSlot = TopBarWidgetSlot;
5299
+ exports.VRM_TIER_LABELS = VRM_TIER_LABELS;
5300
+ exports.VRM_VERIFIED_TOOLTIP = VRM_VERIFIED_TOOLTIP;
5301
+ exports.VrmVerifiedBadge = VrmVerifiedBadge;
5022
5302
  exports.aiCreditsWalletUrl = aiCreditsWalletUrl;
5023
5303
  exports.applyBrandFavicon = applyBrandFavicon;
5024
5304
  exports.buildLineParts = buildLineParts;
5025
5305
  exports.clearBetaBannerDismissal = clearBetaBannerDismissal;
5306
+ exports.contactEmbedUrl = contactEmbedUrl;
5307
+ exports.contactPageUrl = contactPageUrl;
5026
5308
  exports.creditGaugeRatio = creditGaugeRatio;
5027
5309
  exports.creditStateWord = creditStateWord;
5028
5310
  exports.creditTooltipLine = creditTooltipLine;
@@ -5040,6 +5322,7 @@ exports.standardPolitogyNav = standardPolitogyNav;
5040
5322
  exports.topBarIconButtonClass = topBarIconButtonClass;
5041
5323
  exports.useChromeMe = useChromeMe;
5042
5324
  exports.useChromeOrgs = useChromeOrgs;
5325
+ exports.useContactSlideIn = useContactSlideIn;
5043
5326
  exports.useNavChromeDedupedFetch = useNavChromeDedupedFetch;
5044
5327
  exports.useNavChromeFetcher = useNavChromeFetcher;
5045
5328
  exports.useThemePreference = useThemePreference;