diff --git a/.playwright-mcp/console-2026-03-23T20-11-48-316Z.log b/.playwright-mcp/console-2026-03-23T20-11-48-316Z.log
new file mode 100644
index 00000000..cde32898
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T20-11-48-316Z.log
@@ -0,0 +1 @@
+[ 567ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/auth/me:0
diff --git a/.playwright-mcp/console-2026-03-23T20-11-59-703Z.log b/.playwright-mcp/console-2026-03-23T20-11-59-703Z.log
new file mode 100644
index 00000000..504d5ee5
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T20-11-59-703Z.log
@@ -0,0 +1,66 @@
+[ 156566ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 159562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 162561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 165562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 168561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 171561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 174562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 177561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 180561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 183561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 186561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 189561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 192561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 195561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 198562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 201561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 204561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 207561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 210561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 213562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 216562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 219561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 222561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 225562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 228561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 231562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 234562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 237562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 240390ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/dashboard/summary:0
+[ 240562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 243562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 246561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 249561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 252562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 255561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 258561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 261562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 264562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 267562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 270562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 273561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 276562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 279563ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 282561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 285562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 288562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 291562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 294562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 297561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 300562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 303561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 306562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 309561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 312562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 315561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 318561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 321561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 324561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 327561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 330562ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 333561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 336561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 339561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 342561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 345561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 348561ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
diff --git a/.playwright-mcp/console-2026-03-23T20-18-54-805Z.log b/.playwright-mcp/console-2026-03-23T20-18-54-805Z.log
new file mode 100644
index 00000000..2ff3cdcb
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T20-18-54-805Z.log
@@ -0,0 +1,2 @@
+[ 480462ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
+[ 1440463ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
diff --git a/.playwright-mcp/console-2026-03-23T20-52-21-821Z.log b/.playwright-mcp/console-2026-03-23T20-52-21-821Z.log
new file mode 100644
index 00000000..276dbf03
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T20-52-21-821Z.log
@@ -0,0 +1,14 @@
+[ 140214ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 143212ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 146211ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 149211ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/upgrade/status:0
+[ 360382ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
+[ 960378ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/dashboard/summary:0
+[ 1320377ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
+[ 1920379ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/dashboard/summary:0
+[ 2040375ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_REFUSED @ http://localhost:3002/api/dashboard/summary:0
+[ 2280391ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
+[ 2400379ms] [ERROR] Failed to load resource: the server responded with a status of 500 (Internal Server Error) @ http://localhost:3002/api/dashboard/summary:0
+[ 3240382ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
+[ 4200393ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
+[ 5160392ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/dashboard/summary:0
diff --git a/.playwright-mcp/console-2026-03-23T22-33-26-262Z.log b/.playwright-mcp/console-2026-03-23T22-33-26-262Z.log
new file mode 100644
index 00000000..5ab7af6d
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-33-26-262Z.log
@@ -0,0 +1,2 @@
+[ 616ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:3002/favicon.ico:0
+[ 628ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/auth/me:0
diff --git a/.playwright-mcp/console-2026-03-23T22-48-25-770Z.log b/.playwright-mcp/console-2026-03-23T22-48-25-770Z.log
new file mode 100644
index 00000000..62447069
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-48-25-770Z.log
@@ -0,0 +1 @@
+[ 605ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/auth/me:0
diff --git a/.playwright-mcp/console-2026-03-23T22-50-36-491Z.log b/.playwright-mcp/console-2026-03-23T22-50-36-491Z.log
new file mode 100644
index 00000000..f3de76f8
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-50-36-491Z.log
@@ -0,0 +1 @@
+[ 1538ms] [ERROR] Failed to load resource: the server responded with a status of 400 (Bad Request) @ http://localhost:8091/auth/token/refresh:0
diff --git a/.playwright-mcp/console-2026-03-23T22-50-56-794Z.log b/.playwright-mcp/console-2026-03-23T22-50-56-794Z.log
new file mode 100644
index 00000000..e5f60374
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-50-56-794Z.log
@@ -0,0 +1 @@
+[ 32ms] [WARNING] Manifest: property 'start_url' ignored, should be same origin as document. @ data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cHM6Ly9naXQuY21saXRlLm9yZy8iLCJpY29ucyI6W3sic3JjIjoiaHR0cHM6Ly9naXQuY21saXRlLm9yZy9hc3NldHMvaW1nL2xvZ28ucG5nIiwidHlwZSI6ImltYWdlL3BuZyIsInNpemVzIjoiNTEyeDUxMiJ9LHsic3JjIjoiaHR0cHM6Ly9naXQuY21saXRlLm9yZy9hc3NldHMvaW1nL2xvZ28uc3ZnIiwidHlwZSI6ImltYWdlL3N2Zyt4bWwiLCJzaXplcyI6IjUxMng1MTIifV19:0
diff --git a/.playwright-mcp/console-2026-03-23T22-51-07-562Z.log b/.playwright-mcp/console-2026-03-23T22-51-07-562Z.log
new file mode 100644
index 00000000..457e3b61
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-51-07-562Z.log
@@ -0,0 +1 @@
+[ 871ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:5678/rest/login:0
diff --git a/.playwright-mcp/console-2026-03-23T22-51-37-826Z.log b/.playwright-mcp/console-2026-03-23T22-51-37-826Z.log
new file mode 100644
index 00000000..76a1cf80
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-51-37-826Z.log
@@ -0,0 +1 @@
+[ 343ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/favicon.ico:0
diff --git a/.playwright-mcp/console-2026-03-23T22-52-05-150Z.log b/.playwright-mcp/console-2026-03-23T22-52-05-150Z.log
new file mode 100644
index 00000000..1a947742
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-52-05-150Z.log
@@ -0,0 +1 @@
+[ 238ms] [WARNING] Simple Analytics: Set hostname on localhost:8090. See https://docs.simpleanalytics.com/overwrite-domain-name @ https://scripts.simpleanalyticscdn.com/latest.js:2
diff --git a/.playwright-mcp/console-2026-03-23T22-52-17-790Z.log b/.playwright-mcp/console-2026-03-23T22-52-17-790Z.log
new file mode 100644
index 00000000..9f14e7ca
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-52-17-790Z.log
@@ -0,0 +1,5 @@
+[ 967ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/node_modules/vsda/rust/web/vsda_bg.wasm:0
+[ 969ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/node_modules/vsda/rust/web/vsda.js:0
+[ 1271ms] [WARNING] The web worker extension host is started in a same-origin iframe! @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:4591
+[ 1304ms] [WARNING] An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing. @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html?&vscodeWebWorkerExtHostId=2ab26743-4428-4df3-944e-d603e9a82c44:0
+[ 2145ms] [WARNING] AI generated workspace trust dialog contents not available. @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:4552
diff --git a/.playwright-mcp/console-2026-03-23T22-52-56-849Z.log b/.playwright-mcp/console-2026-03-23T22-52-56-849Z.log
new file mode 100644
index 00000000..cd68f88a
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-52-56-849Z.log
@@ -0,0 +1,11 @@
+[ 5ms] [ERROR] %c ERR color: #f33 [lifecycle] Long running operations during shutdown are unsupported in the web (id: join.disconnectRemote) @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:37
+[ 6ms] [ERROR] %c ERR color: #f33 [lifecycle] Long running operations during shutdown are unsupported in the web (id: join.chatSessionStore) @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:37
+[ 7ms] [ERROR] %c ERR color: #f33 [lifecycle] Long running operations during shutdown are unsupported in the web (id: join.chatEditingSession) @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:37
+[ 27ms] [ERROR] %c ERR color: #f33 Error creating chat editing session content folder vscode-remote:/home/coder/.local/share/code-server/User/workspaceStorage/4a334e63/chatEditingSessions/266a91b3-2e96-499a-bfc1-6d451b72bd57/contents Canceled: Canceled
+ at Object.call (http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:612:1374)
+ at http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:613:2181
+ at async vOt.W (http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:4587:115075)
+ at async vOt.createFolder (http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:4587:114875)
+ at async ice.storeState (http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:2978:15032)
+ at async Promise.all (index 0) @ http://localhost:8888/stable-13ca0e47310505f4ab1ac59e891e9a3c5e5eec04/static/out/vs/code/browser/workbench/workbench.js:37
+[ 137ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:8025/api/v2/jim:0
diff --git a/.playwright-mcp/console-2026-03-23T22-53-09-505Z.log b/.playwright-mcp/console-2026-03-23T22-53-09-505Z.log
new file mode 100644
index 00000000..2b461da6
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-53-09-505Z.log
@@ -0,0 +1 @@
+[ 1014ms] [WARNING] GPS permission denied — enable location access in your browser settings @ http://localhost:3002/src/components/canvass/GPSTracker.tsx:32
diff --git a/.playwright-mcp/console-2026-03-23T22-53-56-906Z.log b/.playwright-mcp/console-2026-03-23T22-53-56-906Z.log
new file mode 100644
index 00000000..e32c9eb6
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T22-53-56-906Z.log
@@ -0,0 +1,2 @@
+[ 600748ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/social/notifications/count:0
+[ 1560748ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3002/api/social/notifications/count:0
diff --git a/.playwright-mcp/console-2026-03-23T23-20-48-176Z.log b/.playwright-mcp/console-2026-03-23T23-20-48-176Z.log
new file mode 100644
index 00000000..cb621a81
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T23-20-48-176Z.log
@@ -0,0 +1,12 @@
+[ 127ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 127ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3242:41)
+ at async initSearch (http://localhost:4003/lander/:3307:9) @ http://localhost:4003/lander/:3254
+[ 626262ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 626262ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3212:41)
+ at async initSearch (http://localhost:4003/lander/:3277:9) @ http://localhost:4003/lander/:3224
+[ 628485ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 628485ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3212:41)
+ at async initSearch (http://localhost:4003/lander/:3277:9) @ http://localhost:4003/lander/:3224
diff --git a/.playwright-mcp/console-2026-03-23T23-31-23-226Z.log b/.playwright-mcp/console-2026-03-23T23-31-23-226Z.log
new file mode 100644
index 00000000..29c5febe
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T23-31-23-226Z.log
@@ -0,0 +1,60 @@
+[ 86ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 87ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3212:41)
+ at async initSearch (http://localhost:4003/lander/:3277:9) @ http://localhost:4003/lander/:3224
+[ 426459ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 426459ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3213:41)
+ at async initSearch (http://localhost:4003/lander/:3278:9) @ http://localhost:4003/lander/:3225
+[ 433706ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 433706ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3214:41)
+ at async initSearch (http://localhost:4003/lander/:3279:9) @ http://localhost:4003/lander/:3226
+[ 436108ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 436108ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3214:41)
+ at async initSearch (http://localhost:4003/lander/:3279:9) @ http://localhost:4003/lander/:3226
+[ 445396ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 445396ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3237:41)
+ at async initSearch (http://localhost:4003/lander/:3302:9) @ http://localhost:4003/lander/:3249
+[ 447757ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 447757ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3237:41)
+ at async initSearch (http://localhost:4003/lander/:3302:9) @ http://localhost:4003/lander/:3249
+[ 455113ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 455113ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3237:41)
+ at async initSearch (http://localhost:4003/lander/:3302:9) @ http://localhost:4003/lander/:3249
+[ 457733ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 457733ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3237:41)
+ at async initSearch (http://localhost:4003/lander/:3302:9) @ http://localhost:4003/lander/:3249
+[ 489124ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 489124ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3252:41)
+ at async initSearch (http://localhost:4003/lander/:3317:9) @ http://localhost:4003/lander/:3264
+[ 491509ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 491509ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3252:41)
+ at async initSearch (http://localhost:4003/lander/:3317:9) @ http://localhost:4003/lander/:3264
+[ 510185ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 510185ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3257:41)
+ at async initSearch (http://localhost:4003/lander/:3322:9) @ http://localhost:4003/lander/:3269
+[ 528536ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 528536ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3262:41)
+ at async initSearch (http://localhost:4003/lander/:3327:9) @ http://localhost:4003/lander/:3274
+[ 530976ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 530976ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3262:41)
+ at async initSearch (http://localhost:4003/lander/:3327:9) @ http://localhost:4003/lander/:3274
+[ 541596ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 541596ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3322:41)
+ at async initSearch (http://localhost:4003/lander/:3387:9) @ http://localhost:4003/lander/:3334
+[ 543950ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 543950ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3322:41)
+ at async initSearch (http://localhost:4003/lander/:3387:9) @ http://localhost:4003/lander/:3334
diff --git a/.playwright-mcp/console-2026-03-23T23-40-33-067Z.log b/.playwright-mcp/console-2026-03-23T23-40-33-067Z.log
new file mode 100644
index 00000000..1b05b3b8
--- /dev/null
+++ b/.playwright-mcp/console-2026-03-23T23-40-33-067Z.log
@@ -0,0 +1,28 @@
+[ 96ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 97ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3322:41)
+ at async initSearch (http://localhost:4003/lander/:3387:9) @ http://localhost:4003/lander/:3334
+[ 320202ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 320202ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3335:41)
+ at async initSearch (http://localhost:4003/lander/:3400:9) @ http://localhost:4003/lander/:3347
+[ 329151ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 329151ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3337:41)
+ at async initSearch (http://localhost:4003/lander/:3402:9) @ http://localhost:4003/lander/:3349
+[ 331533ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 331533ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3337:41)
+ at async initSearch (http://localhost:4003/lander/:3402:9) @ http://localhost:4003/lander/:3349
+[ 628619ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 628619ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3337:41)
+ at async initSearch (http://localhost:4003/lander/:3402:9) @ http://localhost:4003/lander/:3349
+[ 631005ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 631005ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3337:41)
+ at async initSearch (http://localhost:4003/lander/:3402:9) @ http://localhost:4003/lander/:3349
+[ 633385ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:4003/lander/search/search_index.json:0
+[ 633385ms] [ERROR] Search init failed: Error: Failed to load search index
+ at MkDocsSearch.initialize (http://localhost:4003/lander/:3337:41)
+ at async initSearch (http://localhost:4003/lander/:3402:9) @ http://localhost:4003/lander/:3349
diff --git a/.playwright-mcp/page-2026-03-23T20-13-17-545Z.png b/.playwright-mcp/page-2026-03-23T20-13-17-545Z.png
new file mode 100644
index 00000000..52136a66
Binary files /dev/null and b/.playwright-mcp/page-2026-03-23T20-13-17-545Z.png differ
diff --git a/.playwright-mcp/page-2026-03-23T20-19-33-396Z.png b/.playwright-mcp/page-2026-03-23T20-19-33-396Z.png
new file mode 100644
index 00000000..45aeaa58
Binary files /dev/null and b/.playwright-mcp/page-2026-03-23T20-19-33-396Z.png differ
diff --git a/admin/src/pages/ListmonkPage.tsx b/admin/src/pages/ListmonkPage.tsx
index bf96fd3c..3a4b219a 100644
--- a/admin/src/pages/ListmonkPage.tsx
+++ b/admin/src/pages/ListmonkPage.tsx
@@ -175,14 +175,20 @@ export default function ListmonkPage() {
const { setPageHeader } = useOutletContext();
+ const buildProxyAuthUrl = useCallback((token: string) => {
+ if (!config) return null;
+ const base = buildServiceUrl(config.listmonkSubdomain, config.domain, config.listmonkPort);
+ return `${base}/auth?token=${encodeURIComponent(token)}`;
+ }, [config]);
+
const loadIframe = useCallback(async () => {
if (iframeInitialized.current && iframeSrc) return;
setIframeLoading(true);
setIframeError(null);
try {
const res = await api.get<{ port: number; token: string }>('/listmonk/proxy-url');
- const { port, token } = res.data;
- const url = `//${window.location.hostname}:${port}/auth?token=${encodeURIComponent(token)}`;
+ const url = buildProxyAuthUrl(res.data.token);
+ if (!url) throw new Error('Config not loaded');
setIframeSrc(url);
iframeInitialized.current = true;
} catch {
@@ -190,11 +196,17 @@ export default function ListmonkPage() {
} finally {
setIframeLoading(false);
}
- }, [iframeSrc]);
+ }, [iframeSrc, buildProxyAuthUrl]);
- const listmonkAdminUrl = config
- ? buildServiceUrl(config.listmonkSubdomain, config.domain, config.listmonkPort)
- : null;
+ const handleOpenListmonk = useCallback(async () => {
+ try {
+ const res = await api.get<{ port: number; token: string }>('/listmonk/proxy-url');
+ const url = buildProxyAuthUrl(res.data.token);
+ if (url) window.open(url, '_blank');
+ } catch {
+ message.error('Failed to get Listmonk auth URL');
+ }
+ }, [buildProxyAuthUrl]);
useEffect(() => {
setPageHeader({ title: 'Newsletter / Listmonk', fullBleed: activeTab === 'admin' });
@@ -234,12 +246,11 @@ export default function ListmonkPage() {
>
Test Connection
- {listmonkAdminUrl && (
+ {config && (
}
- href={listmonkAdminUrl}
- target="_blank"
+ onClick={handleOpenListmonk}
>
Open Listmonk
diff --git a/api/src/modules/services/services.routes.ts b/api/src/modules/services/services.routes.ts
index e8eda816..f2bddad6 100644
--- a/api/src/modules/services/services.routes.ts
+++ b/api/src/modules/services/services.routes.ts
@@ -83,7 +83,7 @@ router.get(
miniqrSubdomain: 'qr',
excalidrawSubdomain: 'draw',
// Listmonk (newsletter platform)
- listmonkPort: 9001,
+ listmonkPort: env.LISTMONK_PROXY_PORT,
listmonkSubdomain: 'listmonk',
// Code Server (web IDE)
codeServerPort: env.CODE_SERVER_PORT,
diff --git a/mkdocs/.cache/plugin/social/assets/images/social/docs/upgrade-test-canary.png b/mkdocs/.cache/plugin/social/assets/images/social/docs/upgrade-test-canary.png
new file mode 100644
index 00000000..31e2739e
Binary files /dev/null and b/mkdocs/.cache/plugin/social/assets/images/social/docs/upgrade-test-canary.png differ
diff --git a/mkdocs/.cache/plugin/social/assets/images/social/test-page.png b/mkdocs/.cache/plugin/social/assets/images/social/test-page.png
index e337ba08..6a97489c 100644
Binary files a/mkdocs/.cache/plugin/social/assets/images/social/test-page.png and b/mkdocs/.cache/plugin/social/assets/images/social/test-page.png differ
diff --git a/mkdocs/.cache/plugin/social/manifest.json b/mkdocs/.cache/plugin/social/manifest.json
index b69e2aaa..bb836ceb 100644
--- a/mkdocs/.cache/plugin/social/manifest.json
+++ b/mkdocs/.cache/plugin/social/manifest.json
@@ -112,6 +112,7 @@
"assets/images/social/docs/phil.png": "ffe46a0052d8c23422f82d91e03a213118869539",
"assets/images/social/docs/services/index.png": "9fcf00324266a9f7b58c7b277da2127e8882aa47",
"assets/images/social/docs/troubleshooting/index.png": "b0ffadb8b01b261dfe7dea1b55fe02a3d639b7e7",
+ "assets/images/social/docs/upgrade-test-canary.png": "3d624f3412465c0f327ac1562675ae45dd30c3ce",
"assets/images/social/docs/user-guide/campaigns.png": "298b1e317e065ba0459d4cd5779ce16a278b3c09",
"assets/images/social/docs/user-guide/donations.png": "a907a64483b99ba1d1b3841a3b5928f1a77d73e4",
"assets/images/social/docs/user-guide/events.png": "b4fed5fb2b288500035a68455b01994710c4aa98",
@@ -149,7 +150,7 @@
"assets/images/social/services/postgresql.png": "831fb68dd3e01d9a017e59b100aaa8a455c8c112",
"assets/images/social/services/static-server.png": "f36d527c80adba4bcb7778784683f429acb4ce74",
"assets/images/social/test-2.png": "a6ae43d52d7c58fc106a562777e03b7da2263f83",
- "assets/images/social/test-page.png": "af2c353ee377343678a58555726f6ad7d0624488",
+ "assets/images/social/test-page.png": "c9d5751a1f0a4c1341336bb7d00c9bc743d33ef4",
"assets/images/social/test.png": "a6ae43d52d7c58fc106a562777e03b7da2263f83",
"assets/images/social/testing.png": "f7aaf394b71cbe7084a6afa0e75a324ca59e23d8",
"assets/images/social/v1/adv/ansible.png": "cb542ad9a3cc9a869258b3b1353966e1b9616a2b",
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-cuts.png b/mkdocs/docs/assets/images/screenshots/features/admin-cuts.png
new file mode 100644
index 00000000..2b74894f
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-cuts.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-dashboard.png b/mkdocs/docs/assets/images/screenshots/features/admin-dashboard.png
new file mode 100644
index 00000000..6a95bec0
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-dashboard.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-listmonk.png b/mkdocs/docs/assets/images/screenshots/features/admin-listmonk.png
new file mode 100644
index 00000000..32ba7211
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-listmonk.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-locations.png b/mkdocs/docs/assets/images/screenshots/features/admin-locations.png
new file mode 100644
index 00000000..4018b0b1
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-locations.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-observability.png b/mkdocs/docs/assets/images/screenshots/features/admin-observability.png
new file mode 100644
index 00000000..0b4c53a6
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-observability.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-settings.png b/mkdocs/docs/assets/images/screenshots/features/admin-settings.png
new file mode 100644
index 00000000..a89cf579
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-settings.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-shifts.png b/mkdocs/docs/assets/images/screenshots/features/admin-shifts.png
new file mode 100644
index 00000000..0f3efc1e
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-shifts.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/admin-users.png b/mkdocs/docs/assets/images/screenshots/features/admin-users.png
new file mode 100644
index 00000000..98f6ce32
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/admin-users.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/canvass-dashboard.png b/mkdocs/docs/assets/images/screenshots/features/canvass-dashboard.png
new file mode 100644
index 00000000..977c4664
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/canvass-dashboard.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/code-server.png b/mkdocs/docs/assets/images/screenshots/features/code-server.png
new file mode 100644
index 00000000..d4cbd531
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/code-server.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/data-quality.png b/mkdocs/docs/assets/images/screenshots/features/data-quality.png
new file mode 100644
index 00000000..070db04e
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/data-quality.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/donation-pages.png b/mkdocs/docs/assets/images/screenshots/features/donation-pages.png
new file mode 100644
index 00000000..e3f49cc9
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/donation-pages.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/email-queue.png b/mkdocs/docs/assets/images/screenshots/features/email-queue.png
new file mode 100644
index 00000000..23134236
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/email-queue.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/email-templates.png b/mkdocs/docs/assets/images/screenshots/features/email-templates.png
new file mode 100644
index 00000000..7aeac9ce
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/email-templates.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/excalidraw.png b/mkdocs/docs/assets/images/screenshots/features/excalidraw.png
new file mode 100644
index 00000000..6f4ff8ba
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/excalidraw.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/gallery-ads.png b/mkdocs/docs/assets/images/screenshots/features/gallery-ads.png
new file mode 100644
index 00000000..a15d1b91
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/gallery-ads.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/gitea.png b/mkdocs/docs/assets/images/screenshots/features/gitea.png
new file mode 100644
index 00000000..1f9a8a57
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/gitea.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/influence-campaigns.png b/mkdocs/docs/assets/images/screenshots/features/influence-campaigns.png
new file mode 100644
index 00000000..a83f3000
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/influence-campaigns.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/landing-pages.png b/mkdocs/docs/assets/images/screenshots/features/landing-pages.png
new file mode 100644
index 00000000..50dda5c8
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/landing-pages.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/mailhog.png b/mkdocs/docs/assets/images/screenshots/features/mailhog.png
new file mode 100644
index 00000000..daa3dd97
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/mailhog.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/map-settings.png b/mkdocs/docs/assets/images/screenshots/features/map-settings.png
new file mode 100644
index 00000000..8f8d8c23
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/map-settings.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/media-analytics.png b/mkdocs/docs/assets/images/screenshots/features/media-analytics.png
new file mode 100644
index 00000000..420e4519
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/media-analytics.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/media-library.png b/mkdocs/docs/assets/images/screenshots/features/media-library.png
new file mode 100644
index 00000000..cbf1671b
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/media-library.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/miniqr.png b/mkdocs/docs/assets/images/screenshots/features/miniqr.png
new file mode 100644
index 00000000..8de75a9e
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/miniqr.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/mkdocs.png b/mkdocs/docs/assets/images/screenshots/features/mkdocs.png
new file mode 100644
index 00000000..9b559289
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/mkdocs.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/n8n.png b/mkdocs/docs/assets/images/screenshots/features/n8n.png
new file mode 100644
index 00000000..490fcfcb
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/n8n.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/nocodb.png b/mkdocs/docs/assets/images/screenshots/features/nocodb.png
new file mode 100644
index 00000000..1bd1d21e
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/nocodb.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/pangolin-tunnel.png b/mkdocs/docs/assets/images/screenshots/features/pangolin-tunnel.png
new file mode 100644
index 00000000..0986ce1d
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/pangolin-tunnel.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/payments-dashboard.png b/mkdocs/docs/assets/images/screenshots/features/payments-dashboard.png
new file mode 100644
index 00000000..38ad2747
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/payments-dashboard.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/products-shop.png b/mkdocs/docs/assets/images/screenshots/features/products-shop.png
new file mode 100644
index 00000000..18db5cd5
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/products-shop.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-campaigns.png b/mkdocs/docs/assets/images/screenshots/features/public-campaigns.png
new file mode 100644
index 00000000..8ab6b80c
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-campaigns.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-donations.png b/mkdocs/docs/assets/images/screenshots/features/public-donations.png
new file mode 100644
index 00000000..39173428
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-donations.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-events.png b/mkdocs/docs/assets/images/screenshots/features/public-events.png
new file mode 100644
index 00000000..01390e64
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-events.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-gallery.png b/mkdocs/docs/assets/images/screenshots/features/public-gallery.png
new file mode 100644
index 00000000..ab54dc81
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-gallery.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-home.png b/mkdocs/docs/assets/images/screenshots/features/public-home.png
new file mode 100644
index 00000000..e4fe9ed9
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-home.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-map.png b/mkdocs/docs/assets/images/screenshots/features/public-map.png
new file mode 100644
index 00000000..3d0d94fd
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-map.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-pricing.png b/mkdocs/docs/assets/images/screenshots/features/public-pricing.png
new file mode 100644
index 00000000..4c5be85a
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-pricing.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-shifts.png b/mkdocs/docs/assets/images/screenshots/features/public-shifts.png
new file mode 100644
index 00000000..9c5f8aae
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-shifts.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-shop.png b/mkdocs/docs/assets/images/screenshots/features/public-shop.png
new file mode 100644
index 00000000..05b5e524
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-shop.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/public-wall-of-fame.png b/mkdocs/docs/assets/images/screenshots/features/public-wall-of-fame.png
new file mode 100644
index 00000000..30fbf7f6
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/public-wall-of-fame.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/sms-dashboard.png b/mkdocs/docs/assets/images/screenshots/features/sms-dashboard.png
new file mode 100644
index 00000000..622a20ff
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/sms-dashboard.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/subscription-plans.png b/mkdocs/docs/assets/images/screenshots/features/subscription-plans.png
new file mode 100644
index 00000000..461e79be
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/subscription-plans.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/volunteer-calendar.png b/mkdocs/docs/assets/images/screenshots/features/volunteer-calendar.png
new file mode 100644
index 00000000..ac5af0f4
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/volunteer-calendar.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/volunteer-dashboard.png b/mkdocs/docs/assets/images/screenshots/features/volunteer-dashboard.png
new file mode 100644
index 00000000..aef11869
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/volunteer-dashboard.png differ
diff --git a/mkdocs/docs/assets/images/screenshots/features/volunteer-friends.png b/mkdocs/docs/assets/images/screenshots/features/volunteer-friends.png
new file mode 100644
index 00000000..86a61f8d
Binary files /dev/null and b/mkdocs/docs/assets/images/screenshots/features/volunteer-friends.png differ
diff --git a/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json b/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json
index 29eb2c62..159085f7 100644
--- a/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json
+++ b/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json
@@ -2,15 +2,15 @@
"full_name": "admin/changemaker.lite",
"name": "changemaker.lite",
"description": "Changemaker-lite is the current active development branch of Changemaker, focused on streamlining core services. These improvements will be merged into the master branch once ready.",
- "html_url": "https://gitea.bnkops.com/admin/changemaker.lite",
+ "html_url": "http://gitea.bnkops.com/admin/changemaker.lite",
"language": "HTML",
"stars_count": 0,
"forks_count": 0,
- "open_issues_count": 23,
- "updated_at": "2026-03-10T18:27:08-06:00",
+ "open_issues_count": 0,
+ "updated_at": "2026-03-23T15:48:06-06:00",
"created_at": "2025-05-28T14:54:59-06:00",
"clone_url": "https://gitea.bnkops.com/admin/changemaker.lite.git",
"ssh_url": "git@gitea.bnkops.com:admin/changemaker.lite.git",
"default_branch": "main",
- "last_build_update": "2026-03-10T18:27:08-06:00"
+ "last_build_update": "2026-03-23T15:48:06-06:00"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/anthropics-claude-code.json b/mkdocs/docs/assets/repo-data/anthropics-claude-code.json
index 75ecaac2..86f4e3f6 100644
--- a/mkdocs/docs/assets/repo-data/anthropics-claude-code.json
+++ b/mkdocs/docs/assets/repo-data/anthropics-claude-code.json
@@ -4,13 +4,13 @@
"description": "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.",
"html_url": "https://github.com/anthropics/claude-code",
"language": "Shell",
- "stars_count": 77129,
- "forks_count": 6266,
- "open_issues_count": 6171,
- "updated_at": "2026-03-12T17:36:34Z",
+ "stars_count": 81725,
+ "forks_count": 6816,
+ "open_issues_count": 7445,
+ "updated_at": "2026-03-23T23:45:06Z",
"created_at": "2025-02-22T17:41:21Z",
"clone_url": "https://github.com/anthropics/claude-code.git",
"ssh_url": "git@github.com:anthropics/claude-code.git",
"default_branch": "main",
- "last_build_update": "2026-03-12T07:12:41Z"
+ "last_build_update": "2026-03-20T22:24:50Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/coder-code-server.json b/mkdocs/docs/assets/repo-data/coder-code-server.json
index bd21bc53..192a8e2c 100644
--- a/mkdocs/docs/assets/repo-data/coder-code-server.json
+++ b/mkdocs/docs/assets/repo-data/coder-code-server.json
@@ -4,13 +4,13 @@
"description": "VS Code in the browser",
"html_url": "https://github.com/coder/code-server",
"language": "TypeScript",
- "stars_count": 76609,
- "forks_count": 6547,
- "open_issues_count": 172,
- "updated_at": "2026-03-12T17:13:08Z",
+ "stars_count": 76802,
+ "forks_count": 6567,
+ "open_issues_count": 167,
+ "updated_at": "2026-03-23T23:30:09Z",
"created_at": "2019-02-27T16:50:41Z",
"clone_url": "https://github.com/coder/code-server.git",
"ssh_url": "git@github.com:coder/code-server.git",
"default_branch": "main",
- "last_build_update": "2026-03-11T22:19:15Z"
+ "last_build_update": "2026-03-23T18:50:37Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/gethomepage-homepage.json b/mkdocs/docs/assets/repo-data/gethomepage-homepage.json
index 34bce9dd..46b3bc59 100644
--- a/mkdocs/docs/assets/repo-data/gethomepage-homepage.json
+++ b/mkdocs/docs/assets/repo-data/gethomepage-homepage.json
@@ -4,13 +4,13 @@
"description": "A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.",
"html_url": "https://github.com/gethomepage/homepage",
"language": "JavaScript",
- "stars_count": 28865,
- "forks_count": 1813,
+ "stars_count": 29108,
+ "forks_count": 1825,
"open_issues_count": 1,
- "updated_at": "2026-03-12T15:01:15Z",
+ "updated_at": "2026-03-23T22:44:02Z",
"created_at": "2022-08-24T07:29:42Z",
"clone_url": "https://github.com/gethomepage/homepage.git",
"ssh_url": "git@github.com:gethomepage/homepage.git",
"default_branch": "dev",
- "last_build_update": "2026-03-12T12:22:19Z"
+ "last_build_update": "2026-03-23T12:27:34Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/go-gitea-gitea.json b/mkdocs/docs/assets/repo-data/go-gitea-gitea.json
index ef4abfd2..2a2d1493 100644
--- a/mkdocs/docs/assets/repo-data/go-gitea-gitea.json
+++ b/mkdocs/docs/assets/repo-data/go-gitea-gitea.json
@@ -4,13 +4,13 @@
"description": "Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD",
"html_url": "https://github.com/go-gitea/gitea",
"language": "Go",
- "stars_count": 54251,
- "forks_count": 6466,
- "open_issues_count": 2853,
- "updated_at": "2026-03-12T17:33:45Z",
+ "stars_count": 54439,
+ "forks_count": 6485,
+ "open_issues_count": 2870,
+ "updated_at": "2026-03-23T23:19:17Z",
"created_at": "2016-11-01T02:13:26Z",
"clone_url": "https://github.com/go-gitea/gitea.git",
"ssh_url": "git@github.com:go-gitea/gitea.git",
"default_branch": "main",
- "last_build_update": "2026-03-12T08:26:47Z"
+ "last_build_update": "2026-03-23T23:20:24Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/knadh-listmonk.json b/mkdocs/docs/assets/repo-data/knadh-listmonk.json
index 015ff904..4381eade 100644
--- a/mkdocs/docs/assets/repo-data/knadh-listmonk.json
+++ b/mkdocs/docs/assets/repo-data/knadh-listmonk.json
@@ -4,13 +4,13 @@
"description": "High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.",
"html_url": "https://github.com/knadh/listmonk",
"language": "Go",
- "stars_count": 19256,
- "forks_count": 1946,
- "open_issues_count": 101,
- "updated_at": "2026-03-12T16:54:34Z",
+ "stars_count": 19329,
+ "forks_count": 1958,
+ "open_issues_count": 105,
+ "updated_at": "2026-03-23T23:36:16Z",
"created_at": "2019-06-26T05:08:39Z",
"clone_url": "https://github.com/knadh/listmonk.git",
"ssh_url": "git@github.com:knadh/listmonk.git",
"default_branch": "master",
- "last_build_update": "2026-03-12T16:54:26Z"
+ "last_build_update": "2026-03-23T11:44:19Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/lyqht-mini-qr.json b/mkdocs/docs/assets/repo-data/lyqht-mini-qr.json
index d2f2f9a8..c67a8a41 100644
--- a/mkdocs/docs/assets/repo-data/lyqht-mini-qr.json
+++ b/mkdocs/docs/assets/repo-data/lyqht-mini-qr.json
@@ -4,13 +4,13 @@
"description": "Create & scan cute qr codes easily \ud83d\udc7e",
"html_url": "https://github.com/lyqht/mini-qr",
"language": "Vue",
- "stars_count": 1905,
- "forks_count": 241,
- "open_issues_count": 19,
- "updated_at": "2026-03-12T17:06:09Z",
+ "stars_count": 1928,
+ "forks_count": 243,
+ "open_issues_count": 20,
+ "updated_at": "2026-03-23T14:42:50Z",
"created_at": "2023-04-21T14:20:14Z",
"clone_url": "https://github.com/lyqht/mini-qr.git",
"ssh_url": "git@github.com:lyqht/mini-qr.git",
"default_branch": "main",
- "last_build_update": "2026-03-11T14:53:40Z"
+ "last_build_update": "2026-03-13T12:48:04Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/n8n-io-n8n.json b/mkdocs/docs/assets/repo-data/n8n-io-n8n.json
index b106ed6c..d57c7a2f 100644
--- a/mkdocs/docs/assets/repo-data/n8n-io-n8n.json
+++ b/mkdocs/docs/assets/repo-data/n8n-io-n8n.json
@@ -4,13 +4,13 @@
"description": "Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.",
"html_url": "https://github.com/n8n-io/n8n",
"language": "TypeScript",
- "stars_count": 178836,
- "forks_count": 55709,
- "open_issues_count": 1414,
- "updated_at": "2026-03-12T17:33:04Z",
+ "stars_count": 180706,
+ "forks_count": 56089,
+ "open_issues_count": 1433,
+ "updated_at": "2026-03-23T23:47:25Z",
"created_at": "2019-06-22T09:24:21Z",
"clone_url": "https://github.com/n8n-io/n8n.git",
"ssh_url": "git@github.com:n8n-io/n8n.git",
"default_branch": "master",
- "last_build_update": "2026-03-12T16:48:37Z"
+ "last_build_update": "2026-03-23T22:55:38Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/nocodb-nocodb.json b/mkdocs/docs/assets/repo-data/nocodb-nocodb.json
index efbfb022..9072cbd1 100644
--- a/mkdocs/docs/assets/repo-data/nocodb-nocodb.json
+++ b/mkdocs/docs/assets/repo-data/nocodb-nocodb.json
@@ -4,13 +4,13 @@
"description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 A Free & Self-hostable Airtable Alternative",
"html_url": "https://github.com/nocodb/nocodb",
"language": "TypeScript",
- "stars_count": 62459,
- "forks_count": 4662,
- "open_issues_count": 636,
- "updated_at": "2026-03-12T17:22:54Z",
+ "stars_count": 62544,
+ "forks_count": 4679,
+ "open_issues_count": 647,
+ "updated_at": "2026-03-23T22:41:15Z",
"created_at": "2017-10-29T18:51:48Z",
"clone_url": "https://github.com/nocodb/nocodb.git",
"ssh_url": "git@github.com:nocodb/nocodb.git",
"default_branch": "develop",
- "last_build_update": "2026-03-12T15:47:46Z"
+ "last_build_update": "2026-03-23T19:39:55Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/ollama-ollama.json b/mkdocs/docs/assets/repo-data/ollama-ollama.json
index beefcf5f..b042dc06 100644
--- a/mkdocs/docs/assets/repo-data/ollama-ollama.json
+++ b/mkdocs/docs/assets/repo-data/ollama-ollama.json
@@ -4,13 +4,13 @@
"description": "Get up and running with Kimi-K2.5, GLM-5, MiniMax, DeepSeek, gpt-oss, Qwen, Gemma and other models.",
"html_url": "https://github.com/ollama/ollama",
"language": "Go",
- "stars_count": 164918,
- "forks_count": 14922,
- "open_issues_count": 2623,
- "updated_at": "2026-03-12T17:11:02Z",
+ "stars_count": 165968,
+ "forks_count": 15121,
+ "open_issues_count": 2708,
+ "updated_at": "2026-03-23T23:47:27Z",
"created_at": "2023-06-26T19:39:32Z",
"clone_url": "https://github.com/ollama/ollama.git",
"ssh_url": "git@github.com:ollama/ollama.git",
"default_branch": "main",
- "last_build_update": "2026-03-12T08:42:26Z"
+ "last_build_update": "2026-03-23T23:31:24Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json b/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json
index bd11df2d..66f348b2 100644
--- a/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json
+++ b/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json
@@ -4,13 +4,13 @@
"description": "Documentation that simply works",
"html_url": "https://github.com/squidfunk/mkdocs-material",
"language": "Python",
- "stars_count": 26261,
- "forks_count": 4053,
- "open_issues_count": 2,
- "updated_at": "2026-03-12T17:20:59Z",
+ "stars_count": 26370,
+ "forks_count": 4058,
+ "open_issues_count": 1,
+ "updated_at": "2026-03-23T21:42:58Z",
"created_at": "2016-01-28T22:09:23Z",
"clone_url": "https://github.com/squidfunk/mkdocs-material.git",
"ssh_url": "git@github.com:squidfunk/mkdocs-material.git",
"default_branch": "master",
- "last_build_update": "2026-03-10T15:42:14Z"
+ "last_build_update": "2026-03-22T15:57:47Z"
}
\ No newline at end of file
diff --git a/mkdocs/docs/lander.md b/mkdocs/docs/lander.md
new file mode 100644
index 00000000..2350380c
--- /dev/null
+++ b/mkdocs/docs/lander.md
@@ -0,0 +1,7 @@
+---
+template: lander.html
+hide:
+ - navigation
+ - toc
+title: "lander"
+---
diff --git a/mkdocs/docs/main.md b/mkdocs/docs/main.md
new file mode 100644
index 00000000..d8ab1699
--- /dev/null
+++ b/mkdocs/docs/main.md
@@ -0,0 +1,7 @@
+---
+template: main.html
+hide:
+ - navigation
+ - toc
+title: "main"
+---
diff --git a/mkdocs/docs/overrides/lander.html b/mkdocs/docs/overrides/lander.html
index 37ace877..9fbda767 100644
--- a/mkdocs/docs/overrides/lander.html
+++ b/mkdocs/docs/overrides/lander.html
@@ -386,6 +386,29 @@
box-shadow: 0 4px 16px rgba(111, 66, 193, 0.4);
}
+ .btn-demo {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.625rem 1.5rem;
+ background: transparent;
+ color: var(--primary-light);
+ font-weight: 600;
+ font-size: 0.9rem;
+ border-radius: 8px;
+ border: 1px solid var(--primary-light);
+ cursor: pointer;
+ transition: all var(--transition);
+ text-decoration: none;
+ }
+
+ .btn-demo:hover {
+ background: rgba(139, 92, 246, 0.1);
+ color: var(--primary-light);
+ transform: translateY(-1px);
+ box-shadow: 0 4px 16px rgba(111, 66, 193, 0.2);
+ }
+
.btn-secondary {
display: inline-flex;
align-items: center;
@@ -1167,6 +1190,141 @@
color: var(--text-muted);
}
+ /* ============================================
+ FEATURE NODE — HOVER SCREENSHOT PREVIEW
+ ============================================ */
+ .feature-node[data-screenshot] {
+ cursor: pointer;
+ }
+
+ .node-screenshot {
+ max-height: 0;
+ overflow: hidden;
+ margin: 0 -1.5rem;
+ border-radius: 0;
+ transition: max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1), margin-top 0.35s ease, margin-bottom 0.35s ease;
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .feature-node:hover .node-screenshot {
+ max-height: 300px;
+ margin-top: 0.75rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .node-screenshot img {
+ width: 100%;
+ height: auto;
+ display: block;
+ border-top: 1px solid var(--border-color);
+ border-bottom: 1px solid var(--border-color);
+ }
+
+ .node-screenshot-label {
+ padding: 0.3rem 1.5rem;
+ font-size: 0.7rem;
+ color: var(--text-muted);
+ display: flex;
+ align-items: center;
+ gap: 0.4rem;
+ background: rgba(0,0,0,0.15);
+ }
+
+ [data-theme="light"] .node-screenshot-label {
+ background: rgba(0,0,0,0.04);
+ }
+
+ .node-screenshot-label .screenshot-dot {
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background: var(--success);
+ flex-shrink: 0;
+ }
+
+ /* On mobile, hide hover screenshots (touch doesn't hover well) */
+ @media (max-width: 768px) {
+ .node-screenshot {
+ display: none;
+ }
+ }
+
+ /* ============================================
+ NARRATIVE BRIDGE SECTION
+ ============================================ */
+ .narrative-bridge {
+ padding: 4rem 0 2rem;
+ background: transparent;
+ }
+
+ .narrative-content {
+ max-width: 720px;
+ margin: 0 auto;
+ text-align: center;
+ background: rgba(30, 41, 59, 0.85);
+ border: 1px solid rgba(148, 163, 184, 0.1);
+ border-radius: var(--radius-lg);
+ padding: 3rem 2.5rem;
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ position: relative;
+ z-index: 2;
+ }
+
+ [data-theme="light"] .narrative-content {
+ background: rgba(255, 255, 255, 0.88);
+ border-color: rgba(100, 116, 139, 0.15);
+ }
+
+ .narrative-eyebrow {
+ font-size: 0.8rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.12em;
+ color: var(--primary-light);
+ margin-bottom: 1rem;
+ }
+
+ .narrative-content h2 {
+ font-size: clamp(1.5rem, 3vw, 2.25rem);
+ margin-bottom: 1.25rem;
+ line-height: 1.3;
+ }
+
+ .narrative-body {
+ color: var(--text-secondary);
+ font-size: 1.1rem;
+ line-height: 1.7;
+ }
+
+ /* In-feature narrative connectors */
+ .branch-narrative {
+ max-width: 640px;
+ margin: 2rem auto 3rem;
+ text-align: center;
+ padding: 1.5rem 2rem;
+ background: rgba(30, 41, 59, 0.85);
+ border: 1px solid rgba(148, 163, 184, 0.1);
+ border-radius: var(--radius-lg);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ position: relative;
+ z-index: 2;
+ }
+
+ [data-theme="light"] .branch-narrative {
+ background: rgba(255, 255, 255, 0.45);
+ border-color: rgba(100, 116, 139, 0.1);
+ }
+
+ .branch-narrative p {
+ color: var(--text-secondary);
+ font-size: 1rem;
+ line-height: 1.7;
+ margin: 0;
+ }
+
/* ============================================
LIVE SITES
============================================ */
@@ -1915,6 +2073,7 @@
+ Explore Demo
Get Started
@@ -1892,6 +2086,7 @@
+ Explore Demo
Get Started