@the-portland-company/shell 0.67.0 → 0.68.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.
@@ -1,4 +1,4 @@
1
- import { readThemeCookie, THEME_STORAGE_KEY, isThemePreference, applyThemePreference, readPendingThemeChoice, writeThemeCookie, clearPendingThemeChoice, markThemeChoicePending } from './chunk-JHIFJZ73.js';
1
+ import { readThemeCookie, THEME_STORAGE_KEY, isThemePreference, applyThemePreference, readPendingThemeChoice, writeThemeCookie, clearPendingThemeChoice, markThemeChoicePending } from './chunk-NHBNM5P3.js';
2
2
  import { createContext, useRef, useState, useEffect, useContext, useCallback, useMemo, useSyncExternalStore } from 'react';
3
3
  import clsx from 'clsx';
4
4
  import { FiUser, FiSettings, FiMessageSquare, FiMail, FiInfo, FiSun, FiMoon, FiHelpCircle, FiLifeBuoy, FiAlertCircle, FiAlertTriangle, FiBell, FiGrid, FiZap, FiBatteryCharging, FiBattery } from 'react-icons/fi';
@@ -84,12 +84,13 @@ function resolveOrgLogoUrl(url) {
84
84
  if (/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(raw)) return raw;
85
85
  return `${CORE_APP_ORIGIN}${raw.startsWith("/") ? "" : "/"}${raw}`;
86
86
  }
87
+ var TOPBAR_GLYPH_SIZE = 17;
87
88
  function topBarIconButtonClass(tone = "default") {
88
89
  const toneClass = tone === "danger" || tone === "warning" ? "text-[color:var(--chrome-danger)] hover:text-[color:var(--chrome-danger)]" : "text-[color:var(--topbar-icon-color,var(--muted))] hover:text-[color:var(--topbar-icon-hover-color,var(--foreground))] hover:bg-[color:var(--topbar-icon-hover-bg,transparent)]";
89
90
  return [
90
91
  // `group/tbtip` powers the shared <TopBarTooltip> rendered inside the trigger.
91
- "group/tbtip relative flex items-center justify-center rounded-full border border-[color:var(--line)] transition",
92
- "h-[var(--topbar-icon-button-size,32px)] w-[var(--topbar-icon-button-size,32px)]",
92
+ "group/tbtip relative flex items-center justify-center rounded-[var(--topbar-icon-button-radius,5px)] border border-[color:var(--line)] transition",
93
+ "h-[var(--topbar-icon-button-size,34px)] w-[var(--topbar-icon-button-size,34px)]",
93
94
  toneClass
94
95
  ].join(" ");
95
96
  }
@@ -112,7 +113,7 @@ function useAnyTopBarPanelOpen() {
112
113
  }
113
114
  function TopBarCountBadge({ count }) {
114
115
  if (!(count > 0)) return null;
115
- return /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--chrome-danger)] px-1 text-[10px] font-normal leading-none text-white", children: count > 99 ? "99+" : count });
116
+ return /* @__PURE__ */ jsx("span", { className: "absolute -top-[5px] -right-[5px] flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--chrome-danger)] px-1 text-[10px] font-bold leading-4 text-white", children: count > 99 ? "99+" : count });
116
117
  }
117
118
  function TopBarTooltip({
118
119
  title,
@@ -298,7 +299,7 @@ function ValueSkeleton({ className }) {
298
299
  function SlotGlyph({
299
300
  slot,
300
301
  fallback: Fallback,
301
- size = 20
302
+ size = TOPBAR_GLYPH_SIZE
302
303
  }) {
303
304
  const glyphName = useTopBarIconSlotGlyph(slot ?? "apps");
304
305
  const BrandGlyph = slot ? resolveBrandGlyph(glyphName) : null;
@@ -390,7 +391,7 @@ function TopBarPopover({
390
391
  ) : null
391
392
  ] });
392
393
  }
393
- function BatteryGlyph({ size = 20, className }) {
394
+ function BatteryGlyph({ size = TOPBAR_GLYPH_SIZE, className }) {
394
395
  return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
395
396
  /* @__PURE__ */ jsx("rect", { x: "1", y: "6", width: "18", height: "12", rx: "2", ry: "2" }),
396
397
  /* @__PURE__ */ jsx("line", { x1: "23", y1: "10", x2: "23", y2: "14" }),
@@ -398,7 +399,7 @@ function BatteryGlyph({ size = 20, className }) {
398
399
  /* @__PURE__ */ jsx("line", { x1: "9", y1: "10", x2: "9", y2: "14" })
399
400
  ] });
400
401
  }
401
- function BellGlyph({ size = 20, className }) {
402
+ function BellGlyph({ size = TOPBAR_GLYPH_SIZE, className }) {
402
403
  return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
403
404
  /* @__PURE__ */ jsx("path", { d: "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" }),
404
405
  /* @__PURE__ */ jsx("path", { d: "M13.73 21a2 2 0 0 1-3.46 0" })
@@ -413,7 +414,7 @@ function BellOffGlyph({ size = 14, className }) {
413
414
  /* @__PURE__ */ jsx("line", { x1: "1", y1: "1", x2: "23", y2: "23" })
414
415
  ] });
415
416
  }
416
- function LifeBuoyGlyph({ size = 20, className }) {
417
+ function LifeBuoyGlyph({ size = TOPBAR_GLYPH_SIZE, className }) {
417
418
  return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
418
419
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
419
420
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
@@ -423,7 +424,7 @@ function LifeBuoyGlyph({ size = 20, className }) {
423
424
  /* @__PURE__ */ jsx("line", { x1: "4.93", y1: "19.07", x2: "9.17", y2: "14.83" })
424
425
  ] });
425
426
  }
426
- function LayoutGlyph({ size = 20, className }) {
427
+ function LayoutGlyph({ size = TOPBAR_GLYPH_SIZE, className }) {
427
428
  return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className, "aria-hidden": true, children: [
428
429
  /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
429
430
  /* @__PURE__ */ jsx("line", { x1: "3", y1: "9", x2: "21", y2: "9" }),
@@ -1441,7 +1442,7 @@ function SpecOverlayAction({ orgId, orgName } = {}) {
1441
1442
  className: topBarIconButtonClass(badgeTone),
1442
1443
  onClick: () => setOpen(true),
1443
1444
  children: [
1444
- /* @__PURE__ */ jsx(LayoutGlyph, { size: 20, className: "text-current" }),
1445
+ /* @__PURE__ */ jsx(LayoutGlyph, { size: TOPBAR_GLYPH_SIZE, className: "text-current" }),
1445
1446
  badgeLabel ? /* @__PURE__ */ jsx(
1446
1447
  "span",
1447
1448
  {
@@ -1763,6 +1764,16 @@ var SIGNS_ORIGIN = "https://signs.politogyvrm.com/";
1763
1764
  var POLLS_ORIGIN = "https://polls.politogyvrm.com/";
1764
1765
  var CONTACTS_TRIBES = "https://contacts.politogyvrm.com/tribes";
1765
1766
  var PETITION_MODE_ORIGIN = "https://petition-mode.politogyvrm.com/";
1767
+ function applyHiddenItems(items, hidden) {
1768
+ if (!hidden || hidden.length === 0) return items;
1769
+ const drop = new Set(hidden.map((h) => h.trim().toLowerCase()));
1770
+ const kept = items.filter((i) => i.kind === "section" || !drop.has(i.label.toLowerCase()));
1771
+ return kept.filter((item, idx) => {
1772
+ if (item.kind !== "section") return true;
1773
+ const next = kept[idx + 1];
1774
+ return !!next && next.kind !== "section";
1775
+ });
1776
+ }
1766
1777
  var CONTACTS_APP = "https://contacts.politogyvrm.com";
1767
1778
  var APP_CONTACTS_CHILDREN = [
1768
1779
  { label: "Dashboard", icon: "grid", href: `${CONTACTS_APP}/` },
@@ -1877,7 +1888,8 @@ function standardPolitogyNav(opts) {
1877
1888
  label: "Contacts",
1878
1889
  icon: icon("users"),
1879
1890
  href: opts.contactsItem.href,
1880
- children: opts.contactsItem.children
1891
+ children: opts.contactsItem.children,
1892
+ badge: opts.contactsItem.count ?? void 0
1881
1893
  } : {
1882
1894
  label: "Contacts",
1883
1895
  icon: icon("users"),
@@ -1889,10 +1901,11 @@ function standardPolitogyNav(opts) {
1889
1901
  }))
1890
1902
  };
1891
1903
  return [
1904
+ { kind: "section", label: "Relationship" },
1892
1905
  { label: "Dashboard", icon: icon("home"), href: withOrg(abs("/relationship/dashboard")) },
1893
1906
  contacts,
1894
1907
  {
1895
- label: "Email Broadcast",
1908
+ label: "Email broadcast",
1896
1909
  icon: icon("mail"),
1897
1910
  href: withOrg(`${EMAIL_APP}/dashboard`),
1898
1911
  children: [
@@ -1900,20 +1913,19 @@ function standardPolitogyNav(opts) {
1900
1913
  ...leaves([EMAIL_V1_LEGACY])
1901
1914
  ]
1902
1915
  },
1903
- // SMS/MMS Blast IS a2p (Specs/A2P) — the standalone delivery engine
1904
- // shared with Campaign Mode, not a core-hosted surface (the old
1905
- // `/relationship/sms-mms-blast/*` core routes are dead; core no longer
1906
- // hosts them). Every link carries `mode=relationship` so a2p's nav
1907
- // resolves the Relationship tree instead of its own Campaign default
1908
- // (resolveActiveMode, mode-preference.ts).
1909
1916
  {
1910
- label: "SMS/MMS Blast",
1917
+ // SMS/MMS Blast is the a2p app entered in RELATIONSHIP mode (a2p is
1918
+ // dual-mode; Specs/A2P). The `?mode=relationship` param pins the
1919
+ // destination's tree so the row that got you there is the row that
1920
+ // lights up on arrival.
1921
+ label: "SMS/MMS blast",
1911
1922
  icon: icon("messageSquare"),
1912
1923
  href: withOrg(`${A2P_ORIGIN}?mode=relationship`),
1913
1924
  children: appLeaves(A2P_ORIGIN, APP_A2P_CHILDREN, "relationship")
1914
1925
  },
1915
- // These two carry no top-level href in VRM core (parent row only toggles).
1916
- { label: "Calls to Action", icon: icon("layout"), children: leaves(CTA_CHILDREN) },
1926
+ { kind: "section", label: "Collect" },
1927
+ // Carries no top-level href in VRM core (parent row only toggles).
1928
+ { label: "Calls to action", icon: icon("layout"), children: leaves(CTA_CHILDREN) },
1917
1929
  {
1918
1930
  label: "Forms",
1919
1931
  icon: icon("activity"),
@@ -1938,9 +1950,12 @@ function standardPolitogyNav(opts) {
1938
1950
  href: withOrg("https://ctas.politogyvrm.com/"),
1939
1951
  children: APP_CTAS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
1940
1952
  },
1953
+ { kind: "section", label: "Account" },
1954
+ // My Profile is global — NOT org-suffixed (main-app ShellChromeBridge).
1955
+ { label: "My profile", icon: icon("user"), href: withOrg(abs("/my-profile")) },
1941
1956
  {
1942
- label: "Organization Settings",
1943
- icon: icon("briefcase"),
1957
+ label: "Organization settings",
1958
+ icon: icon("settings"),
1944
1959
  href: withOrg(abs("/organization-settings")),
1945
1960
  children: branches(ORG_SETTINGS_CHILDREN)
1946
1961
  }
@@ -1996,7 +2011,8 @@ function standardPolitogyNav(opts) {
1996
2011
  } : { label: "Dashboard", icon: icon("home"), href: withOrg(PETITION_MODE_ORIGIN) }
1997
2012
  ];
1998
2013
  const mode = opts.mode ?? "relationship";
1999
- const items = mode === "campaign" ? buildCampaign() : mode === "petition" ? buildPetition() : buildRelationship();
2014
+ const built = mode === "campaign" ? buildCampaign() : mode === "petition" ? buildPetition() : buildRelationship();
2015
+ const items = applyHiddenItems(built, opts.hiddenItems);
2000
2016
  if (opts.supportItem) {
2001
2017
  items.push({
2002
2018
  label: "Support",
@@ -2126,6 +2142,7 @@ function NavSidebar({
2126
2142
  const ModeIcon = mode?.icon;
2127
2143
  const orgLogoSrc = resolveOrgLogoUrl(org?.logoUrl);
2128
2144
  const orgGradient = org?.brandColor ? `linear-gradient(to right, ${org.brandColor}, ${org.brandColorSecondary || org.brandColor})` : "linear-gradient(to right, #007BFF, #A54B7A, #E63946)";
2145
+ const orgCardStyle = hexToRgba(org?.brandColor, 0.42) ? { borderColor: hexToRgba(org?.brandColor, 0.42) } : void 0;
2129
2146
  const activeGroupKey = useMemo(() => {
2130
2147
  for (let i = 0; i < nav.items.length; i++) {
2131
2148
  const item = nav.items[i];
@@ -2159,7 +2176,7 @@ function NavSidebar({
2159
2176
  "aria-modal": open ? "true" : void 0,
2160
2177
  "aria-label": open ? "Navigation" : void 0,
2161
2178
  className: clsx(
2162
- "fixed inset-y-0 left-0 w-[240px] flex-col border-r border-[color:var(--line)] bg-[color:var(--sidebar-bg,var(--nav-surface))] lg:flex",
2179
+ "fixed inset-y-0 left-0 w-[var(--sidebar-width,236px)] flex-col border-r border-[color:var(--sidebar-line,var(--line))] bg-[color:var(--sidebar-bg,var(--nav-surface))] lg:flex",
2163
2180
  open ? "flex z-50" : "hidden z-30"
2164
2181
  ),
2165
2182
  style: { fontFamily: 'var(--font-family, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif)' },
@@ -2179,31 +2196,31 @@ function NavSidebar({
2179
2196
  children: /* @__PURE__ */ jsx(CloseIcon, {})
2180
2197
  }
2181
2198
  ) : null,
2182
- /* @__PURE__ */ jsx(
2183
- Link,
2184
- {
2185
- href: brand.homeHref ?? "/",
2186
- className: "flex h-[64px] flex-shrink-0 items-center gap-2.5 px-6",
2187
- children: brand.logoSrc ? /* @__PURE__ */ jsx(
2188
- "img",
2189
- {
2190
- src: brand.logoSrc,
2191
- alt: brand.logoAlt ?? brand.title,
2192
- draggable: false,
2193
- className: "h-10 w-auto object-contain"
2194
- }
2195
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
2196
- /* @__PURE__ */ jsx("span", { className: "flex h-9 w-9 items-center justify-center rounded-xl bg-[color:var(--color-accent)] text-base font-black text-white shadow-sm", children: brand.badgeLabel }),
2197
- /* @__PURE__ */ jsxs("span", { className: "flex flex-col leading-tight", children: [
2198
- /* @__PURE__ */ jsx("span", { className: "text-base font-extrabold tracking-[-0.01em] text-[color:var(--color-accent)]", children: brand.title }),
2199
- brand.subtitle ? /* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.16em] text-[color:var(--muted)]", children: brand.subtitle }) : null
2199
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 flex-col gap-[14px] border-b border-[color:var(--sidebar-line,var(--line))] px-[18px] py-4", children: [
2200
+ /* @__PURE__ */ jsx(
2201
+ Link,
2202
+ {
2203
+ href: brand.homeHref ?? "/",
2204
+ className: "flex items-center gap-2.5",
2205
+ children: brand.logoSrc ? /* @__PURE__ */ jsx(
2206
+ "img",
2207
+ {
2208
+ src: brand.logoSrc,
2209
+ alt: brand.logoAlt ?? brand.title,
2210
+ draggable: false,
2211
+ className: "h-[var(--sidebar-brand-logo-height,24px)] w-auto object-contain"
2212
+ }
2213
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
2214
+ /* @__PURE__ */ jsx("span", { className: "flex h-9 w-9 items-center justify-center rounded-xl bg-[color:var(--color-accent)] text-base font-black text-white shadow-sm", children: brand.badgeLabel }),
2215
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col leading-tight", children: [
2216
+ /* @__PURE__ */ jsx("span", { className: "text-base font-extrabold tracking-[-0.01em] text-[color:var(--color-accent)]", children: brand.title }),
2217
+ brand.subtitle ? /* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold uppercase tracking-[0.16em] text-[color:var(--muted)]", children: brand.subtitle }) : null
2218
+ ] })
2200
2219
  ] })
2201
- ] })
2202
- }
2203
- ),
2204
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-y-auto px-4 pb-2", children: [
2205
- org ? /* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
2206
- /* @__PURE__ */ jsx("div", { className: "mb-2 flex items-center justify-between px-1", children: /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: "Organization" }) }),
2220
+ }
2221
+ ),
2222
+ org ? /* @__PURE__ */ jsxs("div", { children: [
2223
+ /* @__PURE__ */ jsx("div", { className: "mb-[7px] flex items-center justify-between", children: /* @__PURE__ */ jsx("p", { className: NAV_EYEBROW_CLASS, children: "Organization" }) }),
2207
2224
  org.loading ? /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-2.5 rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] px-2.5 py-2 shadow-sm", children: [
2208
2225
  /* @__PURE__ */ jsx(
2209
2226
  "span",
@@ -2221,34 +2238,41 @@ function NavSidebar({
2221
2238
  ),
2222
2239
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading organization" })
2223
2240
  ] }) : org.organizations && org.organizations.length > 0 && org.onSwitch ? /* @__PURE__ */ jsxs("details", { "data-nav-details": true, className: "group relative", children: [
2224
- /* @__PURE__ */ jsxs("summary", { className: "flex w-full cursor-pointer list-none flex-col overflow-hidden rounded-[5px] border border-[color:var(--line)] bg-[color:var(--panel-elevated)] text-left text-[color:var(--foreground)] shadow-sm transition hover:bg-[color:var(--panel)] [&::-webkit-details-marker]:hidden", children: [
2225
- /* @__PURE__ */ jsxs("span", { className: "relative flex h-[70px] w-full items-center justify-center bg-white px-3", children: [
2226
- orgLogoSrc ? /* @__PURE__ */ jsx("img", { src: orgLogoSrc, alt: "", className: "max-h-[70px] max-w-full object-contain" }) : org.canUploadLogo ? /* @__PURE__ */ jsx(
2227
- "a",
2228
- {
2229
- href: org.uploadLogoHref ?? "#",
2230
- onClick: (e) => e.stopPropagation(),
2231
- className: "text-xs font-semibold text-[color:var(--color-accent)] underline",
2232
- children: "Upload logo"
2233
- }
2234
- ) : /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-neutral-800", children: org.name ?? "Organization" }),
2235
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 h-[3px]", style: { backgroundImage: orgGradient } })
2236
- ] }),
2237
- /* @__PURE__ */ jsxs("span", { className: "flex w-full min-w-0 items-center justify-between gap-2 px-2.5 py-2", children: [
2238
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
2239
- /* @__PURE__ */ jsx(
2240
- "span",
2241
- {
2242
- title: org.name ?? void 0,
2243
- className: "truncate text-[13px] font-semibold",
2244
- children: org.name ?? "No organizations"
2245
- }
2246
- ),
2247
- org.id && !org.loading ? /* @__PURE__ */ jsx(OrgIdCopyButton, { id: org.id }) : null
2248
- ] }),
2249
- /* @__PURE__ */ jsx(ChevronDown, {})
2250
- ] })
2251
- ] }),
2241
+ /* @__PURE__ */ jsxs(
2242
+ "summary",
2243
+ {
2244
+ style: orgCardStyle,
2245
+ className: "flex w-full cursor-pointer list-none flex-col overflow-hidden rounded-[5px] border border-[color:var(--sidebar-card-border,var(--sidebar-line,var(--line)))] bg-[color:var(--sidebar-card-bg,var(--panel-elevated))] text-left text-[color:var(--sidebar-text,var(--foreground))] transition hover:bg-[color:var(--sidebar-row-hover-bg,var(--panel))] [&::-webkit-details-marker]:hidden",
2246
+ children: [
2247
+ /* @__PURE__ */ jsxs("span", { className: "relative flex h-[var(--sidebar-org-band-height,48px)] w-full items-center justify-center bg-white px-3 py-[7px]", children: [
2248
+ orgLogoSrc ? /* @__PURE__ */ jsx("img", { src: orgLogoSrc, alt: "", className: "max-h-full max-w-[132px] object-contain" }) : org.canUploadLogo ? /* @__PURE__ */ jsx(
2249
+ "a",
2250
+ {
2251
+ href: org.uploadLogoHref ?? "#",
2252
+ onClick: (e) => e.stopPropagation(),
2253
+ className: "text-xs font-semibold text-[color:var(--color-accent)] underline",
2254
+ children: "Upload logo"
2255
+ }
2256
+ ) : /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-neutral-800", children: org.name ?? "Organization" }),
2257
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 h-[3px]", style: { backgroundImage: orgGradient } })
2258
+ ] }),
2259
+ /* @__PURE__ */ jsxs("span", { className: "flex w-full min-w-0 items-center justify-between gap-[9px] px-[10px] py-2", children: [
2260
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
2261
+ /* @__PURE__ */ jsx(
2262
+ "span",
2263
+ {
2264
+ title: org.name ?? void 0,
2265
+ className: "truncate text-[12px] font-semibold leading-[1.2]",
2266
+ children: org.name ?? "No organizations"
2267
+ }
2268
+ ),
2269
+ org.id && !org.loading ? /* @__PURE__ */ jsx(OrgIdCopyButton, { id: org.id }) : null
2270
+ ] }),
2271
+ /* @__PURE__ */ jsx(ChevronDown, { size: 14 })
2272
+ ] })
2273
+ ]
2274
+ }
2275
+ ),
2252
2276
  /* @__PURE__ */ jsxs("div", { className: "absolute left-0 right-0 z-40 mt-1 max-h-[min(60vh,520px)] overflow-y-auto rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 shadow-[var(--shadow-soft)]", children: [
2253
2277
  shouldShowOrgFilter(org.organizations.length) ? /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-[color:var(--panel-elevated)] px-2 pb-1 pt-1", children: /* @__PURE__ */ jsx(
2254
2278
  "input",
@@ -2317,10 +2341,11 @@ function NavSidebar({
2317
2341
  {
2318
2342
  type: "button",
2319
2343
  onClick: org.onClick,
2320
- className: "flex w-full flex-col overflow-hidden rounded-[5px] border border-[color:var(--line)] bg-[color:var(--panel-elevated)] text-left text-[color:var(--foreground)] shadow-sm transition hover:bg-[color:var(--panel)]",
2344
+ style: orgCardStyle,
2345
+ className: "flex w-full flex-col overflow-hidden rounded-[5px] border border-[color:var(--sidebar-card-border,var(--sidebar-line,var(--line)))] bg-[color:var(--sidebar-card-bg,var(--panel-elevated))] text-left text-[color:var(--sidebar-text,var(--foreground))] transition hover:bg-[color:var(--sidebar-row-hover-bg,var(--panel))]",
2321
2346
  children: [
2322
- /* @__PURE__ */ jsxs("span", { className: "relative flex h-[70px] w-full items-center justify-center bg-white px-3", children: [
2323
- orgLogoSrc ? /* @__PURE__ */ jsx("img", { src: orgLogoSrc, alt: "", className: "max-h-[70px] max-w-full object-contain" }) : org.canUploadLogo ? /* @__PURE__ */ jsx(
2347
+ /* @__PURE__ */ jsxs("span", { className: "relative flex h-[var(--sidebar-org-band-height,48px)] w-full items-center justify-center bg-white px-3 py-[7px]", children: [
2348
+ orgLogoSrc ? /* @__PURE__ */ jsx("img", { src: orgLogoSrc, alt: "", className: "max-h-full max-w-[132px] object-contain" }) : org.canUploadLogo ? /* @__PURE__ */ jsx(
2324
2349
  "a",
2325
2350
  {
2326
2351
  href: org.uploadLogoHref ?? "#",
@@ -2331,31 +2356,31 @@ function NavSidebar({
2331
2356
  ) : /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-neutral-800", children: org.name ?? "Organization" }),
2332
2357
  /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 h-[3px]", style: { backgroundImage: orgGradient } })
2333
2358
  ] }),
2334
- /* @__PURE__ */ jsxs("span", { className: "flex w-full min-w-0 items-center justify-between gap-2 px-2.5 py-2", children: [
2359
+ /* @__PURE__ */ jsxs("span", { className: "flex w-full min-w-0 items-center justify-between gap-[9px] px-[10px] py-2", children: [
2335
2360
  /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
2336
2361
  /* @__PURE__ */ jsx(
2337
2362
  "span",
2338
2363
  {
2339
2364
  title: org.name ?? void 0,
2340
- className: "truncate text-[13px] font-semibold",
2365
+ className: "truncate text-[12px] font-semibold leading-[1.2]",
2341
2366
  children: org.name ?? "No organizations"
2342
2367
  }
2343
2368
  ),
2344
2369
  org.id && !org.loading ? /* @__PURE__ */ jsx(OrgIdCopyButton, { id: org.id }) : null
2345
2370
  ] }),
2346
- /* @__PURE__ */ jsx(ChevronDown, {})
2371
+ /* @__PURE__ */ jsx(ChevronDown, { size: 14 })
2347
2372
  ] })
2348
2373
  ]
2349
2374
  }
2350
2375
  )
2351
2376
  ] }) : null,
2352
- mode ? /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
2377
+ mode ? /* @__PURE__ */ jsxs("div", { children: [
2353
2378
  /* @__PURE__ */ jsx(
2354
2379
  "div",
2355
2380
  {
2356
2381
  role: "radiogroup",
2357
2382
  "aria-label": "Mode",
2358
- className: "flex items-center justify-start gap-0.5 rounded-lg border border-[color:var(--border-inverse,var(--line))] bg-[color:var(--mode-track-bg,var(--panel-elevated))] p-[3px]",
2383
+ className: "flex w-full items-center gap-1 rounded-lg border border-[color:var(--border-inverse,var(--sidebar-line,var(--line)))] bg-[color:var(--mode-track-bg,var(--panel-elevated))] p-[3px]",
2359
2384
  children: (mode.options && mode.options.length > 0 ? mode.options : [{ id: mode.label, label: mode.label, icon: ModeIcon }]).map(
2360
2385
  (opt) => {
2361
2386
  const selected = opt.label === mode.label;
@@ -2376,8 +2401,8 @@ function NavSidebar({
2376
2401
  },
2377
2402
  disabled: !available,
2378
2403
  className: [
2379
- "flex h-9 items-center justify-center rounded px-[9px] py-[6px] transition",
2380
- !available ? "cursor-not-allowed text-[color:var(--sidebar-text-muted,var(--muted))] opacity-35" : selected ? "bg-[color:var(--mode-accent,var(--color-accent))] text-[color:var(--mode-on-accent,white)] shadow-sm" : "text-[color:var(--sidebar-text-muted,var(--muted))] hover:bg-white/5 hover:text-[color:var(--sidebar-text,var(--foreground))]"
2404
+ "flex flex-1 items-center justify-center rounded-[5px] px-[9px] py-[6px] transition",
2405
+ !available ? "cursor-not-allowed text-[color:var(--sidebar-text-muted,var(--muted))] opacity-35" : selected ? "bg-[color:var(--sidebar-mode-selected-bg,var(--mode-accent,var(--color-accent)))] text-[color:var(--mode-on-accent,white)]" : "text-[color:var(--sidebar-text-muted,var(--muted))] hover:bg-white/5 hover:text-[color:var(--sidebar-text,var(--foreground))]"
2381
2406
  ].join(" "),
2382
2407
  children: OptIcon ? /* @__PURE__ */ jsx(OptIcon, { size: 15, className: "shrink-0" }) : null
2383
2408
  },
@@ -2387,93 +2412,99 @@ function NavSidebar({
2387
2412
  )
2388
2413
  }
2389
2414
  ),
2390
- /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-center text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: mode.label })
2391
- ] }) : null,
2392
- /* @__PURE__ */ jsxs("nav", { className: "flex flex-col gap-1", children: [
2393
- nav.groupLabel ? /* @__PURE__ */ jsx("p", { className: "px-2 pb-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]", children: nav.groupLabel }) : null,
2394
- nav.items.map((item, idx) => {
2395
- if (item.kind === "section") {
2396
- return /* @__PURE__ */ jsx(
2397
- NavSectionRow,
2398
- {
2399
- label: item.label,
2400
- first: idx === 0
2401
- },
2402
- `section-${idx}-${item.label}`
2403
- );
2404
- }
2405
- if (nav.flatten && item.children && item.children.length > 0) {
2406
- return item.children.map((child, i) => {
2407
- if (child.kind === "section") {
2408
- return /* @__PURE__ */ jsx(
2409
- NavSectionRow,
2410
- {
2411
- label: child.label,
2412
- first: idx === 0 && i === 0
2413
- },
2414
- `flat-section-${idx}-${i}-${child.label}`
2415
- );
2416
- }
2415
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-left text-[11px] leading-[1.2] text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))]", children: modeCaption(mode.label) })
2416
+ ] }) : null
2417
+ ] }),
2418
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col overflow-y-auto px-[10px] py-3", children: /* @__PURE__ */ jsxs("nav", { className: "flex flex-col gap-0.5", children: [
2419
+ nav.groupLabel ? /* @__PURE__ */ jsx("p", { className: `${NAV_EYEBROW_CLASS} px-2 pb-1.5 pt-1`, children: nav.groupLabel }) : null,
2420
+ nav.items.map((item, idx) => {
2421
+ if (item.kind === "section") {
2422
+ return /* @__PURE__ */ jsx(
2423
+ NavSectionRow,
2424
+ {
2425
+ label: item.label,
2426
+ first: idx === 0
2427
+ },
2428
+ `section-${idx}-${item.label}`
2429
+ );
2430
+ }
2431
+ if (nav.flatten && item.children && item.children.length > 0) {
2432
+ return item.children.map((child, i) => {
2433
+ if (child.kind === "section") {
2417
2434
  return /* @__PURE__ */ jsx(
2418
- NavRow,
2435
+ NavSectionRow,
2419
2436
  {
2420
- item: child,
2421
- active: child.href ? activeFn(pathname, child.href) : false,
2422
- Link,
2423
- variant: "flat"
2437
+ label: child.label,
2438
+ first: idx === 0 && i === 0
2424
2439
  },
2425
- child.href ?? `flat-${idx}-${i}-${child.label}`
2440
+ `flat-section-${idx}-${i}-${child.label}`
2426
2441
  );
2427
- });
2428
- }
2429
- if (item.children && item.children.length > 0) {
2430
- const key = groupKeyOf(item, idx);
2431
- const selfActive = item.href ? activeFn(pathname, item.href) : false;
2432
- const parentActive = selfActive || hasActiveChild(item, pathname, activeFn);
2442
+ }
2433
2443
  return /* @__PURE__ */ jsx(
2434
- NavGroup,
2444
+ NavRow,
2435
2445
  {
2436
- item,
2437
- active: parentActive,
2438
- open: openGroup === key,
2439
- onToggle: () => toggleGroup(key),
2440
- pathname,
2441
- activeFn,
2442
- Link
2446
+ item: child,
2447
+ active: child.href ? activeFn(pathname, child.href) : false,
2448
+ Link,
2449
+ variant: "flat"
2443
2450
  },
2444
- key
2451
+ child.href ?? `flat-${idx}-${i}-${child.label}`
2445
2452
  );
2446
- }
2447
- const active = item.href ? activeFn(pathname, item.href) : false;
2453
+ });
2454
+ }
2455
+ if (item.children && item.children.length > 0) {
2456
+ const key = groupKeyOf(item, idx);
2457
+ const selfActive = item.href ? activeFn(pathname, item.href) : false;
2458
+ const parentActive = selfActive || hasActiveChild(item, pathname, activeFn);
2448
2459
  return /* @__PURE__ */ jsx(
2449
- NavRow,
2460
+ NavGroup,
2450
2461
  {
2451
2462
  item,
2452
- active,
2463
+ active: parentActive,
2464
+ open: openGroup === key,
2465
+ onToggle: () => toggleGroup(key),
2466
+ pathname,
2467
+ activeFn,
2453
2468
  Link
2454
2469
  },
2455
- item.href ?? `nav-${idx}-${item.label}`
2470
+ key
2456
2471
  );
2457
- })
2458
- ] })
2459
- ] }),
2460
- footer ? /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 border-t border-[color:var(--line)] px-4 py-3", children: [
2461
- footer.links && footer.links.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center justify-center gap-1.5 text-xs", children: footer.links.map((l, idx) => /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
2462
- idx > 0 ? /* @__PURE__ */ jsx("span", { className: "text-[color:var(--muted)]", children: "|" }) : null,
2463
- /* @__PURE__ */ jsx(
2464
- "a",
2472
+ }
2473
+ const active = item.href ? activeFn(pathname, item.href) : false;
2474
+ return /* @__PURE__ */ jsx(
2475
+ NavRow,
2465
2476
  {
2466
- href: safeHref(l.href),
2467
- className: "font-medium text-[color:var(--foreground)] opacity-80 hover:opacity-100 hover:underline",
2468
- children: l.label
2469
- }
2470
- )
2471
- ] }, l.label)) }) : null,
2477
+ item,
2478
+ active,
2479
+ Link
2480
+ },
2481
+ item.href ?? `nav-${idx}-${item.label}`
2482
+ );
2483
+ })
2484
+ ] }) }),
2485
+ footer ? /* @__PURE__ */ jsxs("div", { className: "relative flex-shrink-0 border-t border-[color:var(--sidebar-line,var(--line))] px-[14px] py-3", children: [
2486
+ footer.user ? /* @__PURE__ */ jsx(
2487
+ NavSidebarUserCard,
2488
+ {
2489
+ user: footer.user,
2490
+ userMenu: footer.userMenu ?? void 0,
2491
+ onSignOut: footer.onSignOut
2492
+ }
2493
+ ) : null,
2494
+ footer.links && footer.links.length > 0 ? /* @__PURE__ */ jsx("div", { className: `flex flex-wrap items-center gap-[10px] text-[11px] leading-[1.2] ${footer.user ? "mt-3" : ""}`, children: footer.links.map((l) => /* @__PURE__ */ jsx(
2495
+ "a",
2496
+ {
2497
+ href: safeHref(l.href),
2498
+ className: "text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))] hover:text-[color:var(--sidebar-text,var(--foreground))] hover:underline",
2499
+ children: l.label
2500
+ },
2501
+ l.label
2502
+ )) }) : null,
2472
2503
  footer.envLabel && footer.envLabel.trim().toLowerCase() !== "production" ? /* @__PURE__ */ jsxs(
2473
2504
  "div",
2474
2505
  {
2475
2506
  "data-shell-meta": true,
2476
- className: "mt-1.5 flex flex-col items-center gap-0.5 font-[family-name:var(--font-plex-mono)] text-[10px] text-[color:var(--sidebar-meta-text,var(--sidebar-text))]",
2507
+ className: "mt-1.5 flex flex-col items-start gap-0.5 font-[family-name:var(--font-plex-mono)] text-[10px] text-[color:var(--sidebar-meta-text,var(--sidebar-text))]",
2477
2508
  children: [
2478
2509
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
2479
2510
  /* @__PURE__ */ jsx(
@@ -2536,6 +2567,27 @@ function HamburgerIcon() {
2536
2567
  }
2537
2568
  );
2538
2569
  }
2570
+ function BookOpenIcon() {
2571
+ return /* @__PURE__ */ jsxs(
2572
+ "svg",
2573
+ {
2574
+ width: 14,
2575
+ height: 14,
2576
+ viewBox: "0 0 24 24",
2577
+ fill: "none",
2578
+ stroke: "currentColor",
2579
+ strokeWidth: 2,
2580
+ strokeLinecap: "round",
2581
+ strokeLinejoin: "round",
2582
+ className: "shrink-0",
2583
+ "aria-hidden": "true",
2584
+ children: [
2585
+ /* @__PURE__ */ jsx("path", { d: "M12 7v14" }),
2586
+ /* @__PURE__ */ jsx("path", { d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" })
2587
+ ]
2588
+ }
2589
+ );
2590
+ }
2539
2591
  function SearchIcon({ className } = {}) {
2540
2592
  return /* @__PURE__ */ jsxs(
2541
2593
  "svg",
@@ -2577,12 +2629,12 @@ function CloseIcon() {
2577
2629
  }
2578
2630
  );
2579
2631
  }
2580
- function ChevronDown({ className } = {}) {
2632
+ function ChevronDown({ className, size = 16 } = {}) {
2581
2633
  return /* @__PURE__ */ jsx(
2582
2634
  "svg",
2583
2635
  {
2584
- width: 16,
2585
- height: 16,
2636
+ width: size,
2637
+ height: size,
2586
2638
  viewBox: "0 0 24 24",
2587
2639
  fill: "none",
2588
2640
  stroke: "currentColor",
@@ -2596,6 +2648,28 @@ function ChevronDown({ className } = {}) {
2596
2648
  );
2597
2649
  }
2598
2650
  var NAV_HOVER_GRADIENT = "var(--nav-hover-gradient)";
2651
+ var NAV_EYEBROW_CLASS = "text-[11px] font-bold uppercase leading-[1.2] tracking-[0.09em] text-[color:var(--sidebar-eyebrow,var(--sidebar-text-muted,var(--muted)))]";
2652
+ var NAV_TOP_ICON_SIZE = 17;
2653
+ var NAV_TOP_ROW_CLASS = (active) => `gap-[11px] px-[10px] py-[9px] text-[13px] leading-none ${active ? "font-semibold" : "font-normal"}`;
2654
+ var NAV_TOP_ACTIVE_CLASS = "bg-[color:var(--sidebar-active-bg,var(--color-accent))] text-[color:var(--sidebar-active-text,white)]";
2655
+ var NAV_TOP_INACTIVE_CLASS = "text-[color:var(--sidebar-row-text,var(--sidebar-text,var(--muted)))] hover:bg-[color:var(--sidebar-row-hover-bg,var(--panel-elevated))] hover:text-[color:var(--sidebar-text,var(--foreground))]";
2656
+ function modeCaption(label) {
2657
+ return label.replace(/\s+Mode$/i, " mode");
2658
+ }
2659
+ function NavActiveRail() {
2660
+ return /* @__PURE__ */ jsx(
2661
+ "span",
2662
+ {
2663
+ "aria-hidden": "true",
2664
+ className: "pointer-events-none absolute inset-y-0 left-0 w-[2px]",
2665
+ style: { background: "var(--mode-accent, transparent)" }
2666
+ }
2667
+ );
2668
+ }
2669
+ function NavRowBadge({ value }) {
2670
+ if (value === void 0 || value === null || value === "") return null;
2671
+ return /* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 font-[family-name:var(--font-plex-mono,ui-monospace,monospace)] text-[11px] font-semibold leading-none text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))]", children: value });
2672
+ }
2599
2673
  function NavSectionRow({
2600
2674
  label,
2601
2675
  first,
@@ -2605,9 +2679,9 @@ function NavSectionRow({
2605
2679
  "p",
2606
2680
  {
2607
2681
  className: [
2608
- "text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--sidebar-text-muted,var(--muted))]",
2609
- variant === "sub" ? "px-3 pb-0.5" : "px-2 pb-1",
2610
- first ? "" : "mt-3"
2682
+ NAV_EYEBROW_CLASS,
2683
+ variant === "sub" ? "px-3 pb-0.5" : "px-2 pb-1.5 pt-1",
2684
+ first ? "" : variant === "sub" ? "mt-3" : "mt-[14px]"
2611
2685
  ].join(" "),
2612
2686
  children: label
2613
2687
  }
@@ -2622,39 +2696,32 @@ function NavRow({
2622
2696
  const Icon = item.icon;
2623
2697
  const isSub = variant === "sub";
2624
2698
  const washActive = variant !== "top";
2625
- const activeClasses = washActive ? "bg-[color:var(--mode-accent-surface,var(--panel-elevated))] text-[color:var(--color-accent)] shadow-sm" : "bg-[color:var(--color-accent)] text-white shadow-sm";
2699
+ const activeClasses = washActive ? "bg-[color:var(--mode-accent-surface,var(--panel-elevated))] text-[color:var(--color-accent)] shadow-sm" : NAV_TOP_ACTIVE_CLASS;
2626
2700
  const wrapperClasses = [
2627
- "group relative block overflow-hidden rounded-md transition",
2628
- active ? activeClasses : "text-[color:var(--sidebar-text,var(--muted))] hover:text-white"
2701
+ "group relative block overflow-hidden transition",
2702
+ isSub ? "rounded-md" : "rounded-[5px]",
2703
+ active ? activeClasses : isSub ? "text-[color:var(--sidebar-text,var(--muted))] hover:text-white" : NAV_TOP_INACTIVE_CLASS
2629
2704
  ].join(" ");
2630
- const rowPadding = isSub ? "px-3 py-1.5 text-[13px]" : "px-3 py-2 text-sm";
2631
- const iconSize = isSub ? 16 : 18;
2632
- const iconClass = active && !washActive ? "text-white" : "text-current";
2705
+ const rowPadding = isSub ? "gap-3 px-3 py-1.5 text-[13px] font-semibold" : NAV_TOP_ROW_CLASS(active);
2706
+ const iconSize = isSub ? 16 : NAV_TOP_ICON_SIZE;
2707
+ const iconClass = "text-current";
2633
2708
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
2634
- !active ? /* @__PURE__ */ jsx(
2635
- "span",
2636
- {
2637
- "aria-hidden": "true",
2638
- className: "pointer-events-none absolute inset-y-0 left-0 w-0 transition-[width] duration-300 group-hover:w-full",
2639
- style: { background: NAV_HOVER_GRADIENT }
2640
- }
2641
- ) : (
2642
- // Active-row rail, in the Mode's accent. `--mode-accent` is only set by
2643
- // a declared Mode chrome group, and the inline `transparent` fallback
2644
- // is what every other app gets — so this span is present but invisible
2645
- // there, and being absolutely positioned it moves nothing.
2646
- /* @__PURE__ */ jsx(
2709
+ !active ? (
2710
+ // Sub rows keep the left→right gradient sweep; top-level rows take a
2711
+ // flat wash on hover (design rail: rgba(255,255,255,.05)).
2712
+ isSub ? /* @__PURE__ */ jsx(
2647
2713
  "span",
2648
2714
  {
2649
2715
  "aria-hidden": "true",
2650
- className: "pointer-events-none absolute inset-y-0 left-0 w-[3px] rounded-l-md",
2651
- style: { background: "var(--mode-accent, transparent)" }
2716
+ className: "pointer-events-none absolute inset-y-0 left-0 w-0 transition-[width] duration-300 group-hover:w-full",
2717
+ style: { background: NAV_HOVER_GRADIENT }
2652
2718
  }
2653
- )
2654
- ),
2655
- /* @__PURE__ */ jsxs("span", { className: `relative z-10 flex items-center gap-3 font-semibold ${rowPadding}`, children: [
2656
- Icon ? /* @__PURE__ */ jsx(Icon, { size: iconSize, className: iconClass }) : null,
2657
- item.label
2719
+ ) : null
2720
+ ) : /* @__PURE__ */ jsx(NavActiveRail, {}),
2721
+ /* @__PURE__ */ jsxs("span", { className: `relative z-10 flex items-center ${rowPadding}`, children: [
2722
+ Icon ? /* @__PURE__ */ jsx(Icon, { size: iconSize, className: `shrink-0 ${iconClass}` }) : null,
2723
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
2724
+ /* @__PURE__ */ jsx(NavRowBadge, { value: item.badge })
2658
2725
  ] })
2659
2726
  ] });
2660
2727
  if (item.disabled) {
@@ -2693,8 +2760,8 @@ function NavGroup({
2693
2760
  const Icon = item.icon;
2694
2761
  const headerClasses = [
2695
2762
  "group relative block w-full overflow-hidden text-left transition",
2696
- open ? "rounded-t-md" : "rounded-md",
2697
- active ? "bg-[color:var(--color-accent)] text-white shadow-sm" : open ? "bg-[color:var(--panel)] text-[color:var(--foreground)]" : "text-[color:var(--sidebar-text,var(--muted))] hover:text-white"
2763
+ open ? "rounded-t-[5px]" : "rounded-[5px]",
2764
+ active ? NAV_TOP_ACTIVE_CLASS : open ? "bg-[color:var(--sidebar-row-hover-bg,var(--panel))] text-[color:var(--sidebar-text,var(--foreground))]" : NAV_TOP_INACTIVE_CLASS
2698
2765
  ].join(" ");
2699
2766
  return /* @__PURE__ */ jsxs("div", { children: [
2700
2767
  /* @__PURE__ */ jsxs(
@@ -2708,17 +2775,11 @@ function NavGroup({
2708
2775
  "aria-expanded": open,
2709
2776
  className: headerClasses,
2710
2777
  children: [
2711
- !active && !open ? /* @__PURE__ */ jsx(
2712
- "span",
2713
- {
2714
- "aria-hidden": "true",
2715
- className: "pointer-events-none absolute inset-y-0 left-0 w-0 transition-[width] duration-300 group-hover:w-full",
2716
- style: { background: NAV_HOVER_GRADIENT }
2717
- }
2718
- ) : null,
2719
- /* @__PURE__ */ jsxs("span", { className: "relative z-10 flex items-center gap-3 px-3 py-2 text-sm font-semibold", children: [
2720
- Icon ? /* @__PURE__ */ jsx(Icon, { size: 18, className: active ? "text-white" : "text-current" }) : null,
2721
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: item.label }),
2778
+ active ? /* @__PURE__ */ jsx(NavActiveRail, {}) : null,
2779
+ /* @__PURE__ */ jsxs("span", { className: `relative z-10 flex items-center ${NAV_TOP_ROW_CLASS(active)}`, children: [
2780
+ Icon ? /* @__PURE__ */ jsx(Icon, { size: NAV_TOP_ICON_SIZE, className: "shrink-0 text-current" }) : null,
2781
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
2782
+ /* @__PURE__ */ jsx(NavRowBadge, { value: item.badge }),
2722
2783
  /* @__PURE__ */ jsx(
2723
2784
  ChevronDown,
2724
2785
  {
@@ -2835,8 +2896,8 @@ function OrgIdCopyButton({ id }) {
2835
2896
  setTimeout(() => setCopied(false), 1500);
2836
2897
  },
2837
2898
  title: "Copy organization id",
2838
- className: "rounded px-1 text-[11px] text-[color:var(--muted)] hover:bg-[color:var(--panel)]",
2839
- children: copied ? "Copied" : `...${id.slice(-8)}`
2899
+ className: "-ml-1 rounded px-1 text-left font-[family-name:var(--font-plex-mono,ui-monospace,monospace)] text-[12px] leading-[1.2] text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))] hover:bg-[color:var(--sidebar-row-hover-bg,var(--panel))]",
2900
+ children: copied ? "Copied" : `\u2026${id.slice(-8)}`
2840
2901
  }
2841
2902
  );
2842
2903
  }
@@ -2853,7 +2914,8 @@ function NavTopBar({
2853
2914
  onOpenNav,
2854
2915
  navOpen,
2855
2916
  search,
2856
- buildNotes
2917
+ buildNotes,
2918
+ accountMenu = "topbar"
2857
2919
  }) {
2858
2920
  const rawName = user?.name?.trim() || "";
2859
2921
  const hasRealName = rawName.length > 0 && !rawName.includes("@");
@@ -2861,7 +2923,7 @@ function NavTopBar({
2861
2923
  const initials = (hasRealName ? rawName : user?.email ?? "P").slice(0, 2).toUpperCase();
2862
2924
  const secondary = hasRealName ? user?.email || [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member" : [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member";
2863
2925
  return /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-20", children: [
2864
- /* @__PURE__ */ jsxs("header", { className: "flex h-[var(--topbar-height,60px)] items-center justify-between gap-4 border-b border-[color:var(--line)] bg-[color:var(--panel)] px-[var(--topbar-padding-x,20px)]", children: [
2926
+ /* @__PURE__ */ jsxs("header", { className: "flex h-[var(--topbar-height,60px)] items-center justify-between gap-[14px] border-b border-[color:var(--line)] bg-[color:var(--panel)] px-[var(--topbar-padding-x,20px)]", children: [
2865
2927
  onOpenNav ? /* @__PURE__ */ jsx(
2866
2928
  "button",
2867
2929
  {
@@ -2874,8 +2936,8 @@ function NavTopBar({
2874
2936
  children: /* @__PURE__ */ jsx(HamburgerIcon, {})
2875
2937
  }
2876
2938
  ) : null,
2877
- /* @__PURE__ */ jsxs("label", { className: "relative flex w-[320px] max-w-full shrink-0 items-center", children: [
2878
- /* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-3 h-4 w-4 text-[color:var(--muted)]" }),
2939
+ /* @__PURE__ */ jsxs("label", { className: "relative flex h-9 w-[320px] max-w-full shrink-0 items-center", children: [
2940
+ /* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute left-[10px] h-[15px] w-[15px] text-[color:var(--muted)]" }),
2879
2941
  /* @__PURE__ */ jsx(
2880
2942
  "input",
2881
2943
  {
@@ -2887,32 +2949,35 @@ function NavTopBar({
2887
2949
  if (e.key === "Enter") search.onSubmit?.(e.target.value);
2888
2950
  } : void 0,
2889
2951
  readOnly: !search?.onChange,
2890
- className: "w-full rounded-md border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1.5 pl-9 pr-10 text-sm text-[color:var(--foreground)] placeholder:text-[color:var(--muted)] focus:outline-none focus:ring-2 focus:ring-[color:var(--color-accent)]"
2952
+ className: "h-full w-full rounded-[5px] border border-[color:var(--line)] bg-[color:var(--surface-sunken,var(--panel-elevated))] pl-[33px] pr-10 text-[13px] text-[color:var(--foreground)] placeholder:text-[color:var(--muted)] focus:outline-none focus:ring-2 focus:ring-[color:var(--color-accent)]"
2891
2953
  }
2892
2954
  ),
2893
2955
  /* @__PURE__ */ jsx(
2894
2956
  "kbd",
2895
2957
  {
2896
2958
  "aria-hidden": true,
2897
- className: "pointer-events-none absolute right-2.5 rounded border border-[color:var(--line)] px-1 py-0.5 text-[10px] font-medium text-[color:var(--muted)]",
2959
+ className: "pointer-events-none absolute right-[10px] rounded-[3px] border border-[color:var(--line)] px-[5px] py-px font-[family-name:var(--font-plex-mono,ui-monospace,monospace)] text-[12px] leading-[1.2] text-[color:var(--muted)]",
2898
2960
  children: "/"
2899
2961
  }
2900
2962
  )
2901
2963
  ] }),
2902
2964
  /* @__PURE__ */ jsxs("div", { className: "relative ml-auto flex shrink-0 items-center gap-[var(--topbar-icon-gap,8px)]", children: [
2903
- /* @__PURE__ */ jsx(
2965
+ /* @__PURE__ */ jsxs(
2904
2966
  "button",
2905
2967
  {
2906
2968
  type: "button",
2907
2969
  onClick: buildNotes?.onOpen,
2908
- className: "shrink-0 rounded-md px-2 py-1.5 text-sm font-medium text-[color:var(--muted)] transition hover:bg-[color:var(--panel-elevated)] hover:text-[color:var(--foreground)]",
2909
- children: buildNotes?.label ?? "Build notes"
2970
+ className: "inline-flex h-8 shrink-0 items-center gap-1.5 rounded-[5px] px-3 text-xs font-semibold text-[color:var(--muted)] transition hover:bg-[color:var(--surface-sunken,var(--panel-elevated))] hover:text-[color:var(--foreground)]",
2971
+ children: [
2972
+ /* @__PURE__ */ jsx(BookOpenIcon, {}),
2973
+ buildNotes?.label ?? "Build notes"
2974
+ ]
2910
2975
  }
2911
2976
  ),
2912
2977
  actionsList && actionsList.length > 0 ? actionsList.map((action) => /* @__PURE__ */ jsx(NavTopBarActionButton, { action }, action.key)) : null,
2913
2978
  actions,
2914
2979
  themeToggle,
2915
- /* @__PURE__ */ jsxs("details", { "data-nav-details": true, className: "group/acct relative", children: [
2980
+ accountMenu === "topbar" ? /* @__PURE__ */ jsxs("details", { "data-nav-details": true, className: "group/acct relative", children: [
2916
2981
  /* @__PURE__ */ jsxs("summary", { className: "group/tbtip relative flex cursor-pointer list-none items-center gap-2.5 rounded-full py-1 pl-1 pr-2 transition hover:bg-[color:var(--panel-elevated)] [&::-webkit-details-marker]:hidden", children: [
2917
2982
  /* @__PURE__ */ jsx("span", { className: "flex h-[var(--topbar-icon-button-size,32px)] w-[var(--topbar-icon-button-size,32px)] items-center justify-center overflow-hidden rounded-full bg-[color:var(--color-accent)] text-xs font-bold text-white", children: user?.avatarUrl || user?.memojiUrl ? /* @__PURE__ */ jsx(
2918
2983
  "img",
@@ -2943,127 +3008,9 @@ function NavTopBar({
2943
3008
  }
2944
3009
  ) })
2945
3010
  ] }),
2946
- /* @__PURE__ */ jsxs("div", { className: "absolute right-0 z-30 mt-2 flex max-h-[calc(100vh-5rem)] w-72 flex-col overflow-hidden rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 shadow-[var(--shadow-soft)]", children: [
2947
- /* @__PURE__ */ jsx(TopBarPanelArrow, {}),
2948
- /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain", children: [
2949
- userMenu?.myProfileHref ? /* @__PURE__ */ jsxs(
2950
- "a",
2951
- {
2952
- href: safeHref(userMenu.myProfileHref),
2953
- className: "flex w-full items-center gap-2.5 px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
2954
- children: [
2955
- /* @__PURE__ */ jsx(ProfileIcon, {}),
2956
- "My Profile"
2957
- ]
2958
- }
2959
- ) : null,
2960
- userMenu?.organizationSettingsHref ? /* @__PURE__ */ jsxs(
2961
- "a",
2962
- {
2963
- href: safeHref(userMenu.organizationSettingsHref),
2964
- className: "flex w-full items-center gap-2.5 border-t border-[color:var(--line)] px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
2965
- children: [
2966
- /* @__PURE__ */ jsx(BriefcaseIcon, {}),
2967
- "Organization Settings"
2968
- ]
2969
- }
2970
- ) : null,
2971
- userMenu?.roles && userMenu.roles.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
2972
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Roles & Organizations" }),
2973
- /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: userMenu.roles.map((r, i) => /* @__PURE__ */ jsxs("li", { className: "flex flex-wrap items-center gap-1.5 text-sm", children: [
2974
- /* @__PURE__ */ jsx("span", { className: "rounded-md bg-[color:var(--panel)] px-2 py-0.5 text-xs font-bold uppercase tracking-wide text-[color:var(--foreground)]", children: r.role }),
2975
- r.orgName ? /* @__PURE__ */ jsxs("span", { className: "text-[color:var(--muted)]", children: [
2976
- "in ",
2977
- r.orgName
2978
- ] }) : null
2979
- ] }, `${r.role}-${i}`)) })
2980
- ] }) : null,
2981
- userMenu?.accounts && userMenu.accounts.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
2982
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Accounts" }),
2983
- /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1", children: userMenu.accounts.map((a) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2.5", children: [
2984
- /* @__PURE__ */ jsxs(
2985
- "button",
2986
- {
2987
- type: "button",
2988
- onClick: () => {
2989
- if (!a.active) userMenu.onSwitchAccount?.(a.id);
2990
- },
2991
- className: "flex min-w-0 flex-1 items-center gap-2.5 rounded-lg px-1 py-1 text-left hover:bg-[color:var(--panel)]",
2992
- children: [
2993
- /* @__PURE__ */ jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full bg-[color:var(--color-accent)] text-[11px] font-bold text-white", children: a.avatarUrl ? /* @__PURE__ */ jsx("img", { src: a.avatarUrl, alt: "", className: "h-full w-full object-cover" }) : (a.name ?? a.email ?? "?").slice(0, 2).toUpperCase() }),
2994
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col leading-tight", children: [
2995
- /* @__PURE__ */ jsx(
2996
- "span",
2997
- {
2998
- className: [
2999
- "truncate text-sm font-semibold",
3000
- a.active ? "text-[color:var(--color-accent)]" : "text-[color:var(--foreground)]"
3001
- ].join(" "),
3002
- children: a.name ?? a.email ?? a.id.slice(0, 8)
3003
- }
3004
- ),
3005
- /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-[color:var(--muted)]", children: a.active ? "Active" : a.email ?? "" })
3006
- ] })
3007
- ]
3008
- }
3009
- ),
3010
- !a.active && userMenu.onRemoveAccount ? /* @__PURE__ */ jsx(
3011
- "button",
3012
- {
3013
- type: "button",
3014
- "aria-label": `Remove ${a.name ?? a.email ?? "account"}`,
3015
- onClick: () => userMenu.onRemoveAccount?.(a.id),
3016
- className: "shrink-0 rounded p-1 text-[color:var(--color-accent)] hover:bg-[color:var(--panel)]",
3017
- children: /* @__PURE__ */ jsx(TrashIcon, {})
3018
- }
3019
- ) : null
3020
- ] }, a.id)) }),
3021
- userMenu.addAccountHref || userMenu.onAddAccount ? userMenu.addAccountHref ? /* @__PURE__ */ jsxs(
3022
- "a",
3023
- {
3024
- href: safeHref(userMenu.addAccountHref),
3025
- className: "mt-1.5 flex items-center gap-2.5 rounded-lg px-1 py-1.5 text-sm font-semibold text-[color:var(--color-accent)] hover:bg-[color:var(--panel)]",
3026
- children: [
3027
- /* @__PURE__ */ jsx(AddUserIcon, {}),
3028
- "Add Account"
3029
- ]
3030
- }
3031
- ) : /* @__PURE__ */ jsxs(
3032
- "button",
3033
- {
3034
- type: "button",
3035
- onClick: userMenu.onAddAccount,
3036
- className: "mt-1.5 flex w-full items-center gap-2.5 rounded-lg px-1 py-1.5 text-left text-sm font-semibold text-[color:var(--color-accent)] hover:bg-[color:var(--panel)]",
3037
- children: [
3038
- /* @__PURE__ */ jsx(AddUserIcon, {}),
3039
- "Add Account"
3040
- ]
3041
- }
3042
- ) : null
3043
- ] }) : null,
3044
- userMenu?.theme ? /* @__PURE__ */ jsx("div", { className: "border-t border-[color:var(--line)]", children: /* @__PURE__ */ jsx(
3045
- NavThemeControl,
3046
- {
3047
- value: userMenu.theme.value,
3048
- onChange: userMenu.theme.onChange
3049
- }
3050
- ) }) : null
3051
- ] }),
3052
- onSignOut ? /* @__PURE__ */ jsxs(
3053
- "button",
3054
- {
3055
- type: "button",
3056
- onClick: onSignOut,
3057
- className: "flex w-full shrink-0 items-center gap-2.5 border-t border-[color:var(--line)] px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)] hover:text-[color:var(--color-accent)]",
3058
- children: [
3059
- /* @__PURE__ */ jsx(SignOutIcon, {}),
3060
- "Sign out"
3061
- ]
3062
- }
3063
- ) : null
3064
- ] })
3065
- ] }),
3066
- !hasRealName && user ? /* @__PURE__ */ jsx(NamePromptBubble, { profileHref: userMenu?.myProfileHref }) : null
3011
+ /* @__PURE__ */ jsx(NavAccountMenuPanel, { userMenu, onSignOut, placement: "below" })
3012
+ ] }) : null,
3013
+ accountMenu === "topbar" && !hasRealName && user ? /* @__PURE__ */ jsx(NamePromptBubble, { profileHref: userMenu?.myProfileHref }) : null
3067
3014
  ] })
3068
3015
  ] }),
3069
3016
  /* @__PURE__ */ jsx(
@@ -3078,7 +3025,191 @@ function NavTopBar({
3078
3025
  )
3079
3026
  ] });
3080
3027
  }
3081
- function NamePromptBubble({ profileHref }) {
3028
+ function NavAccountMenuPanel({
3029
+ userMenu,
3030
+ onSignOut,
3031
+ placement
3032
+ }) {
3033
+ const wrapper = placement === "above" ? "absolute bottom-full left-0 right-0 z-40 mb-2 flex max-h-[calc(100vh-5rem)] flex-col overflow-hidden rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 text-[color:var(--foreground)] shadow-[var(--shadow-soft)]" : "absolute right-0 z-30 mt-2 flex max-h-[calc(100vh-5rem)] w-72 flex-col overflow-hidden rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] py-1 shadow-[var(--shadow-soft)]";
3034
+ return /* @__PURE__ */ jsxs("div", { className: wrapper, children: [
3035
+ placement === "below" ? /* @__PURE__ */ jsx(TopBarPanelArrow, {}) : null,
3036
+ /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain", children: [
3037
+ userMenu?.myProfileHref ? /* @__PURE__ */ jsxs(
3038
+ "a",
3039
+ {
3040
+ href: safeHref(userMenu.myProfileHref),
3041
+ className: "flex w-full items-center gap-2.5 px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
3042
+ children: [
3043
+ /* @__PURE__ */ jsx(ProfileIcon, {}),
3044
+ "My Profile"
3045
+ ]
3046
+ }
3047
+ ) : null,
3048
+ userMenu?.organizationSettingsHref ? /* @__PURE__ */ jsxs(
3049
+ "a",
3050
+ {
3051
+ href: safeHref(userMenu.organizationSettingsHref),
3052
+ className: "flex w-full items-center gap-2.5 border-t border-[color:var(--line)] px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
3053
+ children: [
3054
+ /* @__PURE__ */ jsx(BriefcaseIcon, {}),
3055
+ "Organization Settings"
3056
+ ]
3057
+ }
3058
+ ) : null,
3059
+ userMenu?.roles && userMenu.roles.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
3060
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Roles & Organizations" }),
3061
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: userMenu.roles.map((r, i) => /* @__PURE__ */ jsxs("li", { className: "flex flex-wrap items-center gap-1.5 text-sm", children: [
3062
+ /* @__PURE__ */ jsx("span", { className: "rounded-md bg-[color:var(--panel)] px-2 py-0.5 text-xs font-bold uppercase tracking-wide text-[color:var(--foreground)]", children: r.role }),
3063
+ r.orgName ? /* @__PURE__ */ jsxs("span", { className: "text-[color:var(--muted)]", children: [
3064
+ "in ",
3065
+ r.orgName
3066
+ ] }) : null
3067
+ ] }, `${r.role}-${i}`)) })
3068
+ ] }) : null,
3069
+ userMenu?.accounts && userMenu.accounts.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
3070
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Accounts" }),
3071
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1", children: userMenu.accounts.map((a) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2.5", children: [
3072
+ /* @__PURE__ */ jsxs(
3073
+ "button",
3074
+ {
3075
+ type: "button",
3076
+ onClick: () => {
3077
+ if (!a.active) userMenu.onSwitchAccount?.(a.id);
3078
+ },
3079
+ className: "flex min-w-0 flex-1 items-center gap-2.5 rounded-lg px-1 py-1 text-left hover:bg-[color:var(--panel)]",
3080
+ children: [
3081
+ /* @__PURE__ */ jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full bg-[color:var(--color-accent)] text-[11px] font-bold text-white", children: a.avatarUrl ? /* @__PURE__ */ jsx("img", { src: a.avatarUrl, alt: "", className: "h-full w-full object-cover" }) : (a.name ?? a.email ?? "?").slice(0, 2).toUpperCase() }),
3082
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col leading-tight", children: [
3083
+ /* @__PURE__ */ jsx(
3084
+ "span",
3085
+ {
3086
+ className: [
3087
+ "truncate text-sm font-semibold",
3088
+ a.active ? "text-[color:var(--color-accent)]" : "text-[color:var(--foreground)]"
3089
+ ].join(" "),
3090
+ children: a.name ?? a.email ?? a.id.slice(0, 8)
3091
+ }
3092
+ ),
3093
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-[color:var(--muted)]", children: a.active ? "Active" : a.email ?? "" })
3094
+ ] })
3095
+ ]
3096
+ }
3097
+ ),
3098
+ !a.active && userMenu.onRemoveAccount ? /* @__PURE__ */ jsx(
3099
+ "button",
3100
+ {
3101
+ type: "button",
3102
+ "aria-label": `Remove ${a.name ?? a.email ?? "account"}`,
3103
+ onClick: () => userMenu.onRemoveAccount?.(a.id),
3104
+ className: "shrink-0 rounded p-1 text-[color:var(--color-accent)] hover:bg-[color:var(--panel)]",
3105
+ children: /* @__PURE__ */ jsx(TrashIcon, {})
3106
+ }
3107
+ ) : null
3108
+ ] }, a.id)) }),
3109
+ userMenu.addAccountHref || userMenu.onAddAccount ? userMenu.addAccountHref ? /* @__PURE__ */ jsxs(
3110
+ "a",
3111
+ {
3112
+ href: safeHref(userMenu.addAccountHref),
3113
+ className: "mt-1.5 flex items-center gap-2.5 rounded-lg px-1 py-1.5 text-sm font-semibold text-[color:var(--color-accent)] hover:bg-[color:var(--panel)]",
3114
+ children: [
3115
+ /* @__PURE__ */ jsx(AddUserIcon, {}),
3116
+ "Add Account"
3117
+ ]
3118
+ }
3119
+ ) : /* @__PURE__ */ jsxs(
3120
+ "button",
3121
+ {
3122
+ type: "button",
3123
+ onClick: userMenu.onAddAccount,
3124
+ className: "mt-1.5 flex w-full items-center gap-2.5 rounded-lg px-1 py-1.5 text-left text-sm font-semibold text-[color:var(--color-accent)] hover:bg-[color:var(--panel)]",
3125
+ children: [
3126
+ /* @__PURE__ */ jsx(AddUserIcon, {}),
3127
+ "Add Account"
3128
+ ]
3129
+ }
3130
+ ) : null
3131
+ ] }) : null,
3132
+ userMenu?.theme ? /* @__PURE__ */ jsx("div", { className: "border-t border-[color:var(--line)]", children: /* @__PURE__ */ jsx(
3133
+ NavThemeControl,
3134
+ {
3135
+ value: userMenu.theme.value,
3136
+ onChange: userMenu.theme.onChange
3137
+ }
3138
+ ) }) : null,
3139
+ userMenu?.navDisplay ? /* @__PURE__ */ jsxs("div", { className: "border-t border-[color:var(--line)] px-4 py-3", children: [
3140
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]", children: "Navigation display" }),
3141
+ /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": "Navigation display", className: "flex flex-col gap-0.5", children: NAV_DISPLAY_OPTIONS.map((opt) => /* @__PURE__ */ jsxs(
3142
+ "button",
3143
+ {
3144
+ type: "button",
3145
+ role: "radio",
3146
+ "aria-checked": userMenu.navDisplay?.value === opt.value,
3147
+ onClick: () => userMenu.navDisplay?.onChange(opt.value),
3148
+ className: [
3149
+ "flex w-full items-center justify-between rounded-md px-2 py-1.5 text-left text-sm font-medium",
3150
+ userMenu.navDisplay?.value === opt.value ? "text-[color:var(--color-accent)]" : "text-[color:var(--foreground)] hover:bg-[color:var(--panel)]"
3151
+ ].join(" "),
3152
+ children: [
3153
+ opt.label,
3154
+ userMenu.navDisplay?.value === opt.value ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u2713" }) : null
3155
+ ]
3156
+ },
3157
+ opt.value
3158
+ )) })
3159
+ ] }) : null
3160
+ ] }),
3161
+ onSignOut ? /* @__PURE__ */ jsxs(
3162
+ "button",
3163
+ {
3164
+ type: "button",
3165
+ onClick: onSignOut,
3166
+ className: "flex w-full shrink-0 items-center gap-2.5 border-t border-[color:var(--line)] px-4 py-2.5 text-left text-sm font-medium text-[color:var(--foreground)] hover:bg-[color:var(--panel)] hover:text-[color:var(--color-accent)]",
3167
+ children: [
3168
+ /* @__PURE__ */ jsx(SignOutIcon, {}),
3169
+ "Sign out"
3170
+ ]
3171
+ }
3172
+ ) : null
3173
+ ] });
3174
+ }
3175
+ function NavSidebarUserCard({
3176
+ user,
3177
+ userMenu,
3178
+ onSignOut
3179
+ }) {
3180
+ const rawName = user.name?.trim() || "";
3181
+ const hasRealName = rawName.length > 0 && !rawName.includes("@");
3182
+ const displayName = hasRealName ? rawName : user.email ?? "Signed in";
3183
+ const initials = (hasRealName ? rawName : user.email ?? "P").slice(0, 2).toUpperCase();
3184
+ const secondary = hasRealName ? user.email || [user.tier, user.role].filter(Boolean).join(" \xB7 ") || "member" : [user.tier, user.role].filter(Boolean).join(" \xB7 ") || "member";
3185
+ return /* @__PURE__ */ jsxs("details", { "data-nav-details": true, className: "group/acct relative", children: [
3186
+ /* @__PURE__ */ jsxs(
3187
+ "summary",
3188
+ {
3189
+ "aria-label": "My Account",
3190
+ className: "flex w-full cursor-pointer list-none items-center gap-[9px] rounded-[5px] px-1 py-1 text-left transition hover:bg-[color:var(--sidebar-row-hover-bg,var(--panel-elevated))] [&::-webkit-details-marker]:hidden",
3191
+ children: [
3192
+ /* @__PURE__ */ jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center overflow-hidden rounded-full bg-[color:var(--sidebar-avatar-bg,var(--color-accent))] text-[11px] font-bold text-white", children: user.avatarUrl || user.memojiUrl ? /* @__PURE__ */ jsx("img", { src: user.avatarUrl || user.memojiUrl, alt: "", className: "h-full w-full object-cover" }) : initials }),
3193
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [
3194
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[12px] font-semibold leading-[1.2] text-[color:var(--sidebar-text,var(--foreground))]", children: displayName }),
3195
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[11px] leading-[1.3] text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))]", children: secondary })
3196
+ ] }),
3197
+ /* @__PURE__ */ jsx(ChevronDown, { size: 14, className: "shrink-0 rotate-180 text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))] transition group-open/acct:rotate-0" })
3198
+ ]
3199
+ }
3200
+ ),
3201
+ /* @__PURE__ */ jsx(NavAccountMenuPanel, { userMenu, onSignOut, placement: "above" }),
3202
+ !hasRealName ? /* @__PURE__ */ jsx(NamePromptBubble, { profileHref: userMenu?.myProfileHref, placement: "above" }) : null
3203
+ ] });
3204
+ }
3205
+ function hexToRgba(hex, alpha) {
3206
+ if (!hex) return void 0;
3207
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
3208
+ if (!m) return void 0;
3209
+ const n = parseInt(m[1], 16);
3210
+ return `rgba(${n >> 16 & 255}, ${n >> 8 & 255}, ${n & 255}, ${alpha})`;
3211
+ }
3212
+ function NamePromptBubble({ profileHref, placement = "below" }) {
3082
3213
  const KEY = "politogy_name_prompt_dismissed";
3083
3214
  const [dismissed, setDismissed] = useState(true);
3084
3215
  useEffect(() => {
@@ -3089,42 +3220,48 @@ function NamePromptBubble({ profileHref }) {
3089
3220
  }
3090
3221
  }, []);
3091
3222
  if (dismissed) return null;
3092
- return /* @__PURE__ */ jsxs("div", { className: "absolute right-4 top-full z-30 mt-2 w-64 rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] p-3 shadow-[var(--shadow-soft)]", children: [
3093
- /* @__PURE__ */ jsx(
3094
- "span",
3095
- {
3096
- "aria-hidden": true,
3097
- className: "absolute -top-[5px] right-[11px] h-2.5 w-2.5 rotate-45 border-l border-t border-[color:var(--line)] bg-[color:var(--panel-elevated)]"
3098
- }
3099
- ),
3100
- /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: "Add your name" }),
3101
- /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs leading-snug text-[color:var(--muted)]", children: "Set your first and last name so teammates see you \u2014 not your email." }),
3102
- /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
3103
- profileHref ? /* @__PURE__ */ jsx(
3104
- "a",
3105
- {
3106
- href: safeHref(profileHref),
3107
- className: "rounded-full bg-[color:var(--color-accent)] px-3 py-1 text-xs font-semibold text-white hover:opacity-90",
3108
- children: "Set name"
3109
- }
3110
- ) : null,
3111
- /* @__PURE__ */ jsx(
3112
- "button",
3113
- {
3114
- type: "button",
3115
- onClick: () => {
3116
- setDismissed(true);
3117
- try {
3118
- sessionStorage.setItem(KEY, "1");
3119
- } catch {
3223
+ return /* @__PURE__ */ jsxs(
3224
+ "div",
3225
+ {
3226
+ className: placement === "above" ? "absolute bottom-full left-0 z-30 mb-2 w-64 rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] p-3 text-left shadow-[var(--shadow-soft)]" : "absolute right-4 top-full z-30 mt-2 w-64 rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] p-3 shadow-[var(--shadow-soft)]",
3227
+ children: [
3228
+ /* @__PURE__ */ jsx(
3229
+ "span",
3230
+ {
3231
+ "aria-hidden": true,
3232
+ className: placement === "above" ? "absolute -bottom-[5px] left-[14px] h-2.5 w-2.5 rotate-45 border-b border-r border-[color:var(--line)] bg-[color:var(--panel-elevated)]" : "absolute -top-[5px] right-[11px] h-2.5 w-2.5 rotate-45 border-l border-t border-[color:var(--line)] bg-[color:var(--panel-elevated)]"
3233
+ }
3234
+ ),
3235
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: "Add your name" }),
3236
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs leading-snug text-[color:var(--muted)]", children: "Set your first and last name so teammates see you \u2014 not your email." }),
3237
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
3238
+ profileHref ? /* @__PURE__ */ jsx(
3239
+ "a",
3240
+ {
3241
+ href: safeHref(profileHref),
3242
+ className: "rounded-full bg-[color:var(--color-accent)] px-3 py-1 text-xs font-semibold text-white hover:opacity-90",
3243
+ children: "Set name"
3120
3244
  }
3121
- },
3122
- className: "rounded-full border border-[color:var(--line)] px-3 py-1 text-xs font-semibold text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
3123
- children: "Dismiss"
3124
- }
3125
- )
3126
- ] })
3127
- ] });
3245
+ ) : null,
3246
+ /* @__PURE__ */ jsx(
3247
+ "button",
3248
+ {
3249
+ type: "button",
3250
+ onClick: () => {
3251
+ setDismissed(true);
3252
+ try {
3253
+ sessionStorage.setItem(KEY, "1");
3254
+ } catch {
3255
+ }
3256
+ },
3257
+ className: "rounded-full border border-[color:var(--line)] px-3 py-1 text-xs font-semibold text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
3258
+ children: "Dismiss"
3259
+ }
3260
+ )
3261
+ ] })
3262
+ ]
3263
+ }
3264
+ );
3128
3265
  }
3129
3266
  function formatFirstLast(name) {
3130
3267
  const parts = name.split(/\s+/).filter(Boolean);
@@ -3185,8 +3322,8 @@ function NavTopBarActionButton({ action }) {
3185
3322
  const BrandGlyph = action.slot ? resolveBrandGlyph(glyphName) : null;
3186
3323
  const Glyph = BrandGlyph ?? Icon;
3187
3324
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
3188
- /* @__PURE__ */ jsx(Glyph, { size: 20, className: "text-current" }),
3189
- typeof action.badge === "number" && action.badge > 0 ? /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--color-accent)] px-1 text-[10px] text-white", children: action.badge }) : null,
3325
+ /* @__PURE__ */ jsx(Glyph, { size: TOPBAR_GLYPH_SIZE, className: "text-current" }),
3326
+ typeof action.badge === "number" && action.badge > 0 ? /* @__PURE__ */ jsx("span", { className: "absolute -top-[5px] -right-[5px] flex h-4 min-w-4 items-center justify-center rounded-full bg-[color:var(--chrome-danger,var(--color-accent))] px-1 text-[10px] font-bold leading-4 text-white", children: action.badge }) : null,
3190
3327
  /* @__PURE__ */ jsx(TopBarTooltip, { title: action.label, description: action.description })
3191
3328
  ] });
3192
3329
  const isExternal = action.href ? /^https?:\/\//.test(action.href) : false;
@@ -3411,6 +3548,7 @@ function NavAppShell({
3411
3548
  topBar,
3412
3549
  betaBanner,
3413
3550
  contentWrapper = "padded",
3551
+ accountMenuPlacement = "sidebar",
3414
3552
  modeId,
3415
3553
  children
3416
3554
  }) {
@@ -3427,15 +3565,29 @@ function NavAppShell({
3427
3565
  document.body.style.overflow = previous;
3428
3566
  };
3429
3567
  }, [navOpen]);
3568
+ const sidebarFooter = accountMenuPlacement === "sidebar" && topBar.user ? {
3569
+ ...sidebar.footer ?? {},
3570
+ user: sidebar.footer?.user ?? topBar.user,
3571
+ userMenu: sidebar.footer?.userMenu ?? topBar.userMenu,
3572
+ onSignOut: sidebar.footer?.onSignOut ?? topBar.onSignOut
3573
+ } : sidebar.footer;
3430
3574
  return /* @__PURE__ */ jsxs(
3431
3575
  "div",
3432
3576
  {
3433
3577
  "data-politogy-mode": modeId,
3434
3578
  className: "min-h-screen bg-[color:var(--background)] text-[color:var(--foreground)]",
3435
3579
  children: [
3436
- /* @__PURE__ */ jsx(NavSidebar, { ...sidebar, open: navOpen, onClose: () => setNavOpen(false) }),
3437
- /* @__PURE__ */ jsxs("div", { className: "lg:pl-[240px]", children: [
3438
- /* @__PURE__ */ jsx(NavTopBar, { ...topBar, onOpenNav: () => setNavOpen(true), navOpen }),
3580
+ /* @__PURE__ */ jsx(NavSidebar, { ...sidebar, footer: sidebarFooter, open: navOpen, onClose: () => setNavOpen(false) }),
3581
+ /* @__PURE__ */ jsxs("div", { className: "lg:pl-[var(--sidebar-width,236px)]", children: [
3582
+ /* @__PURE__ */ jsx(
3583
+ NavTopBar,
3584
+ {
3585
+ ...topBar,
3586
+ accountMenu: topBar.accountMenu ?? (accountMenuPlacement === "sidebar" ? "sidebar" : "topbar"),
3587
+ onOpenNav: () => setNavOpen(true),
3588
+ navOpen
3589
+ }
3590
+ ),
3439
3591
  betaBanner ? /* @__PURE__ */ jsx(NavBetaBanner, { ...betaBanner }) : null,
3440
3592
  topBar.title ? /* @__PURE__ */ jsx("h1", { className: "px-6 pt-7 text-xl font-semibold text-[color:var(--foreground)]", children: topBar.title }) : null,
3441
3593
  contentWrapper === "bare" ? /* @__PURE__ */ jsx("div", { "data-shell-content": "", className: topBar.title ? "mt-[22px]" : void 0, children }) : (
@@ -3460,5 +3612,5 @@ function NavAppShell({
3460
3612
  }
3461
3613
 
3462
3614
  export { BETA_BANNER_DISMISS_KEY, CAMPAIGN_FEATURE_AVAILABILITY, CORE_APP_ORIGIN, CORE_BILLING_PATH, FuelAction, NavAppShell, NavBetaBanner, NavChromeProvider, NavDisplayAction, NavSidebar, NavTabStrip, NavThemeControl, NavTopBar, NotificationsAction, SPECS_ORIGIN, SpecOverlayAction, SupportAction, TopBarCountBadge, TopBarPanelArrow, TopBarPopover, TopBarTooltip, TopBarWidgetSlot, clearBetaBannerDismissal, envChipClasses, isNavItemActive, resolveOrgLogoUrl, standardPolitogyNav, topBarIconButtonClass, useChromeMe, useChromeOrgs, useNavChromeFetcher, useThemePreference };
3463
- //# sourceMappingURL=chunk-T5ERHFNT.js.map
3464
- //# sourceMappingURL=chunk-T5ERHFNT.js.map
3615
+ //# sourceMappingURL=chunk-ZKYREVCK.js.map
3616
+ //# sourceMappingURL=chunk-ZKYREVCK.js.map