diff --git a/.opencode/init b/.opencode/init
new file mode 100644
index 0000000..e69de29
diff --git a/.opencode/opencode.db b/.opencode/opencode.db
new file mode 100644
index 0000000..4e86411
Binary files /dev/null and b/.opencode/opencode.db differ
diff --git a/.opencode/opencode.db-shm b/.opencode/opencode.db-shm
new file mode 100644
index 0000000..ba6df8f
Binary files /dev/null and b/.opencode/opencode.db-shm differ
diff --git a/.opencode/opencode.db-wal b/.opencode/opencode.db-wal
new file mode 100644
index 0000000..bdb67af
Binary files /dev/null and b/.opencode/opencode.db-wal differ
diff --git a/OpenCode.md b/OpenCode.md
new file mode 100644
index 0000000..3df9927
--- /dev/null
+++ b/OpenCode.md
@@ -0,0 +1,33 @@
+# Dealspace Coding Guide
+
+## Build & Test
+
+```bash
+make build # Local build
+make build-linux # Linux/amd64 with CGO + fts5
+make test # Run all tests
+CGO_ENABLED=1 go test -tags fts5 ./lib -run TestPackUnpack -v # Single test
+```
+
+## Code Style
+
+- **Format**: `gofmt` (standard Go formatting)
+- **Imports**: stdlib → third-party → internal (github.com/mish/dealspace)
+- **Types**: Use JSON tags with `snake_case`, e.g., `EntryID string `json:"entry_id"``
+- **Naming**: PascalCase for exported, camelCase for unexported; constants use prefix like `TypeProject`, `StageDataroom`
+- **Errors**: Wrap with `fmt.Errorf("context: %w", err)`; check sentinel errors with `==`
+
+## Architecture Rules
+
+**Database access ONLY through three choke points in `lib/dbcore.go`:**
+- `EntryRead(db, cfg, actorID, projectID, filter)` — all reads
+- `EntryWrite(db, cfg, actorID, entries...)` — all writes
+- `EntryDelete(db, actorID, projectID, entryIDs...)` — all deletes
+
+**FORBIDDEN:** `db.Exec()`, `db.Query()`, `db.QueryRow()` outside dbcore.go; wrapper functions bypassing choke points; modifications to dbcore.go without explicit approval.
+
+`actorID=""` = system/internal access (always granted). RBAC enforced at DB level, not UI.
+
+## Tech Stack
+
+Go 1.24, SQLite with mattn/go-sqlite3 (CGO required), chi router, uuid, pdfcpu, excelize, golang.org/x/crypto
diff --git a/portal/portal/emails/answer_approved.html b/portal/portal/emails/answer_approved.html
deleted file mode 100644
index 3d47e58..0000000
--- a/portal/portal/emails/answer_approved.html
+++ /dev/null
@@ -1,85 +0,0 @@
-{{define "answer_approved.html"}}
-
-
-
-
-
- Your answer was approved ✓
-
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
-
-
-
-
-
- Your answer was approved
-
-
-
- Hi{{if .RecipientName}} {{.RecipientName}}{{end}},
-
-
-
- Great news! Your answer for {{.RequestTitle}} has been approved.
-
-
- {{if .Published}}
-
-
- 📁 Published to Data Room — Your response is now visible to authorized buyers.
-
-
- {{end}}
-
- {{if .DataRoomURL}}
-
-
- {{end}}
-
-
- Thank you for your prompt response. Keep up the excellent work!
-
- |
-
-
-
-
- |
-
- Questions? Contact support@muskepo.com
-
-
- © 2026 Dealspace · Privacy Policy · Terms of Service
-
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/emails/answer_rejected.html b/portal/portal/emails/answer_rejected.html
deleted file mode 100644
index 3a5da95..0000000
--- a/portal/portal/emails/answer_rejected.html
+++ /dev/null
@@ -1,76 +0,0 @@
-{{define "answer_rejected.html"}}
-
-
-
-
-
- Your answer needs revision
-
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
-
-
- Your answer needs revision
-
-
-
- Hi{{if .RecipientName}} {{.RecipientName}}{{end}},
-
-
-
- Your answer for {{.RequestTitle}} requires some changes before it can be approved.
-
-
-
- {{if .Reason}}
-
- Feedback
- {{.Reason}}
-
- {{end}}
-
-
-
-
-
- Please update your response based on the feedback above. If you have any questions, you can reply directly in the request thread.
-
- |
-
-
-
-
- |
-
- Questions? Contact support@muskepo.com
-
-
- © 2026 Dealspace · Privacy Policy · Terms of Service
-
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/emails/answer_submitted.html b/portal/portal/emails/answer_submitted.html
deleted file mode 100644
index a496ead..0000000
--- a/portal/portal/emails/answer_submitted.html
+++ /dev/null
@@ -1,92 +0,0 @@
-{{define "answer_submitted.html"}}
-
-
-
-
-
- {{.AnswererName}} submitted an answer for: {{.RequestTitle}}
-
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
- |
-
- ACTION REQUIRED
-
-
-
- New answer submitted for review
-
-
-
- Hi{{if .RecipientName}} {{.RecipientName}}{{end}},
-
-
-
- {{.AnswererName}} has submitted an answer that needs your review.
-
-
-
-
-
- |
- Request
- {{.RequestTitle}}
-
- {{if .WorkstreamName}}
- Workstream
- {{.WorkstreamName}}
- {{end}}
-
- {{if .AnswerPreview}}
- Preview
- "{{truncate .AnswerPreview 200}}"
- {{end}}
- |
-
-
-
-
-
-
-
- Once approved, this answer will be published to the data room and visible to authorized buyers.
-
- |
-
-
-
-
- |
-
- Questions? Contact support@muskepo.com
-
-
- © 2026 Dealspace · Privacy Policy · Terms of Service
-
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/emails/invite.html b/portal/portal/emails/invite.html
deleted file mode 100644
index 3ba8281..0000000
--- a/portal/portal/emails/invite.html
+++ /dev/null
@@ -1,76 +0,0 @@
-{{define "invite.html"}}
-
-
-
-
-
- You're invited to {{.ProjectName}}
-
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
-
-
- You've been invited to join {{.ProjectName}}
-
-
-
- Hi{{if .RecipientName}} {{.RecipientName}}{{end}},
-
-
-
- {{.InviterName}} from {{.InviterOrg}} has invited you to join the due diligence process for {{.ProjectName}}.
-
-
-
-
-
-
-
- What is Dealspace?
-
- Dealspace is a secure platform for managing M&A due diligence. All documents are encrypted and watermarked. You control what gets shared and when.
-
-
-
-
- ⏱ This invitation expires in {{if .ExpiresIn}}{{.ExpiresIn}}{{else}}7 days{{end}}.
-
- |
-
-
-
-
- |
-
- Questions? Contact support@muskepo.com
-
-
- © 2026 Dealspace · Privacy Policy · Terms of Service
-
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/emails/request_forwarded.html b/portal/portal/emails/request_forwarded.html
deleted file mode 100644
index 317d184..0000000
--- a/portal/portal/emails/request_forwarded.html
+++ /dev/null
@@ -1,85 +0,0 @@
-{{define "request_forwarded.html"}}
-
-
-
-
-
- {{.SenderName}} forwarded a request to you
-
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
-
-
- Request forwarded to you
-
-
-
- Hi{{if .RecipientName}} {{.RecipientName}}{{end}},
-
-
-
- {{.SenderName}} has forwarded a request to you for your input.
-
-
-
-
-
- |
- Request
- {{.RequestTitle}}
-
- {{if .HasDueDate}}
-
- Due Date
- {{.DueDate}}
-
- {{end}}
- |
-
-
-
-
-
-
-
- You can respond to this request directly in Dealspace. Your response will be routed back to {{.SenderName}} for review.
-
- |
-
-
-
-
- |
-
- Questions? Contact support@muskepo.com
-
-
- © 2026 Dealspace · Privacy Policy · Terms of Service
-
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/emails/tasks_assigned.html b/portal/portal/emails/tasks_assigned.html
deleted file mode 100644
index 7f73ca3..0000000
--- a/portal/portal/emails/tasks_assigned.html
+++ /dev/null
@@ -1,87 +0,0 @@
-{{define "tasks_assigned.html"}}
-
-
-
-
-
- You have {{.Count}} new task{{if gt .Count 1}}s{{end}} on {{.ProjectName}}
-
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
-
-
- You have {{.Count}} new task{{if gt .Count 1}}s{{end}} on {{.ProjectName}}
-
-
-
- Hi{{if .RecipientName}} {{.RecipientName}}{{end}},
-
-
-
- The following request{{if gt .Count 1}}s have{{else}} has{{end}} been assigned to you:
-
-
-
-
- {{range $i, $task := .Tasks}}
- {{if lt $i 5}}
-
- |
- {{$task.Title}}
- {{if $task.DueDate}}
- Due: {{$task.DueDate}}{{if eq $task.Priority "high"}} · High Priority{{end}}
- {{end}}
- |
-
- |
- {{end}}
- {{end}}
-
-
- {{if gt .Count 5}}
-
- ...and {{sub .Count 5}} more
-
- {{end}}
-
-
-
- |
-
-
-
-
- |
-
- You're receiving this because you're assigned to requests in {{.ProjectName}}.
-
-
- © 2026 Dealspace · Manage Notifications · Unsubscribe
-
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/emails/welcome.html b/portal/portal/emails/welcome.html
deleted file mode 100644
index 2f08a32..0000000
--- a/portal/portal/emails/welcome.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{{define "welcome.html"}}
-
-
-
-
-
- Welcome to Dealspace
-
-
-
-
-
-
-
-
- DEALSPACE
- |
-
-
-
-
- Welcome to Dealspace{{if .RecipientName}}, {{.RecipientName}}{{end}}! 🎉
-
-
- You're all set up and ready to go. Here are three quick tips to get you started:
-
-
- 📥 Your inbox is your home
- Everything assigned to you appears in your task inbox. Start there each day to see what needs your attention.
-
-
- 📋 Requests, not folders
- We organize by requests, not file folders. Each request tracks its own status, comments, and documents — all in one place.
-
-
- 🤖 Ask Aria
- Not sure where something is? Ask Aria, our AI assistant. She can find documents, answer questions, and guide you through the process.
-
-
- We're excited to have you on board. Let's make this deal happen! 🚀
- |
-
-
- |
- Need help? Contact support@muskepo.com
- © 2026 Dealspace · Privacy Policy · Terms of Service
- |
-
-
- |
-
-
-
-
-{{end}}
diff --git a/portal/portal/static/themes.css b/portal/portal/static/themes.css
deleted file mode 100644
index e51d614..0000000
--- a/portal/portal/static/themes.css
+++ /dev/null
@@ -1,744 +0,0 @@
-/**
- * Dealspace Theme System
- *
- * All colors are CSS custom properties. Zero hardcoded values in templates.
- * Switch themes by changing the class on : theme-light, theme-dark, theme-contrast
- * Per-project overrides use data-project attribute.
- */
-
-/* ==========================================================================
- BASE TOKENS (shared across themes)
- ========================================================================== */
-
-:root {
- /* Spacing */
- --space-xs: 0.25rem; /* 4px */
- --space-sm: 0.5rem; /* 8px */
- --space-md: 1rem; /* 16px */
- --space-lg: 1.5rem; /* 24px */
- --space-xl: 2rem; /* 32px */
- --space-2xl: 3rem; /* 48px */
-
- /* Border radius */
- --radius-sm: 0.25rem; /* 4px */
- --radius-md: 0.5rem; /* 8px */
- --radius-lg: 0.75rem; /* 12px */
- --radius-full: 9999px;
-
- /* Typography */
- --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
- --font-mono: "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
-
- --text-xs: 0.75rem; /* 12px */
- --text-sm: 0.875rem; /* 14px */
- --text-base: 1rem; /* 16px */
- --text-lg: 1.125rem; /* 18px */
- --text-xl: 1.25rem; /* 20px */
- --text-2xl: 1.5rem; /* 24px */
-
- --leading-tight: 1.25;
- --leading-normal: 1.5;
- --leading-relaxed: 1.75;
-
- /* Transitions */
- --transition-fast: 150ms ease;
- --transition-normal: 250ms ease;
-
- /* Z-index scale */
- --z-dropdown: 100;
- --z-modal: 200;
- --z-toast: 300;
-}
-
-
-/* ==========================================================================
- LIGHT THEME (default)
- ========================================================================== */
-
-.theme-light,
-:root {
- /* Surfaces */
- --color-bg-primary: #ffffff;
- --color-bg-secondary: #f9fafb;
- --color-bg-tertiary: #f3f4f6;
- --color-bg-inverse: #1f2937;
- --color-bg-hover: #f3f4f6;
- --color-bg-selected: #eff6ff;
-
- /* Text */
- --color-text-primary: #111827;
- --color-text-secondary: #6b7280;
- --color-text-tertiary: #9ca3af;
- --color-text-inverse: #ffffff;
- --color-text-link: #2563eb;
- --color-text-link-hover: #1d4ed8;
-
- /* Borders */
- --color-border-primary: #e5e7eb;
- --color-border-secondary: #f3f4f6;
- --color-border-focus: #2563eb;
-
- /* Semantic colors */
- --color-accent: #2563eb;
- --color-accent-hover: #1d4ed8;
- --color-accent-light: #dbeafe;
- --color-success: #059669;
- --color-success-light: #d1fae5;
- --color-warning: #d97706;
- --color-warning-light: #fef3c7;
- --color-error: #dc2626;
- --color-error-light: #fee2e2;
- --color-info: #0284c7;
- --color-info-light: #e0f2fe;
-
- /* Priority indicators */
- --color-priority-high: #dc2626;
- --color-priority-normal: #d97706;
- --color-priority-low: #9ca3af;
-
- /* Status badges */
- --color-status-open: #6b7280;
- --color-status-open-bg: #f3f4f6;
- --color-status-assigned: #2563eb;
- --color-status-assigned-bg: #dbeafe;
- --color-status-answered: #d97706;
- --color-status-answered-bg: #fef3c7;
- --color-status-vetted: #7c3aed;
- --color-status-vetted-bg: #ede9fe;
- --color-status-published: #059669;
- --color-status-published-bg: #d1fae5;
- --color-status-closed: #9ca3af;
- --color-status-closed-bg: #f3f4f6;
-
- /* Components */
- --color-header-bg: #ffffff;
- --color-header-text: #111827;
- --color-header-border: #e5e7eb;
- --color-card-bg: #ffffff;
- --color-card-border: #e5e7eb;
- --color-card-shadow: rgba(0, 0, 0, 0.05);
- --color-input-bg: #ffffff;
- --color-input-border: #d1d5db;
- --color-input-focus: #2563eb;
- --color-input-placeholder: #9ca3af;
- --color-badge-bg: #ef4444;
- --color-badge-text: #ffffff;
-
- /* Shadows */
- --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
- --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
- --shadow-focus: 0 0 0 3px rgba(37, 99, 235, 0.2);
-}
-
-
-/* ==========================================================================
- DARK THEME
- ========================================================================== */
-
-.theme-dark {
- /* Surfaces */
- --color-bg-primary: #111827;
- --color-bg-secondary: #1f2937;
- --color-bg-tertiary: #374151;
- --color-bg-inverse: #f9fafb;
- --color-bg-hover: #374151;
- --color-bg-selected: #1e3a5f;
-
- /* Text */
- --color-text-primary: #f9fafb;
- --color-text-secondary: #9ca3af;
- --color-text-tertiary: #6b7280;
- --color-text-inverse: #111827;
- --color-text-link: #60a5fa;
- --color-text-link-hover: #93c5fd;
-
- /* Borders */
- --color-border-primary: #374151;
- --color-border-secondary: #4b5563;
- --color-border-focus: #60a5fa;
-
- /* Semantic colors */
- --color-accent: #3b82f6;
- --color-accent-hover: #60a5fa;
- --color-accent-light: #1e3a5f;
- --color-success: #10b981;
- --color-success-light: #064e3b;
- --color-warning: #f59e0b;
- --color-warning-light: #78350f;
- --color-error: #ef4444;
- --color-error-light: #7f1d1d;
- --color-info: #0ea5e9;
- --color-info-light: #0c4a6e;
-
- /* Priority indicators */
- --color-priority-high: #ef4444;
- --color-priority-normal: #f59e0b;
- --color-priority-low: #6b7280;
-
- /* Status badges */
- --color-status-open: #9ca3af;
- --color-status-open-bg: #374151;
- --color-status-assigned: #60a5fa;
- --color-status-assigned-bg: #1e3a5f;
- --color-status-answered: #f59e0b;
- --color-status-answered-bg: #78350f;
- --color-status-vetted: #a78bfa;
- --color-status-vetted-bg: #4c1d95;
- --color-status-published: #10b981;
- --color-status-published-bg: #064e3b;
- --color-status-closed: #6b7280;
- --color-status-closed-bg: #374151;
-
- /* Components */
- --color-header-bg: #1f2937;
- --color-header-text: #f9fafb;
- --color-header-border: #374151;
- --color-card-bg: #1f2937;
- --color-card-border: #374151;
- --color-card-shadow: rgba(0, 0, 0, 0.3);
- --color-input-bg: #374151;
- --color-input-border: #4b5563;
- --color-input-focus: #60a5fa;
- --color-input-placeholder: #6b7280;
- --color-badge-bg: #ef4444;
- --color-badge-text: #ffffff;
-
- /* Shadows */
- --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
- --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
- --shadow-focus: 0 0 0 3px rgba(96, 165, 250, 0.3);
-}
-
-
-/* ==========================================================================
- HIGH CONTRAST THEME
- ========================================================================== */
-
-.theme-contrast {
- /* Surfaces */
- --color-bg-primary: #000000;
- --color-bg-secondary: #1a1a1a;
- --color-bg-tertiary: #333333;
- --color-bg-inverse: #ffffff;
- --color-bg-hover: #333333;
- --color-bg-selected: #003366;
-
- /* Text */
- --color-text-primary: #ffffff;
- --color-text-secondary: #e0e0e0;
- --color-text-tertiary: #b0b0b0;
- --color-text-inverse: #000000;
- --color-text-link: #66b3ff;
- --color-text-link-hover: #99ccff;
-
- /* Borders */
- --color-border-primary: #ffffff;
- --color-border-secondary: #808080;
- --color-border-focus: #ffff00;
-
- /* Semantic colors */
- --color-accent: #66b3ff;
- --color-accent-hover: #99ccff;
- --color-accent-light: #003366;
- --color-success: #00ff00;
- --color-success-light: #003300;
- --color-warning: #ffff00;
- --color-warning-light: #333300;
- --color-error: #ff3333;
- --color-error-light: #330000;
- --color-info: #00ffff;
- --color-info-light: #003333;
-
- /* Priority indicators */
- --color-priority-high: #ff3333;
- --color-priority-normal: #ffff00;
- --color-priority-low: #808080;
-
- /* Status badges */
- --color-status-open: #ffffff;
- --color-status-open-bg: #333333;
- --color-status-assigned: #66b3ff;
- --color-status-assigned-bg: #003366;
- --color-status-answered: #ffff00;
- --color-status-answered-bg: #333300;
- --color-status-vetted: #cc99ff;
- --color-status-vetted-bg: #330066;
- --color-status-published: #00ff00;
- --color-status-published-bg: #003300;
- --color-status-closed: #808080;
- --color-status-closed-bg: #1a1a1a;
-
- /* Components */
- --color-header-bg: #000000;
- --color-header-text: #ffffff;
- --color-header-border: #ffffff;
- --color-card-bg: #1a1a1a;
- --color-card-border: #ffffff;
- --color-card-shadow: none;
- --color-input-bg: #1a1a1a;
- --color-input-border: #ffffff;
- --color-input-focus: #ffff00;
- --color-input-placeholder: #808080;
- --color-badge-bg: #ff3333;
- --color-badge-text: #ffffff;
-
- /* Shadows - disabled for clarity */
- --shadow-sm: none;
- --shadow-md: none;
- --shadow-lg: none;
- --shadow-focus: 0 0 0 3px #ffff00;
-}
-
-/* High contrast specific: underline all links */
-.theme-contrast a {
- text-decoration: underline;
-}
-
-.theme-contrast a:focus {
- outline: 3px solid var(--color-border-focus);
- outline-offset: 2px;
-}
-
-
-/* ==========================================================================
- PER-PROJECT BRAND OVERRIDES
- ========================================================================== */
-
-/* Project overrides cascade on top of the selected theme */
-/* Example: data-project="alpha" */
-
-[data-project="alpha"] {
- --color-accent: #7c3aed; /* Purple accent */
- --color-accent-hover: #6d28d9;
- --color-header-bg: #7c3aed;
- --color-header-text: #ffffff;
-}
-
-[data-project="beta"] {
- --color-accent: #059669; /* Emerald accent */
- --color-accent-hover: #047857;
- --color-header-bg: #059669;
- --color-header-text: #ffffff;
-}
-
-
-/* ==========================================================================
- COMPONENT STYLES (using theme variables)
- ========================================================================== */
-
-/* Base reset */
-*, *::before, *::after {
- box-sizing: border-box;
-}
-
-body {
- font-family: var(--font-sans);
- font-size: var(--text-base);
- line-height: var(--leading-normal);
- color: var(--color-text-primary);
- background-color: var(--color-bg-primary);
- margin: 0;
- padding: 0;
-}
-
-/* Header */
-.global-header {
- display: flex;
- align-items: center;
- gap: var(--space-lg);
- padding: var(--space-md) var(--space-lg);
- background: var(--color-header-bg);
- border-bottom: 1px solid var(--color-header-border);
-}
-
-.global-header .logo {
- font-size: var(--text-xl);
- font-weight: 700;
- color: var(--color-header-text);
-}
-
-/* Project selector */
-.project-select {
- flex: 1;
- max-width: 400px;
- padding: var(--space-sm) var(--space-md);
- font-size: var(--text-sm);
- color: var(--color-text-primary);
- background: var(--color-input-bg);
- border: 1px solid var(--color-input-border);
- border-radius: var(--radius-md);
- cursor: pointer;
-}
-
-.project-select:focus {
- outline: none;
- border-color: var(--color-input-focus);
- box-shadow: var(--shadow-focus);
-}
-
-/* Workstream tabs */
-.workstream-tabs {
- display: flex;
- gap: var(--space-xs);
- padding: 0 var(--space-lg);
- background: var(--color-bg-secondary);
- border-bottom: 1px solid var(--color-border-primary);
-}
-
-.workstream-tabs a {
- display: inline-flex;
- align-items: center;
- gap: var(--space-sm);
- padding: var(--space-md) var(--space-lg);
- font-size: var(--text-sm);
- font-weight: 500;
- color: var(--color-text-secondary);
- text-decoration: none;
- border-bottom: 2px solid transparent;
- transition: color var(--transition-fast), border-color var(--transition-fast);
-}
-
-.workstream-tabs a:hover {
- color: var(--color-text-primary);
-}
-
-.workstream-tabs a.active {
- color: var(--color-accent);
- border-bottom-color: var(--color-accent);
-}
-
-/* Badge */
-.badge {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- min-width: 1.25rem;
- height: 1.25rem;
- padding: 0 var(--space-xs);
- font-size: var(--text-xs);
- font-weight: 600;
- color: var(--color-badge-text);
- background: var(--color-badge-bg);
- border-radius: var(--radius-full);
-}
-
-.badge-muted {
- background: var(--color-bg-tertiary);
- color: var(--color-text-secondary);
-}
-
-/* Task card */
-.task-card {
- display: block;
- padding: var(--space-md) var(--space-lg);
- background: var(--color-card-bg);
- border: 1px solid var(--color-card-border);
- border-radius: var(--radius-lg);
- box-shadow: var(--shadow-sm);
- text-decoration: none;
- color: inherit;
- transition: box-shadow var(--transition-fast), border-color var(--transition-fast);
-}
-
-.task-card:hover {
- border-color: var(--color-border-focus);
- box-shadow: var(--shadow-md);
-}
-
-.task-card-header {
- display: flex;
- align-items: flex-start;
- gap: var(--space-md);
- margin-bottom: var(--space-sm);
-}
-
-.task-card-priority {
- width: 0.625rem;
- height: 0.625rem;
- border-radius: var(--radius-full);
- flex-shrink: 0;
- margin-top: 0.375rem;
-}
-
-.task-card-priority.high { background: var(--color-priority-high); }
-.task-card-priority.normal { background: var(--color-priority-normal); }
-.task-card-priority.low { background: var(--color-priority-low); }
-
-.task-card-ref {
- font-size: var(--text-sm);
- font-weight: 600;
- color: var(--color-text-secondary);
- font-family: var(--font-mono);
-}
-
-.task-card-title {
- flex: 1;
- font-size: var(--text-base);
- font-weight: 600;
- color: var(--color-text-primary);
-}
-
-.task-card-due {
- font-size: var(--text-sm);
- color: var(--color-text-secondary);
- white-space: nowrap;
-}
-
-.task-card-due.overdue {
- color: var(--color-error);
- font-weight: 600;
-}
-
-.task-card-due.today {
- color: var(--color-warning);
- font-weight: 600;
-}
-
-.task-card-meta {
- font-size: var(--text-sm);
- color: var(--color-text-secondary);
- margin-bottom: var(--space-sm);
-}
-
-.task-card-preview {
- font-size: var(--text-sm);
- color: var(--color-text-tertiary);
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-/* Status badge */
-.status-badge {
- display: inline-flex;
- align-items: center;
- padding: var(--space-xs) var(--space-sm);
- font-size: var(--text-xs);
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.025em;
- border-radius: var(--radius-sm);
-}
-
-.status-badge.open { color: var(--color-status-open); background: var(--color-status-open-bg); }
-.status-badge.assigned { color: var(--color-status-assigned); background: var(--color-status-assigned-bg); }
-.status-badge.answered { color: var(--color-status-answered); background: var(--color-status-answered-bg); }
-.status-badge.vetted { color: var(--color-status-vetted); background: var(--color-status-vetted-bg); }
-.status-badge.published { color: var(--color-status-published); background: var(--color-status-published-bg); }
-.status-badge.closed { color: var(--color-status-closed); background: var(--color-status-closed-bg); }
-
-/* Buttons */
-.btn {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- gap: var(--space-sm);
- padding: var(--space-sm) var(--space-md);
- font-size: var(--text-sm);
- font-weight: 500;
- text-decoration: none;
- border-radius: var(--radius-md);
- border: 1px solid transparent;
- cursor: pointer;
- transition: all var(--transition-fast);
-}
-
-.btn-primary {
- color: var(--color-text-inverse);
- background: var(--color-accent);
- border-color: var(--color-accent);
-}
-
-.btn-primary:hover {
- background: var(--color-accent-hover);
- border-color: var(--color-accent-hover);
-}
-
-.btn-secondary {
- color: var(--color-text-primary);
- background: var(--color-bg-secondary);
- border-color: var(--color-border-primary);
-}
-
-.btn-secondary:hover {
- background: var(--color-bg-tertiary);
-}
-
-.btn:focus {
- outline: none;
- box-shadow: var(--shadow-focus);
-}
-
-/* Form inputs */
-.input, .textarea {
- width: 100%;
- padding: var(--space-sm) var(--space-md);
- font-size: var(--text-base);
- color: var(--color-text-primary);
- background: var(--color-input-bg);
- border: 1px solid var(--color-input-border);
- border-radius: var(--radius-md);
-}
-
-.input::placeholder, .textarea::placeholder {
- color: var(--color-input-placeholder);
-}
-
-.input:focus, .textarea:focus {
- outline: none;
- border-color: var(--color-input-focus);
- box-shadow: var(--shadow-focus);
-}
-
-.textarea {
- min-height: 100px;
- resize: vertical;
-}
-
-/* Thread messages */
-.thread-message {
- padding: var(--space-md);
- background: var(--color-card-bg);
- border: 1px solid var(--color-card-border);
- border-radius: var(--radius-lg);
- margin-bottom: var(--space-md);
-}
-
-.thread-message-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: var(--space-sm);
-}
-
-.thread-message-author {
- font-weight: 600;
- color: var(--color-text-primary);
-}
-
-.thread-message-time {
- font-size: var(--text-sm);
- color: var(--color-text-tertiary);
-}
-
-.thread-message-body {
- color: var(--color-text-primary);
- line-height: var(--leading-relaxed);
-}
-
-.thread-message-attachment {
- display: inline-flex;
- align-items: center;
- gap: var(--space-sm);
- margin-top: var(--space-sm);
- padding: var(--space-sm) var(--space-md);
- background: var(--color-bg-tertiary);
- border-radius: var(--radius-md);
- font-size: var(--text-sm);
- color: var(--color-text-link);
- text-decoration: none;
-}
-
-.thread-message-attachment:hover {
- color: var(--color-text-link-hover);
-}
-
-/* Routing chain */
-.routing-chain {
- display: flex;
- align-items: center;
- gap: var(--space-md);
- padding: var(--space-md);
- background: var(--color-bg-secondary);
- border-radius: var(--radius-lg);
- overflow-x: auto;
-}
-
-.routing-step {
- display: flex;
- align-items: center;
- gap: var(--space-sm);
- white-space: nowrap;
- font-size: var(--text-sm);
- color: var(--color-text-secondary);
-}
-
-.routing-step.current {
- font-weight: 600;
- color: var(--color-accent);
-}
-
-.routing-arrow {
- color: var(--color-text-tertiary);
-}
-
-/* Empty state */
-.empty-state {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: var(--space-2xl);
- text-align: center;
-}
-
-.empty-state-icon {
- font-size: 3rem;
- margin-bottom: var(--space-md);
-}
-
-.empty-state-title {
- font-size: var(--text-xl);
- font-weight: 600;
- color: var(--color-text-primary);
- margin-bottom: var(--space-sm);
-}
-
-.empty-state-text {
- color: var(--color-text-secondary);
-}
-
-
-/* ==========================================================================
- UTILITY CLASSES
- ========================================================================== */
-
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- white-space: nowrap;
- border: 0;
-}
-
-.container {
- max-width: 1200px;
- margin: 0 auto;
- padding: 0 var(--space-lg);
-}
-
-.flex { display: flex; }
-.flex-col { flex-direction: column; }
-.items-center { align-items: center; }
-.justify-between { justify-content: space-between; }
-.gap-sm { gap: var(--space-sm); }
-.gap-md { gap: var(--space-md); }
-.gap-lg { gap: var(--space-lg); }
-
-.mt-sm { margin-top: var(--space-sm); }
-.mt-md { margin-top: var(--space-md); }
-.mt-lg { margin-top: var(--space-lg); }
-.mb-sm { margin-bottom: var(--space-sm); }
-.mb-md { margin-bottom: var(--space-md); }
-.mb-lg { margin-bottom: var(--space-lg); }
-
-.text-sm { font-size: var(--text-sm); }
-.text-lg { font-size: var(--text-lg); }
-.text-muted { color: var(--color-text-secondary); }
-.font-semibold { font-weight: 600; }
diff --git a/portal/portal/templates/admin/dashboard.html b/portal/portal/templates/admin/dashboard.html
deleted file mode 100644
index 988f20b..0000000
--- a/portal/portal/templates/admin/dashboard.html
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
- Admin — Dealspace
-
-
-
-
-
-
-
-
-
- Admin Dashboard
- Platform overview and management.
-
-
-
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/app/orgs.html b/portal/portal/templates/app/orgs.html
deleted file mode 100644
index a445794..0000000
--- a/portal/portal/templates/app/orgs.html
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-
-
- Organizations — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
Organizations
-
Company directory — parties eligible to participate in deals.
-
-
-
-
-
-
🏢
-
No organizations yet
-
Add buyer, seller, IB, and advisor organizations.
-
-
-
-
-
-
-
-
New Organization
-
-
-
-
-
-
-
Comma-separated. Only emails from these domains can be invited for this org.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/app/project.html b/portal/portal/templates/app/project.html
deleted file mode 100644
index 5445b18..0000000
--- a/portal/portal/templates/app/project.html
+++ /dev/null
@@ -1,494 +0,0 @@
-
-
-
-
- Project — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
📋
-
No requests yet
-
Import a diligence checklist or create requests manually.
-
-
-
-
-
-
Parties involved in this deal.
-
-
-
-
-
-
-
People with access to this deal.
-
-
-
-
-
-
-
-
-
Import Diligence Checklist
-
-
-
-
-
-
-
-
-
Add Party
-
Enter the email address of someone at the organization.
-
-
-
-
-
-
-
- Scanning website...
-
-
-
-
-
-
-
-
-
Organization Details
-
-
-
-
-
-
-
-
-
-
Select Colleagues
-
Choose who to add to this deal. They'll receive an invite email.
-
-
- 0 selected
-
-
-
No team members found on the website.
-
-
-
-
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/app/projects.html b/portal/portal/templates/app/projects.html
deleted file mode 100644
index 10669c8..0000000
--- a/portal/portal/templates/app/projects.html
+++ /dev/null
@@ -1,155 +0,0 @@
-
-
-
-
- Projects — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
Projects
-
All deals you have access to.
-
-
-
-
-
-
📁
-
No projects yet
-
You haven't been added to any deals yet.
-
-
-
-
-
-
-
-
New Project
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/app/request.html b/portal/portal/templates/app/request.html
deleted file mode 100644
index 635835c..0000000
--- a/portal/portal/templates/app/request.html
+++ /dev/null
@@ -1,204 +0,0 @@
-
-
-
-
- Request — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Response
-
-
-
📎
-
Drop files here or click to upload
-
PDF, DOCX, XLSX, images
-
-
-
-
-
-
-
-
Comments
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/app/tasks.html b/portal/portal/templates/app/tasks.html
deleted file mode 100644
index 74b8343..0000000
--- a/portal/portal/templates/app/tasks.html
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
-
-
- My Tasks — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Here are your pending tasks.
-
-
-
-
-
-
-
-
🎉
-
You're all caught up
-
No tasks need your attention right now.
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/auth/login.html b/portal/portal/templates/auth/login.html
deleted file mode 100644
index eaf9b07..0000000
--- a/portal/portal/templates/auth/login.html
+++ /dev/null
@@ -1,206 +0,0 @@
-
-
-
-
-
- Login — Dealspace
-
-
-
-
-
-
-
-
-
-
- Dealspace
-
-
Secure M&A deal management
-
-
-
-
-
Sign in
-
Enter your email to receive a login code.
-
-
-
-
-
-
-
-
-
Enter your code
-
- We sent a 6-digit code to
-
-
-
-
-
-
-
-
-
-
-
-
-
- Don’t have an account? Dealspace is invite-only.
- Request access on muskepo.com
-
-
© 2026 Muskepo B.V. — Amsterdam
-
-
-
-
-
diff --git a/portal/portal/templates/auth/setup.html b/portal/portal/templates/auth/setup.html
deleted file mode 100644
index f5c827c..0000000
--- a/portal/portal/templates/auth/setup.html
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
- Setup — Dealspace
-
-
-
-
-
-
-
-
-
-
- Dealspace
-
-
First-time setup
-
-
-
-
-
Create admin account
-
This will be the first administrator account for your Dealspace instance.
-
-
-
-
-
-
-
-
© 2026 Muskepo B.V. — Amsterdam
-
-
-
-
-
diff --git a/portal/portal/templates/request-detail.html b/portal/portal/templates/request-detail.html
deleted file mode 100644
index c3579a6..0000000
--- a/portal/portal/templates/request-detail.html
+++ /dev/null
@@ -1,572 +0,0 @@
-
-
-
-
-
- FIN-042: Audited financials FY2024 — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
- ← Back to Inbox
-
-
-
-
-
-
-
-
-
- Routing
-
-
-
- Acme Capital (Buyer)
-
- →
-
- J. Smith (IB)
-
- →
-
- M. Chen (CFO)
-
- →
-
- ★ You
-
-
-
- When done, returns to: M. Chen (CFO)
-
-
-
-
-
-
-
-
-
-
- Thread
-
-
-
-
-
-
Please provide audited financial statements for FY2024.
-
We need the following documents:
-
- - Income statement (P&L)
- - Balance sheet
- - Cash flow statement
- - Auditor's opinion letter
-
-
Please ensure these are the final audited versions, not draft.
-
-
-
-
-
-
-
-
@accountant Can you pull these from the ERP? The audit was finalized last month.
-
Attaching last year's format for reference so we maintain consistency.
-
-
- 📎 fy2023-financials-format.xlsx
-
-
-
-
-
-
-
-
On it. Just waiting for the auditor to send the final signed opinion letter. Should have everything by EOD Thursday.
-
-
-
-
-
-
-
- Your Response
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/portal/portal/templates/task-inbox.html b/portal/portal/templates/task-inbox.html
deleted file mode 100644
index 995cf91..0000000
--- a/portal/portal/templates/task-inbox.html
+++ /dev/null
@@ -1,258 +0,0 @@
-
-
-
-
-
- My Tasks — Dealspace
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-