lobsterboard 0.8.4 → 0.8.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.6] - 2026-05-06
4
+
5
+ ### Fixed
6
+ - **Search widget restored** — reinstated the PR27 Search widget in the picker with DuckDuckGo-style `!bangs`, keyboard focus shortcut, and query recall
7
+ - **Finance widgets restored** — reinstated the PR27 Stock Ticker and Crypto Price widgets plus their server-side finance routes
8
+ - **npm package contents** — ensured the published package includes required runtime server files and restored PR27 widget assets
9
+ - **Remote stats cleanup** — improved remote stats poller teardown to avoid stale pollers and overlapping requests
10
+
11
+ ## [0.8.5] - 2026-05-06
12
+
13
+ ### Fixed
14
+ - **npm package contents** — restored missing `server/` runtime files in the published package so `npx lobsterboard` and `node server.cjs` no longer crash with `Cannot find module './server/config.cjs'`
15
+
3
16
  ## [0.8.3] - 2026-04-02
4
17
 
5
18
  ### Fixed
package/app.html CHANGED
@@ -336,6 +336,10 @@
336
336
  <span class="widget-name">GitHub Stats</span>
337
337
  <span class="widget-verified" title="Tested & Verified">✓</span>
338
338
  </div>
339
+ <div class="widget-item" draggable="true" data-widget="search">
340
+ <span class="widget-icon">🔍</span>
341
+ <span class="widget-name">Search</span>
342
+ </div>
339
343
  </div>
340
344
  </div>
341
345
 
@@ -1,4 +1,4 @@
1
- /* LobsterBoard v0.8.4 - Dashboard Styles */
1
+ /* LobsterBoard v0.8.6 - Dashboard Styles */
2
2
  /* LobsterBoard Dashboard - Generated Styles */
3
3
 
4
4
  :root {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * LobsterBoard v0.8.4
2
+ * LobsterBoard v0.8.6
3
3
  * Dashboard builder with customizable widgets
4
4
  * https://github.com/curbob/LobsterBoard
5
5
  * @license MIT
@@ -651,11 +651,6 @@ const WIDGETS = {
651
651
  </div>
652
652
  </div>`,
653
653
  generateJs: (props) => `
654
- function registerWidgetInterval(widgetId, intervalId) {
655
- window.__lobsterboardWidgetIntervals = window.__lobsterboardWidgetIntervals || {};
656
- if (window.__lobsterboardWidgetIntervals[widgetId]) clearInterval(window.__lobsterboardWidgetIntervals[widgetId]);
657
- window.__lobsterboardWidgetIntervals[widgetId] = intervalId;
658
- }
659
654
  async function update_${props.id.replace(/-/g, '_')}() {
660
655
  var list = document.getElementById('${props.id}-list');
661
656
  var badge = document.getElementById('${props.id}-badge');
@@ -682,7 +677,7 @@ const WIDGETS = {
682
677
  }
683
678
  }
684
679
  update_${props.id.replace(/-/g, '_')}();
685
- registerWidgetInterval('${props.id}', setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000}));
680
+ setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000});
686
681
  `
687
682
  },
688
683
 
@@ -715,11 +710,6 @@ const WIDGETS = {
715
710
  </div>
716
711
  </div>`,
717
712
  generateJs: (props) => `
718
- function registerWidgetInterval(widgetId, intervalId) {
719
- window.__lobsterboardWidgetIntervals = window.__lobsterboardWidgetIntervals || {};
720
- if (window.__lobsterboardWidgetIntervals[widgetId]) clearInterval(window.__lobsterboardWidgetIntervals[widgetId]);
721
- window.__lobsterboardWidgetIntervals[widgetId] = intervalId;
722
- }
723
713
  async function update_${props.id.replace(/-/g, '_')}() {
724
714
  var list = document.getElementById('${props.id}-list');
725
715
  var badge = document.getElementById('${props.id}-badge');
@@ -744,7 +734,7 @@ const WIDGETS = {
744
734
  }
745
735
  }
746
736
  update_${props.id.replace(/-/g, '_')}();
747
- registerWidgetInterval('${props.id}', setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000}));
737
+ setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000});
748
738
  `
749
739
  },
750
740
 
@@ -794,7 +784,6 @@ const WIDGETS = {
794
784
  (function() {
795
785
  var BANGS = ${JSON.stringify(bangs)};
796
786
  var DEFAULT_URL = '${defaultUrl}';
797
- var widgetId = '${props.id}';
798
787
  var lastQuery = '';
799
788
  function navigate(q) {
800
789
  q = q.trim(); if (!q) return; lastQuery = q;
@@ -808,19 +797,13 @@ const WIDGETS = {
808
797
  var input = document.getElementById('${props.id}-input');
809
798
  if (form) form.addEventListener('submit', function() { navigate(input.value); });
810
799
  if (input) input.addEventListener('keydown', function(e) { if (e.key === 'ArrowUp') { e.preventDefault(); input.value = lastQuery; } });
811
- window.__lobsterboardSearchHandlers = window.__lobsterboardSearchHandlers || {};
812
- if (window.__lobsterboardSearchHandlers[widgetId]) {
813
- document.removeEventListener('keydown', window.__lobsterboardSearchHandlers[widgetId]);
814
- }
815
- var searchFocusHandler = function(e) {
800
+ document.addEventListener('keydown', function(e) {
816
801
  var tag = document.activeElement && document.activeElement.tagName;
817
802
  if (e.key === 's' && tag !== 'INPUT' && tag !== 'TEXTAREA' && !e.ctrlKey && !e.metaKey) {
818
- var inp = document.getElementById(widgetId + '-input');
803
+ var inp = document.getElementById('${props.id}-input');
819
804
  if (inp) { inp.focus(); inp.select(); e.preventDefault(); }
820
805
  }
821
- };
822
- window.__lobsterboardSearchHandlers[widgetId] = searchFocusHandler;
823
- document.addEventListener('keydown', searchFocusHandler);
806
+ });
824
807
  })();
825
808
  `;
826
809
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lobsterboard.esm.js","sources":["../src/widgets.js","../src/builder.js","../src/index.js"],"sourcesContent":["/**\n * LobsterBoard - Widget Definitions\n * Each widget defines its default size, properties, and generated code\n * \n * @module lobsterboard/widgets\n */\n\nexport const WIDGETS = {\n // ─────────────────────────────────────────────\n // SMALL CARDS (KPI style)\n // ─────────────────────────────────────────────\n \n 'weather': {\n name: 'Local Weather',\n icon: '🌡️',\n category: 'small',\n description: 'Shows current weather for a single location using wttr.in (no API key needed).',\n defaultWidth: 200,\n defaultHeight: 120,\n hasApiKey: false,\n properties: {\n title: 'Local Weather',\n location: 'Atlanta',\n units: 'F',\n refreshInterval: 600\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"font-size:24px;\">72°F</div>\n <div style=\"font-size:11px;color:#8b949e;\">Atlanta</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🌡️ ${props.title || 'Local Weather'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;align-items:center;justify-content:center;gap:10px;\">\n <span id=\"${props.id}-icon\" style=\"font-size:24px;\">🌡️</span>\n <div>\n <div class=\"kpi-value blue\" id=\"${props.id}-value\">—</div>\n <div class=\"kpi-label\" id=\"${props.id}-label\">${props.location || 'Location'}</div>\n </div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Weather Widget: ${props.id} (uses free wttr.in API - no key needed)\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const location = encodeURIComponent('${props.location || 'Atlanta'}');\n const res = await fetch('https://wttr.in/' + location + '?format=j1');\n const data = await res.json();\n const current = data.current_condition[0];\n const temp = '${props.units}' === 'C' ? current.temp_C : current.temp_F;\n const unit = '${props.units}' === 'C' ? '°C' : '°F';\n document.getElementById('${props.id}-value').textContent = temp + unit;\n document.getElementById('${props.id}-label').textContent = current.weatherDesc[0].value;\n const code = parseInt(current.weatherCode);\n let icon = '🌡️';\n if (code === 113) icon = '☀️';\n else if (code === 116 || code === 119) icon = '⛅';\n else if (code >= 176 && code <= 359) icon = '🌧️';\n else if (code >= 368 && code <= 395) icon = '❄️';\n document.getElementById('${props.id}-icon').textContent = icon;\n } catch (e) {\n console.error('Weather widget error:', e);\n document.getElementById('${props.id}-value').textContent = '—';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 600) * 1000});\n `\n },\n\n 'clock': {\n name: 'Clock',\n icon: '🕐',\n category: 'small',\n description: 'Simple digital clock. Supports 12h or 24h format.',\n defaultWidth: 200,\n defaultHeight: 120,\n hasApiKey: false,\n properties: {\n title: 'Clock',\n timezone: 'local',\n format24h: false\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"font-size:24px;\">3:45 PM</div>\n <div style=\"font-size:11px;color:#8b949e;\">Wed, Feb 5</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🕐 ${props.title || 'Clock'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;flex-direction:column;align-items:center;justify-content:center;\">\n <div class=\"kpi-value\" id=\"${props.id}-time\">—</div>\n <div class=\"kpi-label\" id=\"${props.id}-date\">—</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Clock Widget: ${props.id}\n function updateClock_${props.id.replace(/-/g, '_')}() {\n const now = new Date();\n const timeEl = document.getElementById('${props.id}-time');\n const dateEl = document.getElementById('${props.id}-date');\n const opts = { hour: 'numeric', minute: '2-digit', hour12: ${!props.format24h} };\n timeEl.textContent = now.toLocaleTimeString('en-US', opts);\n dateEl.textContent = now.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });\n }\n updateClock_${props.id.replace(/-/g, '_')}();\n setInterval(updateClock_${props.id.replace(/-/g, '_')}, 1000);\n `\n },\n\n 'auth-status': {\n name: 'Auth Status',\n icon: '🔐',\n category: 'small',\n description: 'Shows if OpenClaw is using Anthropic Max subscription (green) or API key fallback (yellow).',\n defaultWidth: 180,\n defaultHeight: 100,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Auth Type',\n endpoint: '/api/status',\n refreshInterval: 30\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"width:10px;height:10px;background:#3fb950;border-radius:50%;margin:0 auto 4px;\"></div>\n <div style=\"font-size:13px;\">OAuth</div>\n <div style=\"font-size:11px;color:#8b949e;\">Auth</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🔐 ${props.title || 'Auth Type'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;align-items:center;justify-content:center;gap:10px;\">\n <div class=\"kpi-indicator\" id=\"${props.id}-dot\"></div>\n <div class=\"kpi-value\" id=\"${props.id}-value\">—</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Auth Status Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/status'}');\n const json = await res.json();\n const data = json.data || json;\n const dot = document.getElementById('${props.id}-dot');\n const val = document.getElementById('${props.id}-value');\n val.textContent = data.authMode === 'oauth' ? 'Subscription' : 'API';\n dot.className = 'kpi-indicator ' + (data.authMode === 'oauth' ? 'green' : 'yellow');\n } catch (e) {\n console.error('Auth status widget error:', e);\n document.getElementById('${props.id}-value').textContent = '—';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 30) * 1000});\n `\n },\n\n 'session-count': {\n name: 'Active Sessions',\n icon: '💬',\n category: 'small',\n description: 'Shows count of active OpenClaw sessions.',\n defaultWidth: 160,\n defaultHeight: 100,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Sessions',\n endpoint: '/api/sessions',\n refreshInterval: 30\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"font-size:28px;color:#58a6ff;\">3</div>\n <div style=\"font-size:11px;color:#8b949e;\">Active</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"kpi-card kpi-sm\" id=\"widget-${props.id}\">\n <div class=\"kpi-icon\">💬</div>\n <div class=\"kpi-data\">\n <div class=\"kpi-value blue\" id=\"${props.id}-count\">—</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Session Count Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/sessions'}');\n const json = await res.json();\n const data = json.data || json;\n document.getElementById('${props.id}-count').textContent = data.active || data.length || 0;\n } catch (e) {\n document.getElementById('${props.id}-count').textContent = '—';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 30) * 1000});\n `\n },\n\n // ─────────────────────────────────────────────\n // LARGE CARDS (Content)\n // ─────────────────────────────────────────────\n\n 'activity-list': {\n name: 'Activity List',\n icon: '📋',\n category: 'large',\n description: 'Shows recent OpenClaw activity from /api/activity endpoint.',\n defaultWidth: 400,\n defaultHeight: 300,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Today',\n endpoint: '/api/activity',\n maxItems: 10,\n refreshInterval: 60\n },\n preview: `<div style=\"padding:4px;font-size:11px;color:#8b949e;\">\n <div>• Meeting at 2pm</div>\n <div>• Review PR #42</div>\n <div>• Deploy v1.2</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">📋 ${props.title || 'Today'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body compact-list\" id=\"${props.id}-list\">\n <div class=\"list-item\">• Team standup at 10am</div>\n <div class=\"list-item\">• Review PR #42</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Activity List Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/activity'}');\n const json = await res.json();\n const data = json.data || json;\n const list = document.getElementById('${props.id}-list');\n const badge = document.getElementById('${props.id}-badge');\n const items = data.items || [];\n list.innerHTML = items.slice(0, ${props.maxItems || 10}).map(item => \n '<div class=\"list-item\">' + item.text + '</div>'\n ).join('');\n badge.textContent = items.length + ' items';\n } catch (e) {\n console.error('Activity list widget error:', e);\n document.getElementById('${props.id}-list').innerHTML = '<div class=\"list-item\">—</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 60) * 1000});\n `\n },\n\n 'cron-jobs': {\n name: 'Cron Jobs',\n icon: '⏰',\n category: 'large',\n description: 'Lists scheduled cron jobs from OpenClaw /api/cron endpoint.',\n defaultWidth: 400,\n defaultHeight: 250,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Cron',\n endpoint: '/api/cron',\n refreshInterval: 30\n },\n preview: `<div style=\"padding:4px;font-size:11px;color:#8b949e;\">\n <div>⏰ Daily backup - 2am</div>\n <div>⏰ Sync data - */5 *</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">⏰ ${props.title || 'Cron'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body\" id=\"${props.id}-list\">\n <div class=\"cron-item\"><span class=\"cron-name\">Daily backup</span><span class=\"cron-next\">2:00 AM</span></div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Cron Jobs Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/cron'}');\n const json = await res.json();\n const data = json.data || json;\n const list = document.getElementById('${props.id}-list');\n const badge = document.getElementById('${props.id}-badge');\n const jobs = data.jobs || [];\n list.innerHTML = jobs.map(job => \n '<div class=\"cron-item\"><span class=\"cron-name\">' + job.name + '</span><span class=\"cron-next\">' + job.next + '</span></div>'\n ).join('');\n badge.textContent = jobs.length + ' jobs';\n } catch (e) {\n console.error('Cron jobs widget error:', e);\n document.getElementById('${props.id}-list').innerHTML = '<div class=\"cron-item\"><span class=\"cron-name\">—</span></div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 30) * 1000});\n `\n },\n\n 'system-log': {\n name: 'System Log',\n icon: '🔧',\n category: 'large',\n description: 'Shows recent system logs from OpenClaw /api/logs endpoint.',\n defaultWidth: 500,\n defaultHeight: 400,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'System Log',\n endpoint: '/api/logs',\n maxLines: 50,\n refreshInterval: 10\n },\n preview: `<div style=\"padding:4px;font-size:10px;font-family:monospace;color:#8b949e;\">\n <div>[INFO] System started</div>\n <div>[DEBUG] Loading config</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🔧 ${props.title || 'System Log'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body compact-list syslog-scroll\" id=\"${props.id}-log\">\n <div class=\"log-line\">[INFO] System started successfully</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // System Log Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/logs'}');\n const json = await res.json();\n const data = json.data || json;\n const log = document.getElementById('${props.id}-log');\n const badge = document.getElementById('${props.id}-badge');\n const lines = data.lines || [];\n log.innerHTML = lines.slice(-${props.maxLines || 50}).map(line => \n '<div class=\"log-line\">' + line + '</div>'\n ).join('');\n badge.textContent = lines.length + ' lines';\n log.scrollTop = log.scrollHeight;\n } catch (e) {\n console.error('System log widget error:', e);\n document.getElementById('${props.id}-log').innerHTML = '<div class=\"log-line\">—</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 10) * 1000});\n `\n },\n\n // ─────────────────────────────────────────────\n // BARS\n // ─────────────────────────────────────────────\n\n 'pages-menu': {\n name: 'Pages Menu',\n icon: '📑',\n category: 'small',\n description: 'Navigation links to all discovered LobsterBoard pages. Supports vertical or horizontal layout.',\n defaultWidth: 220,\n defaultHeight: 200,\n hasApiKey: false,\n properties: {\n title: 'Pages',\n layout: 'vertical',\n refreshInterval: 60\n },\n preview: `<div style=\"padding:6px;font-size:11px;color:#8b949e;\">\n <div>📝 Notes</div>\n <div>📋 Board</div>\n <div>📅 Calendar</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">📑 ${props.title || 'Pages'}</span>\n </div>\n <div class=\"dash-card-body pages-menu ${props.layout === 'horizontal' ? 'pages-menu-horizontal' : 'pages-menu-vertical'}\" id=\"${props.id}-list\">\n <span class=\"pages-menu-item\">Loading…</span>\n </div>\n </div>\n <style>\n .pages-menu-vertical { display:flex; flex-direction:column; gap:4px; overflow-y:auto; }\n .pages-menu-horizontal { display:flex; flex-direction:row; flex-wrap:wrap; gap:6px; align-items:center; }\n .pages-menu-item {\n display:inline-flex; align-items:center; gap:6px;\n padding:6px 10px; border-radius:6px;\n background:#21262d; color:#c9d1d9;\n text-decoration:none; font-size:13px;\n transition: background .15s, color .15s;\n }\n .pages-menu-item:hover { background:#30363d; color:#58a6ff; }\n .pages-menu-item .pages-menu-icon { font-size:15px; }\n </style>`,\n generateJs: (props) => `\n // Pages Menu Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('/api/pages');\n const pages = await res.json();\n const list = document.getElementById('${props.id}-list');\n if (!pages.length) { list.innerHTML = '<span class=\"pages-menu-item\">No pages found</span>'; return; }\n list.innerHTML = pages.map(p =>\n '<a class=\"pages-menu-item\" href=\"/pages/' + p.id + '\" title=\"' + (p.description || p.title || p.name || '') + '\">' +\n '<span class=\"pages-menu-icon\">' + (p.icon || '📄') + '</span>' +\n '<span>' + (p.title || p.name || p.id) + '</span></a>'\n ).join('');\n } catch (e) {\n console.error('Pages menu widget error:', e);\n document.getElementById('${props.id}-list').innerHTML = '<span class=\"pages-menu-item\">Error loading pages</span>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 60) * 1000});\n `\n },\n\n 'topbar': {\n name: 'Top Nav Bar',\n icon: '🔝',\n category: 'bar',\n description: 'Navigation bar with clock, weather, and system stats.',\n defaultWidth: 1920,\n defaultHeight: 48,\n hasApiKey: false,\n properties: {\n title: 'OpenClaw',\n links: 'Dashboard,Activity,Settings'\n },\n preview: `<div style=\"background:#161b22;padding:8px;font-size:11px;display:flex;gap:12px;\">\n <span>🤖 OpenClaw</span>\n <span style=\"color:#58a6ff;\">Dashboard</span>\n </div>`,\n generateHtml: (props) => `\n <nav class=\"topbar\" id=\"widget-${props.id}\">\n <div class=\"topbar-left\">\n <span class=\"topbar-brand\">🤖 ${props.title || 'OpenClaw'}</span>\n ${(props.links || 'Dashboard').split(',').map((link, i) => \n `<a href=\"#\" class=\"topbar-link${i === 0 ? ' active' : ''}\">${link.trim()}</a>`\n ).join('')}\n </div>\n <div class=\"topbar-right\">\n <span class=\"topbar-meta\" id=\"${props.id}-refresh\">—</span>\n <button class=\"topbar-refresh\" onclick=\"location.reload()\" title=\"Refresh\">↻</button>\n </div>\n </nav>`,\n generateJs: (props) => `\n // Top Bar Widget: ${props.id}\n document.getElementById('${props.id}-refresh').textContent = \n new Date().toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });\n `\n },\n\n 'system-graphical': {\n name: 'System (Graphical)',\n icon: '💻',\n category: 'system',\n description: 'Graphical CPU and Memory usage with circular progress rings. Supports remote servers via lobsterboard-agent.',\n defaultWidth: 240,\n defaultHeight: 140,\n hasApiKey: false,\n properties: {\n title: 'System',\n server: 'local',\n refreshInterval: 5,\n showPercentages: true,\n showLabels: true\n },\n preview: `<div style=\"display:flex;align-items:center;justify-content:space-around;padding:8px;\">\n <div style=\"position:relative;width:50px;height:50px;\">\n <svg viewBox=\"0 0 48 48\" style=\"width:100%;height:100%;transform:rotate(-90deg);\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#30363d\" stroke-width=\"4\"/>\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#58a6ff\" stroke-width=\"4\"\n stroke-dasharray=\"113\" stroke-dashoffset=\"85\" stroke-linecap=\"round\"/>\n </svg>\n <div style=\"position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:10px;font-weight:600;color:#58a6ff;\">25%</div>\n </div>\n <div style=\"position:relative;width:50px;height:50px;\">\n <svg viewBox=\"0 0 48 48\" style=\"width:100%;height:100%;transform:rotate(-90deg);\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#30363d\" stroke-width=\"4\"/>\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#3fb950\" stroke-width=\"4\"\n stroke-dasharray=\"113\" stroke-dashoffset=\"68\" stroke-linecap=\"round\"/>\n </svg>\n <div style=\"position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:10px;font-weight:600;color:#3fb950;\">40%</div>\n </div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">${renderIcon('cpu')} ${props.title || 'System'}</span>\n ${props.server && props.server !== 'local' ? `<span class=\"dash-card-badge\" style=\"font-size:10px;\">🌐</span>` : ''}\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;align-items:center;justify-content:space-around;padding:12px;\">\n <div class=\"system-metric\">\n ${props.showLabels ? '<div class=\"metric-label\">CPU</div>' : ''}\n <div class=\"progress-ring-container\">\n <svg class=\"progress-ring\" viewBox=\"0 0 48 48\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"var(--bg-tertiary)\" stroke-width=\"4\"/>\n <circle id=\"${props.id}-cpu-ring\" cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#58a6ff\" stroke-width=\"4\"\n stroke-dasharray=\"113.1\" stroke-dashoffset=\"113.1\" stroke-linecap=\"round\"\n style=\"transition: stroke-dashoffset 0.6s ease, stroke 0.3s ease; transform: rotate(-90deg); transform-origin: 50% 50%;\"/>\n </svg>\n <div class=\"progress-ring-text\">\n <span id=\"${props.id}-cpu-pct\" ${props.showPercentages ? '' : 'style=\"display:none;\"'}>—</span>\n <span id=\"${props.id}-cpu-icon\" ${props.showPercentages ? 'style=\"display:none;\"' : ''}>💻</span>\n </div>\n </div>\n </div>\n <div class=\"system-metric\">\n ${props.showLabels ? '<div class=\"metric-label\">MEM</div>' : ''}\n <div class=\"progress-ring-container\">\n <svg class=\"progress-ring\" viewBox=\"0 0 48 48\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"var(--bg-tertiary)\" stroke-width=\"4\"/>\n <circle id=\"${props.id}-mem-ring\" cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#3fb950\" stroke-width=\"4\"\n stroke-dasharray=\"113.1\" stroke-dashoffset=\"113.1\" stroke-linecap=\"round\"\n style=\"transition: stroke-dashoffset 0.6s ease, stroke 0.3s ease; transform: rotate(-90deg); transform-origin: 50% 50%;\"/>\n </svg>\n <div class=\"progress-ring-text\">\n <span id=\"${props.id}-mem-pct\" ${props.showPercentages ? '' : 'style=\"display:none;\"'}>—</span>\n <span id=\"${props.id}-mem-icon\" ${props.showPercentages ? 'style=\"display:none;\"' : ''}>🧠</span>\n </div>\n </div>\n </div>\n </div>\n </div>`,\n generateJs: (props) => `\n // System (Graphical) Widget: ${props.id} — ${props.server === 'local' ? 'local SSE' : 'remote: ' + props.server}\n \n function getUsageColor(percentage) {\n if (percentage >= 90) return '#f85149'; // Red for critical\n if (percentage >= 75) return '#d29922'; // Yellow for warning\n if (percentage >= 50) return '#58a6ff'; // Blue for moderate\n return '#3fb950'; // Green for good\n }\n \n function updateProgressRing(ringId, percentage, textId) {\n const ring = document.getElementById(ringId);\n const text = document.getElementById(textId);\n if (!ring || !text) return;\n \n const normalizedPct = Math.max(0, Math.min(100, percentage || 0));\n const circumference = 113.1; // 2 * π * 18\n const offset = circumference - (normalizedPct / 100 * circumference);\n const color = getUsageColor(normalizedPct);\n \n ring.style.strokeDashoffset = offset;\n ring.style.stroke = color;\n text.textContent = Math.round(normalizedPct) + '%';\n text.style.color = color;\n }\n \n onStats('${props.server || 'local'}', function(data) {\n // Handle offline state\n if (data._offline) {\n document.getElementById('${props.id}-cpu-pct').textContent = '⚠️';\n document.getElementById('${props.id}-mem-pct').textContent = '⚠️';\n document.getElementById('${props.id}-cpu-ring').style.strokeDashoffset = '113.1';\n document.getElementById('${props.id}-mem-ring').style.strokeDashoffset = '113.1';\n return;\n }\n \n // Update CPU ring\n if (data.cpu && data.cpu.currentLoad != null) {\n updateProgressRing('${props.id}-cpu-ring', data.cpu.currentLoad, '${props.id}-cpu-pct');\n }\n \n // Update Memory ring \n if (data.memory && data.memory.total && data.memory.active != null) {\n const memoryPct = (data.memory.active / data.memory.total) * 100;\n updateProgressRing('${props.id}-mem-ring', memoryPct, '${props.id}-mem-pct');\n }\n }, ${(props.refreshInterval || 5) * 1000});\n `\n },\n\n 'claude-usage': {\n name: 'Claude Usage',\n icon: '🤖',\n category: 'large',\n description: 'Real-time Claude Code subscription usage (5h session, 7d weekly, Opus, Sonnet limits). Reads credentials from ~/.claude.',\n defaultWidth: 380,\n defaultHeight: 260,\n hasApiKey: false,\n properties: { title: 'Claude Usage', refreshInterval: 120 },\n preview: `<div style=\"padding:8px;font-size:11px;\"><div><b>5h Session</b> 28%</div><div><b>7d Weekly</b> 31%</div></div>`,\n generateHtml: (props) => `<div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\"><div class=\"dash-card-head\"><span class=\"dash-card-title\">🤖 ${props.title || 'Claude Usage'}</span><span id=\"${props.id}-sub\" style=\"font-size:10px;color:#8b949e;margin-left:auto;\"></span></div><div class=\"dash-card-body\" id=\"${props.id}-body\" style=\"padding:8px 12px;overflow-y:auto;\"><div style=\"color:#8b949e;text-align:center;\">Loading...</div></div></div>`,\n generateJs: (props) => `\n function barColor(pct) { return pct >= 80 ? '#f85149' : pct >= 50 ? '#d29922' : '#3fb950'; }\n function timeLeft(iso) { if (!iso) return ''; const ms = new Date(iso) - Date.now(); if (ms <= 0) return 'now'; const h = Math.floor(ms/3600000), m = Math.floor((ms%3600000)/60000); return h > 0 ? h+'h '+m+'m' : m+'m'; }\n function usageBar(label, pct, resetIso) { const p = Math.min(100,Math.max(0,pct||0)), c = barColor(p), reset = resetIso ? '<span style=\"color:#8b949e;font-size:10px;\">resets '+timeLeft(resetIso)+'</span>' : ''; return '<div style=\"margin-bottom:10px;\"><div style=\"display:flex;justify-content:space-between;margin-bottom:3px;\"><span style=\"font-weight:600;font-size:12px;\">'+label+'</span><span style=\"font-size:13px;font-weight:700;color:'+c+';\">'+p.toFixed(0)+'%</span></div><div style=\"background:#21262d;border-radius:4px;height:8px;overflow:hidden;\"><div style=\"width:'+p+'%;height:100%;background:'+c+';border-radius:4px;transition:width .5s;\"></div></div>'+(reset?'<div style=\"text-align:right;margin-top:2px;\">'+reset+'</div>':'')+'</div>'; }\n async function update_${props.id.replace(/-/g,'_')}() { const body = document.getElementById('${props.id}-body'); const subEl = document.getElementById('${props.id}-sub'); try { const res = await fetch('/api/pages/claude-usage/usage'); const d = await res.json(); if (d.error) { body.innerHTML='<div style=\"color:#f85149;\">'+d.error+'</div>'; return; } if (subEl) { subEl.textContent = {max:'Max (5×)',pro:'Pro',free:'Free'}[d.subscription]||d.subscription||''; } let html=''; if(d.five_hour) html+=usageBar('5h Session',d.five_hour.utilization,d.five_hour.resets_at); if(d.seven_day) html+=usageBar('7d Weekly',d.seven_day.utilization,d.seven_day.resets_at); if(d.seven_day_opus) html+=usageBar('Opus (7d)',d.seven_day_opus.utilization,d.seven_day_opus.resets_at); if(d.seven_day_sonnet&&d.seven_day_sonnet.utilization>0) html+=usageBar('Sonnet (7d)',d.seven_day_sonnet.utilization,d.seven_day_sonnet.resets_at); if(d.extra_usage&&d.extra_usage.is_enabled){const used=(d.extra_usage.used_credits/100).toFixed(2),limit=d.extra_usage.monthly_limit>0?(d.extra_usage.monthly_limit/100).toFixed(2):'∞';html+='<div style=\"margin-top:4px;padding-top:6px;border-top:1px solid #30363d;\"><div style=\"display:flex;justify-content:space-between;font-size:11px;\"><span style=\"color:#8b949e;\">Extra Usage</span><span style=\"font-weight:600;\">$'+used+' / $'+limit+'</span></div></div>';} if(!html) html='<div style=\"color:#8b949e;\">No usage data</div>'; body.innerHTML=html; } catch(e) { console.error('Claude usage error:',e); body.innerHTML='<div style=\"color:#f85149;\">Failed to load</div>'; } }\n update_${props.id.replace(/-/g,'_')}(); setInterval(update_${props.id.replace(/-/g,'_')}, ${(props.refreshInterval||120)*1000});\n `\n },\n\n // ── Finance ──────────────────────────────────────────────────────────────\n\n 'stock-ticker': {\n name: 'Stock Ticker',\n icon: '📈',\n category: 'large',\n description: 'Live stock prices via Yahoo Finance. No API key required.',\n defaultWidth: 320,\n defaultHeight: 280,\n hasApiKey: false,\n properties: {\n title: 'Stocks',\n symbols: 'AAPL,MSFT,GOOGL,AMZN',\n refreshInterval: 300\n },\n preview: `<div style=\"padding:6px;font-size:11px;\">\n <div style=\"display:flex;justify-content:space-between;\"><span>AAPL</span><span>$182.50 <span style=\"color:#3fb950;\">+1.24%</span></span></div>\n <div style=\"display:flex;justify-content:space-between;\"><span>MSFT</span><span>$375.20 <span style=\"color:#f85149;\">-0.38%</span></span></div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">📈 ${props.title || 'Stocks'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body\" id=\"${props.id}-list\" style=\"overflow-y:auto;padding:4px 8px;\">\n <div style=\"color:#8b949e;font-size:12px;\">Loading...</div>\n </div>\n </div>`,\n generateJs: (props) => `\n function registerWidgetInterval(widgetId, intervalId) {\n window.__lobsterboardWidgetIntervals = window.__lobsterboardWidgetIntervals || {};\n if (window.__lobsterboardWidgetIntervals[widgetId]) clearInterval(window.__lobsterboardWidgetIntervals[widgetId]);\n window.__lobsterboardWidgetIntervals[widgetId] = intervalId;\n }\n async function update_${props.id.replace(/-/g, '_')}() {\n var list = document.getElementById('${props.id}-list');\n var badge = document.getElementById('${props.id}-badge');\n if (!list) return;\n try {\n var res = await fetch('/api/finance/stocks?symbols=' + encodeURIComponent('${props.symbols || 'AAPL,MSFT'}'));\n if (!res.ok) throw new Error('HTTP ' + res.status);\n var data = await res.json();\n var ok = data.filter(function(d) { return !d.error; });\n list.innerHTML = data.map(function(d) {\n if (d.error) return '<div style=\"padding:5px 0;border-bottom:1px solid #21262d;color:#8b949e;font-size:12px;\">' + _esc(d.symbol) + ' — ' + _esc(d.error) + '</div>';\n var color = d.up ? '#3fb950' : '#f85149';\n return '<div style=\"display:flex;justify-content:space-between;align-items:center;padding:5px 0;border-bottom:1px solid #21262d;\">'\n + '<span style=\"font-weight:600;font-size:13px;\">' + _esc(d.symbol) + '</span>'\n + '<span style=\"text-align:right;\">'\n + '<span style=\"font-size:13px;font-weight:700;margin-right:8px;\">$' + _esc(d.price) + '</span>'\n + '<span style=\"font-size:11px;color:' + color + ';font-weight:600;\">' + _esc(d.pctChange) + '%</span>'\n + '</span></div>';\n }).join('');\n if (badge) badge.textContent = ok.length + ' stocks';\n } catch (e) {\n console.error('Stock ticker error:', e);\n if (list) list.innerHTML = '<div style=\"color:#f85149;font-size:12px;\">Failed to load</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n registerWidgetInterval('${props.id}', setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000}));\n `\n },\n\n 'crypto-price': {\n name: 'Crypto Price',\n icon: '₿',\n category: 'large',\n description: 'Live crypto prices via CoinGecko. No API key required.',\n defaultWidth: 320,\n defaultHeight: 280,\n hasApiKey: false,\n properties: {\n title: 'Crypto',\n coins: 'bitcoin,ethereum,solana',\n currency: 'usd',\n refreshInterval: 300\n },\n preview: `<div style=\"padding:6px;font-size:11px;\">\n <div style=\"display:flex;justify-content:space-between;\"><span>Bitcoin</span><span>$67,240 <span style=\"color:#3fb950;\">+2.1%</span></span></div>\n <div style=\"display:flex;justify-content:space-between;\"><span>Ethereum</span><span>$3,521 <span style=\"color:#f85149;\">-0.8%</span></span></div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">₿ ${props.title || 'Crypto'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body\" id=\"${props.id}-list\" style=\"overflow-y:auto;padding:4px 8px;\">\n <div style=\"color:#8b949e;font-size:12px;\">Loading...</div>\n </div>\n </div>`,\n generateJs: (props) => `\n function registerWidgetInterval(widgetId, intervalId) {\n window.__lobsterboardWidgetIntervals = window.__lobsterboardWidgetIntervals || {};\n if (window.__lobsterboardWidgetIntervals[widgetId]) clearInterval(window.__lobsterboardWidgetIntervals[widgetId]);\n window.__lobsterboardWidgetIntervals[widgetId] = intervalId;\n }\n async function update_${props.id.replace(/-/g, '_')}() {\n var list = document.getElementById('${props.id}-list');\n var badge = document.getElementById('${props.id}-badge');\n if (!list) return;\n try {\n var res = await fetch('/api/finance/crypto?coins=' + encodeURIComponent('${props.coins || 'bitcoin,ethereum'}') + '&currency=${props.currency || 'usd'}');\n if (!res.ok) throw new Error('HTTP ' + res.status);\n var data = await res.json();\n list.innerHTML = data.map(function(d) {\n var color = d.up ? '#3fb950' : '#f85149';\n return '<div style=\"display:flex;justify-content:space-between;align-items:center;padding:5px 0;border-bottom:1px solid #21262d;\">'\n + '<span style=\"font-weight:600;font-size:13px;\">' + _esc(d.name) + '</span>'\n + '<span style=\"text-align:right;\">'\n + '<span style=\"font-size:13px;font-weight:700;margin-right:8px;\">${(props.currency || 'usd').toUpperCase()} ' + _esc(d.price) + '</span>'\n + '<span style=\"font-size:11px;color:' + color + ';font-weight:600;\">' + _esc(d.pctChange) + '%</span>'\n + '</span></div>';\n }).join('');\n if (badge) badge.textContent = data.length + ' coins';\n } catch (e) {\n console.error('Crypto price error:', e);\n if (list) list.innerHTML = '<div style=\"color:#f85149;font-size:12px;\">Failed to load</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n registerWidgetInterval('${props.id}', setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000}));\n `\n },\n\n // ── Search ────────────────────────────────────────────────────────────────\n\n 'search': {\n name: 'Search',\n icon: '🔍',\n category: 'large',\n description: 'Search box with DuckDuckGo-style !bangs. Press S to focus, ↑ for last query.',\n defaultWidth: 460,\n defaultHeight: 120,\n hasApiKey: false,\n properties: {\n title: 'Search',\n placeholder: 'Search or use !bangs',\n searchEngine: 'duckduckgo',\n openInNewTab: true,\n showBangHints: true\n },\n preview: `<div style=\"padding:10px;\">\n <input style=\"width:100%;padding:6px 10px;background:#21262d;border:1px solid #30363d;border-radius:6px;color:#e6edf3;font-size:13px;\" placeholder=\"Search or use !bangs\" readonly />\n <div style=\"font-size:10px;color:#8b949e;margin-top:6px;\">!yt YouTube &nbsp; !gh GitHub &nbsp; !r Reddit &nbsp; !so Stack Overflow</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🔍 ${props.title || 'Search'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"padding:8px 10px;\">\n <form id=\"${props.id}-form\" style=\"display:flex;gap:6px;\" onsubmit=\"return false;\">\n <input id=\"${props.id}-input\" type=\"text\"\n placeholder=\"${props.placeholder || 'Search or use !bangs'}\"\n autocomplete=\"off\" spellcheck=\"false\"\n style=\"flex:1;padding:7px 11px;background:#21262d;border:1px solid #30363d;border-radius:6px;color:#e6edf3;font-size:13px;outline:none;\" />\n <button type=\"submit\"\n style=\"padding:7px 14px;background:#238636;border:none;border-radius:6px;color:#fff;font-size:13px;cursor:pointer;\">Go</button>\n </form>\n ${props.showBangHints !== false ? `<div style=\"font-size:10px;color:#8b949e;margin-top:5px;\"><span style=\"opacity:.7;\">!g Google &nbsp; !yt YouTube &nbsp; !gh GitHub &nbsp; !r Reddit &nbsp; !so Stack Overflow &nbsp; !w Wikipedia &nbsp; !npm npm</span></div>` : ''}\n </div>\n </div>`,\n generateJs: (props) => {\n const providers = { duckduckgo:'https://duckduckgo.com/?q={q}', google:'https://www.google.com/search?q={q}', bing:'https://www.bing.com/search?q={q}', brave:'https://search.brave.com/search?q={q}' };\n const bangs = { g:'https://www.google.com/search?q={q}',b:'https://www.bing.com/search?q={q}',yt:'https://www.youtube.com/results?search_query={q}',gh:'https://github.com/search?q={q}',r:'https://www.reddit.com/search/?q={q}',so:'https://stackoverflow.com/search?q={q}',w:'https://en.wikipedia.org/wiki/Special:Search/{q}',img:'https://www.google.com/search?tbm=isch&q={q}',maps:'https://www.google.com/maps/search/{q}',ddg:'https://duckduckgo.com/?q={q}',npm:'https://www.npmjs.com/search?q={q}',mdn:'https://developer.mozilla.org/en-US/search?q={q}',x:'https://x.com/search?q={q}',tw:'https://x.com/search?q={q}' };\n const defaultUrl = providers[props.searchEngine] || providers.duckduckgo;\n return `\n (function() {\n var BANGS = ${JSON.stringify(bangs)};\n var DEFAULT_URL = '${defaultUrl}';\n var widgetId = '${props.id}';\n var lastQuery = '';\n function navigate(q) {\n q = q.trim(); if (!q) return; lastQuery = q;\n var url = DEFAULT_URL;\n var m = q.match(/^!(\\\\S+)\\\\s*(.*)/);\n if (m) { var bang = m[1].toLowerCase(), rest = m[2]; if (BANGS[bang]) { url = BANGS[bang]; q = rest || q; } }\n var target = url.replace('{q}', encodeURIComponent(q));\n if (${props.openInNewTab !== false}) { window.open(target, '_blank', 'noopener'); } else { window.location.href = target; }\n }\n var form = document.getElementById('${props.id}-form');\n var input = document.getElementById('${props.id}-input');\n if (form) form.addEventListener('submit', function() { navigate(input.value); });\n if (input) input.addEventListener('keydown', function(e) { if (e.key === 'ArrowUp') { e.preventDefault(); input.value = lastQuery; } });\n window.__lobsterboardSearchHandlers = window.__lobsterboardSearchHandlers || {};\n if (window.__lobsterboardSearchHandlers[widgetId]) {\n document.removeEventListener('keydown', window.__lobsterboardSearchHandlers[widgetId]);\n }\n var searchFocusHandler = function(e) {\n var tag = document.activeElement && document.activeElement.tagName;\n if (e.key === 's' && tag !== 'INPUT' && tag !== 'TEXTAREA' && !e.ctrlKey && !e.metaKey) {\n var inp = document.getElementById(widgetId + '-input');\n if (inp) { inp.focus(); inp.select(); e.preventDefault(); }\n }\n };\n window.__lobsterboardSearchHandlers[widgetId] = searchFocusHandler;\n document.addEventListener('keydown', searchFocusHandler);\n })();\n `;\n }\n }\n};\n\n// Helper to get widget categories\nexport function getWidgetCategories() {\n const categories = {};\n for (const [key, widget] of Object.entries(WIDGETS)) {\n const cat = widget.category || 'other';\n if (!categories[cat]) categories[cat] = [];\n categories[cat].push({ key, ...widget });\n }\n return categories;\n}\n\n// Helper to get widget by type\nexport function getWidget(type) {\n return WIDGETS[type] || null;\n}\n\n// Helper to list all widget types\nexport function getWidgetTypes() {\n return Object.keys(WIDGETS);\n}\n\nexport default WIDGETS;\n","/**\n * LobsterBoard - Dashboard Builder Core\n * Provides utilities for generating dashboard HTML, CSS, and JS\n * \n * @module lobsterboard/builder\n */\n\nimport { WIDGETS } from './widgets.js';\n\n// ─────────────────────────────────────────────\n// SECURITY HELPERS\n// ─────────────────────────────────────────────\n\n/**\n * Escape HTML to prevent XSS attacks\n * @param {string} str - String to escape\n * @returns {string} Escaped string\n */\nexport function escapeHtml(str) {\n if (!str) return '';\n if (typeof document !== 'undefined') {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n // Fallback for Node.js\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\n// ─────────────────────────────────────────────\n// HTML PROCESSING\n// ─────────────────────────────────────────────\n\n/**\n * Process widget HTML to conditionally remove header\n * @param {string} html - Widget HTML\n * @param {boolean} showHeader - Whether to show the header\n * @returns {string} Processed HTML\n */\nexport function processWidgetHtml(html, showHeader) {\n if (showHeader !== false) return html;\n const headerRegex = /<div\\s+class=\"dash-card-head\"[^>]*>[\\s\\S]*?<\\/div>/i;\n return html.replace(headerRegex, '');\n}\n\n// ─────────────────────────────────────────────\n// CSS GENERATION\n// ─────────────────────────────────────────────\n\n/**\n * Generate the base dashboard CSS\n * @returns {string} CSS styles\n */\nexport function generateDashboardCss() {\n return `/* LobsterBoard Dashboard - Generated Styles */\n\n:root {\n --bg-primary: #0d1117;\n --bg-secondary: #161b22;\n --bg-tertiary: #21262d;\n --bg-hover: #30363d;\n --border: #30363d;\n --text-primary: #e6edf3;\n --text-secondary: #8b949e;\n --text-muted: #6e7681;\n --accent-blue: #58a6ff;\n --accent-green: #3fb950;\n --accent-orange: #d29922;\n --accent-red: #f85149;\n --accent-purple: #a371f7;\n}\n\n* {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: var(--bg-primary);\n color: var(--text-primary);\n min-height: 100vh;\n}\n\n.dashboard {\n margin: 0 auto;\n overflow: hidden;\n}\n\n.widget-container {\n overflow: hidden;\n}\n\n/* KPI Cards */\n.kpi-card {\n background: var(--bg-secondary);\n border: 1px solid var(--border);\n border-radius: 8px;\n padding: 16px;\n display: flex;\n align-items: center;\n gap: 12px;\n height: 100%;\n}\n\n.kpi-sm {\n padding: 12px;\n}\n\n.kpi-icon {\n font-size: 24px;\n}\n\n.kpi-data {\n flex: 1;\n}\n\n.kpi-value {\n font-size: 20px;\n font-weight: 600;\n}\n\n.kpi-value.blue { color: var(--accent-blue); }\n.kpi-value.green { color: var(--accent-green); }\n.kpi-value.orange { color: var(--accent-orange); }\n.kpi-value.red { color: var(--accent-red); }\n\n.kpi-label {\n font-size: 12px;\n color: var(--text-secondary);\n margin-top: 2px;\n}\n\n.kpi-indicator {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--text-muted);\n}\n\n.kpi-indicator.green { background: var(--accent-green); }\n.kpi-indicator.yellow { background: var(--accent-orange); }\n.kpi-indicator.red { background: var(--accent-red); }\n\n/* Dash Cards */\n.dash-card {\n background: var(--bg-secondary);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.dash-card-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n border-bottom: 1px solid var(--border);\n background: var(--bg-tertiary);\n}\n\n.dash-card-title {\n font-size: 13px;\n font-weight: 600;\n}\n\n.dash-card-badge {\n font-size: 11px;\n color: var(--text-secondary);\n background: var(--bg-primary);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.dash-card-body {\n flex: 1;\n padding: 12px 16px;\n overflow-y: auto;\n}\n\n.compact-list {\n font-size: 12px;\n}\n\n.syslog-scroll {\n font-family: 'SF Mono', Monaco, monospace;\n font-size: 11px;\n}\n\n/* Top Bar */\n.topbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 20px;\n background: var(--bg-secondary);\n border-bottom: 1px solid var(--border);\n height: 100%;\n}\n\n.topbar-left {\n display: flex;\n align-items: center;\n gap: 20px;\n}\n\n.topbar-brand {\n font-weight: 600;\n font-size: 14px;\n}\n\n.topbar-link {\n color: var(--text-secondary);\n text-decoration: none;\n font-size: 13px;\n}\n\n.topbar-link:hover,\n.topbar-link.active {\n color: var(--accent-blue);\n}\n\n.topbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.topbar-meta {\n font-size: 12px;\n color: var(--text-muted);\n}\n\n.topbar-refresh {\n background: var(--bg-tertiary);\n border: 1px solid var(--border);\n color: var(--text-secondary);\n padding: 4px 8px;\n border-radius: 4px;\n cursor: pointer;\n}\n\n/* List Items */\n.list-item {\n padding: 6px 0;\n border-bottom: 1px solid var(--border);\n}\n\n.list-item:last-child {\n border-bottom: none;\n}\n\n.cron-item {\n display: flex;\n justify-content: space-between;\n padding: 6px 0;\n border-bottom: 1px solid var(--border);\n}\n\n.cron-name {\n color: var(--text-primary);\n}\n\n.cron-next {\n color: var(--text-muted);\n font-size: 11px;\n}\n\n.log-line {\n padding: 2px 0;\n border-bottom: 1px solid rgba(48, 54, 61, 0.5);\n}\n\n/* Weather */\n.weather-row {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0;\n border-bottom: 1px solid var(--border);\n}\n\n.weather-row:last-child {\n border-bottom: none;\n}\n\n.weather-icon {\n font-size: 18px;\n}\n\n.weather-loc {\n flex: 1;\n color: var(--text-primary);\n}\n\n.weather-temp {\n font-weight: 600;\n color: var(--accent-blue);\n}\n\n/* Utilities */\n.loading-sm {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n}\n\n.spinner-sm {\n width: 20px;\n height: 20px;\n border: 2px solid var(--bg-tertiary);\n border-top-color: var(--accent-blue);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n.error {\n color: var(--accent-red);\n padding: 10px;\n text-align: center;\n}\n\n::-webkit-scrollbar {\n width: 6px;\n}\n\n::-webkit-scrollbar-track {\n background: var(--bg-primary);\n}\n\n::-webkit-scrollbar-thumb {\n background: var(--bg-tertiary);\n border-radius: 3px;\n}\n\n/* Post-Export Edit Mode */\n.edit-mode .widget-container {\n cursor: move;\n outline: 2px dashed #3b82f6;\n outline-offset: -2px;\n}\n\n.edit-mode .widget-container:hover {\n outline-color: #60a5fa;\n}\n\n.edit-mode .widget-container.dragging {\n opacity: 0.8;\n z-index: 1000;\n}\n\n.resize-handle-edit {\n display: none;\n position: absolute;\n bottom: 0;\n right: 0;\n width: 16px;\n height: 16px;\n cursor: se-resize;\n background: #3b82f6;\n border-radius: 2px 0 0 0;\n z-index: 10;\n}\n\n.edit-mode .resize-handle-edit {\n display: block;\n}\n\n#edit-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 9999;\n padding: 8px 16px;\n background: #1e293b;\n color: white;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n}\n\n#edit-toggle:hover {\n background: #334155;\n}\n\n#edit-toggle.active {\n background: #3b82f6;\n}\n`;\n}\n\n// ─────────────────────────────────────────────\n// JS GENERATION\n// ─────────────────────────────────────────────\n\n/**\n * Generate the post-export edit mode JS\n * @returns {string} JavaScript code\n */\nexport function generateEditJs() {\n return `\n// ─────────────────────────────────────────────\n// POST-EXPORT LAYOUT EDITING\n// ─────────────────────────────────────────────\n\n(function() {\n const STORAGE_KEY = 'lobsterboard-layout';\n const GRID_SIZE = 20;\n const MIN_WIDTH = 100;\n const MIN_HEIGHT = 60;\n \n let editMode = false;\n let activeWidget = null;\n let startX, startY, origLeft, origTop, origWidth, origHeight;\n let isResizing = false;\n\n document.addEventListener('DOMContentLoaded', initEditMode);\n\n function initEditMode() {\n const btn = document.createElement('button');\n btn.id = 'edit-toggle';\n btn.textContent = '✏️ Edit Layout';\n btn.onclick = toggleEditMode;\n document.body.appendChild(btn);\n document.querySelectorAll('.widget-container').forEach(initWidget);\n loadPositions();\n }\n\n function initWidget(widget) {\n const handle = document.createElement('div');\n handle.className = 'resize-handle-edit';\n widget.appendChild(handle);\n widget.addEventListener('mousedown', onWidgetMouseDown);\n handle.addEventListener('mousedown', onResizeMouseDown);\n }\n\n function toggleEditMode() {\n editMode = !editMode;\n document.body.classList.toggle('edit-mode', editMode);\n document.getElementById('edit-toggle').classList.toggle('active', editMode);\n document.getElementById('edit-toggle').textContent = editMode ? '💾 Save Layout' : '✏️ Edit Layout';\n if (!editMode) savePositions();\n }\n\n function onWidgetMouseDown(e) {\n if (!editMode) return;\n if (e.target.classList.contains('resize-handle-edit')) return;\n if (e.button !== 0) return;\n e.preventDefault();\n activeWidget = e.currentTarget;\n isResizing = false;\n startX = e.clientX;\n startY = e.clientY;\n origLeft = activeWidget.offsetLeft;\n origTop = activeWidget.offsetTop;\n activeWidget.classList.add('dragging');\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n }\n\n function onResizeMouseDown(e) {\n if (!editMode) return;\n e.preventDefault();\n e.stopPropagation();\n activeWidget = e.target.parentElement;\n isResizing = true;\n startX = e.clientX;\n startY = e.clientY;\n origWidth = activeWidget.offsetWidth;\n origHeight = activeWidget.offsetHeight;\n activeWidget.classList.add('dragging');\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n }\n\n function onMouseMove(e) {\n if (!activeWidget) return;\n const dx = e.clientX - startX;\n const dy = e.clientY - startY;\n if (isResizing) {\n activeWidget.style.width = Math.max(MIN_WIDTH, origWidth + dx) + 'px';\n activeWidget.style.height = Math.max(MIN_HEIGHT, origHeight + dy) + 'px';\n } else {\n activeWidget.style.left = Math.max(0, origLeft + dx) + 'px';\n activeWidget.style.top = Math.max(0, origTop + dy) + 'px';\n }\n }\n\n function onMouseUp() {\n if (!activeWidget) return;\n if (isResizing) {\n activeWidget.style.width = snapToGrid(activeWidget.offsetWidth) + 'px';\n activeWidget.style.height = snapToGrid(activeWidget.offsetHeight) + 'px';\n } else {\n activeWidget.style.left = snapToGrid(activeWidget.offsetLeft) + 'px';\n activeWidget.style.top = snapToGrid(activeWidget.offsetTop) + 'px';\n }\n activeWidget.classList.remove('dragging');\n activeWidget = null;\n isResizing = false;\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n }\n\n function snapToGrid(value) {\n return Math.round(value / GRID_SIZE) * GRID_SIZE;\n }\n\n function savePositions() {\n const positions = {};\n document.querySelectorAll('.widget-container').forEach(widget => {\n const id = widget.dataset.widgetId;\n if (id) {\n positions[id] = {\n left: widget.offsetLeft,\n top: widget.offsetTop,\n width: widget.offsetWidth,\n height: widget.offsetHeight\n };\n }\n });\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(positions));\n } catch (e) {}\n }\n\n function loadPositions() {\n try {\n const saved = localStorage.getItem(STORAGE_KEY);\n if (!saved) return;\n const positions = JSON.parse(saved);\n document.querySelectorAll('.widget-container').forEach(widget => {\n const id = widget.dataset.widgetId;\n const pos = positions[id];\n if (pos) {\n widget.style.left = pos.left + 'px';\n widget.style.top = pos.top + 'px';\n widget.style.width = pos.width + 'px';\n widget.style.height = pos.height + 'px';\n }\n });\n } catch (e) {}\n }\n})();\n`;\n}\n\n// ─────────────────────────────────────────────\n// DASHBOARD GENERATION\n// ─────────────────────────────────────────────\n\n/**\n * Generate widget HTML for a widget configuration\n * @param {Object} widget - Widget configuration\n * @returns {string} Widget HTML\n */\nexport function generateWidgetHtml(widget) {\n const template = WIDGETS[widget.type];\n if (!template) return '';\n\n const props = { ...widget.properties, id: widget.id };\n let html = processWidgetHtml(template.generateHtml(props), widget.properties.showHeader);\n\n return `\n <div class=\"widget-container\" data-widget-id=\"${widget.id}\" style=\"position:absolute;left:${widget.x}px;top:${widget.y}px;width:${widget.width}px;height:${widget.height}px;\">\n ${html}\n </div>`;\n}\n\n/**\n * Generate widget JavaScript for a widget configuration\n * @param {Object} widget - Widget configuration\n * @returns {string} Widget JavaScript\n */\nexport function generateWidgetJs(widget) {\n const template = WIDGETS[widget.type];\n if (!template || !template.generateJs) return '';\n\n const props = { ...widget.properties, id: widget.id };\n return template.generateJs(props);\n}\n\n/**\n * Generate complete dashboard HTML\n * @param {Object} config - Dashboard configuration\n * @param {Object} config.canvas - Canvas dimensions { width, height }\n * @param {Array} config.widgets - Array of widget configurations\n * @returns {string} Complete HTML document\n */\nexport function generateDashboardHtml(config) {\n const { canvas, widgets } = config;\n const widgetHtml = widgets.map(generateWidgetHtml).join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>My LobsterBoard Dashboard</title>\n <link rel=\"stylesheet\" href=\"css/style.css\">\n</head>\n<body>\n <main class=\"dashboard\" style=\"width:${canvas.width}px;height:${canvas.height}px;position:relative;\">\n ${widgetHtml}\n </main>\n <script src=\"js/dashboard.js\"></script>\n</body>\n</html>`;\n}\n\n/**\n * Generate complete dashboard JavaScript\n * @param {Array} widgets - Array of widget configurations\n * @returns {string} Complete JavaScript\n */\nexport function generateDashboardJs(widgets) {\n const widgetJs = widgets.map(generateWidgetJs).filter(Boolean).join('\\n\\n');\n const editJs = generateEditJs();\n\n return `/**\n * LobsterBoard Dashboard - Generated JavaScript\n * Replace YOUR_*_API_KEY placeholders with your actual API keys\n */\n\ndocument.addEventListener('DOMContentLoaded', () => {\n console.log('Dashboard loaded');\n});\n\n${widgetJs}\n\n${editJs}\n`;\n}\n\n/**\n * Generate README for exported dashboard\n * @param {Array} widgets - Array of widget configurations\n * @returns {string} README markdown\n */\nexport function generateReadme(widgets) {\n const apiKeys = [];\n const needsOpenClaw = widgets.some(w => \n ['openclaw-release', 'auth-status', 'activity-list', 'cron-jobs', 'system-log', 'session-count', 'token-gauge'].includes(w.type)\n );\n \n widgets.forEach(widget => {\n const template = WIDGETS[widget.type];\n if (template?.hasApiKey && template.apiKeyName) {\n if (!apiKeys.includes(template.apiKeyName)) {\n apiKeys.push(template.apiKeyName);\n }\n }\n });\n\n return `# LobsterBoard Dashboard\n\nThis dashboard was generated with LobsterBoard Dashboard Builder.\n\n## Quick Start\n\n${needsOpenClaw ? `### Running with OpenClaw widgets\n\nYour dashboard includes widgets that connect to OpenClaw. Run the included server:\n\n\\`\\`\\`bash\nnode server.js\n\\`\\`\\`\n\nOpen http://localhost:8080 in your browser.\n` : ''}\n### Static mode\n\nOpen \\`index.html\\` directly in a browser.\n\n## Files\n\n| File | Description |\n|------|-------------|\n| \\`index.html\\` | Dashboard page |\n| \\`css/style.css\\` | Styles |\n| \\`js/dashboard.js\\` | Widget logic |\n| \\`server.js\\` | Server with OpenClaw API proxy |\n\n${apiKeys.length > 0 ? `## API Keys\n\nEdit \\`js/dashboard.js\\` and replace these placeholders:\n${apiKeys.map(key => `- \\`YOUR_${key}\\``).join('\\n')}\n` : ''}\n\n---\n\nGenerated with LobsterBoard - https://github.com/curbob/LobsterBoard\n`;\n}\n\nexport default {\n escapeHtml,\n processWidgetHtml,\n generateDashboardCss,\n generateEditJs,\n generateWidgetHtml,\n generateWidgetJs,\n generateDashboardHtml,\n generateDashboardJs,\n generateReadme\n};\n","/**\n * LobsterBoard - Dashboard Builder Library\n * \n * A library for building and generating dashboard configurations\n * with customizable widgets.\n * \n * @module lobsterboard\n * @example\n * // ESM\n * import { WIDGETS, generateDashboardHtml, generateDashboardCss } from 'lobsterboard';\n * \n * // CommonJS\n * const { WIDGETS, generateDashboardHtml } = require('lobsterboard');\n * \n * // Browser (UMD)\n * <script src=\"https://unpkg.com/lobsterboard\"></script>\n * const { WIDGETS } = LobsterBoard;\n */\n\n// Widget definitions\nexport { \n WIDGETS, \n getWidgetCategories, \n getWidget, \n getWidgetTypes \n} from './widgets.js';\n\n// Builder utilities\nexport {\n escapeHtml,\n processWidgetHtml,\n generateDashboardCss,\n generateEditJs,\n generateWidgetHtml,\n generateWidgetJs,\n generateDashboardHtml,\n generateDashboardJs,\n generateReadme\n} from './builder.js';\n\n// Re-export defaults for convenience\nimport { WIDGETS } from './widgets.js';\nimport builder from './builder.js';\n\n// Version (will be replaced during build)\nexport const VERSION = '0.1.0';\n\n// Default export for convenience\nexport default {\n VERSION,\n WIDGETS,\n ...builder\n};\n"],"names":[],"mappings":"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;AACA;AACO,SAAS,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE;AACpD,EAAE,IAAI,UAAU,KAAK,KAAK,EAAE,OAAO,IAAI;AACvC,EAAE,MAAM,WAAW,GAAG,qDAAqD;AAC3E,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;AACtC;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACO,SAAS,oBAAoB,GAAG;AACvC,EAAE,OAAO,CAAC;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,CAAC;AACD;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACO,SAAS,cAAc,GAAG;AACjC,EAAE,OAAO;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA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"}
1
+ {"version":3,"file":"lobsterboard.esm.js","sources":["../src/widgets.js","../src/builder.js","../src/index.js"],"sourcesContent":["/**\n * LobsterBoard - Widget Definitions\n * Each widget defines its default size, properties, and generated code\n * \n * @module lobsterboard/widgets\n */\n\nexport const WIDGETS = {\n // ─────────────────────────────────────────────\n // SMALL CARDS (KPI style)\n // ─────────────────────────────────────────────\n \n 'weather': {\n name: 'Local Weather',\n icon: '🌡️',\n category: 'small',\n description: 'Shows current weather for a single location using wttr.in (no API key needed).',\n defaultWidth: 200,\n defaultHeight: 120,\n hasApiKey: false,\n properties: {\n title: 'Local Weather',\n location: 'Atlanta',\n units: 'F',\n refreshInterval: 600\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"font-size:24px;\">72°F</div>\n <div style=\"font-size:11px;color:#8b949e;\">Atlanta</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🌡️ ${props.title || 'Local Weather'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;align-items:center;justify-content:center;gap:10px;\">\n <span id=\"${props.id}-icon\" style=\"font-size:24px;\">🌡️</span>\n <div>\n <div class=\"kpi-value blue\" id=\"${props.id}-value\">—</div>\n <div class=\"kpi-label\" id=\"${props.id}-label\">${props.location || 'Location'}</div>\n </div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Weather Widget: ${props.id} (uses free wttr.in API - no key needed)\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const location = encodeURIComponent('${props.location || 'Atlanta'}');\n const res = await fetch('https://wttr.in/' + location + '?format=j1');\n const data = await res.json();\n const current = data.current_condition[0];\n const temp = '${props.units}' === 'C' ? current.temp_C : current.temp_F;\n const unit = '${props.units}' === 'C' ? '°C' : '°F';\n document.getElementById('${props.id}-value').textContent = temp + unit;\n document.getElementById('${props.id}-label').textContent = current.weatherDesc[0].value;\n const code = parseInt(current.weatherCode);\n let icon = '🌡️';\n if (code === 113) icon = '☀️';\n else if (code === 116 || code === 119) icon = '⛅';\n else if (code >= 176 && code <= 359) icon = '🌧️';\n else if (code >= 368 && code <= 395) icon = '❄️';\n document.getElementById('${props.id}-icon').textContent = icon;\n } catch (e) {\n console.error('Weather widget error:', e);\n document.getElementById('${props.id}-value').textContent = '—';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 600) * 1000});\n `\n },\n\n 'clock': {\n name: 'Clock',\n icon: '🕐',\n category: 'small',\n description: 'Simple digital clock. Supports 12h or 24h format.',\n defaultWidth: 200,\n defaultHeight: 120,\n hasApiKey: false,\n properties: {\n title: 'Clock',\n timezone: 'local',\n format24h: false\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"font-size:24px;\">3:45 PM</div>\n <div style=\"font-size:11px;color:#8b949e;\">Wed, Feb 5</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🕐 ${props.title || 'Clock'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;flex-direction:column;align-items:center;justify-content:center;\">\n <div class=\"kpi-value\" id=\"${props.id}-time\">—</div>\n <div class=\"kpi-label\" id=\"${props.id}-date\">—</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Clock Widget: ${props.id}\n function updateClock_${props.id.replace(/-/g, '_')}() {\n const now = new Date();\n const timeEl = document.getElementById('${props.id}-time');\n const dateEl = document.getElementById('${props.id}-date');\n const opts = { hour: 'numeric', minute: '2-digit', hour12: ${!props.format24h} };\n timeEl.textContent = now.toLocaleTimeString('en-US', opts);\n dateEl.textContent = now.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });\n }\n updateClock_${props.id.replace(/-/g, '_')}();\n setInterval(updateClock_${props.id.replace(/-/g, '_')}, 1000);\n `\n },\n\n 'auth-status': {\n name: 'Auth Status',\n icon: '🔐',\n category: 'small',\n description: 'Shows if OpenClaw is using Anthropic Max subscription (green) or API key fallback (yellow).',\n defaultWidth: 180,\n defaultHeight: 100,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Auth Type',\n endpoint: '/api/status',\n refreshInterval: 30\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"width:10px;height:10px;background:#3fb950;border-radius:50%;margin:0 auto 4px;\"></div>\n <div style=\"font-size:13px;\">OAuth</div>\n <div style=\"font-size:11px;color:#8b949e;\">Auth</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🔐 ${props.title || 'Auth Type'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;align-items:center;justify-content:center;gap:10px;\">\n <div class=\"kpi-indicator\" id=\"${props.id}-dot\"></div>\n <div class=\"kpi-value\" id=\"${props.id}-value\">—</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Auth Status Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/status'}');\n const json = await res.json();\n const data = json.data || json;\n const dot = document.getElementById('${props.id}-dot');\n const val = document.getElementById('${props.id}-value');\n val.textContent = data.authMode === 'oauth' ? 'Subscription' : 'API';\n dot.className = 'kpi-indicator ' + (data.authMode === 'oauth' ? 'green' : 'yellow');\n } catch (e) {\n console.error('Auth status widget error:', e);\n document.getElementById('${props.id}-value').textContent = '—';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 30) * 1000});\n `\n },\n\n 'session-count': {\n name: 'Active Sessions',\n icon: '💬',\n category: 'small',\n description: 'Shows count of active OpenClaw sessions.',\n defaultWidth: 160,\n defaultHeight: 100,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Sessions',\n endpoint: '/api/sessions',\n refreshInterval: 30\n },\n preview: `<div style=\"text-align:center;padding:8px;\">\n <div style=\"font-size:28px;color:#58a6ff;\">3</div>\n <div style=\"font-size:11px;color:#8b949e;\">Active</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"kpi-card kpi-sm\" id=\"widget-${props.id}\">\n <div class=\"kpi-icon\">💬</div>\n <div class=\"kpi-data\">\n <div class=\"kpi-value blue\" id=\"${props.id}-count\">—</div>\n <div class=\"kpi-label\">Active</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Session Count Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/sessions'}');\n const json = await res.json();\n const data = json.data || json;\n document.getElementById('${props.id}-count').textContent = data.active || data.length || 0;\n } catch (e) {\n document.getElementById('${props.id}-count').textContent = '—';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 30) * 1000});\n `\n },\n\n // ─────────────────────────────────────────────\n // LARGE CARDS (Content)\n // ─────────────────────────────────────────────\n\n 'activity-list': {\n name: 'Activity List',\n icon: '📋',\n category: 'large',\n description: 'Shows recent OpenClaw activity from /api/activity endpoint.',\n defaultWidth: 400,\n defaultHeight: 300,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Today',\n endpoint: '/api/activity',\n maxItems: 10,\n refreshInterval: 60\n },\n preview: `<div style=\"padding:4px;font-size:11px;color:#8b949e;\">\n <div>• Meeting at 2pm</div>\n <div>• Review PR #42</div>\n <div>• Deploy v1.2</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">📋 ${props.title || 'Today'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body compact-list\" id=\"${props.id}-list\">\n <div class=\"list-item\">• Team standup at 10am</div>\n <div class=\"list-item\">• Review PR #42</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Activity List Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/activity'}');\n const json = await res.json();\n const data = json.data || json;\n const list = document.getElementById('${props.id}-list');\n const badge = document.getElementById('${props.id}-badge');\n const items = data.items || [];\n list.innerHTML = items.slice(0, ${props.maxItems || 10}).map(item => \n '<div class=\"list-item\">' + item.text + '</div>'\n ).join('');\n badge.textContent = items.length + ' items';\n } catch (e) {\n console.error('Activity list widget error:', e);\n document.getElementById('${props.id}-list').innerHTML = '<div class=\"list-item\">—</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 60) * 1000});\n `\n },\n\n 'cron-jobs': {\n name: 'Cron Jobs',\n icon: '⏰',\n category: 'large',\n description: 'Lists scheduled cron jobs from OpenClaw /api/cron endpoint.',\n defaultWidth: 400,\n defaultHeight: 250,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'Cron',\n endpoint: '/api/cron',\n refreshInterval: 30\n },\n preview: `<div style=\"padding:4px;font-size:11px;color:#8b949e;\">\n <div>⏰ Daily backup - 2am</div>\n <div>⏰ Sync data - */5 *</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">⏰ ${props.title || 'Cron'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body\" id=\"${props.id}-list\">\n <div class=\"cron-item\"><span class=\"cron-name\">Daily backup</span><span class=\"cron-next\">2:00 AM</span></div>\n </div>\n </div>`,\n generateJs: (props) => `\n // Cron Jobs Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/cron'}');\n const json = await res.json();\n const data = json.data || json;\n const list = document.getElementById('${props.id}-list');\n const badge = document.getElementById('${props.id}-badge');\n const jobs = data.jobs || [];\n list.innerHTML = jobs.map(job => \n '<div class=\"cron-item\"><span class=\"cron-name\">' + job.name + '</span><span class=\"cron-next\">' + job.next + '</span></div>'\n ).join('');\n badge.textContent = jobs.length + ' jobs';\n } catch (e) {\n console.error('Cron jobs widget error:', e);\n document.getElementById('${props.id}-list').innerHTML = '<div class=\"cron-item\"><span class=\"cron-name\">—</span></div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 30) * 1000});\n `\n },\n\n 'system-log': {\n name: 'System Log',\n icon: '🔧',\n category: 'large',\n description: 'Shows recent system logs from OpenClaw /api/logs endpoint.',\n defaultWidth: 500,\n defaultHeight: 400,\n hasApiKey: true,\n apiKeyName: 'OPENCLAW_API',\n properties: {\n title: 'System Log',\n endpoint: '/api/logs',\n maxLines: 50,\n refreshInterval: 10\n },\n preview: `<div style=\"padding:4px;font-size:10px;font-family:monospace;color:#8b949e;\">\n <div>[INFO] System started</div>\n <div>[DEBUG] Loading config</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🔧 ${props.title || 'System Log'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body compact-list syslog-scroll\" id=\"${props.id}-log\">\n <div class=\"log-line\">[INFO] System started successfully</div>\n </div>\n </div>`,\n generateJs: (props) => `\n // System Log Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('${props.endpoint || '/api/logs'}');\n const json = await res.json();\n const data = json.data || json;\n const log = document.getElementById('${props.id}-log');\n const badge = document.getElementById('${props.id}-badge');\n const lines = data.lines || [];\n log.innerHTML = lines.slice(-${props.maxLines || 50}).map(line => \n '<div class=\"log-line\">' + line + '</div>'\n ).join('');\n badge.textContent = lines.length + ' lines';\n log.scrollTop = log.scrollHeight;\n } catch (e) {\n console.error('System log widget error:', e);\n document.getElementById('${props.id}-log').innerHTML = '<div class=\"log-line\">—</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 10) * 1000});\n `\n },\n\n // ─────────────────────────────────────────────\n // BARS\n // ─────────────────────────────────────────────\n\n 'pages-menu': {\n name: 'Pages Menu',\n icon: '📑',\n category: 'small',\n description: 'Navigation links to all discovered LobsterBoard pages. Supports vertical or horizontal layout.',\n defaultWidth: 220,\n defaultHeight: 200,\n hasApiKey: false,\n properties: {\n title: 'Pages',\n layout: 'vertical',\n refreshInterval: 60\n },\n preview: `<div style=\"padding:6px;font-size:11px;color:#8b949e;\">\n <div>📝 Notes</div>\n <div>📋 Board</div>\n <div>📅 Calendar</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">📑 ${props.title || 'Pages'}</span>\n </div>\n <div class=\"dash-card-body pages-menu ${props.layout === 'horizontal' ? 'pages-menu-horizontal' : 'pages-menu-vertical'}\" id=\"${props.id}-list\">\n <span class=\"pages-menu-item\">Loading…</span>\n </div>\n </div>\n <style>\n .pages-menu-vertical { display:flex; flex-direction:column; gap:4px; overflow-y:auto; }\n .pages-menu-horizontal { display:flex; flex-direction:row; flex-wrap:wrap; gap:6px; align-items:center; }\n .pages-menu-item {\n display:inline-flex; align-items:center; gap:6px;\n padding:6px 10px; border-radius:6px;\n background:#21262d; color:#c9d1d9;\n text-decoration:none; font-size:13px;\n transition: background .15s, color .15s;\n }\n .pages-menu-item:hover { background:#30363d; color:#58a6ff; }\n .pages-menu-item .pages-menu-icon { font-size:15px; }\n </style>`,\n generateJs: (props) => `\n // Pages Menu Widget: ${props.id}\n async function update_${props.id.replace(/-/g, '_')}() {\n try {\n const res = await fetch('/api/pages');\n const pages = await res.json();\n const list = document.getElementById('${props.id}-list');\n if (!pages.length) { list.innerHTML = '<span class=\"pages-menu-item\">No pages found</span>'; return; }\n list.innerHTML = pages.map(p =>\n '<a class=\"pages-menu-item\" href=\"/pages/' + p.id + '\" title=\"' + (p.description || p.title || p.name || '') + '\">' +\n '<span class=\"pages-menu-icon\">' + (p.icon || '📄') + '</span>' +\n '<span>' + (p.title || p.name || p.id) + '</span></a>'\n ).join('');\n } catch (e) {\n console.error('Pages menu widget error:', e);\n document.getElementById('${props.id}-list').innerHTML = '<span class=\"pages-menu-item\">Error loading pages</span>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 60) * 1000});\n `\n },\n\n 'topbar': {\n name: 'Top Nav Bar',\n icon: '🔝',\n category: 'bar',\n description: 'Navigation bar with clock, weather, and system stats.',\n defaultWidth: 1920,\n defaultHeight: 48,\n hasApiKey: false,\n properties: {\n title: 'OpenClaw',\n links: 'Dashboard,Activity,Settings'\n },\n preview: `<div style=\"background:#161b22;padding:8px;font-size:11px;display:flex;gap:12px;\">\n <span>🤖 OpenClaw</span>\n <span style=\"color:#58a6ff;\">Dashboard</span>\n </div>`,\n generateHtml: (props) => `\n <nav class=\"topbar\" id=\"widget-${props.id}\">\n <div class=\"topbar-left\">\n <span class=\"topbar-brand\">🤖 ${props.title || 'OpenClaw'}</span>\n ${(props.links || 'Dashboard').split(',').map((link, i) => \n `<a href=\"#\" class=\"topbar-link${i === 0 ? ' active' : ''}\">${link.trim()}</a>`\n ).join('')}\n </div>\n <div class=\"topbar-right\">\n <span class=\"topbar-meta\" id=\"${props.id}-refresh\">—</span>\n <button class=\"topbar-refresh\" onclick=\"location.reload()\" title=\"Refresh\">↻</button>\n </div>\n </nav>`,\n generateJs: (props) => `\n // Top Bar Widget: ${props.id}\n document.getElementById('${props.id}-refresh').textContent = \n new Date().toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });\n `\n },\n\n 'system-graphical': {\n name: 'System (Graphical)',\n icon: '💻',\n category: 'system',\n description: 'Graphical CPU and Memory usage with circular progress rings. Supports remote servers via lobsterboard-agent.',\n defaultWidth: 240,\n defaultHeight: 140,\n hasApiKey: false,\n properties: {\n title: 'System',\n server: 'local',\n refreshInterval: 5,\n showPercentages: true,\n showLabels: true\n },\n preview: `<div style=\"display:flex;align-items:center;justify-content:space-around;padding:8px;\">\n <div style=\"position:relative;width:50px;height:50px;\">\n <svg viewBox=\"0 0 48 48\" style=\"width:100%;height:100%;transform:rotate(-90deg);\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#30363d\" stroke-width=\"4\"/>\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#58a6ff\" stroke-width=\"4\"\n stroke-dasharray=\"113\" stroke-dashoffset=\"85\" stroke-linecap=\"round\"/>\n </svg>\n <div style=\"position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:10px;font-weight:600;color:#58a6ff;\">25%</div>\n </div>\n <div style=\"position:relative;width:50px;height:50px;\">\n <svg viewBox=\"0 0 48 48\" style=\"width:100%;height:100%;transform:rotate(-90deg);\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#30363d\" stroke-width=\"4\"/>\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#3fb950\" stroke-width=\"4\"\n stroke-dasharray=\"113\" stroke-dashoffset=\"68\" stroke-linecap=\"round\"/>\n </svg>\n <div style=\"position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:10px;font-weight:600;color:#3fb950;\">40%</div>\n </div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">${renderIcon('cpu')} ${props.title || 'System'}</span>\n ${props.server && props.server !== 'local' ? `<span class=\"dash-card-badge\" style=\"font-size:10px;\">🌐</span>` : ''}\n </div>\n <div class=\"dash-card-body\" style=\"display:flex;align-items:center;justify-content:space-around;padding:12px;\">\n <div class=\"system-metric\">\n ${props.showLabels ? '<div class=\"metric-label\">CPU</div>' : ''}\n <div class=\"progress-ring-container\">\n <svg class=\"progress-ring\" viewBox=\"0 0 48 48\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"var(--bg-tertiary)\" stroke-width=\"4\"/>\n <circle id=\"${props.id}-cpu-ring\" cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#58a6ff\" stroke-width=\"4\"\n stroke-dasharray=\"113.1\" stroke-dashoffset=\"113.1\" stroke-linecap=\"round\"\n style=\"transition: stroke-dashoffset 0.6s ease, stroke 0.3s ease; transform: rotate(-90deg); transform-origin: 50% 50%;\"/>\n </svg>\n <div class=\"progress-ring-text\">\n <span id=\"${props.id}-cpu-pct\" ${props.showPercentages ? '' : 'style=\"display:none;\"'}>—</span>\n <span id=\"${props.id}-cpu-icon\" ${props.showPercentages ? 'style=\"display:none;\"' : ''}>💻</span>\n </div>\n </div>\n </div>\n <div class=\"system-metric\">\n ${props.showLabels ? '<div class=\"metric-label\">MEM</div>' : ''}\n <div class=\"progress-ring-container\">\n <svg class=\"progress-ring\" viewBox=\"0 0 48 48\">\n <circle cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"var(--bg-tertiary)\" stroke-width=\"4\"/>\n <circle id=\"${props.id}-mem-ring\" cx=\"24\" cy=\"24\" r=\"18\" fill=\"none\" stroke=\"#3fb950\" stroke-width=\"4\"\n stroke-dasharray=\"113.1\" stroke-dashoffset=\"113.1\" stroke-linecap=\"round\"\n style=\"transition: stroke-dashoffset 0.6s ease, stroke 0.3s ease; transform: rotate(-90deg); transform-origin: 50% 50%;\"/>\n </svg>\n <div class=\"progress-ring-text\">\n <span id=\"${props.id}-mem-pct\" ${props.showPercentages ? '' : 'style=\"display:none;\"'}>—</span>\n <span id=\"${props.id}-mem-icon\" ${props.showPercentages ? 'style=\"display:none;\"' : ''}>🧠</span>\n </div>\n </div>\n </div>\n </div>\n </div>`,\n generateJs: (props) => `\n // System (Graphical) Widget: ${props.id} — ${props.server === 'local' ? 'local SSE' : 'remote: ' + props.server}\n \n function getUsageColor(percentage) {\n if (percentage >= 90) return '#f85149'; // Red for critical\n if (percentage >= 75) return '#d29922'; // Yellow for warning\n if (percentage >= 50) return '#58a6ff'; // Blue for moderate\n return '#3fb950'; // Green for good\n }\n \n function updateProgressRing(ringId, percentage, textId) {\n const ring = document.getElementById(ringId);\n const text = document.getElementById(textId);\n if (!ring || !text) return;\n \n const normalizedPct = Math.max(0, Math.min(100, percentage || 0));\n const circumference = 113.1; // 2 * π * 18\n const offset = circumference - (normalizedPct / 100 * circumference);\n const color = getUsageColor(normalizedPct);\n \n ring.style.strokeDashoffset = offset;\n ring.style.stroke = color;\n text.textContent = Math.round(normalizedPct) + '%';\n text.style.color = color;\n }\n \n onStats('${props.server || 'local'}', function(data) {\n // Handle offline state\n if (data._offline) {\n document.getElementById('${props.id}-cpu-pct').textContent = '⚠️';\n document.getElementById('${props.id}-mem-pct').textContent = '⚠️';\n document.getElementById('${props.id}-cpu-ring').style.strokeDashoffset = '113.1';\n document.getElementById('${props.id}-mem-ring').style.strokeDashoffset = '113.1';\n return;\n }\n \n // Update CPU ring\n if (data.cpu && data.cpu.currentLoad != null) {\n updateProgressRing('${props.id}-cpu-ring', data.cpu.currentLoad, '${props.id}-cpu-pct');\n }\n \n // Update Memory ring \n if (data.memory && data.memory.total && data.memory.active != null) {\n const memoryPct = (data.memory.active / data.memory.total) * 100;\n updateProgressRing('${props.id}-mem-ring', memoryPct, '${props.id}-mem-pct');\n }\n }, ${(props.refreshInterval || 5) * 1000});\n `\n },\n\n 'claude-usage': {\n name: 'Claude Usage',\n icon: '🤖',\n category: 'large',\n description: 'Real-time Claude Code subscription usage (5h session, 7d weekly, Opus, Sonnet limits). Reads credentials from ~/.claude.',\n defaultWidth: 380,\n defaultHeight: 260,\n hasApiKey: false,\n properties: { title: 'Claude Usage', refreshInterval: 120 },\n preview: `<div style=\"padding:8px;font-size:11px;\"><div><b>5h Session</b> 28%</div><div><b>7d Weekly</b> 31%</div></div>`,\n generateHtml: (props) => `<div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\"><div class=\"dash-card-head\"><span class=\"dash-card-title\">🤖 ${props.title || 'Claude Usage'}</span><span id=\"${props.id}-sub\" style=\"font-size:10px;color:#8b949e;margin-left:auto;\"></span></div><div class=\"dash-card-body\" id=\"${props.id}-body\" style=\"padding:8px 12px;overflow-y:auto;\"><div style=\"color:#8b949e;text-align:center;\">Loading...</div></div></div>`,\n generateJs: (props) => `\n function barColor(pct) { return pct >= 80 ? '#f85149' : pct >= 50 ? '#d29922' : '#3fb950'; }\n function timeLeft(iso) { if (!iso) return ''; const ms = new Date(iso) - Date.now(); if (ms <= 0) return 'now'; const h = Math.floor(ms/3600000), m = Math.floor((ms%3600000)/60000); return h > 0 ? h+'h '+m+'m' : m+'m'; }\n function usageBar(label, pct, resetIso) { const p = Math.min(100,Math.max(0,pct||0)), c = barColor(p), reset = resetIso ? '<span style=\"color:#8b949e;font-size:10px;\">resets '+timeLeft(resetIso)+'</span>' : ''; return '<div style=\"margin-bottom:10px;\"><div style=\"display:flex;justify-content:space-between;margin-bottom:3px;\"><span style=\"font-weight:600;font-size:12px;\">'+label+'</span><span style=\"font-size:13px;font-weight:700;color:'+c+';\">'+p.toFixed(0)+'%</span></div><div style=\"background:#21262d;border-radius:4px;height:8px;overflow:hidden;\"><div style=\"width:'+p+'%;height:100%;background:'+c+';border-radius:4px;transition:width .5s;\"></div></div>'+(reset?'<div style=\"text-align:right;margin-top:2px;\">'+reset+'</div>':'')+'</div>'; }\n async function update_${props.id.replace(/-/g,'_')}() { const body = document.getElementById('${props.id}-body'); const subEl = document.getElementById('${props.id}-sub'); try { const res = await fetch('/api/pages/claude-usage/usage'); const d = await res.json(); if (d.error) { body.innerHTML='<div style=\"color:#f85149;\">'+d.error+'</div>'; return; } if (subEl) { subEl.textContent = {max:'Max (5×)',pro:'Pro',free:'Free'}[d.subscription]||d.subscription||''; } let html=''; if(d.five_hour) html+=usageBar('5h Session',d.five_hour.utilization,d.five_hour.resets_at); if(d.seven_day) html+=usageBar('7d Weekly',d.seven_day.utilization,d.seven_day.resets_at); if(d.seven_day_opus) html+=usageBar('Opus (7d)',d.seven_day_opus.utilization,d.seven_day_opus.resets_at); if(d.seven_day_sonnet&&d.seven_day_sonnet.utilization>0) html+=usageBar('Sonnet (7d)',d.seven_day_sonnet.utilization,d.seven_day_sonnet.resets_at); if(d.extra_usage&&d.extra_usage.is_enabled){const used=(d.extra_usage.used_credits/100).toFixed(2),limit=d.extra_usage.monthly_limit>0?(d.extra_usage.monthly_limit/100).toFixed(2):'∞';html+='<div style=\"margin-top:4px;padding-top:6px;border-top:1px solid #30363d;\"><div style=\"display:flex;justify-content:space-between;font-size:11px;\"><span style=\"color:#8b949e;\">Extra Usage</span><span style=\"font-weight:600;\">$'+used+' / $'+limit+'</span></div></div>';} if(!html) html='<div style=\"color:#8b949e;\">No usage data</div>'; body.innerHTML=html; } catch(e) { console.error('Claude usage error:',e); body.innerHTML='<div style=\"color:#f85149;\">Failed to load</div>'; } }\n update_${props.id.replace(/-/g,'_')}(); setInterval(update_${props.id.replace(/-/g,'_')}, ${(props.refreshInterval||120)*1000});\n `\n },\n\n // ── Finance ──────────────────────────────────────────────────────────────\n\n 'stock-ticker': {\n name: 'Stock Ticker',\n icon: '📈',\n category: 'large',\n description: 'Live stock prices via Yahoo Finance. No API key required.',\n defaultWidth: 320,\n defaultHeight: 280,\n hasApiKey: false,\n properties: {\n title: 'Stocks',\n symbols: 'AAPL,MSFT,GOOGL,AMZN',\n refreshInterval: 300\n },\n preview: `<div style=\"padding:6px;font-size:11px;\">\n <div style=\"display:flex;justify-content:space-between;\"><span>AAPL</span><span>$182.50 <span style=\"color:#3fb950;\">+1.24%</span></span></div>\n <div style=\"display:flex;justify-content:space-between;\"><span>MSFT</span><span>$375.20 <span style=\"color:#f85149;\">-0.38%</span></span></div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">📈 ${props.title || 'Stocks'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body\" id=\"${props.id}-list\" style=\"overflow-y:auto;padding:4px 8px;\">\n <div style=\"color:#8b949e;font-size:12px;\">Loading...</div>\n </div>\n </div>`,\n generateJs: (props) => `\n async function update_${props.id.replace(/-/g, '_')}() {\n var list = document.getElementById('${props.id}-list');\n var badge = document.getElementById('${props.id}-badge');\n if (!list) return;\n try {\n var res = await fetch('/api/finance/stocks?symbols=' + encodeURIComponent('${props.symbols || 'AAPL,MSFT'}'));\n if (!res.ok) throw new Error('HTTP ' + res.status);\n var data = await res.json();\n var ok = data.filter(function(d) { return !d.error; });\n list.innerHTML = data.map(function(d) {\n if (d.error) return '<div style=\"padding:5px 0;border-bottom:1px solid #21262d;color:#8b949e;font-size:12px;\">' + _esc(d.symbol) + ' — ' + _esc(d.error) + '</div>';\n var color = d.up ? '#3fb950' : '#f85149';\n return '<div style=\"display:flex;justify-content:space-between;align-items:center;padding:5px 0;border-bottom:1px solid #21262d;\">'\n + '<span style=\"font-weight:600;font-size:13px;\">' + _esc(d.symbol) + '</span>'\n + '<span style=\"text-align:right;\">'\n + '<span style=\"font-size:13px;font-weight:700;margin-right:8px;\">$' + _esc(d.price) + '</span>'\n + '<span style=\"font-size:11px;color:' + color + ';font-weight:600;\">' + _esc(d.pctChange) + '%</span>'\n + '</span></div>';\n }).join('');\n if (badge) badge.textContent = ok.length + ' stocks';\n } catch (e) {\n console.error('Stock ticker error:', e);\n if (list) list.innerHTML = '<div style=\"color:#f85149;font-size:12px;\">Failed to load</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000});\n `\n },\n\n 'crypto-price': {\n name: 'Crypto Price',\n icon: '₿',\n category: 'large',\n description: 'Live crypto prices via CoinGecko. No API key required.',\n defaultWidth: 320,\n defaultHeight: 280,\n hasApiKey: false,\n properties: {\n title: 'Crypto',\n coins: 'bitcoin,ethereum,solana',\n currency: 'usd',\n refreshInterval: 300\n },\n preview: `<div style=\"padding:6px;font-size:11px;\">\n <div style=\"display:flex;justify-content:space-between;\"><span>Bitcoin</span><span>$67,240 <span style=\"color:#3fb950;\">+2.1%</span></span></div>\n <div style=\"display:flex;justify-content:space-between;\"><span>Ethereum</span><span>$3,521 <span style=\"color:#f85149;\">-0.8%</span></span></div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">₿ ${props.title || 'Crypto'}</span>\n <span class=\"dash-card-badge\" id=\"${props.id}-badge\">—</span>\n </div>\n <div class=\"dash-card-body\" id=\"${props.id}-list\" style=\"overflow-y:auto;padding:4px 8px;\">\n <div style=\"color:#8b949e;font-size:12px;\">Loading...</div>\n </div>\n </div>`,\n generateJs: (props) => `\n async function update_${props.id.replace(/-/g, '_')}() {\n var list = document.getElementById('${props.id}-list');\n var badge = document.getElementById('${props.id}-badge');\n if (!list) return;\n try {\n var res = await fetch('/api/finance/crypto?coins=' + encodeURIComponent('${props.coins || 'bitcoin,ethereum'}') + '&currency=${props.currency || 'usd'}');\n if (!res.ok) throw new Error('HTTP ' + res.status);\n var data = await res.json();\n list.innerHTML = data.map(function(d) {\n var color = d.up ? '#3fb950' : '#f85149';\n return '<div style=\"display:flex;justify-content:space-between;align-items:center;padding:5px 0;border-bottom:1px solid #21262d;\">'\n + '<span style=\"font-weight:600;font-size:13px;\">' + _esc(d.name) + '</span>'\n + '<span style=\"text-align:right;\">'\n + '<span style=\"font-size:13px;font-weight:700;margin-right:8px;\">${(props.currency || 'usd').toUpperCase()} ' + _esc(d.price) + '</span>'\n + '<span style=\"font-size:11px;color:' + color + ';font-weight:600;\">' + _esc(d.pctChange) + '%</span>'\n + '</span></div>';\n }).join('');\n if (badge) badge.textContent = data.length + ' coins';\n } catch (e) {\n console.error('Crypto price error:', e);\n if (list) list.innerHTML = '<div style=\"color:#f85149;font-size:12px;\">Failed to load</div>';\n }\n }\n update_${props.id.replace(/-/g, '_')}();\n setInterval(update_${props.id.replace(/-/g, '_')}, ${(props.refreshInterval || 300) * 1000});\n `\n },\n\n // ── Search ────────────────────────────────────────────────────────────────\n\n 'search': {\n name: 'Search',\n icon: '🔍',\n category: 'large',\n description: 'Search box with DuckDuckGo-style !bangs. Press S to focus, ↑ for last query.',\n defaultWidth: 460,\n defaultHeight: 120,\n hasApiKey: false,\n properties: {\n title: 'Search',\n placeholder: 'Search or use !bangs',\n searchEngine: 'duckduckgo',\n openInNewTab: true,\n showBangHints: true\n },\n preview: `<div style=\"padding:10px;\">\n <input style=\"width:100%;padding:6px 10px;background:#21262d;border:1px solid #30363d;border-radius:6px;color:#e6edf3;font-size:13px;\" placeholder=\"Search or use !bangs\" readonly />\n <div style=\"font-size:10px;color:#8b949e;margin-top:6px;\">!yt YouTube &nbsp; !gh GitHub &nbsp; !r Reddit &nbsp; !so Stack Overflow</div>\n </div>`,\n generateHtml: (props) => `\n <div class=\"dash-card\" id=\"widget-${props.id}\" style=\"height:100%;\">\n <div class=\"dash-card-head\">\n <span class=\"dash-card-title\">🔍 ${props.title || 'Search'}</span>\n </div>\n <div class=\"dash-card-body\" style=\"padding:8px 10px;\">\n <form id=\"${props.id}-form\" style=\"display:flex;gap:6px;\" onsubmit=\"return false;\">\n <input id=\"${props.id}-input\" type=\"text\"\n placeholder=\"${props.placeholder || 'Search or use !bangs'}\"\n autocomplete=\"off\" spellcheck=\"false\"\n style=\"flex:1;padding:7px 11px;background:#21262d;border:1px solid #30363d;border-radius:6px;color:#e6edf3;font-size:13px;outline:none;\" />\n <button type=\"submit\"\n style=\"padding:7px 14px;background:#238636;border:none;border-radius:6px;color:#fff;font-size:13px;cursor:pointer;\">Go</button>\n </form>\n ${props.showBangHints !== false ? `<div style=\"font-size:10px;color:#8b949e;margin-top:5px;\"><span style=\"opacity:.7;\">!g Google &nbsp; !yt YouTube &nbsp; !gh GitHub &nbsp; !r Reddit &nbsp; !so Stack Overflow &nbsp; !w Wikipedia &nbsp; !npm npm</span></div>` : ''}\n </div>\n </div>`,\n generateJs: (props) => {\n const providers = { duckduckgo:'https://duckduckgo.com/?q={q}', google:'https://www.google.com/search?q={q}', bing:'https://www.bing.com/search?q={q}', brave:'https://search.brave.com/search?q={q}' };\n const bangs = { g:'https://www.google.com/search?q={q}',b:'https://www.bing.com/search?q={q}',yt:'https://www.youtube.com/results?search_query={q}',gh:'https://github.com/search?q={q}',r:'https://www.reddit.com/search/?q={q}',so:'https://stackoverflow.com/search?q={q}',w:'https://en.wikipedia.org/wiki/Special:Search/{q}',img:'https://www.google.com/search?tbm=isch&q={q}',maps:'https://www.google.com/maps/search/{q}',ddg:'https://duckduckgo.com/?q={q}',npm:'https://www.npmjs.com/search?q={q}',mdn:'https://developer.mozilla.org/en-US/search?q={q}',x:'https://x.com/search?q={q}',tw:'https://x.com/search?q={q}' };\n const defaultUrl = providers[props.searchEngine] || providers.duckduckgo;\n return `\n (function() {\n var BANGS = ${JSON.stringify(bangs)};\n var DEFAULT_URL = '${defaultUrl}';\n var lastQuery = '';\n function navigate(q) {\n q = q.trim(); if (!q) return; lastQuery = q;\n var url = DEFAULT_URL;\n var m = q.match(/^!(\\\\S+)\\\\s*(.*)/);\n if (m) { var bang = m[1].toLowerCase(), rest = m[2]; if (BANGS[bang]) { url = BANGS[bang]; q = rest || q; } }\n var target = url.replace('{q}', encodeURIComponent(q));\n if (${props.openInNewTab !== false}) { window.open(target, '_blank', 'noopener'); } else { window.location.href = target; }\n }\n var form = document.getElementById('${props.id}-form');\n var input = document.getElementById('${props.id}-input');\n if (form) form.addEventListener('submit', function() { navigate(input.value); });\n if (input) input.addEventListener('keydown', function(e) { if (e.key === 'ArrowUp') { e.preventDefault(); input.value = lastQuery; } });\n document.addEventListener('keydown', function(e) {\n var tag = document.activeElement && document.activeElement.tagName;\n if (e.key === 's' && tag !== 'INPUT' && tag !== 'TEXTAREA' && !e.ctrlKey && !e.metaKey) {\n var inp = document.getElementById('${props.id}-input');\n if (inp) { inp.focus(); inp.select(); e.preventDefault(); }\n }\n });\n })();\n `;\n }\n }\n};\n\n// Helper to get widget categories\nexport function getWidgetCategories() {\n const categories = {};\n for (const [key, widget] of Object.entries(WIDGETS)) {\n const cat = widget.category || 'other';\n if (!categories[cat]) categories[cat] = [];\n categories[cat].push({ key, ...widget });\n }\n return categories;\n}\n\n// Helper to get widget by type\nexport function getWidget(type) {\n return WIDGETS[type] || null;\n}\n\n// Helper to list all widget types\nexport function getWidgetTypes() {\n return Object.keys(WIDGETS);\n}\n\nexport default WIDGETS;\n","/**\n * LobsterBoard - Dashboard Builder Core\n * Provides utilities for generating dashboard HTML, CSS, and JS\n * \n * @module lobsterboard/builder\n */\n\nimport { WIDGETS } from './widgets.js';\n\n// ─────────────────────────────────────────────\n// SECURITY HELPERS\n// ─────────────────────────────────────────────\n\n/**\n * Escape HTML to prevent XSS attacks\n * @param {string} str - String to escape\n * @returns {string} Escaped string\n */\nexport function escapeHtml(str) {\n if (!str) return '';\n if (typeof document !== 'undefined') {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n // Fallback for Node.js\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\n// ─────────────────────────────────────────────\n// HTML PROCESSING\n// ─────────────────────────────────────────────\n\n/**\n * Process widget HTML to conditionally remove header\n * @param {string} html - Widget HTML\n * @param {boolean} showHeader - Whether to show the header\n * @returns {string} Processed HTML\n */\nexport function processWidgetHtml(html, showHeader) {\n if (showHeader !== false) return html;\n const headerRegex = /<div\\s+class=\"dash-card-head\"[^>]*>[\\s\\S]*?<\\/div>/i;\n return html.replace(headerRegex, '');\n}\n\n// ─────────────────────────────────────────────\n// CSS GENERATION\n// ─────────────────────────────────────────────\n\n/**\n * Generate the base dashboard CSS\n * @returns {string} CSS styles\n */\nexport function generateDashboardCss() {\n return `/* LobsterBoard Dashboard - Generated Styles */\n\n:root {\n --bg-primary: #0d1117;\n --bg-secondary: #161b22;\n --bg-tertiary: #21262d;\n --bg-hover: #30363d;\n --border: #30363d;\n --text-primary: #e6edf3;\n --text-secondary: #8b949e;\n --text-muted: #6e7681;\n --accent-blue: #58a6ff;\n --accent-green: #3fb950;\n --accent-orange: #d29922;\n --accent-red: #f85149;\n --accent-purple: #a371f7;\n}\n\n* {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: var(--bg-primary);\n color: var(--text-primary);\n min-height: 100vh;\n}\n\n.dashboard {\n margin: 0 auto;\n overflow: hidden;\n}\n\n.widget-container {\n overflow: hidden;\n}\n\n/* KPI Cards */\n.kpi-card {\n background: var(--bg-secondary);\n border: 1px solid var(--border);\n border-radius: 8px;\n padding: 16px;\n display: flex;\n align-items: center;\n gap: 12px;\n height: 100%;\n}\n\n.kpi-sm {\n padding: 12px;\n}\n\n.kpi-icon {\n font-size: 24px;\n}\n\n.kpi-data {\n flex: 1;\n}\n\n.kpi-value {\n font-size: 20px;\n font-weight: 600;\n}\n\n.kpi-value.blue { color: var(--accent-blue); }\n.kpi-value.green { color: var(--accent-green); }\n.kpi-value.orange { color: var(--accent-orange); }\n.kpi-value.red { color: var(--accent-red); }\n\n.kpi-label {\n font-size: 12px;\n color: var(--text-secondary);\n margin-top: 2px;\n}\n\n.kpi-indicator {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--text-muted);\n}\n\n.kpi-indicator.green { background: var(--accent-green); }\n.kpi-indicator.yellow { background: var(--accent-orange); }\n.kpi-indicator.red { background: var(--accent-red); }\n\n/* Dash Cards */\n.dash-card {\n background: var(--bg-secondary);\n border: 1px solid var(--border);\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.dash-card-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n border-bottom: 1px solid var(--border);\n background: var(--bg-tertiary);\n}\n\n.dash-card-title {\n font-size: 13px;\n font-weight: 600;\n}\n\n.dash-card-badge {\n font-size: 11px;\n color: var(--text-secondary);\n background: var(--bg-primary);\n padding: 2px 8px;\n border-radius: 10px;\n}\n\n.dash-card-body {\n flex: 1;\n padding: 12px 16px;\n overflow-y: auto;\n}\n\n.compact-list {\n font-size: 12px;\n}\n\n.syslog-scroll {\n font-family: 'SF Mono', Monaco, monospace;\n font-size: 11px;\n}\n\n/* Top Bar */\n.topbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 20px;\n background: var(--bg-secondary);\n border-bottom: 1px solid var(--border);\n height: 100%;\n}\n\n.topbar-left {\n display: flex;\n align-items: center;\n gap: 20px;\n}\n\n.topbar-brand {\n font-weight: 600;\n font-size: 14px;\n}\n\n.topbar-link {\n color: var(--text-secondary);\n text-decoration: none;\n font-size: 13px;\n}\n\n.topbar-link:hover,\n.topbar-link.active {\n color: var(--accent-blue);\n}\n\n.topbar-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.topbar-meta {\n font-size: 12px;\n color: var(--text-muted);\n}\n\n.topbar-refresh {\n background: var(--bg-tertiary);\n border: 1px solid var(--border);\n color: var(--text-secondary);\n padding: 4px 8px;\n border-radius: 4px;\n cursor: pointer;\n}\n\n/* List Items */\n.list-item {\n padding: 6px 0;\n border-bottom: 1px solid var(--border);\n}\n\n.list-item:last-child {\n border-bottom: none;\n}\n\n.cron-item {\n display: flex;\n justify-content: space-between;\n padding: 6px 0;\n border-bottom: 1px solid var(--border);\n}\n\n.cron-name {\n color: var(--text-primary);\n}\n\n.cron-next {\n color: var(--text-muted);\n font-size: 11px;\n}\n\n.log-line {\n padding: 2px 0;\n border-bottom: 1px solid rgba(48, 54, 61, 0.5);\n}\n\n/* Weather */\n.weather-row {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 0;\n border-bottom: 1px solid var(--border);\n}\n\n.weather-row:last-child {\n border-bottom: none;\n}\n\n.weather-icon {\n font-size: 18px;\n}\n\n.weather-loc {\n flex: 1;\n color: var(--text-primary);\n}\n\n.weather-temp {\n font-weight: 600;\n color: var(--accent-blue);\n}\n\n/* Utilities */\n.loading-sm {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n}\n\n.spinner-sm {\n width: 20px;\n height: 20px;\n border: 2px solid var(--bg-tertiary);\n border-top-color: var(--accent-blue);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n.error {\n color: var(--accent-red);\n padding: 10px;\n text-align: center;\n}\n\n::-webkit-scrollbar {\n width: 6px;\n}\n\n::-webkit-scrollbar-track {\n background: var(--bg-primary);\n}\n\n::-webkit-scrollbar-thumb {\n background: var(--bg-tertiary);\n border-radius: 3px;\n}\n\n/* Post-Export Edit Mode */\n.edit-mode .widget-container {\n cursor: move;\n outline: 2px dashed #3b82f6;\n outline-offset: -2px;\n}\n\n.edit-mode .widget-container:hover {\n outline-color: #60a5fa;\n}\n\n.edit-mode .widget-container.dragging {\n opacity: 0.8;\n z-index: 1000;\n}\n\n.resize-handle-edit {\n display: none;\n position: absolute;\n bottom: 0;\n right: 0;\n width: 16px;\n height: 16px;\n cursor: se-resize;\n background: #3b82f6;\n border-radius: 2px 0 0 0;\n z-index: 10;\n}\n\n.edit-mode .resize-handle-edit {\n display: block;\n}\n\n#edit-toggle {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 9999;\n padding: 8px 16px;\n background: #1e293b;\n color: white;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n}\n\n#edit-toggle:hover {\n background: #334155;\n}\n\n#edit-toggle.active {\n background: #3b82f6;\n}\n`;\n}\n\n// ─────────────────────────────────────────────\n// JS GENERATION\n// ─────────────────────────────────────────────\n\n/**\n * Generate the post-export edit mode JS\n * @returns {string} JavaScript code\n */\nexport function generateEditJs() {\n return `\n// ─────────────────────────────────────────────\n// POST-EXPORT LAYOUT EDITING\n// ─────────────────────────────────────────────\n\n(function() {\n const STORAGE_KEY = 'lobsterboard-layout';\n const GRID_SIZE = 20;\n const MIN_WIDTH = 100;\n const MIN_HEIGHT = 60;\n \n let editMode = false;\n let activeWidget = null;\n let startX, startY, origLeft, origTop, origWidth, origHeight;\n let isResizing = false;\n\n document.addEventListener('DOMContentLoaded', initEditMode);\n\n function initEditMode() {\n const btn = document.createElement('button');\n btn.id = 'edit-toggle';\n btn.textContent = '✏️ Edit Layout';\n btn.onclick = toggleEditMode;\n document.body.appendChild(btn);\n document.querySelectorAll('.widget-container').forEach(initWidget);\n loadPositions();\n }\n\n function initWidget(widget) {\n const handle = document.createElement('div');\n handle.className = 'resize-handle-edit';\n widget.appendChild(handle);\n widget.addEventListener('mousedown', onWidgetMouseDown);\n handle.addEventListener('mousedown', onResizeMouseDown);\n }\n\n function toggleEditMode() {\n editMode = !editMode;\n document.body.classList.toggle('edit-mode', editMode);\n document.getElementById('edit-toggle').classList.toggle('active', editMode);\n document.getElementById('edit-toggle').textContent = editMode ? '💾 Save Layout' : '✏️ Edit Layout';\n if (!editMode) savePositions();\n }\n\n function onWidgetMouseDown(e) {\n if (!editMode) return;\n if (e.target.classList.contains('resize-handle-edit')) return;\n if (e.button !== 0) return;\n e.preventDefault();\n activeWidget = e.currentTarget;\n isResizing = false;\n startX = e.clientX;\n startY = e.clientY;\n origLeft = activeWidget.offsetLeft;\n origTop = activeWidget.offsetTop;\n activeWidget.classList.add('dragging');\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n }\n\n function onResizeMouseDown(e) {\n if (!editMode) return;\n e.preventDefault();\n e.stopPropagation();\n activeWidget = e.target.parentElement;\n isResizing = true;\n startX = e.clientX;\n startY = e.clientY;\n origWidth = activeWidget.offsetWidth;\n origHeight = activeWidget.offsetHeight;\n activeWidget.classList.add('dragging');\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n }\n\n function onMouseMove(e) {\n if (!activeWidget) return;\n const dx = e.clientX - startX;\n const dy = e.clientY - startY;\n if (isResizing) {\n activeWidget.style.width = Math.max(MIN_WIDTH, origWidth + dx) + 'px';\n activeWidget.style.height = Math.max(MIN_HEIGHT, origHeight + dy) + 'px';\n } else {\n activeWidget.style.left = Math.max(0, origLeft + dx) + 'px';\n activeWidget.style.top = Math.max(0, origTop + dy) + 'px';\n }\n }\n\n function onMouseUp() {\n if (!activeWidget) return;\n if (isResizing) {\n activeWidget.style.width = snapToGrid(activeWidget.offsetWidth) + 'px';\n activeWidget.style.height = snapToGrid(activeWidget.offsetHeight) + 'px';\n } else {\n activeWidget.style.left = snapToGrid(activeWidget.offsetLeft) + 'px';\n activeWidget.style.top = snapToGrid(activeWidget.offsetTop) + 'px';\n }\n activeWidget.classList.remove('dragging');\n activeWidget = null;\n isResizing = false;\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n }\n\n function snapToGrid(value) {\n return Math.round(value / GRID_SIZE) * GRID_SIZE;\n }\n\n function savePositions() {\n const positions = {};\n document.querySelectorAll('.widget-container').forEach(widget => {\n const id = widget.dataset.widgetId;\n if (id) {\n positions[id] = {\n left: widget.offsetLeft,\n top: widget.offsetTop,\n width: widget.offsetWidth,\n height: widget.offsetHeight\n };\n }\n });\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(positions));\n } catch (e) {}\n }\n\n function loadPositions() {\n try {\n const saved = localStorage.getItem(STORAGE_KEY);\n if (!saved) return;\n const positions = JSON.parse(saved);\n document.querySelectorAll('.widget-container').forEach(widget => {\n const id = widget.dataset.widgetId;\n const pos = positions[id];\n if (pos) {\n widget.style.left = pos.left + 'px';\n widget.style.top = pos.top + 'px';\n widget.style.width = pos.width + 'px';\n widget.style.height = pos.height + 'px';\n }\n });\n } catch (e) {}\n }\n})();\n`;\n}\n\n// ─────────────────────────────────────────────\n// DASHBOARD GENERATION\n// ─────────────────────────────────────────────\n\n/**\n * Generate widget HTML for a widget configuration\n * @param {Object} widget - Widget configuration\n * @returns {string} Widget HTML\n */\nexport function generateWidgetHtml(widget) {\n const template = WIDGETS[widget.type];\n if (!template) return '';\n\n const props = { ...widget.properties, id: widget.id };\n let html = processWidgetHtml(template.generateHtml(props), widget.properties.showHeader);\n\n return `\n <div class=\"widget-container\" data-widget-id=\"${widget.id}\" style=\"position:absolute;left:${widget.x}px;top:${widget.y}px;width:${widget.width}px;height:${widget.height}px;\">\n ${html}\n </div>`;\n}\n\n/**\n * Generate widget JavaScript for a widget configuration\n * @param {Object} widget - Widget configuration\n * @returns {string} Widget JavaScript\n */\nexport function generateWidgetJs(widget) {\n const template = WIDGETS[widget.type];\n if (!template || !template.generateJs) return '';\n\n const props = { ...widget.properties, id: widget.id };\n return template.generateJs(props);\n}\n\n/**\n * Generate complete dashboard HTML\n * @param {Object} config - Dashboard configuration\n * @param {Object} config.canvas - Canvas dimensions { width, height }\n * @param {Array} config.widgets - Array of widget configurations\n * @returns {string} Complete HTML document\n */\nexport function generateDashboardHtml(config) {\n const { canvas, widgets } = config;\n const widgetHtml = widgets.map(generateWidgetHtml).join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>My LobsterBoard Dashboard</title>\n <link rel=\"stylesheet\" href=\"css/style.css\">\n</head>\n<body>\n <main class=\"dashboard\" style=\"width:${canvas.width}px;height:${canvas.height}px;position:relative;\">\n ${widgetHtml}\n </main>\n <script src=\"js/dashboard.js\"></script>\n</body>\n</html>`;\n}\n\n/**\n * Generate complete dashboard JavaScript\n * @param {Array} widgets - Array of widget configurations\n * @returns {string} Complete JavaScript\n */\nexport function generateDashboardJs(widgets) {\n const widgetJs = widgets.map(generateWidgetJs).filter(Boolean).join('\\n\\n');\n const editJs = generateEditJs();\n\n return `/**\n * LobsterBoard Dashboard - Generated JavaScript\n * Replace YOUR_*_API_KEY placeholders with your actual API keys\n */\n\ndocument.addEventListener('DOMContentLoaded', () => {\n console.log('Dashboard loaded');\n});\n\n${widgetJs}\n\n${editJs}\n`;\n}\n\n/**\n * Generate README for exported dashboard\n * @param {Array} widgets - Array of widget configurations\n * @returns {string} README markdown\n */\nexport function generateReadme(widgets) {\n const apiKeys = [];\n const needsOpenClaw = widgets.some(w => \n ['openclaw-release', 'auth-status', 'activity-list', 'cron-jobs', 'system-log', 'session-count', 'token-gauge'].includes(w.type)\n );\n \n widgets.forEach(widget => {\n const template = WIDGETS[widget.type];\n if (template?.hasApiKey && template.apiKeyName) {\n if (!apiKeys.includes(template.apiKeyName)) {\n apiKeys.push(template.apiKeyName);\n }\n }\n });\n\n return `# LobsterBoard Dashboard\n\nThis dashboard was generated with LobsterBoard Dashboard Builder.\n\n## Quick Start\n\n${needsOpenClaw ? `### Running with OpenClaw widgets\n\nYour dashboard includes widgets that connect to OpenClaw. Run the included server:\n\n\\`\\`\\`bash\nnode server.js\n\\`\\`\\`\n\nOpen http://localhost:8080 in your browser.\n` : ''}\n### Static mode\n\nOpen \\`index.html\\` directly in a browser.\n\n## Files\n\n| File | Description |\n|------|-------------|\n| \\`index.html\\` | Dashboard page |\n| \\`css/style.css\\` | Styles |\n| \\`js/dashboard.js\\` | Widget logic |\n| \\`server.js\\` | Server with OpenClaw API proxy |\n\n${apiKeys.length > 0 ? `## API Keys\n\nEdit \\`js/dashboard.js\\` and replace these placeholders:\n${apiKeys.map(key => `- \\`YOUR_${key}\\``).join('\\n')}\n` : ''}\n\n---\n\nGenerated with LobsterBoard - https://github.com/curbob/LobsterBoard\n`;\n}\n\nexport default {\n escapeHtml,\n processWidgetHtml,\n generateDashboardCss,\n generateEditJs,\n generateWidgetHtml,\n generateWidgetJs,\n generateDashboardHtml,\n generateDashboardJs,\n generateReadme\n};\n","/**\n * LobsterBoard - Dashboard Builder Library\n * \n * A library for building and generating dashboard configurations\n * with customizable widgets.\n * \n * @module lobsterboard\n * @example\n * // ESM\n * import { WIDGETS, generateDashboardHtml, generateDashboardCss } from 'lobsterboard';\n * \n * // CommonJS\n * const { WIDGETS, generateDashboardHtml } = require('lobsterboard');\n * \n * // Browser (UMD)\n * <script src=\"https://unpkg.com/lobsterboard\"></script>\n * const { WIDGETS } = LobsterBoard;\n */\n\n// Widget definitions\nexport { \n WIDGETS, \n getWidgetCategories, \n getWidget, \n getWidgetTypes \n} from './widgets.js';\n\n// Builder utilities\nexport {\n escapeHtml,\n processWidgetHtml,\n generateDashboardCss,\n generateEditJs,\n generateWidgetHtml,\n generateWidgetJs,\n generateDashboardHtml,\n generateDashboardJs,\n generateReadme\n} from './builder.js';\n\n// Re-export defaults for convenience\nimport { WIDGETS } from './widgets.js';\nimport builder from './builder.js';\n\n// Version (will be replaced during build)\nexport const VERSION = '0.1.0';\n\n// Default export for convenience\nexport default {\n VERSION,\n WIDGETS,\n ...builder\n};\n"],"names":[],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;;AAEY,MAAC,OAAO,GAAG;AACvB;AACA;AACA;AACA;AACA,EAAE,SAAS,EAAE;AACb,IAAI,IAAI,EAAE,eAAe;AACzB,IAAI,IAAI,EAAE,KAAK;AACf,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,gFAAgF;AACjG,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,eAAe;AAC5B,MAAM,QAAQ,EAAE,SAAS;AACzB,MAAM,KAAK,EAAE,GAAG;AAChB,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,4CAA4C,EAAE,KAAK,CAAC,KAAK,IAAI,eAAe,CAAC;AAC7E;AACA;AACA,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC;AAC/B;AACA,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD,uCAAuC,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,UAAU,CAAC;AACzF;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC;AACpC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA,+CAA+C,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC;AAC7E;AACA;AACA;AACA,wBAAwB,EAAE,KAAK,CAAC,KAAK,CAAC;AACtC,wBAAwB,EAAE,KAAK,CAAC,KAAK,CAAC;AACtC,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,GAAG,IAAI,IAAI,CAAC;AACjG,IAAI;AACJ,GAAG;;AAEH,EAAE,OAAO,EAAE;AACX,IAAI,IAAI,EAAE,OAAO;AACjB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,mDAAmD;AACpE,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,OAAO;AACpB,MAAM,QAAQ,EAAE,OAAO;AACvB,MAAM,SAAS,EAAE;AACjB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC;AACpE;AACA;AACA,qCAAqC,EAAE,KAAK,CAAC,EAAE,CAAC;AAChD,qCAAqC,EAAE,KAAK,CAAC,EAAE,CAAC;AAChD;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,uBAAuB,EAAE,KAAK,CAAC,EAAE;AACjC,2BAA2B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACzD;AACA,gDAAgD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC3D,gDAAgD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC3D,mEAAmE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;AACtF;AACA;AACA;AACA,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAChD,8BAA8B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5D,IAAI;AACJ,GAAG;;AAEH,EAAE,aAAa,EAAE;AACjB,IAAI,IAAI,EAAE,aAAa;AACvB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,6FAA6F;AAC9G,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,IAAI;AACnB,IAAI,UAAU,EAAE,cAAc;AAC9B,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,WAAW;AACxB,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,WAAW,CAAC;AACxE;AACA;AACA,yCAAyC,EAAE,KAAK,CAAC,EAAE,CAAC;AACpD,qCAAqC,EAAE,KAAK,CAAC,EAAE,CAAC;AAChD;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,6BAA6B,EAAE,KAAK,CAAC,EAAE;AACvC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA,mCAAmC,EAAE,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC;AACrE;AACA;AACA,+CAA+C,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1D,+CAA+C,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1D;AACA;AACA;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,IAAI,IAAI,CAAC;AAChG,IAAI;AACJ,GAAG;;AAEH,EAAE,eAAe,EAAE;AACnB,IAAI,IAAI,EAAE,iBAAiB;AAC3B,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,0CAA0C;AAC3D,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,IAAI;AACnB,IAAI,UAAU,EAAE,cAAc;AAC9B,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,UAAU;AACvB,MAAM,QAAQ,EAAE,eAAe;AAC/B,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,8CAA8C,EAAE,KAAK,CAAC,EAAE,CAAC;AACzD;AACA;AACA,0CAA0C,EAAE,KAAK,CAAC,EAAE,CAAC;AACrD;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,+BAA+B,EAAE,KAAK,CAAC,EAAE;AACzC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA,mCAAmC,EAAE,KAAK,CAAC,QAAQ,IAAI,eAAe,CAAC;AACvE;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,IAAI,IAAI,CAAC;AAChG,IAAI;AACJ,GAAG;;AAEH;AACA;AACA;;AAEA,EAAE,eAAe,EAAE;AACnB,IAAI,IAAI,EAAE,eAAe;AACzB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,6DAA6D;AAC9E,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,IAAI;AACnB,IAAI,UAAU,EAAE,cAAc;AAC9B,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,OAAO;AACpB,MAAM,QAAQ,EAAE,eAAe;AAC/B,MAAM,QAAQ,EAAE,EAAE;AAClB,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC;AACpE,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD;AACA,qDAAqD,EAAE,KAAK,CAAC,EAAE,CAAC;AAChE;AACA;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,+BAA+B,EAAE,KAAK,CAAC,EAAE;AACzC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA,mCAAmC,EAAE,KAAK,CAAC,QAAQ,IAAI,eAAe,CAAC;AACvE;AACA;AACA,gDAAgD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC3D,iDAAiD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5D;AACA,0CAA0C,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;AACjE;AACA;AACA;AACA;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,IAAI,IAAI,CAAC;AAChG,IAAI;AACJ,GAAG;;AAEH,EAAE,WAAW,EAAE;AACf,IAAI,IAAI,EAAE,WAAW;AACrB,IAAI,IAAI,EAAE,GAAG;AACb,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,6DAA6D;AAC9E,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,IAAI;AACnB,IAAI,UAAU,EAAE,cAAc;AAC9B,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,MAAM;AACnB,MAAM,QAAQ,EAAE,WAAW;AAC3B,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,0CAA0C,EAAE,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC;AAClE,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD;AACA,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,2BAA2B,EAAE,KAAK,CAAC,EAAE;AACrC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA,mCAAmC,EAAE,KAAK,CAAC,QAAQ,IAAI,WAAW,CAAC;AACnE;AACA;AACA,gDAAgD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC3D,iDAAiD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,IAAI,IAAI,CAAC;AAChG,IAAI;AACJ,GAAG;;AAEH,EAAE,YAAY,EAAE;AAChB,IAAI,IAAI,EAAE,YAAY;AACtB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,4DAA4D;AAC7E,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,IAAI;AACnB,IAAI,UAAU,EAAE,cAAc;AAC9B,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,YAAY;AACzB,MAAM,QAAQ,EAAE,WAAW;AAC3B,MAAM,QAAQ,EAAE,EAAE;AAClB,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,YAAY,CAAC;AACzE,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD;AACA,mEAAmE,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9E;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,4BAA4B,EAAE,KAAK,CAAC,EAAE;AACtC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA,mCAAmC,EAAE,KAAK,CAAC,QAAQ,IAAI,WAAW,CAAC;AACnE;AACA;AACA,+CAA+C,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1D,iDAAiD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5D;AACA,uCAAuC,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,IAAI,IAAI,CAAC;AAChG,IAAI;AACJ,GAAG;;AAEH;AACA;AACA;;AAEA,EAAE,YAAY,EAAE;AAChB,IAAI,IAAI,EAAE,YAAY;AACtB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,gGAAgG;AACjH,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,OAAO;AACpB,MAAM,MAAM,EAAE,UAAU;AACxB,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC;AACpE;AACA,8CAA8C,EAAE,KAAK,CAAC,MAAM,KAAK,YAAY,GAAG,uBAAuB,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;AACjJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc,CAAC;AACf,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,4BAA4B,EAAE,KAAK,CAAC,EAAE;AACtC,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D;AACA;AACA;AACA,gDAAgD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,IAAI,IAAI,CAAC;AAChG,IAAI;AACJ,GAAG;;AAEH,EAAE,QAAQ,EAAE;AACZ,IAAI,IAAI,EAAE,aAAa;AACvB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,KAAK;AACnB,IAAI,WAAW,EAAE,uDAAuD;AACxE,IAAI,YAAY,EAAE,IAAI;AACtB,IAAI,aAAa,EAAE,EAAE;AACrB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,UAAU;AACvB,MAAM,KAAK,EAAE;AACb,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,qCAAqC,EAAE,KAAK,CAAC,EAAE,CAAC;AAChD;AACA,wCAAwC,EAAE,KAAK,CAAC,KAAK,IAAI,UAAU,CAAC;AACpE,UAAU,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAChE,YAAY,CAAC,8BAA8B,EAAE,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI;AAC1F,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;AACpB;AACA;AACA,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,yBAAyB,EAAE,KAAK,CAAC,EAAE;AACnC,+BAA+B,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1C;AACA,IAAI;AACJ,GAAG;;AAEH,EAAE,kBAAkB,EAAE;AACtB,IAAI,IAAI,EAAE,oBAAoB;AAC9B,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,QAAQ;AACtB,IAAI,WAAW,EAAE,8GAA8G;AAC/H,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,QAAQ;AACrB,MAAM,MAAM,EAAE,OAAO;AACrB,MAAM,eAAe,EAAE,CAAC;AACxB,MAAM,eAAe,EAAE,IAAI;AAC3B,MAAM,UAAU,EAAE;AAClB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,wCAAwC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC;AACvF,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,GAAG,CAAC,+DAA+D,CAAC,GAAG,EAAE;AAC7H;AACA;AACA;AACA,YAAY,EAAE,KAAK,CAAC,UAAU,GAAG,qCAAqC,GAAG,EAAE;AAC3E;AACA;AACA;AACA,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC;AACvC;AACA;AACA;AACA;AACA,0BAA0B,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,eAAe,GAAG,EAAE,GAAG,uBAAuB,CAAC;AACtG,0BAA0B,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,eAAe,GAAG,uBAAuB,GAAG,EAAE,CAAC;AACvG;AACA;AACA;AACA;AACA,YAAY,EAAE,KAAK,CAAC,UAAU,GAAG,qCAAqC,GAAG,EAAE;AAC3E;AACA;AACA;AACA,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC;AACvC;AACA;AACA;AACA;AACA,0BAA0B,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,eAAe,GAAG,EAAE,GAAG,uBAAuB,CAAC;AACtG,0BAA0B,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,eAAe,GAAG,uBAAuB,GAAG,EAAE,CAAC;AACvG;AACA;AACA;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,oCAAoC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,KAAK,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC,MAAM;AACtH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,EAAE,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC;AACzC;AACA;AACA,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC9C;AACA;AACA;AACA;AACA;AACA,8BAA8B,EAAE,KAAK,CAAC,EAAE,CAAC,mCAAmC,EAAE,KAAK,CAAC,EAAE,CAAC;AACvF;AACA;AACA;AACA;AACA;AACA,8BAA8B,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5E;AACA,SAAS,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,IAAI,IAAI,CAAC;AAC/C,IAAI;AACJ,GAAG;;AAEH,EAAE,cAAc,EAAE;AAClB,IAAI,IAAI,EAAE,cAAc;AACxB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,0HAA0H;AAC3I,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,EAAE;AAC/D,IAAI,OAAO,EAAE,CAAC,8GAA8G,CAAC;AAC7H,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,EAAE,CAAC,oFAAoF,EAAE,KAAK,CAAC,KAAK,IAAI,cAAc,CAAC,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,0GAA0G,EAAE,KAAK,CAAC,EAAE,CAAC,2HAA2H,CAAC;AAC5c,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B;AACA;AACA;AACA,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,2CAA2C,EAAE,KAAK,CAAC,EAAE,CAAC,gDAAgD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1K,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC;AACpI,IAAI;AACJ,GAAG;;AAEH;;AAEA,EAAE,cAAc,EAAE;AAClB,IAAI,IAAI,EAAE,cAAc;AACxB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,2DAA2D;AAC5E,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,QAAQ;AACrB,MAAM,OAAO,EAAE,sBAAsB;AACrC,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC;AACrE,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD;AACA,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD,6CAA6C,EAAE,KAAK,CAAC,EAAE,CAAC;AACxD;AACA;AACA,qFAAqF,EAAE,KAAK,CAAC,OAAO,IAAI,WAAW,CAAC;AACpH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,GAAG,IAAI,IAAI,CAAC;AACjG,IAAI;AACJ,GAAG;;AAEH,EAAE,cAAc,EAAE;AAClB,IAAI,IAAI,EAAE,cAAc;AACxB,IAAI,IAAI,EAAE,GAAG;AACb,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,wDAAwD;AACzE,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,QAAQ;AACrB,MAAM,KAAK,EAAE,yBAAyB;AACtC,MAAM,QAAQ,EAAE,KAAK;AACrB,MAAM,eAAe,EAAE;AACvB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,0CAA0C,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC;AACpE,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD;AACA,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,4BAA4B,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1D,4CAA4C,EAAE,KAAK,CAAC,EAAE,CAAC;AACvD,6CAA6C,EAAE,KAAK,CAAC,EAAE,CAAC;AACxD;AACA;AACA,mFAAmF,EAAE,KAAK,CAAC,KAAK,IAAI,kBAAkB,CAAC,gBAAgB,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC;AACjK;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gFAAgF,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,EAAE,WAAW,EAAE,CAAC;AAC1H;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,IAAI,GAAG,IAAI,IAAI,CAAC;AACjG,IAAI;AACJ,GAAG;;AAEH;;AAEA,EAAE,QAAQ,EAAE;AACZ,IAAI,IAAI,EAAE,QAAQ;AAClB,IAAI,IAAI,EAAE,IAAI;AACd,IAAI,QAAQ,EAAE,OAAO;AACrB,IAAI,WAAW,EAAE,8EAA8E;AAC/F,IAAI,YAAY,EAAE,GAAG;AACrB,IAAI,aAAa,EAAE,GAAG;AACtB,IAAI,SAAS,EAAE,KAAK;AACpB,IAAI,UAAU,EAAE;AAChB,MAAM,KAAK,EAAE,QAAQ;AACrB,MAAM,WAAW,EAAE,sBAAsB;AACzC,MAAM,YAAY,EAAE,YAAY;AAChC,MAAM,YAAY,EAAE,IAAI;AACxB,MAAM,aAAa,EAAE;AACrB,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd;AACA;AACA,UAAU,CAAC;AACX,IAAI,YAAY,EAAE,CAAC,KAAK,KAAK;AAC7B,wCAAwC,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD;AACA,2CAA2C,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC;AACrE;AACA;AACA,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC;AAC/B,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC;AAClC,2BAA2B,EAAE,KAAK,CAAC,WAAW,IAAI,sBAAsB,CAAC;AACzE;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE,KAAK,CAAC,aAAa,KAAK,KAAK,GAAG,CAAC,8NAA8N,CAAC,GAAG,EAAE;AACjR;AACA,YAAY,CAAC;AACb,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK;AAC3B,MAAM,MAAM,SAAS,GAAG,EAAE,UAAU,CAAC,+BAA+B,EAAE,MAAM,CAAC,qCAAqC,EAAE,IAAI,CAAC,mCAAmC,EAAE,KAAK,CAAC,uCAAuC,EAAE;AAC7M,MAAM,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,mCAAmC,CAAC,EAAE,CAAC,kDAAkD,CAAC,EAAE,CAAC,iCAAiC,CAAC,CAAC,CAAC,sCAAsC,CAAC,EAAE,CAAC,wCAAwC,CAAC,CAAC,CAAC,kDAAkD,CAAC,GAAG,CAAC,8CAA8C,CAAC,IAAI,CAAC,wCAAwC,CAAC,GAAG,CAAC,+BAA+B,CAAC,GAAG,CAAC,oCAAoC,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC,CAAC,4BAA4B,CAAC,EAAE,CAAC,4BAA4B,EAAE;AAC9mB,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,UAAU;AAC9E,MAAM,OAAO;AACb;AACA,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC9C,6BAA6B,EAAE,UAAU,CAAC;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,EAAE,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC;AAC/C;AACA,8CAA8C,EAAE,KAAK,CAAC,EAAE,CAAC;AACzD,+CAA+C,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1D;AACA;AACA;AACA;AACA;AACA,iDAAiD,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5D;AACA;AACA;AACA;AACA,MAAM,CAAC;AACP,IAAI;AACJ;AACA;;AAEA;AACO,SAAS,mBAAmB,GAAG;AACtC,EAAE,MAAM,UAAU,GAAG,EAAE;AACvB,EAAE,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACvD,IAAI,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,IAAI,OAAO;AAC1C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE;AAC9C,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;AAC5C,EAAE;AACF,EAAE,OAAO,UAAU;AACnB;;AAEA;AACO,SAAS,SAAS,CAAC,IAAI,EAAE;AAChC,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI;AAC9B;;AAEA;AACO,SAAS,cAAc,GAAG;AACjC,EAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AAC7B;;ACzzBA;AACA;AACA;AACA;AACA;AACA;;;AAIA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,UAAU,CAAC,GAAG,EAAE;AAChC,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;AACrB,EAAE,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE;AACvC,IAAI,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;AAC7C,IAAI,GAAG,CAAC,WAAW,GAAG,GAAG;AACzB,IAAI,OAAO,GAAG,CAAC,SAAS;AACxB,EAAE;AACF;AACA,EAAE,OAAO;AACT,KAAK,OAAO,CAAC,IAAI,EAAE,OAAO;AAC1B,KAAK,OAAO,CAAC,IAAI,EAAE,MAAM;AACzB,KAAK,OAAO,CAAC,IAAI,EAAE,MAAM;AACzB,KAAK,OAAO,CAAC,IAAI,EAAE,QAAQ;AAC3B,KAAK,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;AAC5B;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE;AACpD,EAAE,IAAI,UAAU,KAAK,KAAK,EAAE,OAAO,IAAI;AACvC,EAAE,MAAM,WAAW,GAAG,qDAAqD;AAC3E,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;AACtC;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACO,SAAS,oBAAoB,GAAG;AACvC,EAAE,OAAO,CAAC;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,CAAC;AACD;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACO,SAAS,cAAc,GAAG;AACjC,EAAE,OAAO;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;;AAEA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"}