@shahmilsaari/memory-core 1.0.31 → 1.0.33

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.
@@ -0,0 +1 @@
1
+ :root{color-scheme:light dark;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}body{margin:0;min-width:320px;min-height:100vh}button,input,select,textarea{font:inherit}button{border:0}:root{--primary: #0040e0;--primary-dim: #2e5bff;--primary-container: #efefff;--on-primary: #ffffff;--surface: #f8f9fb;--surface-low: #f3f4f6;--surface-mid: #edeef0;--surface-high: #e7e8ea;--surface-highest: #e1e2e4;--on-surface: #191c1e;--on-surface-var: #434656;--outline: #747688;--outline-var: #c4c5d9;--error: #ba1a1a;--error-bg: #ffdad6;--tertiary: #993100;--green: #10b981;--green-bg: rgba(16,185,129,.1);--green-border: rgba(16,185,129,.3);--mono: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;--sans: "Hanken Grotesk", Inter, ui-sans-serif, system-ui, sans-serif;--sidebar-bg: #f0f1f5;--sidebar-border: #e0e1e9;--sidebar-text: #191c1e;--sidebar-muted: #747688;--sidebar-hover: rgba(0,0,0,.05);--sidebar-active-bg: #e4e8ff}body{margin:0;background:var(--surface);color:var(--on-surface);font-family:var(--sans);font-size:14px;overflow:hidden;height:100vh}*{box-sizing:border-box}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-track{background:var(--surface-low)}::-webkit-scrollbar-thumb{background:var(--outline-var);border-radius:4px}.shell.svelte-d3ct2b{display:flex;flex-direction:column;height:100vh;overflow:hidden}.topbar.svelte-d3ct2b{display:flex;align-items:center;gap:12px;height:48px;padding:0 20px;background:var(--surface);border-bottom:1px solid var(--outline-var);flex-shrink:0;z-index:30}.topbar-brand.svelte-d3ct2b{display:flex;align-items:center;gap:10px;flex-shrink:0}.topbar-project.svelte-d3ct2b{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--on-surface);letter-spacing:.02em;text-transform:uppercase}.topbar-arch-pill.svelte-d3ct2b{font-family:var(--mono);font-size:10px;font-weight:600;color:var(--primary);background:var(--primary-container);border:1px solid var(--primary-dim);border-radius:4px;padding:2px 7px;letter-spacing:.04em;text-transform:uppercase}.topbar-search.svelte-d3ct2b{flex:1;max-width:480px;margin:0 auto;position:relative}.search-icon.svelte-d3ct2b{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--on-surface-var);font-size:18px;pointer-events:none;line-height:1}.search-input.svelte-d3ct2b{width:100%;height:36px;padding:0 12px 0 36px;background:var(--surface-mid);border:1px solid var(--outline-var);border-radius:8px;color:var(--on-surface);font-family:var(--sans);font-size:13px;outline:none;transition:border-color .15s}.search-input.svelte-d3ct2b:focus{border-color:var(--primary-dim)}.topbar-actions.svelte-d3ct2b{display:flex;align-items:center;gap:4px;flex-shrink:0}.icon-btn.svelte-d3ct2b{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;border-radius:8px;color:var(--on-surface-var);cursor:pointer;transition:background .15s,color .15s}.icon-btn.svelte-d3ct2b:hover{background:var(--surface-low);color:var(--primary)}.icon-btn-active.svelte-d3ct2b{color:var(--primary)!important;background:var(--primary-container)!important}.avatar.svelte-d3ct2b{width:32px;height:32px;border-radius:50%;background:var(--primary-dim);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;margin-left:8px;border:1px solid var(--outline-var);flex-shrink:0;cursor:default}.body.svelte-d3ct2b{display:flex;flex:1;min-height:0;overflow:hidden}.sidebar.svelte-d3ct2b{width:188px;flex-shrink:0;display:flex;flex-direction:column;padding:0;background:var(--sidebar-bg);border-right:1px solid var(--sidebar-border);z-index:20}.sidebar-logo.svelte-d3ct2b{display:flex;align-items:center;gap:10px;padding:0 16px;height:48px;border-bottom:1px solid var(--sidebar-border);color:var(--sidebar-text);flex-shrink:0}.sidebar-brand-label.svelte-d3ct2b{font-family:var(--mono);font-size:12px;font-weight:700;letter-spacing:.04em;color:var(--sidebar-text, #e2e2e8);text-transform:uppercase}.sidebar-nav.svelte-d3ct2b{display:flex;flex-direction:column;gap:2px;padding:12px 8px;flex:1}.side-btn.svelte-d3ct2b{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;background:transparent;border:none;border-left:2px solid transparent;border-radius:0 6px 6px 0;color:var(--sidebar-muted);font-family:var(--sans);font-size:13px;font-weight:500;cursor:pointer;text-align:left;transition:color .12s,background .12s,border-color .12s;margin-left:-8px}.side-btn.svelte-d3ct2b:hover{color:var(--sidebar-text);background:var(--sidebar-hover)}.side-btn-active.svelte-d3ct2b{color:var(--sidebar-text)!important;background:var(--sidebar-active-bg)!important;border-left-color:var(--primary)!important}.side-badge.svelte-d3ct2b{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;border-radius:8px;background:var(--error);color:#fff;font-size:9px;font-weight:700;margin-left:2px}.sidebar-footer.svelte-d3ct2b{display:flex;align-items:center;gap:8px;padding:12px 16px;border-top:1px solid var(--sidebar-border)}.sidebar-conn-dot.svelte-d3ct2b{width:7px;height:7px;border-radius:50%;background:var(--outline);flex-shrink:0}.sidebar-conn-label.svelte-d3ct2b{font-family:var(--mono);font-size:10px;font-weight:600;color:var(--sidebar-muted);text-transform:uppercase;letter-spacing:.06em}.dot-live.svelte-d3ct2b{background:var(--green)!important;box-shadow:0 0 6px var(--green)}.sidebar-user.svelte-d3ct2b{display:flex;align-items:center;gap:6px;flex:1;min-width:0;overflow:hidden}.sidebar-avatar.svelte-d3ct2b{width:22px;height:22px;border-radius:50%;background:var(--primary);color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.sidebar-username.svelte-d3ct2b{font-size:12px;color:var(--sidebar-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}.sidebar-logout.svelte-d3ct2b{background:none;border:none;cursor:pointer;padding:3px;color:var(--sidebar-muted);display:flex;align-items:center;border-radius:4px;flex-shrink:0}.sidebar-logout.svelte-d3ct2b:hover{color:var(--error)}.login-screen.svelte-d3ct2b{min-height:100vh;display:flex;align-items:center;justify-content:center;background:var(--surface)}.login-card.svelte-d3ct2b{width:360px;background:var(--surface-low);border:1px solid var(--outline-var);border-radius:12px;padding:40px 36px 32px;display:flex;flex-direction:column;align-items:center;gap:8px;box-shadow:0 4px 24px #00000014}.login-logo.svelte-d3ct2b{margin-bottom:4px}.login-title.svelte-d3ct2b{font-family:var(--sans);font-size:22px;font-weight:700;color:var(--on-surface);margin:0}.login-sub.svelte-d3ct2b{font-size:13px;color:var(--on-surface-var);margin:0 0 8px}.login-error.svelte-d3ct2b{width:100%;background:var(--error-bg);color:var(--error);border-radius:6px;padding:8px 12px;font-size:13px;margin:0}.login-form.svelte-d3ct2b{width:100%;display:flex;flex-direction:column;gap:6px}.login-label.svelte-d3ct2b{font-size:12px;font-weight:600;color:var(--on-surface-var);margin-top:4px}.login-input.svelte-d3ct2b{width:100%;padding:9px 12px;border:1px solid var(--outline-var);border-radius:7px;background:var(--surface);color:var(--on-surface);font-size:14px;box-sizing:border-box;transition:border-color .15s}.login-input.svelte-d3ct2b:focus{outline:none;border-color:var(--primary)}.login-btn.svelte-d3ct2b{margin-top:10px;padding:10px;background:var(--primary);color:var(--on-primary);border:none;border-radius:7px;font-size:14px;font-weight:600;cursor:pointer;transition:opacity .15s}.login-btn.svelte-d3ct2b:disabled{opacity:.6;cursor:not-allowed}.login-btn.svelte-d3ct2b:not(:disabled):hover{opacity:.88}.login-hint.svelte-d3ct2b{font-size:12px;color:var(--on-surface-var);margin:8px 0 0;text-align:center}.login-hint.svelte-d3ct2b code:where(.svelte-d3ct2b){font-family:var(--mono);font-size:11px;background:var(--surface-mid);padding:1px 5px;border-radius:4px}.content.svelte-d3ct2b{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden;background:var(--surface)}.health-bar.svelte-d3ct2b{display:flex;align-items:center;gap:8px;padding:6px 24px;border-bottom:1px solid var(--outline-var);background:#fff;flex-shrink:0;flex-wrap:wrap}.health-label.svelte-d3ct2b{font-family:var(--mono);font-size:10px;font-weight:700;color:var(--outline);text-transform:uppercase;letter-spacing:.06em;margin-right:4px}.health-badge.svelte-d3ct2b{display:flex;align-items:center;gap:4px;padding:2px 8px;border-radius:4px;font-family:var(--mono);font-size:10px;font-weight:700}.health-green.svelte-d3ct2b{background:var(--green-bg);color:var(--green);border:1px solid var(--green-border)}.health-blue.svelte-d3ct2b{background:#0040e014;color:var(--primary);border:1px solid rgba(0,64,224,.2)}.health-warn.svelte-d3ct2b{background:#ba1a1a14;color:var(--error);border:1px solid rgba(186,26,26,.25)}.health-error.svelte-d3ct2b{font-family:var(--mono);font-size:10px;color:var(--error);font-weight:700}.dot.svelte-d3ct2b{width:6px;height:6px;border-radius:50%;flex-shrink:0}.dot-green.svelte-d3ct2b{background:var(--green)}.dot-blue.svelte-d3ct2b{background:var(--primary)}.dot-warn.svelte-d3ct2b{background:var(--error)}.dot-pulse.svelte-d3ct2b{animation:svelte-d3ct2b-pulse 1.4s ease-in-out infinite}@keyframes svelte-d3ct2b-pulse{0%,to{opacity:1}50%{opacity:.35}}.filter-bar.svelte-d3ct2b{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 24px;background:var(--surface-low);border-bottom:1px solid var(--outline-var);flex-shrink:0}.filter-left.svelte-d3ct2b,.filter-right.svelte-d3ct2b{display:flex;align-items:center;gap:8px}.chip.svelte-d3ct2b{display:flex;align-items:center;gap:4px;padding:4px 10px;border-radius:8px;font-family:var(--mono);font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap;border:none}.chip-primary.svelte-d3ct2b{background:var(--primary-dim);color:#fff}.chip-close.svelte-d3ct2b{background:transparent;border:none;color:#fffc;cursor:pointer;padding:0;font-size:10px;line-height:1}.chip-outline.svelte-d3ct2b{background:var(--surface);color:var(--on-surface-var);border:1px solid var(--outline-var);transition:border-color .15s}.chip-outline.svelte-d3ct2b:hover{border-color:var(--primary-dim)}.chevron.svelte-d3ct2b{transition:transform .2s}.chevron-open.svelte-d3ct2b{transform:rotate(180deg)}.service-dropdown-wrap.svelte-d3ct2b{position:relative}.dropdown.svelte-d3ct2b{position:absolute;top:calc(100% + 4px);left:0;min-width:180px;background:#fff;border:1px solid var(--outline-var);border-radius:8px;box-shadow:0 8px 24px #0000001f;z-index:100;overflow:hidden;animation:svelte-d3ct2b-dropIn .12s ease}@keyframes svelte-d3ct2b-dropIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.dropdown-item.svelte-d3ct2b{display:flex;align-items:center;gap:8px;width:100%;padding:10px 14px;background:transparent;border:none;color:var(--on-surface-var);font-family:var(--sans);font-size:13px;font-weight:500;cursor:pointer;transition:background .12s;text-align:left}.dropdown-item.svelte-d3ct2b:hover{background:var(--surface-low)}.dropdown-item-active.svelte-d3ct2b{color:var(--primary);background:var(--primary-container)}.dropdown-item-active.svelte-d3ct2b:hover{background:var(--primary-container)}.dropdown-badge.svelte-d3ct2b{margin-left:auto;background:var(--error);color:#fff;border-radius:999px;padding:1px 6px;font-size:10px;font-weight:700}.divider-v.svelte-d3ct2b{width:1px;height:28px;background:var(--outline-var);margin:0 4px}.metrics-strip.svelte-d3ct2b{display:flex;align-items:center;gap:24px}.metric-item.svelte-d3ct2b{display:flex;flex-direction:column;align-items:center}.metric-label.svelte-d3ct2b{font-family:var(--mono);font-size:9px;font-weight:700;color:var(--outline);text-transform:uppercase;letter-spacing:.05em;line-height:1}.metric-value.svelte-d3ct2b{font-family:var(--mono);font-size:14px;font-weight:700;color:var(--on-surface);line-height:1.4}.metric-value-warn.svelte-d3ct2b{color:var(--error)}.live-badge.svelte-d3ct2b{display:flex;align-items:center;gap:6px;padding:4px 10px;border:1px solid var(--outline-var);border-radius:8px;background:#fff;font-family:var(--mono);font-size:11px;font-weight:600;color:var(--on-surface);white-space:nowrap}.feed-area.svelte-d3ct2b{flex:1;min-height:0;overflow-y:auto;padding:12px 24px;background:#fff;font-family:var(--mono);font-size:12px}.log-row.svelte-d3ct2b{display:flex;align-items:baseline;gap:12px;padding:3px 8px;border-radius:4px;transition:background .1s;min-height:22px}.log-row.svelte-d3ct2b:hover{background:var(--surface-low)}.log-row-warn.svelte-d3ct2b{background:#ba1a1a0a}.log-row-fail.svelte-d3ct2b{background:#9931000a}.log-time.svelte-d3ct2b{width:80px;flex-shrink:0;color:var(--outline)}.log-label.svelte-d3ct2b{width:56px;flex-shrink:0;font-weight:700}.label-sys.svelte-d3ct2b{color:var(--primary)}.label-ok.svelte-d3ct2b{color:var(--green)}.label-warn.svelte-d3ct2b{color:var(--tertiary)}.label-info.svelte-d3ct2b{color:var(--on-surface-var)}.label-hook.svelte-d3ct2b{color:var(--error)}.label-chck.svelte-d3ct2b{color:var(--outline)}.log-msg.svelte-d3ct2b{flex:1;min-width:0;color:var(--on-surface-var);word-break:break-all;line-height:1.5}.log-msg.svelte-d3ct2b strong:where(.svelte-d3ct2b){color:var(--on-surface);font-weight:600}.copy-btn.svelte-d3ct2b{opacity:0;background:transparent;border:none;color:var(--outline);cursor:pointer;font-size:14px;padding:0 4px;transition:opacity .15s,color .15s;flex-shrink:0}.log-row.svelte-d3ct2b:hover .copy-btn:where(.svelte-d3ct2b){opacity:1}.copy-btn.svelte-d3ct2b:hover{color:var(--primary)}.log-detail.svelte-d3ct2b{display:flex;gap:8px;padding:3px 8px 3px 148px;font-size:11px;border-left:2px solid rgba(153,49,0,.3);margin-left:8px;margin-bottom:2px}.detail-index.svelte-d3ct2b{color:var(--outline);flex-shrink:0;width:24px}.detail-body.svelte-d3ct2b{color:var(--on-surface-var);flex:1;min-width:0;line-height:1.5}.detail-fix.svelte-d3ct2b{color:var(--primary)}.cursor-blink.svelte-d3ct2b{animation:svelte-d3ct2b-blink 1s step-start infinite}@keyframes svelte-d3ct2b-blink{0%,to{opacity:1}50%{opacity:0}}.section-header.svelte-d3ct2b{display:flex;align-items:baseline;gap:12px;padding:8px 8px 10px;border-bottom:1px solid var(--outline-var);margin-bottom:8px}.section-title.svelte-d3ct2b{font-family:var(--sans);font-size:14px;font-weight:700;color:var(--on-surface)}.section-meta.svelte-d3ct2b{font-size:11px;color:var(--outline);font-family:var(--mono)}.rules-toolbar.svelte-d3ct2b{display:flex;gap:8px;padding:8px;margin-bottom:4px}.rules-select.svelte-d3ct2b,.rules-input.svelte-d3ct2b,.rules-textarea.svelte-d3ct2b{padding:6px 10px;background:var(--surface-low);border:1px solid var(--outline-var);border-radius:6px;color:var(--on-surface);font-family:var(--sans);font-size:13px;outline:none;transition:border-color .15s}.rules-select.svelte-d3ct2b:focus,.rules-input.svelte-d3ct2b:focus,.rules-textarea.svelte-d3ct2b:focus{border-color:var(--primary-dim)}.rules-textarea.svelte-d3ct2b{resize:vertical;flex:1;min-width:0}.rule-form-wrap.svelte-d3ct2b{padding:0 8px 8px;border-bottom:1px solid var(--outline-var);margin-bottom:8px}.rule-form.svelte-d3ct2b{display:flex;flex-direction:column;gap:8px}.rule-form-row.svelte-d3ct2b{display:flex;gap:8px;align-items:flex-start}.add-btn.svelte-d3ct2b{padding:8px 16px;background:var(--primary);color:var(--on-primary);border:none;border-radius:6px;font-family:var(--mono);font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;transition:background .15s;align-self:flex-end}.add-btn.svelte-d3ct2b:hover:not(:disabled){background:var(--primary-dim)}.add-btn.svelte-d3ct2b:disabled{opacity:.5;cursor:not-allowed}.rule-list.svelte-d3ct2b{display:flex;flex-direction:column;gap:4px;overflow-y:auto;max-height:400px;padding:0 8px}.rule-row.svelte-d3ct2b{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--outline-var);border-radius:6px;background:var(--surface-low);font-size:12px;min-width:0;transition:background .1s}.rule-row.svelte-d3ct2b:hover{background:var(--surface-mid)}.rule-badge.svelte-d3ct2b{padding:2px 7px;background:var(--primary-container);color:var(--primary);border-radius:4px;font-family:var(--mono);font-size:10px;font-weight:700;text-transform:uppercase;flex-shrink:0}.rule-scope.svelte-d3ct2b{color:var(--outline);font-family:var(--mono);font-size:10px;font-weight:600;flex-shrink:0}.rule-content.svelte-d3ct2b{flex:1;min-width:0;color:var(--on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rule-reason.svelte-d3ct2b{color:var(--on-surface-var);font-size:11px;flex-shrink:0;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.del-btn.svelte-d3ct2b{background:transparent;border:none;color:var(--outline);cursor:pointer;font-size:12px;padding:2px 6px;border-radius:4px;flex-shrink:0;transition:background .1s,color .1s}.del-btn.svelte-d3ct2b:hover{background:var(--error-bg);color:var(--error)}.metrics-footer.svelte-d3ct2b{display:flex;align-items:center;justify-content:space-between;height:48px;padding:0 24px;border-top:1px solid var(--outline-var);background:var(--surface);flex-shrink:0}.footer-left.svelte-d3ct2b,.footer-right.svelte-d3ct2b{display:flex;align-items:center;gap:24px}.footer-metric.svelte-d3ct2b{display:flex;align-items:center;gap:6px}.footer-label.svelte-d3ct2b{font-family:var(--mono);font-size:10px;font-weight:700;color:var(--outline);text-transform:uppercase;letter-spacing:.04em}.footer-val.svelte-d3ct2b{font-family:var(--mono);font-size:14px;font-weight:700;color:var(--on-surface)}.footer-val-error.svelte-d3ct2b{color:var(--error)}.footer-unit.svelte-d3ct2b{font-family:var(--mono);font-size:9px;color:var(--outline);text-transform:uppercase}.storage-bar-wrap.svelte-d3ct2b{display:flex;align-items:center;gap:8px}.storage-bar.svelte-d3ct2b{width:96px;height:6px;background:var(--surface-mid);border-radius:999px;overflow:hidden}.storage-fill.svelte-d3ct2b{height:100%;background:var(--primary-dim);border-radius:999px;transition:width .6s ease}.cli-btn.svelte-d3ct2b{display:flex;align-items:center;gap:6px;padding:5px 12px;background:var(--surface-high);border:none;border-radius:4px;color:var(--on-surface);font-family:var(--mono);font-size:11px;font-weight:700;cursor:pointer;transition:background .15s}.cli-btn.svelte-d3ct2b:hover{background:var(--outline-var)}:root[data-theme=dark]{--primary: #4f9eff;--primary-dim: #3b82f6;--primary-container: #172036;--on-primary: #001b3e;--surface: #111318;--surface-low: #0c0e12;--surface-mid: #1e2128;--surface-high: #252930;--surface-highest: #2e3138;--on-surface: #e6edf3;--on-surface-var: #8b949e;--outline: #484f58;--outline-var: #30363d;--error: #f85149;--error-bg: rgba(248,81,73,.15);--tertiary: #f0883e;--green: #3fb950;--green-bg: rgba(63,185,80,.12);--green-border: rgba(63,185,80,.3);--sidebar-bg: #0d1117;--sidebar-border: #21262d;--sidebar-text: #e6edf3;--sidebar-muted: #6e7681;--sidebar-hover: rgba(255,255,255,.04);--sidebar-active-bg: rgba(79,158,255,.1)}html[data-theme=dark] .topbar.svelte-d3ct2b{background:#161b22;border-bottom-color:var(--outline-var)}html[data-theme=dark] .health-bar.svelte-d3ct2b{background:#1a1c20;border-bottom-color:var(--outline-var)}html[data-theme=dark] .filter-bar.svelte-d3ct2b{background:#111318;border-bottom-color:var(--outline-var)}html[data-theme=dark] .feed-area.svelte-d3ct2b{background:#0c0e12}html[data-theme=dark] .metrics-footer.svelte-d3ct2b{background:#111318;border-top-color:var(--outline-var)}html[data-theme=dark] .search-input.svelte-d3ct2b{background:#1e2024;border-color:var(--outline-var);color:var(--on-surface)}html[data-theme=dark] .dropdown.svelte-d3ct2b{background:#1e2024;border-color:var(--outline-var);box-shadow:0 8px 24px #00000073}html[data-theme=dark] .dropdown-item.svelte-d3ct2b:hover{background:#282a2e}html[data-theme=dark] .dropdown-item-active.svelte-d3ct2b{background:var(--primary-container);color:var(--primary)}html[data-theme=dark] .chip-outline.svelte-d3ct2b,html[data-theme=dark] .live-badge.svelte-d3ct2b{background:#1e2024}html[data-theme=dark] .rule-row.svelte-d3ct2b{background:#1e2024;border-color:var(--outline-var)}html[data-theme=dark] .rule-row.svelte-d3ct2b:hover{background:#282a2e}html[data-theme=dark] .rules-select.svelte-d3ct2b,html[data-theme=dark] .rules-input.svelte-d3ct2b,html[data-theme=dark] .rules-textarea.svelte-d3ct2b{background:#1e2024;border-color:var(--outline-var);color:var(--on-surface)}html[data-theme=dark] .log-row.svelte-d3ct2b:hover{background:#1e2024}html[data-theme=dark] .log-row-warn.svelte-d3ct2b{background:#ffb4ab0d}html[data-theme=dark] .log-row-fail.svelte-d3ct2b{background:#ffba200a}html[data-theme=dark] .section-header.svelte-d3ct2b{border-bottom-color:var(--outline-var)}html[data-theme=dark] .storage-bar.svelte-d3ct2b{background:#282a2e}html[data-theme=dark] .badge-warn.svelte-d3ct2b{background:#422006;color:#fbbf24}html[data-theme=dark] .log-detail.svelte-d3ct2b{border-left-color:#ffba204d}html[data-theme=dark] .history-entry.svelte-d3ct2b{border-color:var(--outline-var);background:#1a1c20}html[data-theme=dark] .history-header.svelte-d3ct2b{background:#1e2024;border-bottom-color:var(--outline-var)}html[data-theme=dark] .history-violation.svelte-d3ct2b{border-bottom-color:var(--outline-var)}html[data-theme=dark] .arch-node-panel.svelte-d3ct2b{background:#1a1c20;border-color:var(--outline-var)}html[data-theme=dark] .arch-node-panel-path.svelte-d3ct2b{background:#1e2024}html[data-theme=dark] .arch-rule-row.svelte-d3ct2b{background:#1a1c20;border-color:var(--outline-var)}html[data-theme=dark] .arch-svg.svelte-d3ct2b{background:#0c0e12;border-color:var(--outline-var)}html[data-theme=dark] .footer-actions.svelte-d3ct2b .action-btn:where(.svelte-d3ct2b){background:#1e2024}html[data-theme=dark] .cli-btn.svelte-d3ct2b{background:#1e2024}html[data-theme=dark] .modal-status-row.svelte-d3ct2b{border-bottom-color:var(--outline-var)}html[data-theme=dark] .modal-input.svelte-d3ct2b{background:#1e2024;border-color:var(--outline-var);color:var(--on-surface)}html[data-theme=dark] .modal-btn.svelte-d3ct2b{background:#1e2024;border-color:var(--outline-var);color:var(--on-surface-var)}html[data-theme=dark] .modal-btn.svelte-d3ct2b:hover:not(:disabled){background:#282a2e}html[data-theme=dark] .rule-form-wrap.svelte-d3ct2b{border-bottom-color:var(--outline-var)}@media (max-width: 768px){.sidebar.svelte-d3ct2b{width:48px}.sidebar-brand-label.svelte-d3ct2b{display:none}.side-btn.svelte-d3ct2b span:where(.svelte-d3ct2b){display:none}.sidebar-conn-label.svelte-d3ct2b,.metrics-strip.svelte-d3ct2b{display:none}.filter-bar.svelte-d3ct2b,.feed-area.svelte-d3ct2b{padding:8px 12px}.metrics-footer.svelte-d3ct2b{padding:0 12px;gap:12px}.footer-metric.svelte-d3ct2b:nth-child(n+2){display:none}}.footer-actions.svelte-d3ct2b{display:flex;gap:6px;align-items:center;margin-right:12px}.action-btn.svelte-d3ct2b{font-size:11px;font-family:var(--mono);padding:4px 10px;border-radius:6px;border:1px solid var(--outline-var);background:var(--surface-low);color:var(--on-surface-var);cursor:pointer;transition:background .15s,border-color .15s}.action-btn.svelte-d3ct2b:hover:not(:disabled){background:var(--primary-container);border-color:var(--primary);color:var(--primary)}.action-btn.svelte-d3ct2b:disabled{opacity:.5;cursor:not-allowed}.action-btn-warn.svelte-d3ct2b:hover:not(:disabled){background:#fff3e0;border-color:#f59e0b;color:#b45309}.modal-backdrop.svelte-d3ct2b{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:200}.modal.svelte-d3ct2b{background:var(--surface);border:1px solid var(--outline-var);border-radius:12px;width:480px;max-width:calc(100vw - 32px);box-shadow:0 8px 32px #0000002e;overflow:hidden}.modal-header.svelte-d3ct2b{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--outline-var)}.modal-title.svelte-d3ct2b{font-size:14px;font-weight:600;color:var(--on-surface)}.modal-close.svelte-d3ct2b{background:none;border:none;cursor:pointer;color:var(--outline);font-size:16px;line-height:1}.modal-section.svelte-d3ct2b{padding:16px 20px;border-bottom:1px solid var(--outline-var)}.modal-section.svelte-d3ct2b:last-child{border-bottom:none}.modal-section-title.svelte-d3ct2b{font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--outline);text-transform:uppercase;margin-bottom:12px}.modal-row.svelte-d3ct2b{display:grid;grid-template-columns:100px 1fr;gap:8px;align-items:center;margin-bottom:10px}.modal-label.svelte-d3ct2b{font-size:12px;color:var(--on-surface-var)}.modal-input.svelte-d3ct2b{font-size:12px;font-family:var(--mono);padding:6px 10px;border:1px solid var(--outline-var);border-radius:6px;background:var(--surface-low);color:var(--on-surface);outline:none;width:100%}.modal-input.svelte-d3ct2b:focus{border-color:var(--primary)}.modal-row-actions.svelte-d3ct2b{display:flex;gap:8px}.modal-btn.svelte-d3ct2b{font-size:12px;padding:6px 14px;border:1px solid var(--outline-var);border-radius:6px;background:var(--surface-low);color:var(--on-surface-var);cursor:pointer}.modal-btn.svelte-d3ct2b:hover:not(:disabled){background:var(--surface-mid)}.modal-btn.svelte-d3ct2b:disabled{opacity:.5;cursor:not-allowed}.modal-btn-primary.svelte-d3ct2b{background:var(--primary);color:var(--on-primary);border-color:var(--primary)}.modal-btn-primary.svelte-d3ct2b:hover:not(:disabled){background:var(--primary-dim)}.modal-msg.svelte-d3ct2b{font-size:12px;margin-top:8px;padding:6px 10px;border-radius:6px}.modal-msg-ok.svelte-d3ct2b{background:var(--green-bg);color:var(--green);border:1px solid var(--green-border)}.modal-msg-err.svelte-d3ct2b{background:var(--error-bg);color:var(--error);border:1px solid var(--error)}.modal-status-row.svelte-d3ct2b{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--surface-mid)}.modal-status-row.svelte-d3ct2b:last-child{border-bottom:none}.modal-status-label.svelte-d3ct2b{font-size:11px;color:var(--outline)}.modal-status-val.svelte-d3ct2b{font-size:11px;font-family:var(--mono);color:var(--on-surface)}html[data-theme=dark] .modal.svelte-d3ct2b{background:var(--surface);border-color:var(--outline-var)}.arch-graph-wrap.svelte-d3ct2b{display:flex;flex-direction:column;gap:16px;padding:16px}.arch-svg.svelte-d3ct2b{display:block;border:1px solid var(--outline-var);border-radius:8px;background:var(--surface-low);width:100%;max-width:640px}.arch-node-rect.svelte-d3ct2b{fill:var(--surface-mid);stroke:var(--outline-var);stroke-width:1.5}.arch-node-domain.arch-node-rect.svelte-d3ct2b{fill:#eff6ff;stroke:#3b82f6}.arch-node-application.arch-node-rect.svelte-d3ct2b{fill:#f0fdf4;stroke:#22c55e}.arch-node-infrastructure.arch-node-rect.svelte-d3ct2b{fill:#fff7ed;stroke:#f97316}.arch-node-api.arch-node-rect.svelte-d3ct2b{fill:#faf5ff;stroke:#a855f7}.arch-node-shared.arch-node-rect.svelte-d3ct2b{fill:#f8fafc;stroke:#94a3b8}.arch-node-controllers.arch-node-rect.svelte-d3ct2b{fill:#eff6ff;stroke:#3b82f6}.arch-node-handlers.arch-node-rect.svelte-d3ct2b{fill:#faf5ff;stroke:#a855f7}.arch-node-services.arch-node-rect.svelte-d3ct2b{fill:#f0fdf4;stroke:#22c55e}.arch-node-repositories.arch-node-rect.svelte-d3ct2b{fill:#fff7ed;stroke:#f97316}.arch-node-modules.arch-node-rect.svelte-d3ct2b{fill:#eef2ff;stroke:#6366f1}.arch-node-common.arch-node-rect.svelte-d3ct2b{fill:#f8fafc;stroke:#94a3b8}.arch-node-models.arch-node-rect.svelte-d3ct2b{fill:#f0fdfa;stroke:#14b8a6}.arch-node-views.arch-node-rect.svelte-d3ct2b{fill:#fefce8;stroke:#eab308}.arch-node-pages.arch-node-rect.svelte-d3ct2b,.arch-node-screens.arch-node-rect.svelte-d3ct2b,.arch-node-routes.arch-node-rect.svelte-d3ct2b{fill:#eff6ff;stroke:#3b82f6}.arch-node-components.arch-node-rect.svelte-d3ct2b{fill:#fdf2f8;stroke:#ec4899}.arch-node-hooks.arch-node-rect.svelte-d3ct2b{fill:#f5f3ff;stroke:#8b5cf6}.arch-node-composables.arch-node-rect.svelte-d3ct2b{fill:#ecfeff;stroke:#06b6d4}.arch-node-store.arch-node-rect.svelte-d3ct2b,.arch-node-stores.arch-node-rect.svelte-d3ct2b{fill:#fffbeb;stroke:#f59e0b}.arch-node-lib.arch-node-rect.svelte-d3ct2b{fill:#f0fdfa;stroke:#14b8a6}.arch-node-utils.arch-node-rect.svelte-d3ct2b{fill:#f8fafc;stroke:#94a3b8}.arch-node-guards.arch-node-rect.svelte-d3ct2b{fill:#fff1f2;stroke:#f43f5e}.arch-node-server.arch-node-rect.svelte-d3ct2b{fill:#fff7ed;stroke:#f97316}.arch-node-ports.arch-node-rect.svelte-d3ct2b{fill:#ecfeff;stroke:#06b6d4}.arch-node-adapters.arch-node-rect.svelte-d3ct2b{fill:#f0fdfa;stroke:#14b8a6}html[data-theme=dark] .arch-node-domain.arch-node-rect.svelte-d3ct2b{fill:#1e3a5f;stroke:#3b82f6}html[data-theme=dark] .arch-node-application.arch-node-rect.svelte-d3ct2b{fill:#14352a;stroke:#22c55e}html[data-theme=dark] .arch-node-infrastructure.arch-node-rect.svelte-d3ct2b{fill:#3d2006;stroke:#f97316}html[data-theme=dark] .arch-node-api.arch-node-rect.svelte-d3ct2b{fill:#2e1a47;stroke:#a855f7}html[data-theme=dark] .arch-node-shared.arch-node-rect.svelte-d3ct2b{fill:#1e2535;stroke:#94a3b8}html[data-theme=dark] .arch-node-controllers.arch-node-rect.svelte-d3ct2b{fill:#1e3a5f;stroke:#3b82f6}html[data-theme=dark] .arch-node-handlers.arch-node-rect.svelte-d3ct2b{fill:#2e1a47;stroke:#a855f7}html[data-theme=dark] .arch-node-services.arch-node-rect.svelte-d3ct2b{fill:#14352a;stroke:#22c55e}html[data-theme=dark] .arch-node-repositories.arch-node-rect.svelte-d3ct2b{fill:#3d2006;stroke:#f97316}html[data-theme=dark] .arch-node-modules.arch-node-rect.svelte-d3ct2b{fill:#1e1b4b;stroke:#6366f1}html[data-theme=dark] .arch-node-common.arch-node-rect.svelte-d3ct2b{fill:#1e2535;stroke:#94a3b8}html[data-theme=dark] .arch-node-models.arch-node-rect.svelte-d3ct2b{fill:#0f2922;stroke:#14b8a6}html[data-theme=dark] .arch-node-views.arch-node-rect.svelte-d3ct2b{fill:#29240a;stroke:#eab308}html[data-theme=dark] .arch-node-pages.arch-node-rect.svelte-d3ct2b,html[data-theme=dark] .arch-node-screens.arch-node-rect.svelte-d3ct2b,html[data-theme=dark] .arch-node-routes.arch-node-rect.svelte-d3ct2b{fill:#1e3a5f;stroke:#3b82f6}html[data-theme=dark] .arch-node-components.arch-node-rect.svelte-d3ct2b{fill:#3d0e2e;stroke:#ec4899}html[data-theme=dark] .arch-node-hooks.arch-node-rect.svelte-d3ct2b{fill:#1e1547;stroke:#8b5cf6}html[data-theme=dark] .arch-node-composables.arch-node-rect.svelte-d3ct2b{fill:#042934;stroke:#06b6d4}html[data-theme=dark] .arch-node-store.arch-node-rect.svelte-d3ct2b,html[data-theme=dark] .arch-node-stores.arch-node-rect.svelte-d3ct2b{fill:#2d200a;stroke:#f59e0b}html[data-theme=dark] .arch-node-lib.arch-node-rect.svelte-d3ct2b{fill:#0f2922;stroke:#14b8a6}html[data-theme=dark] .arch-node-utils.arch-node-rect.svelte-d3ct2b{fill:#1e2535;stroke:#94a3b8}html[data-theme=dark] .arch-node-guards.arch-node-rect.svelte-d3ct2b{fill:#3d0a14;stroke:#f43f5e}html[data-theme=dark] .arch-node-server.arch-node-rect.svelte-d3ct2b{fill:#3d2006;stroke:#f97316}html[data-theme=dark] .arch-node-ports.arch-node-rect.svelte-d3ct2b{fill:#042934;stroke:#06b6d4}html[data-theme=dark] .arch-node-adapters.arch-node-rect.svelte-d3ct2b{fill:#0f2922;stroke:#14b8a6}.arch-node-label.svelte-d3ct2b{font-family:var(--mono);font-size:11px;font-weight:600;fill:var(--on-surface)}.arch-node-desc.svelte-d3ct2b{font-family:var(--sans);font-size:9px;fill:var(--outline)}.arch-node-clickable.svelte-d3ct2b{cursor:pointer}.arch-node-clickable.svelte-d3ct2b:hover .arch-node-rect:where(.svelte-d3ct2b){filter:brightness(.95)}html[data-theme=dark] .arch-node-clickable.svelte-d3ct2b:hover .arch-node-rect:where(.svelte-d3ct2b){filter:brightness(1.15)}.arch-node-panel.svelte-d3ct2b{border:1px solid var(--outline-var);border-radius:8px;background:var(--surface-low);padding:12px 16px;max-width:640px;display:flex;flex-direction:column;gap:10px}.arch-node-panel-header.svelte-d3ct2b{display:flex;align-items:center;gap:10px}.arch-node-panel-name.svelte-d3ct2b{font-family:var(--mono);font-weight:700;font-size:13px;color:var(--on-surface)}.arch-node-panel-meta.svelte-d3ct2b{font-size:12px;color:var(--outline);flex:1}.arch-node-panel-close.svelte-d3ct2b{background:none;border:none;cursor:pointer;color:var(--outline);font-size:14px;padding:0;line-height:1}.arch-node-panel-close.svelte-d3ct2b:hover{color:var(--on-surface)}.arch-node-panel-paths.svelte-d3ct2b{display:flex;flex-direction:column;gap:4px}.arch-node-panel-section.svelte-d3ct2b{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--outline);margin-bottom:2px}.arch-node-panel-path.svelte-d3ct2b{font-family:var(--mono);font-size:11px;color:var(--cyan, #22d3ee);background:var(--surface-mid);padding:3px 8px;border-radius:4px}.arch-node-panel-rule.svelte-d3ct2b{display:flex;align-items:center;gap:8px;font-size:12px}.arch-legend.svelte-d3ct2b{display:flex;gap:16px;align-items:center;font-size:11px;color:var(--outline)}.legend-item.svelte-d3ct2b{display:flex;align-items:center;gap:6px}.arch-rule-list.svelte-d3ct2b{display:flex;flex-direction:column;gap:4px;max-width:640px}.arch-rule-row.svelte-d3ct2b{display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--surface-low);border-radius:4px;border:1px solid var(--outline-var)}.tab-badge.svelte-d3ct2b{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:16px;padding:0 5px;border-radius:8px;background:var(--error);color:#fff;font-size:10px;font-weight:700;margin-left:4px;vertical-align:middle}.history-list.svelte-d3ct2b{display:flex;flex-direction:column;gap:8px;max-width:760px}.history-entry.svelte-d3ct2b{border:1px solid var(--outline-var);border-radius:6px;background:var(--surface-low);overflow:hidden}.history-header.svelte-d3ct2b{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid var(--outline-var);background:var(--surface-mid)}.history-file.svelte-d3ct2b{font-family:var(--mono);font-size:12px;font-weight:600;color:var(--cyan, #22d3ee)}.history-time.svelte-d3ct2b{font-size:11px;color:var(--outline)}.history-violation.svelte-d3ct2b{display:flex;align-items:center;gap:8px;padding:6px 12px;border-bottom:1px solid var(--outline-var);flex-wrap:wrap}.history-violation.svelte-d3ct2b:last-child{border-bottom:none}.history-badge.svelte-d3ct2b{flex-shrink:0;font-family:var(--mono);font-size:10px;font-weight:700;padding:2px 6px;border-radius:3px;background:var(--error-bg);color:var(--error);white-space:nowrap}.history-rule.svelte-d3ct2b{font-size:12px;font-weight:600;color:var(--on-surface)}.history-issue.svelte-d3ct2b{font-size:12px;color:var(--outline)}.history-entry-resolved.svelte-d3ct2b{opacity:.5}.history-entry-resolved.svelte-d3ct2b .history-file:where(.svelte-d3ct2b){text-decoration:line-through}.history-resolved-badge.svelte-d3ct2b{font-family:var(--mono);font-size:10px;font-weight:700;color:var(--green);letter-spacing:.04em}.history-resolve-btn.svelte-d3ct2b{margin-left:auto;padding:2px 8px;font-family:var(--mono);font-size:10px;font-weight:700;background:var(--surface-mid);border:1px solid var(--outline-var);border-radius:4px;color:var(--outline);cursor:pointer;transition:color .12s,border-color .12s,background .12s;white-space:nowrap}.history-resolve-btn.svelte-d3ct2b:hover{color:var(--green);border-color:var(--green);background:var(--green-bg)}.history-resolve-btn-active.svelte-d3ct2b{color:var(--green)!important;border-color:var(--green-border)!important;background:var(--green-bg)!important}.history-toggle-label.svelte-d3ct2b{display:flex;align-items:center;gap:5px;font-family:var(--mono);font-size:10px;color:var(--outline);cursor:pointer;-webkit-user-select:none;user-select:none}.arch-rule-badge.svelte-d3ct2b{font-size:10px;font-family:var(--mono);font-weight:700;padding:2px 6px;border-radius:3px}.badge-block.svelte-d3ct2b{background:var(--error-bg);color:var(--error)}.badge-warn.svelte-d3ct2b{background:#fef3c7;color:#92400e}.badge-allow.svelte-d3ct2b{background:var(--green-bg);color:var(--green)}.arch-rule-layers.svelte-d3ct2b{font-family:var(--mono);font-size:11px;color:var(--on-surface);white-space:nowrap}.arch-rule-name.svelte-d3ct2b{font-size:11px;color:var(--outline);flex:1}.arch-edit-btn.svelte-d3ct2b{padding:4px 10px;font-family:var(--mono);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;background:var(--surface-mid);border:1px solid var(--outline-var);border-radius:4px;color:var(--on-surface-var);cursor:pointer;transition:background .15s,color .15s}.arch-edit-btn.svelte-d3ct2b:hover{background:var(--primary-container);color:var(--primary);border-color:var(--primary-dim)}.arch-edit-btn-active.svelte-d3ct2b{background:var(--primary-container)!important;color:var(--primary)!important;border-color:var(--primary-dim)!important}.arch-reset-btn.svelte-d3ct2b{color:var(--tertiary)!important;border-color:var(--tertiary)!important}.arch-reset-btn.svelte-d3ct2b:hover{background:#fff3eb!important}html[data-theme=dark] .arch-reset-btn.svelte-d3ct2b:hover{background:#3d1a00!important}.arch-rule-del.svelte-d3ct2b{background:none;border:none;color:var(--outline);cursor:pointer;font-size:12px;padding:0 4px;line-height:1;transition:color .15s}.arch-rule-del.svelte-d3ct2b:hover{color:var(--error)}.arch-add-form.svelte-d3ct2b{display:flex;flex-direction:column;gap:8px;background:var(--surface-low);border:1px solid var(--outline-var);border-radius:6px;padding:12px;max-width:640px}.arch-add-form-title.svelte-d3ct2b{font-family:var(--mono);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--outline)}.arch-add-row.svelte-d3ct2b{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end}.arch-add-input.svelte-d3ct2b{height:30px;padding:0 8px;background:var(--surface);border:1px solid var(--outline-var);border-radius:4px;color:var(--on-surface);font-family:var(--mono);font-size:11px;outline:none;min-width:80px}.arch-add-input.svelte-d3ct2b:focus{border-color:var(--primary-dim)}.arch-add-select.svelte-d3ct2b{height:30px;padding:0 6px;background:var(--surface);border:1px solid var(--outline-var);border-radius:4px;color:var(--on-surface);font-family:var(--mono);font-size:11px;outline:none}.arch-add-submit.svelte-d3ct2b{height:30px;padding:0 12px;background:var(--primary);border:none;border-radius:4px;color:#fff;font-family:var(--mono);font-size:11px;font-weight:700;cursor:pointer;transition:background .15s}.arch-add-submit.svelte-d3ct2b:hover{background:var(--primary-dim)}.arch-add-submit.svelte-d3ct2b:disabled{opacity:.5;cursor:default}.arch-add-label.svelte-d3ct2b{font-size:10px;color:var(--outline);font-family:var(--mono)}.arch-add-field.svelte-d3ct2b{display:flex;flex-direction:column;gap:2px}.an-summary.svelte-d3ct2b{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px}.an-card.svelte-d3ct2b{display:flex;flex-direction:column;align-items:center;padding:12px 20px;background:var(--surface-low);border:1px solid var(--outline-var);border-radius:8px;min-width:100px}.an-card-val.svelte-d3ct2b{font-family:var(--mono);font-size:24px;font-weight:700;color:var(--on-surface);line-height:1}.an-card-label.svelte-d3ct2b{font-family:var(--mono);font-size:10px;color:var(--outline);text-transform:uppercase;letter-spacing:.06em;margin-top:4px}.an-card-warn.svelte-d3ct2b .an-card-val:where(.svelte-d3ct2b){color:var(--error)}.an-card-green.svelte-d3ct2b .an-card-val:where(.svelte-d3ct2b){color:var(--green)}.an-tabs.svelte-d3ct2b{display:flex;gap:2px;margin-bottom:14px;border-bottom:1px solid var(--outline-var)}.an-tab.svelte-d3ct2b{padding:6px 14px;background:transparent;border:none;border-bottom:2px solid transparent;color:var(--outline);font-family:var(--mono);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;transition:color .12s,border-color .12s;margin-bottom:-1px}.an-tab.svelte-d3ct2b:hover{color:var(--on-surface)}.an-tab-active.svelte-d3ct2b{color:var(--primary)!important;border-bottom-color:var(--primary)!important}.an-chart-wrap.svelte-d3ct2b{background:var(--surface-low);border:1px solid var(--outline-var);border-radius:8px;padding:16px;max-width:760px}.an-chart-svg.svelte-d3ct2b{display:block;width:100%;height:160px}.an-chart-legend.svelte-d3ct2b{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:11px;color:var(--outline)}.an-legend-dot.svelte-d3ct2b{width:10px;height:10px;border-radius:50%;display:inline-block}.an-heat-table.svelte-d3ct2b,.an-rule-table.svelte-d3ct2b{display:flex;flex-direction:column;gap:3px;max-width:760px}.an-heat-header.svelte-d3ct2b{display:grid;grid-template-columns:2fr 2fr 80px 100px;gap:8px;padding:4px 10px;font-family:var(--mono);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--outline)}.an-rule-table.svelte-d3ct2b .an-heat-header:where(.svelte-d3ct2b){grid-template-columns:2fr 1.5fr 2fr 100px}.an-heat-row.svelte-d3ct2b{display:grid;grid-template-columns:2fr 2fr 80px 100px;gap:8px;align-items:center;padding:6px 10px;background:var(--surface-low);border-radius:4px;border:1px solid var(--outline-var)}.an-rule-table.svelte-d3ct2b .an-heat-row:where(.svelte-d3ct2b){grid-template-columns:2fr 1.5fr 2fr 100px}.an-heat-file.svelte-d3ct2b{font-family:var(--mono);font-size:11px;color:var(--on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.an-heat-bar-wrap.svelte-d3ct2b{display:flex;align-items:center;gap:6px}.an-heat-bar.svelte-d3ct2b{height:8px;border-radius:4px;min-width:2px;flex-shrink:0}.an-heat-count.svelte-d3ct2b{font-family:var(--mono);font-size:11px;font-weight:700;color:var(--on-surface);white-space:nowrap}.an-heat-resolved.svelte-d3ct2b{font-family:var(--mono);font-size:11px;color:var(--green)}.an-heat-time.svelte-d3ct2b{font-size:11px;color:var(--outline);white-space:nowrap}.an-rule-name.svelte-d3ct2b{font-family:var(--mono);font-size:11px;color:var(--on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.an-rule-layers.svelte-d3ct2b{font-family:var(--mono);font-size:10px;color:var(--outline)}.an-row-dead.svelte-d3ct2b{opacity:.45}.an-dead-count.svelte-d3ct2b{color:var(--outline)!important;font-weight:400!important}.profile-panel.svelte-d3ct2b{background:var(--surface-low);border:1px solid var(--outline-var);border-radius:6px;padding:12px;display:flex;flex-direction:column;gap:10px;max-width:760px}.profile-save-row.svelte-d3ct2b{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.profile-name-input.svelte-d3ct2b{height:30px;padding:0 8px;background:var(--surface);border:1px solid var(--outline-var);border-radius:4px;color:var(--on-surface);font-family:var(--mono);font-size:11px;outline:none;min-width:160px;flex:1}.profile-name-input.svelte-d3ct2b:focus{border-color:var(--primary-dim)}.profile-scope-label.svelte-d3ct2b{display:flex;align-items:center;gap:4px;font-family:var(--mono);font-size:10px;color:var(--outline);white-space:nowrap;cursor:pointer}.profile-msg.svelte-d3ct2b{font-family:var(--mono);font-size:10px;color:var(--green)}.profile-empty.svelte-d3ct2b{font-size:12px;color:var(--outline);font-style:italic}.profile-list.svelte-d3ct2b{display:flex;flex-direction:column;gap:4px}.profile-row.svelte-d3ct2b{display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--surface-mid);border:1px solid var(--outline-var);border-radius:4px}.profile-name.svelte-d3ct2b{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--on-surface)}.profile-meta.svelte-d3ct2b{font-size:11px;color:var(--outline);flex:1}
@@ -7,8 +7,8 @@
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
9
  <link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
10
- <script type="module" crossorigin src="/assets/index-B5TFTqLb.js"></script>
11
- <link rel="stylesheet" crossorigin href="/assets/index-Cfkgvz08.css">
10
+ <script type="module" crossorigin src="/assets/index-DqbNcMwV.js"></script>
11
+ <link rel="stylesheet" crossorigin href="/assets/index-y7eHWJtq.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="app"></div>
@@ -6,23 +6,29 @@ import {
6
6
  embed,
7
7
  inferProjectArchitectures,
8
8
  startWatch
9
- } from "./chunk-KNZ3JNHE.js";
9
+ } from "./chunk-23GUWJ6F.js";
10
10
  import {
11
11
  getChatProviderLabel
12
12
  } from "./chunk-PQBWHAZN.js";
13
13
  import {
14
14
  Config,
15
15
  closePool,
16
+ countUsers,
17
+ createUser,
16
18
  deleteArchProfile,
17
19
  deleteMemory,
20
+ deleteUser,
18
21
  getArchProfile,
19
22
  getPool,
23
+ getUserByEmail,
20
24
  listArchProfiles,
21
25
  listMemories,
26
+ listUsers,
22
27
  saveArchProfile,
23
28
  saveMemory,
29
+ updateLastLogin,
24
30
  updateMemory
25
- } from "./chunk-4ZSVQMI7.js";
31
+ } from "./chunk-GIPKVQSA.js";
26
32
  import "./chunk-ZZBQEXEO.js";
27
33
 
28
34
  // src/dashboard-server.ts
@@ -33,6 +39,46 @@ import { createServer } from "http";
33
39
  import { basename, dirname, extname, join, normalize, relative, resolve } from "path";
34
40
  import { fileURLToPath } from "url";
35
41
  import chalk from "chalk";
42
+
43
+ // src/auth.ts
44
+ import jwt from "jsonwebtoken";
45
+ import bcrypt from "bcryptjs";
46
+ var BCRYPT_ROUNDS = 12;
47
+ var JWT_EXPIRY = "30d";
48
+ function getJwtSecret() {
49
+ const secret = process.env.MC_JWT_SECRET;
50
+ if (!secret) throw new Error("MC_JWT_SECRET not set. Add it to .memory-core.env.");
51
+ return secret;
52
+ }
53
+ function signToken(payload) {
54
+ return jwt.sign(payload, getJwtSecret(), { expiresIn: JWT_EXPIRY });
55
+ }
56
+ function verifyToken(token) {
57
+ return jwt.verify(token, getJwtSecret());
58
+ }
59
+ async function hashPassword(password) {
60
+ return bcrypt.hash(password, BCRYPT_ROUNDS);
61
+ }
62
+ async function comparePassword(password, hash) {
63
+ return bcrypt.compare(password, hash);
64
+ }
65
+ function extractBearerToken(authHeader) {
66
+ if (!authHeader?.startsWith("Bearer ")) return null;
67
+ return authHeader.slice(7).trim() || null;
68
+ }
69
+
70
+ // src/dashboard-server.ts
71
+ var authEnabled = false;
72
+ function requireAuth(req) {
73
+ if (!authEnabled) return { userId: 0, email: "local", username: "local", role: "admin", teamName: null };
74
+ const token = extractBearerToken(req.headers["authorization"]);
75
+ if (!token) return null;
76
+ try {
77
+ return verifyToken(token);
78
+ } catch {
79
+ return null;
80
+ }
81
+ }
36
82
  var clients = /* @__PURE__ */ new Set();
37
83
  var fileStatuses = /* @__PURE__ */ new Map();
38
84
  var recentEvents = [];
@@ -969,6 +1015,136 @@ async function handleApi(req, res, url) {
969
1015
  }
970
1016
  return;
971
1017
  }
1018
+ if (req.method === "POST" && url.pathname === "/api/auth/setup") {
1019
+ if (!authEnabled) {
1020
+ sendJson(res, 403, { error: "Auth not enabled. Start dashboard with --auth flag." });
1021
+ return;
1022
+ }
1023
+ const count = await countUsers();
1024
+ if (count > 0) {
1025
+ sendJson(res, 409, { error: "Admin already exists. Use /api/auth/login." });
1026
+ return;
1027
+ }
1028
+ const body = await readBody(req);
1029
+ const email = typeof body.email === "string" ? body.email.trim() : "";
1030
+ const username = typeof body.username === "string" ? body.username.trim() : "";
1031
+ const password = typeof body.password === "string" ? body.password : "";
1032
+ const teamName = typeof body.teamName === "string" ? body.teamName.trim() : void 0;
1033
+ if (!email || !username || password.length < 8) {
1034
+ sendJson(res, 400, { error: "email, username, and password (min 8 chars) required" });
1035
+ return;
1036
+ }
1037
+ const passwordHash = await hashPassword(password);
1038
+ const user = await createUser({ email, username, passwordHash, role: "admin", teamName });
1039
+ await updateLastLogin(user.id);
1040
+ const token = signToken({ userId: user.id, email: user.email, username: user.username, role: user.role, teamName: user.team_name });
1041
+ sendJson(res, 201, { token, user: { id: user.id, email: user.email, username: user.username, role: user.role, teamName: user.team_name } });
1042
+ return;
1043
+ }
1044
+ if (req.method === "POST" && url.pathname === "/api/auth/login") {
1045
+ if (!authEnabled) {
1046
+ sendJson(res, 403, { error: "Auth not enabled." });
1047
+ return;
1048
+ }
1049
+ const body = await readBody(req);
1050
+ const email = typeof body.email === "string" ? body.email.trim() : "";
1051
+ const password = typeof body.password === "string" ? body.password : "";
1052
+ if (!email || !password) {
1053
+ sendJson(res, 400, { error: "email and password required" });
1054
+ return;
1055
+ }
1056
+ const user = await getUserByEmail(email);
1057
+ if (!user) {
1058
+ sendJson(res, 401, { error: "Invalid credentials" });
1059
+ return;
1060
+ }
1061
+ const ok = await comparePassword(password, user.password_hash);
1062
+ if (!ok) {
1063
+ sendJson(res, 401, { error: "Invalid credentials" });
1064
+ return;
1065
+ }
1066
+ await updateLastLogin(user.id);
1067
+ const token = signToken({ userId: user.id, email: user.email, username: user.username, role: user.role, teamName: user.team_name });
1068
+ sendJson(res, 200, { token, user: { id: user.id, email: user.email, username: user.username, role: user.role, teamName: user.team_name } });
1069
+ return;
1070
+ }
1071
+ if (req.method === "GET" && url.pathname === "/api/auth/me") {
1072
+ const payload = requireAuth(req);
1073
+ if (!payload) {
1074
+ sendJson(res, 401, { error: "Unauthorized", authEnabled });
1075
+ return;
1076
+ }
1077
+ sendJson(res, 200, { user: { userId: payload.userId, email: payload.email, username: payload.username, role: payload.role, teamName: payload.teamName }, authEnabled });
1078
+ return;
1079
+ }
1080
+ if (req.method === "POST" && url.pathname === "/api/auth/logout") {
1081
+ sendJson(res, 200, { ok: true });
1082
+ return;
1083
+ }
1084
+ if (req.method === "GET" && url.pathname === "/api/users") {
1085
+ const payload = requireAuth(req);
1086
+ if (!payload) {
1087
+ sendJson(res, 401, { error: "Unauthorized" });
1088
+ return;
1089
+ }
1090
+ if (payload.role !== "admin") {
1091
+ sendJson(res, 403, { error: "Admin only" });
1092
+ return;
1093
+ }
1094
+ const users = await listUsers();
1095
+ sendJson(res, 200, { users });
1096
+ return;
1097
+ }
1098
+ if (req.method === "POST" && url.pathname === "/api/users") {
1099
+ const payload = requireAuth(req);
1100
+ if (!payload) {
1101
+ sendJson(res, 401, { error: "Unauthorized" });
1102
+ return;
1103
+ }
1104
+ if (payload.role !== "admin") {
1105
+ sendJson(res, 403, { error: "Admin only" });
1106
+ return;
1107
+ }
1108
+ const body = await readBody(req);
1109
+ const email = typeof body.email === "string" ? body.email.trim() : "";
1110
+ const username = typeof body.username === "string" ? body.username.trim() : "";
1111
+ const password = typeof body.password === "string" ? body.password : "";
1112
+ const role = body.role === "admin" ? "admin" : "viewer";
1113
+ const teamName = typeof body.teamName === "string" ? body.teamName.trim() : void 0;
1114
+ if (!email || !username || password.length < 8) {
1115
+ sendJson(res, 400, { error: "email, username, and password (min 8 chars) required" });
1116
+ return;
1117
+ }
1118
+ const passwordHash = await hashPassword(password);
1119
+ try {
1120
+ const user = await createUser({ email, username, passwordHash, role, teamName });
1121
+ sendJson(res, 201, { user: { id: user.id, email: user.email, username: user.username, role: user.role, teamName: user.team_name } });
1122
+ } catch (err) {
1123
+ const msg = err.message;
1124
+ sendJson(res, 409, { error: msg.includes("unique") ? "Email or username already exists" : msg });
1125
+ }
1126
+ return;
1127
+ }
1128
+ const userMatch = url.pathname.match(/^\/api\/users\/(\d+)$/);
1129
+ if (userMatch && req.method === "DELETE") {
1130
+ const payload = requireAuth(req);
1131
+ if (!payload) {
1132
+ sendJson(res, 401, { error: "Unauthorized" });
1133
+ return;
1134
+ }
1135
+ if (payload.role !== "admin") {
1136
+ sendJson(res, 403, { error: "Admin only" });
1137
+ return;
1138
+ }
1139
+ const uid = parseInt(userMatch[1], 10);
1140
+ if (uid === payload.userId) {
1141
+ sendJson(res, 400, { error: "Cannot delete yourself" });
1142
+ return;
1143
+ }
1144
+ const deleted = await deleteUser(uid);
1145
+ sendJson(res, deleted ? 200 : 404, deleted ? { ok: true } : { error: "User not found" });
1146
+ return;
1147
+ }
972
1148
  sendJson(res, 404, { error: "Not found" });
973
1149
  } catch (err) {
974
1150
  sendJson(res, 500, { error: err.message });
@@ -1231,6 +1407,7 @@ function startConfigWatch() {
1231
1407
  }
1232
1408
  async function startDashboard(options = {}) {
1233
1409
  projectRoot = resolveDashboardProjectRoot(options.path);
1410
+ authEnabled = options.auth ?? false;
1234
1411
  reloadRuntimeEnv();
1235
1412
  const port = options.port ?? 5178;
1236
1413
  const stopConfigWatch = startConfigWatch();
@@ -1,37 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  closePool,
4
+ countUsers,
5
+ createUser,
4
6
  deleteArchProfile,
5
7
  deleteMemories,
6
8
  deleteMemory,
9
+ deleteUser,
7
10
  getArchProfile,
8
11
  getMemory,
9
12
  getPool,
13
+ getUserByEmail,
14
+ getUserById,
10
15
  hashMemoryContent,
11
16
  listArchProfiles,
12
17
  listMemories,
18
+ listUsers,
13
19
  runMigrations,
14
20
  saveArchProfile,
15
21
  saveMemory,
16
22
  searchMemories,
23
+ updateLastLogin,
17
24
  updateMemory,
18
25
  upsertMemory
19
- } from "./chunk-4ZSVQMI7.js";
26
+ } from "./chunk-GIPKVQSA.js";
20
27
  export {
21
28
  closePool,
29
+ countUsers,
30
+ createUser,
22
31
  deleteArchProfile,
23
32
  deleteMemories,
24
33
  deleteMemory,
34
+ deleteUser,
25
35
  getArchProfile,
26
36
  getMemory,
27
37
  getPool,
38
+ getUserByEmail,
39
+ getUserById,
28
40
  hashMemoryContent,
29
41
  listArchProfiles,
30
42
  listMemories,
43
+ listUsers,
31
44
  runMigrations,
32
45
  saveArchProfile,
33
46
  saveMemory,
34
47
  searchMemories,
48
+ updateLastLogin,
35
49
  updateMemory,
36
50
  upsertMemory
37
51
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shahmilsaari/memory-core",
3
- "version": "1.0.31",
3
+ "version": "1.0.33",
4
4
  "description": "Universal AI memory core — generate AI context files from architecture profiles with RAG support",
5
5
  "homepage": "https://memory-core.shahmilsaari.my/",
6
6
  "type": "module",
@@ -33,18 +33,22 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@inquirer/prompts": "^5.0.0",
36
+ "bcryptjs": "^3.0.3",
36
37
  "chalk": "^5.3.0",
37
38
  "chokidar": "^5.0.0",
38
39
  "commander": "^12.0.0",
39
40
  "dotenv": "^16.4.0",
40
41
  "handlebars": "^4.7.8",
41
42
  "js-yaml": "^4.1.0",
43
+ "jsonwebtoken": "^9.0.3",
42
44
  "ora": "^8.0.0",
43
45
  "pg": "^8.11.0"
44
46
  },
45
47
  "devDependencies": {
46
48
  "@sveltejs/vite-plugin-svelte": "^4.0.4",
49
+ "@types/bcryptjs": "^2.4.6",
47
50
  "@types/js-yaml": "^4.0.9",
51
+ "@types/jsonwebtoken": "^9.0.10",
48
52
  "@types/node": "^20.0.0",
49
53
  "@types/pg": "^8.11.0",
50
54
  "svelte": "^5.55.5",