@the-portland-company/shell 0.69.0 → 0.71.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/native.cjs CHANGED
@@ -88,6 +88,56 @@ function normalize(s) {
88
88
  return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().trim();
89
89
  }
90
90
 
91
+ // src/nav-preference.ts
92
+ var NAV_DISPLAY_STORAGE_KEY = "politogy_nav_display";
93
+ var NAV_DISPLAY_COOKIE = "politogy_nav_display";
94
+ `(function(){try{
95
+ var KEY=${JSON.stringify(NAV_DISPLAY_STORAGE_KEY)};
96
+ var VALID=["menu","tabs","both"];
97
+ function fromCookie(){try{var m=document.cookie.match(/(?:^|;\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)/);return m?decodeURIComponent(m[1]):null;}catch(e){return null;}}
98
+ var cookie=fromCookie();
99
+ if(cookie&&VALID.indexOf(cookie)!==-1){var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}
100
+ if(cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}}
101
+ }catch(e){}})();`;
102
+ var RAIL_STORAGE_KEY = "politogy_rail";
103
+ var RAIL_COOKIE = "politogy_rail";
104
+ var RAIL_DEFAULT = "collapsed";
105
+ function isRailPreference(v) {
106
+ return v === "expanded" || v === "collapsed";
107
+ }
108
+ function readRailPreference() {
109
+ if (typeof document !== "undefined") {
110
+ try {
111
+ const m = document.cookie.match(new RegExp(`(?:^|;\\s*)${RAIL_COOKIE}=([^;]+)`));
112
+ const v = m ? decodeURIComponent(m[1]) : null;
113
+ if (isRailPreference(v)) return v;
114
+ } catch {
115
+ }
116
+ }
117
+ if (typeof localStorage !== "undefined") {
118
+ try {
119
+ const v = localStorage.getItem(RAIL_STORAGE_KEY);
120
+ if (isRailPreference(v)) return v;
121
+ } catch {
122
+ }
123
+ }
124
+ return RAIL_DEFAULT;
125
+ }
126
+ function writeRailPreference(pref) {
127
+ if (typeof document === "undefined" || typeof window === "undefined") return;
128
+ const host = window.location.hostname;
129
+ const domainAttr = /(^|\.)politogyvrm\.com$/i.test(host) ? "; Domain=.politogyvrm.com" : "";
130
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
131
+ try {
132
+ document.cookie = `${RAIL_COOKIE}=${pref}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
133
+ } catch {
134
+ }
135
+ try {
136
+ localStorage.setItem(RAIL_STORAGE_KEY, pref);
137
+ } catch {
138
+ }
139
+ }
140
+
91
141
  // src/theme-preference.ts
92
142
  var THEME_STORAGE_KEY = "politogy_theme";
93
143
  var THEME_COOKIE = "politogy_theme";
@@ -206,7 +256,7 @@ function topBarIconButtonClass(tone = "default") {
206
256
  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)]";
207
257
  return [
208
258
  // `group/tbtip` powers the shared <TopBarTooltip> rendered inside the trigger.
209
- "group/tbtip relative flex items-center justify-center rounded-[var(--topbar-icon-button-radius,5px)] border border-[color:var(--line)] transition",
259
+ "group/tbtip relative flex items-center justify-center rounded-[var(--topbar-icon-button-radius,5px)] border border-transparent transition",
210
260
  "h-[var(--topbar-icon-button-size,34px)] w-[var(--topbar-icon-button-size,34px)]",
211
261
  toneClass
212
262
  ].join(" ");
@@ -1882,7 +1932,6 @@ var PHONEBANK_ORIGIN = "https://phonebank.politogyvrm.com/";
1882
1932
  var CANVASS_ORIGIN = "https://canvass.politogyvrm.com/";
1883
1933
  var SIGNS_ORIGIN = "https://signs.politogyvrm.com/";
1884
1934
  var POLLS_ORIGIN = "https://polls.politogyvrm.com/";
1885
- var CONTACTS_TRIBES = "https://contacts.politogyvrm.com/tribes";
1886
1935
  var PETITION_MODE_ORIGIN = "https://petition-mode.politogyvrm.com/";
1887
1936
  function applyHiddenItems(items, hidden) {
1888
1937
  if (!hidden || hidden.length === 0) return items;
@@ -1952,10 +2001,6 @@ var APP_POLLS_CHILDREN = [
1952
2001
  { label: "Command Center", icon: "grid", href: "https://polls.politogyvrm.com/" },
1953
2002
  { label: "New Poll", icon: "edit", href: "https://polls.politogyvrm.com/polls/new" }
1954
2003
  ];
1955
- var APP_CTAS_CHILDREN = [
1956
- { label: "CTAs", icon: "list", href: "https://ctas.politogyvrm.com/" },
1957
- { label: "Canvas", icon: "edit", href: "https://ctas.politogyvrm.com/?tab=canvas" }
1958
- ];
1959
2004
  var APP_A2P_CHILDREN = [
1960
2005
  { label: "Dashboard", icon: "grid", path: "dashboard" },
1961
2006
  { label: "Compose", icon: "edit", path: "compose" },
@@ -2003,16 +2048,27 @@ function standardPolitogyNav(opts) {
2003
2048
  return { label: c.label, icon: icon(c.icon), href: withOrg(withMode) };
2004
2049
  });
2005
2050
  };
2051
+ const accountRows = () => [
2052
+ { kind: "section", label: "Account" },
2053
+ // My Profile is global — NOT org-suffixed (main-app ShellChromeBridge).
2054
+ { label: "My profile", icon: icon("circleUser"), href: withOrg(abs("/my-profile")) },
2055
+ {
2056
+ label: "Organization settings",
2057
+ icon: icon("settings"),
2058
+ href: withOrg(abs("/organization-settings")),
2059
+ children: branches(ORG_SETTINGS_CHILDREN)
2060
+ }
2061
+ ];
2006
2062
  const buildRelationship = () => {
2007
2063
  const contacts = opts.contactsItem ? {
2008
2064
  label: "Contacts",
2009
- icon: icon("users"),
2065
+ icon: icon("usersRound"),
2010
2066
  href: opts.contactsItem.href,
2011
2067
  children: opts.contactsItem.children,
2012
2068
  badge: opts.contactsItem.count ?? void 0
2013
2069
  } : {
2014
2070
  label: "Contacts",
2015
- icon: icon("users"),
2071
+ icon: icon("usersRound"),
2016
2072
  href: withOrg(`${CONTACTS_APP}/`),
2017
2073
  children: APP_CONTACTS_CHILDREN.map((c) => ({
2018
2074
  label: c.label,
@@ -2022,7 +2078,7 @@ function standardPolitogyNav(opts) {
2022
2078
  };
2023
2079
  return [
2024
2080
  { kind: "section", label: "Relationship" },
2025
- { label: "Dashboard", icon: icon("home"), href: withOrg(abs("/relationship/dashboard")) },
2081
+ { label: "Dashboard", icon: icon("layoutDashboard"), href: withOrg(abs("/relationship/dashboard")) },
2026
2082
  contacts,
2027
2083
  {
2028
2084
  label: "Email broadcast",
@@ -2045,40 +2101,20 @@ function standardPolitogyNav(opts) {
2045
2101
  },
2046
2102
  { kind: "section", label: "Collect" },
2047
2103
  // Carries no top-level href in VRM core (parent row only toggles).
2048
- { label: "Calls to action", icon: icon("layout"), children: leaves(CTA_CHILDREN) },
2104
+ { label: "Calls to action", icon: icon("mousePointerClick"), children: leaves(CTA_CHILDREN) },
2049
2105
  {
2050
2106
  label: "Forms",
2051
- icon: icon("activity"),
2107
+ icon: icon("fileText"),
2052
2108
  href: withOrg("https://forms.politogyvrm.com/"),
2053
2109
  children: APP_FORMS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
2054
2110
  },
2055
2111
  {
2056
2112
  label: "Surveys",
2057
- icon: icon("fileText"),
2113
+ icon: icon("clipboardList"),
2058
2114
  href: withOrg("https://surveys.politogyvrm.com/surveys"),
2059
2115
  children: APP_SURVEYS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
2060
2116
  },
2061
- {
2062
- label: "Polls",
2063
- icon: icon("barChart"),
2064
- href: withOrg("https://polls.politogyvrm.com/"),
2065
- children: APP_POLLS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
2066
- },
2067
- {
2068
- label: "CTAs",
2069
- icon: icon("layout"),
2070
- href: withOrg("https://ctas.politogyvrm.com/"),
2071
- children: APP_CTAS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) }))
2072
- },
2073
- { kind: "section", label: "Account" },
2074
- // My Profile is global — NOT org-suffixed (main-app ShellChromeBridge).
2075
- { label: "My profile", icon: icon("user"), href: withOrg(abs("/my-profile")) },
2076
- {
2077
- label: "Organization settings",
2078
- icon: icon("settings"),
2079
- href: withOrg(abs("/organization-settings")),
2080
- children: branches(ORG_SETTINGS_CHILDREN)
2081
- }
2117
+ ...accountRows()
2082
2118
  ];
2083
2119
  };
2084
2120
  const buildCampaign = () => {
@@ -2087,40 +2123,57 @@ function standardPolitogyNav(opts) {
2087
2123
  ...opts.campaignAvailability
2088
2124
  };
2089
2125
  const rows = [
2090
- { label: "Dashboard", icon: icon("home"), href: withOrg(abs("/campaign/dashboard")) },
2091
- { label: "Voter Contact", icon: icon("target"), href: withOrg(abs("/campaign/campaigns")) },
2126
+ // Left-Navigation §9.2: Race data -> Research -> GOTV -> Account.
2127
+ // Battleground is the Campaign landing page; there is no Campaign
2128
+ // Dashboard row, and Voter Contact and Tribes have no row.
2129
+ { kind: "section", label: "Race data" },
2130
+ { label: "Battleground", icon: icon("crosshair"), href: withOrg(abs("/campaign/battleground")) },
2131
+ { label: "District data", icon: icon("landmark"), href: withOrg(abs("/campaign/districts")) },
2132
+ { kind: "section", label: "Research" },
2092
2133
  {
2093
- label: "A2P",
2094
- icon: icon("messageSquare"),
2095
- href: withOrg(A2P_ORIGIN),
2096
- children: appLeaves(A2P_ORIGIN, APP_A2P_CHILDREN),
2097
- flag: "a2p"
2134
+ label: "Polling",
2135
+ icon: icon("chartNoAxes"),
2136
+ href: withOrg(POLLS_ORIGIN),
2137
+ children: APP_POLLS_CHILDREN.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(c.href) })),
2138
+ flag: "polling"
2139
+ },
2140
+ { kind: "section", label: "GOTV" },
2141
+ {
2142
+ label: "Field canvassing",
2143
+ icon: icon("doorOpen"),
2144
+ href: withOrg(CANVASS_ORIGIN),
2145
+ children: appLeaves(CANVASS_ORIGIN, APP_CANVASS_CHILDREN),
2146
+ flag: "canvass"
2098
2147
  },
2099
2148
  {
2100
- label: "Phone Banking",
2149
+ label: "Phone banking",
2101
2150
  icon: icon("phone"),
2102
2151
  href: withOrg(PHONEBANK_ORIGIN),
2103
2152
  children: appLeaves(PHONEBANK_ORIGIN, APP_PHONEBANK_CHILDREN),
2104
2153
  flag: "phonebank"
2105
2154
  },
2106
2155
  {
2107
- label: "Field Canvassing",
2108
- icon: icon("map"),
2109
- href: withOrg(CANVASS_ORIGIN),
2110
- children: appLeaves(CANVASS_ORIGIN, APP_CANVASS_CHILDREN),
2111
- flag: "canvass"
2156
+ label: "A2P texting",
2157
+ icon: icon("messageSquare"),
2158
+ href: withOrg(A2P_ORIGIN),
2159
+ children: appLeaves(A2P_ORIGIN, APP_A2P_CHILDREN),
2160
+ flag: "a2p"
2112
2161
  },
2113
2162
  {
2114
- label: "Sign Mapping",
2115
- icon: icon("mapPin"),
2163
+ label: "Sign mapping",
2164
+ icon: icon("signpost"),
2116
2165
  href: withOrg(SIGNS_ORIGIN),
2117
2166
  children: appLeaves(SIGNS_ORIGIN, APP_SIGNS_CHILDREN),
2118
2167
  flag: "signs"
2119
2168
  },
2120
- { label: "Tribes", icon: icon("users"), href: withOrg(CONTACTS_TRIBES), flag: "tribes" },
2121
- { label: "Polling Engine", icon: icon("barChart"), href: withOrg(POLLS_ORIGIN), flag: "polling" }
2169
+ ...accountRows()
2122
2170
  ];
2123
- return rows.filter((r) => !r.flag || avail[r.flag]).map(({ flag: _flag, ...item }) => item);
2171
+ const kept = rows.filter((r) => !r.flag || avail[r.flag]).map(({ flag: _flag, ...item }) => item);
2172
+ return kept.filter((item, idx) => {
2173
+ if (item.kind !== "section") return true;
2174
+ const next = kept[idx + 1];
2175
+ return !!next && next.kind !== "section";
2176
+ });
2124
2177
  };
2125
2178
  const buildPetition = () => [
2126
2179
  opts.petitionsItem ? {
@@ -2227,7 +2280,9 @@ function NavSidebar({
2227
2280
  footer,
2228
2281
  linkComponent,
2229
2282
  open,
2230
- onClose
2283
+ onClose,
2284
+ onOpen,
2285
+ onNavigate
2231
2286
  }) {
2232
2287
  const Link = linkComponent ?? DefaultLink;
2233
2288
  const collapsible = !open;
@@ -2324,7 +2379,7 @@ function NavSidebar({
2324
2379
  style: { fontFamily: 'var(--font-family, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif)' },
2325
2380
  onKeyDown: trapTab,
2326
2381
  onClick: (e) => {
2327
- if (open && e.target.closest("a[href]")) onClose?.();
2382
+ if (open && e.target.closest("a[href]")) (onNavigate ?? onClose)?.();
2328
2383
  },
2329
2384
  children: [
2330
2385
  open ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -2333,18 +2388,30 @@ function NavSidebar({
2333
2388
  type: "button",
2334
2389
  ref: closeButtonRef,
2335
2390
  onClick: onClose,
2336
- "aria-label": "Close menu",
2391
+ "aria-label": "Collapse navigation",
2337
2392
  className: "absolute right-3 top-3 flex h-8 w-8 items-center justify-center rounded-full text-[color:var(--muted)] transition hover:bg-[color:var(--panel-elevated)] hover:text-[color:var(--foreground)] md:hidden",
2338
2393
  children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {})
2339
2394
  }
2340
2395
  ) : null,
2341
2396
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-shrink-0 flex-col gap-[14px] border-b border-[color:var(--sidebar-line,var(--line))] px-[18px] py-4 ${rc("max-md:items-center max-md:px-[10px]")}`, children: [
2397
+ onOpen ? /* @__PURE__ */ jsxRuntime.jsx(
2398
+ "button",
2399
+ {
2400
+ type: "button",
2401
+ onClick: onOpen,
2402
+ "aria-label": "Expand navigation",
2403
+ "aria-expanded": open ?? false,
2404
+ "data-rail-toggle": "expand",
2405
+ className: `hidden h-8 w-8 items-center justify-center rounded-lg ${rc("max-md:flex")}`,
2406
+ children: brand.logoSquareSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: brand.logoSquareSrc, alt: "", draggable: false, className: "h-8 w-8 object-contain" }) : brand.logoPending ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "block h-8 w-8" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-8 w-8 items-center justify-center rounded-xl bg-[color:var(--color-accent)] text-sm font-black text-[#FFFFFF]", children: brand.badgeLabel })
2407
+ }
2408
+ ) : null,
2342
2409
  /* @__PURE__ */ jsxRuntime.jsxs(
2343
2410
  Link,
2344
2411
  {
2345
2412
  href: brand.homeHref ?? "/",
2346
2413
  "aria-label": brand.logoAlt ?? brand.title,
2347
- className: `flex items-center gap-2.5 ${rc("max-md:justify-center")}`,
2414
+ className: `flex items-center gap-2.5 ${rc("max-md:justify-center")} ${onOpen ? rc("max-md:hidden") : ""}`,
2348
2415
  children: [
2349
2416
  brand.logoSquareSrc ? /* @__PURE__ */ jsxRuntime.jsx(
2350
2417
  "img",
@@ -2388,7 +2455,7 @@ function NavSidebar({
2388
2455
  }
2389
2456
  ),
2390
2457
  org ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rc("max-md:flex max-md:justify-center"), children: [
2391
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `mb-[7px] flex items-center justify-between ${rc("max-md:hidden")}`, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: NAV_EYEBROW_CLASS, children: "Organization" }) }),
2458
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `mb-[7px] mt-[7px] flex items-center justify-between ${rc("max-md:hidden")}`, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: NAV_EYEBROW_CLASS, children: "Organization" }) }),
2392
2459
  org.loading ? /* @__PURE__ */ jsxRuntime.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 ${rc("max-md:w-auto max-md:border-0 max-md:bg-transparent max-md:p-0 max-md:shadow-none")}`, children: [
2393
2460
  /* @__PURE__ */ jsxRuntime.jsx(
2394
2461
  "span",
@@ -2414,7 +2481,7 @@ function NavSidebar({
2414
2481
  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 ${rc("max-md:w-auto max-md:items-center max-md:overflow-visible max-md:border-0 max-md:bg-transparent")}`,
2415
2482
  children: [
2416
2483
  /* @__PURE__ */ jsxRuntime.jsx(OrgIconMark, { org, logoSrc: orgLogoSrc }),
2417
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `relative flex h-[var(--sidebar-org-band-height,48px)] w-full items-center justify-center bg-[#FFFFFF] px-3 py-[7px] ${rc("max-md:hidden")}`, children: [
2484
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `relative flex h-[var(--sidebar-org-band-height,70px)] w-full items-center justify-center bg-[#FFFFFF] px-3 py-[7px] ${rc("max-md:hidden")}`, children: [
2418
2485
  orgLogoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: orgLogoSrc, alt: "", className: "max-h-full max-w-[132px] object-contain" }) : org.canUploadLogo ? /* @__PURE__ */ jsxRuntime.jsx(
2419
2486
  "a",
2420
2487
  {
@@ -2426,7 +2493,7 @@ function NavSidebar({
2426
2493
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold text-neutral-800", children: org.name ?? "Organization" }),
2427
2494
  /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 h-[3px]", style: { backgroundImage: orgGradient } })
2428
2495
  ] }),
2429
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `flex w-full min-w-0 items-center justify-between gap-[9px] px-[10px] py-2 ${rc("max-md:hidden")}`, children: [
2496
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `flex w-full min-w-0 items-center justify-between gap-[9px] px-[10px] py-[10px] ${rc("max-md:hidden")}`, children: [
2430
2497
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
2431
2498
  /* @__PURE__ */ jsxRuntime.jsx(
2432
2499
  "span",
@@ -2516,7 +2583,7 @@ function NavSidebar({
2516
2583
  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))] ${rc("max-md:w-auto max-md:items-center max-md:overflow-visible max-md:border-0 max-md:bg-transparent")}`,
2517
2584
  children: [
2518
2585
  /* @__PURE__ */ jsxRuntime.jsx(OrgIconMark, { org, logoSrc: orgLogoSrc }),
2519
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `relative flex h-[var(--sidebar-org-band-height,48px)] w-full items-center justify-center bg-[#FFFFFF] px-3 py-[7px] ${rc("max-md:hidden")}`, children: [
2586
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `relative flex h-[var(--sidebar-org-band-height,70px)] w-full items-center justify-center bg-[#FFFFFF] px-3 py-[7px] ${rc("max-md:hidden")}`, children: [
2520
2587
  orgLogoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: orgLogoSrc, alt: "", className: "max-h-full max-w-[132px] object-contain" }) : org.canUploadLogo ? /* @__PURE__ */ jsxRuntime.jsx(
2521
2588
  "a",
2522
2589
  {
@@ -2528,7 +2595,7 @@ function NavSidebar({
2528
2595
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold text-neutral-800", children: org.name ?? "Organization" }),
2529
2596
  /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-0 h-[3px]", style: { backgroundImage: orgGradient } })
2530
2597
  ] }),
2531
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `flex w-full min-w-0 items-center justify-between gap-[9px] px-[10px] py-2 ${rc("max-md:hidden")}`, children: [
2598
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `flex w-full min-w-0 items-center justify-between gap-[9px] px-[10px] py-[10px] ${rc("max-md:hidden")}`, children: [
2532
2599
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
2533
2600
  /* @__PURE__ */ jsxRuntime.jsx(
2534
2601
  "span",
@@ -2573,7 +2640,7 @@ function NavSidebar({
2573
2640
  },
2574
2641
  disabled: !available,
2575
2642
  className: [
2576
- "flex flex-1 items-center justify-center rounded-[5px] px-[9px] py-[6px] transition",
2643
+ `flex flex-none items-center justify-center rounded-[5px] px-[9px] py-[6px] transition ${rc("max-md:flex-1")}`,
2577
2644
  !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-[#FFFFFF]/5 hover:text-[color:var(--sidebar-text,var(--foreground))]"
2578
2645
  ].join(" "),
2579
2646
  children: OptIcon ? /* @__PURE__ */ jsxRuntime.jsx(OptIcon, { size: 15, className: "shrink-0" }) : null
@@ -2663,15 +2730,17 @@ function NavSidebar({
2663
2730
  onSignOut: footer.onSignOut
2664
2731
  }
2665
2732
  ) : null,
2666
- footer.links && footer.links.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex flex-wrap items-center gap-[10px] text-[11px] leading-[1.2] ${footer.user ? "mt-3" : ""} ${rc("max-md:hidden")}`, children: footer.links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
2667
- "a",
2668
- {
2669
- href: safeHref(l.href),
2670
- className: "text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))] hover:text-[color:var(--sidebar-text,var(--foreground))] hover:underline",
2671
- children: l.label
2672
- },
2673
- l.label
2674
- )) }) : null,
2733
+ footer.links && footer.links.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex flex-wrap items-center justify-center gap-[6px] text-[11px] leading-[1.2] ${footer.user ? "mt-3" : ""} ${rc("max-md:hidden")}`, children: footer.links.map((l, i) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
2734
+ i > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))]", children: "\xB7" }) : null,
2735
+ /* @__PURE__ */ jsxRuntime.jsx(
2736
+ "a",
2737
+ {
2738
+ href: safeHref(l.href),
2739
+ className: "text-[color:var(--sidebar-caption,var(--sidebar-text-muted,var(--muted)))] hover:text-[color:var(--sidebar-text,var(--foreground))] hover:underline",
2740
+ children: l.label
2741
+ }
2742
+ )
2743
+ ] }, l.label)) }) : null,
2675
2744
  footer.envLabel && footer.envLabel.trim().toLowerCase() !== "production" ? /* @__PURE__ */ jsxRuntime.jsxs(
2676
2745
  "div",
2677
2746
  {
@@ -3118,7 +3187,7 @@ function NavTopBar({
3118
3187
  const initials = (hasRealName ? rawName : user?.email ?? "P").slice(0, 2).toUpperCase();
3119
3188
  const secondary = hasRealName ? user?.email || [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member" : [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member";
3120
3189
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-20", children: [
3121
- /* @__PURE__ */ jsxRuntime.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: [
3190
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex min-w-0 h-[var(--topbar-height,60px)] items-center justify-between gap-[8px] md:gap-[14px] border-b border-[color:var(--line)] bg-[color:var(--panel)] px-[var(--topbar-padding-x,20px)]", children: [
3122
3191
  onOpenNav ? /* @__PURE__ */ jsxRuntime.jsx(
3123
3192
  "button",
3124
3193
  {
@@ -3131,7 +3200,7 @@ function NavTopBar({
3131
3200
  children: /* @__PURE__ */ jsxRuntime.jsx(HamburgerIcon, {})
3132
3201
  }
3133
3202
  ) : null,
3134
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "relative flex h-9 w-[320px] max-w-full shrink-0 items-center", children: [
3203
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "relative flex h-9 w-[320px] min-w-0 max-w-full shrink items-center md:shrink-0", children: [
3135
3204
  /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "pointer-events-none absolute left-[10px] h-[15px] w-[15px] text-[color:var(--muted)]" }),
3136
3205
  /* @__PURE__ */ jsxRuntime.jsx(
3137
3206
  "input",
@@ -3151,13 +3220,13 @@ function NavTopBar({
3151
3220
  "kbd",
3152
3221
  {
3153
3222
  "aria-hidden": true,
3154
- 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)]",
3223
+ className: "pointer-events-none absolute right-[10px] hidden md:block 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)]",
3155
3224
  children: "/"
3156
3225
  }
3157
3226
  )
3158
3227
  ] }),
3159
3228
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative ml-auto flex shrink-0 items-center gap-[var(--topbar-icon-gap,8px)]", children: [
3160
- /* @__PURE__ */ jsxRuntime.jsxs(
3229
+ buildNotes ? /* @__PURE__ */ jsxRuntime.jsxs(
3161
3230
  "button",
3162
3231
  {
3163
3232
  type: "button",
@@ -3168,7 +3237,7 @@ function NavTopBar({
3168
3237
  buildNotes?.label ?? "Build notes"
3169
3238
  ]
3170
3239
  }
3171
- ),
3240
+ ) : null,
3172
3241
  actionsList && actionsList.length > 0 ? actionsList.map((action) => /* @__PURE__ */ jsxRuntime.jsx(NavTopBarActionButton, { action }, action.key)) : null,
3173
3242
  actions,
3174
3243
  themeToggle,
@@ -3743,9 +3812,22 @@ function NavAppShell({
3743
3812
  );
3744
3813
  }
3745
3814
  const [navOpen, setNavOpen] = react.useState(false);
3815
+ const expandRail = () => {
3816
+ writeRailPreference("expanded");
3817
+ setNavOpen(true);
3818
+ };
3819
+ const collapseRail = () => {
3820
+ writeRailPreference("collapsed");
3821
+ setNavOpen(false);
3822
+ };
3746
3823
  react.useEffect(() => {
3747
3824
  setNavOpen(false);
3748
3825
  }, [sidebar.pathname]);
3826
+ react.useEffect(() => {
3827
+ if (readRailPreference() !== "expanded") return;
3828
+ const narrow = typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(max-width: 767.98px)").matches : false;
3829
+ if (narrow) setNavOpen(true);
3830
+ }, []);
3749
3831
  react.useEffect(() => {
3750
3832
  if (!navOpen) return;
3751
3833
  const previous = document.body.style.overflow;
@@ -3766,15 +3848,23 @@ function NavAppShell({
3766
3848
  "data-politogy-mode": modeId,
3767
3849
  className: "min-h-screen bg-[color:var(--background)] text-[color:var(--foreground)]",
3768
3850
  children: [
3769
- /* @__PURE__ */ jsxRuntime.jsx(NavSidebar, { ...sidebar, footer: sidebarFooter, open: navOpen, onClose: () => setNavOpen(false) }),
3851
+ /* @__PURE__ */ jsxRuntime.jsx(
3852
+ NavSidebar,
3853
+ {
3854
+ ...sidebar,
3855
+ footer: sidebarFooter,
3856
+ open: navOpen,
3857
+ onClose: collapseRail,
3858
+ onOpen: expandRail,
3859
+ onNavigate: () => setNavOpen(false)
3860
+ }
3861
+ ),
3770
3862
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pl-[var(--sidebar-collapsed-width,64px)] md:pl-[var(--sidebar-width,236px)]", children: [
3771
3863
  /* @__PURE__ */ jsxRuntime.jsx(
3772
3864
  NavTopBar,
3773
3865
  {
3774
3866
  ...topBar,
3775
- accountMenu: topBar.accountMenu ?? (accountMenuPlacement === "sidebar" ? "sidebar" : "topbar"),
3776
- onOpenNav: () => setNavOpen(true),
3777
- navOpen
3867
+ accountMenu: topBar.accountMenu ?? (accountMenuPlacement === "sidebar" ? "sidebar" : "topbar")
3778
3868
  }
3779
3869
  ),
3780
3870
  betaBanner ? /* @__PURE__ */ jsxRuntime.jsx(NavBetaBanner, { ...betaBanner }) : null,