diff --git a/audit/platform-ui-findings.md b/audit/platform-ui-findings.md
new file mode 100644
index 0000000..2adad83
--- /dev/null
+++ b/audit/platform-ui-findings.md
@@ -0,0 +1,269 @@
+# Cameleer SaaS Platform UI Audit Findings
+
+**Date:** 2026-04-09
+**Auditor:** Claude Opus 4.6
+**URL:** https://desktop-fb5vgj9.siegeln.internal/
+**Credentials:** admin/admin
+**Browser:** Playwright (Chromium)
+
+---
+
+## 1. Login Page (`/sign-in`)
+
+**Screenshot:** `03-login-page.png`, `04-login-error.png`
+
+### What works well
+- Clean, centered card layout with consistent design system components
+- Fun rotating subtitle taglines (e.g., "No ticket, no caravan") add personality
+- Cameleer logo is displayed correctly
+- Error handling works -- "Invalid username or password" alert appears on bad credentials (red alert banner)
+- Sign in button is correctly disabled until both fields are populated
+- Loading state on button during authentication
+- Uses proper `autoComplete` attributes (`username`, `current-password`)
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| Important | **No password visibility toggle** -- the Password input uses `type="password"` with no eye icon to reveal. Most modern login forms offer this. | Password field |
+| Important | **Branding says "cameleer3"** not "Cameleer" or "Cameleer SaaS" -- the product name on the login page is the internal repo name, not the user-facing brand | `.logo` text content |
+| Nice-to-have | **No "Forgot password" link** -- even if it goes to a "contact admin" page, users expect this | Below password field |
+| Nice-to-have | **No Enter-key submit hint** -- though Enter does work via form submit, there's no visual affordance | Form area |
+| Nice-to-have | **Page title is "Sign in -- cameleer3"** -- should match product branding ("Cameleer SaaS") | `
` tag |
+
+---
+
+## 2. Platform Dashboard (`/platform/`)
+
+**Screenshots:** `05-platform-dashboard-loggedin.png`, `15-dashboard-desktop-1280.png`, `19-tenant-info-detail.png`, `20-kpi-strip-detail.png`
+
+### What works well
+- Clear tenant name as page heading ("Example Tenant")
+- Tier badge next to tenant name provides immediate context
+- KPI strip with Tier, Status, License cards is visually clean and well-structured
+- License KPI card shows expiry date in green "expires 8.4.2027" trend indicator
+- "Server Management" card provides clear description of what the server dashboard does
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| **Critical** | **Label/value collision in Tenant Information card** -- "Slugdefault", "Created8.4.2026" have no visual separation between label and value. The source uses `flex justify-between` but the deployed Card component doesn't give the inner `div` full width, so items stack/collapse. | Tenant Information card |
+| **Critical** | **"Open Server Dashboard" appears 3 times** on one page: (1) primary button in header area below tenant name, (2) "Server Management" card with secondary button, (3) sidebar footer link. This is redundant and clutters the page. Reduce to 1-2 locations max. | Header area, Server Management card, sidebar footer |
+| Important | **Breadcrumb is always empty** -- the `breadcrumb` prop is passed as `[]`. Platform pages should have breadcrumbs like "Platform > Dashboard" or "Platform > License". | TopBar breadcrumb nav |
+| Important | **Massive empty space below content** -- the dashboard only has ~4 cards but the page extends far below with blank white/cream space. The page feels sparse and "stub-like." | Below Server Management card |
+| Important | **Tier badge color is misleading** -- "LOW" tier uses `primary` (orange) color, which doesn't convey it's the lowest/cheapest tier. The `tierColor()` function in DashboardPage maps to enterprise=success, pro=primary, starter=warning, but the actual data uses LOW/MID/HIGH/BUSINESS tiers (defined in LicensePage). Dashboard and License pages have different tier color mappings. | Tier badge |
+| Important | **Status is shown redundantly** -- "ACTIVE" appears in (1) KPI strip Status card, (2) Tenant Information card with badge, and (3) header area badge. This is excessive for a single piece of information. | Multiple locations |
+| Nice-to-have | **No tenant ID/slug in breadcrumb or subtitle** -- the slug "default" only appears buried in the Tenant Information card | Page header area |
+
+---
+
+## 3. License Page (`/platform/license`)
+
+**Screenshots:** `06-license-page.png`, `07-license-token-revealed.png`, `16-license-features-detail.png`, `17-license-limits-detail.png`, `18-license-validity-detail.png`
+
+### What works well
+- Well-structured layout with logical sections (Validity, Features, Limits, License Token)
+- Tier badge in header provides context
+- Feature matrix clearly shows enabled vs disabled features
+- "Days remaining" with color-coded badge (green for healthy, warning for <30 days, red for expired)
+- Token show/hide toggle works correctly
+- Token revealed in monospace code block with appropriate styling
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| **Critical** | **Label/value collision in Validity section** -- "Issued8. April 2026" and "Expires8. April 2027" have no separation. Source code uses `flex items-center justify-between` but the flex container seems to not be stretching to full width. | Validity card rows |
+| **Critical** | **Label/value collision in Limits section** -- "Max Agents3", "Retention Days7", "Max Environments1" have labels and values mashed together. Source uses `flex items-center justify-between` layout but the same rendering bug prevents proper spacing. | Limits card rows |
+| Important | **No "Copy to clipboard" button** for the license token -- users need to manually select and copy. A copy button with confirmation toast is standard UX for tokens/secrets. | License Token section |
+| Important | **Feature badge text mismatch** -- Source code says `'Not included'` for disabled features, but deployed version shows "DISABLED". This suggests the deployed build is out of sync with the source. | Features card badges |
+| Important | **"Disabled" badge color** -- disabled features use `color='auto'` (which renders as a neutral/red-ish badge), while "Enabled" uses green. Consider using a muted gray for "Not included" to make it feel less like an error state. Red implies something is wrong, but a feature simply not being in the plan is not an error. | Features card disabled badges |
+| Nice-to-have | **Limits values are not right-aligned** -- due to the label/value collision, the numeric values don't align in a column, making comparison harder | Limits card |
+| Nice-to-have | **No units on limits** -- "Retention Days7" should be "7 days", "Max Agents3" should be "3 agents" or just "3" with clear formatting | Limits card values |
+
+---
+
+## 4. Admin Pages (`/platform/admin/tenants`)
+
+**No screenshot available -- page returns HTTP error**
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| **Critical** | **Admin page returns HTTP error (net::ERR_HTTP_RESPONSE_CODE_FAILURE)** -- navigating to `/platform/admin/tenants` fails with an HTTP error. The route exists in the router (`AdminTenantsPage`), but the admin section is not visible in the sidebar (no "Platform" item shown). | Admin route |
+| Important | **Admin section not visible in sidebar** -- the `platform:admin` scope check in Layout.tsx hides the "Platform" sidebar item. Even though the user is "admin", they apparently don't have the `platform:admin` scope in their JWT. This may be intentional (scope not assigned) or a bug. | Sidebar Platform section |
+| Important | **No graceful fallback for unauthorized admin access** -- if a user manually navigates to `/admin/tenants` without the scope, the page should show a "Not authorized" message rather than an HTTP error. | Admin route error handling |
+
+---
+
+## 5. Navigation
+
+**Screenshots:** `21-sidebar-detail.png`, `12-sidebar-collapsed.png`
+
+### What works well
+- Clean sidebar with Cameleer SaaS branding and logo
+- "Open Server Dashboard" in sidebar footer is a good location
+- Sidebar has only 2 navigation items (Dashboard, License) which keeps it simple
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| **Critical** | **No active state on sidebar navigation items** -- when on the Dashboard page, neither Dashboard nor License is highlighted/active. The sidebar uses `Sidebar.Section` components with `open={false}` as navigation links via `onToggle`, but `Section` is designed for expandable/collapsible groups, not navigation links. There is no visual indicator of the current page. | Sidebar items |
+| Important | **Sidebar collapse doesn't work visually** -- clicking "Collapse sidebar" toggles the `active` state on the button but the sidebar doesn't visually collapse. The Layout component passes `collapsed={false}` as a hardcoded prop and `onCollapseToggle={() => {}}` as a no-op. | Sidebar collapse button |
+| Important | **No clear distinction between "platform" and "server" levels** -- there's nothing in the sidebar header that says "Platform" vs "Server". The sidebar says "Cameleer SaaS" but when you switch to the server dashboard, it becomes a completely different app. A user might not understand the relationship. | Sidebar header |
+| Nice-to-have | **"Open Server Dashboard" opens in new tab** -- `window.open('/server/', '_blank', 'noopener')` is used. While reasonable, there's no visual indicator (external link icon) that it will open a new tab. | Sidebar footer link, dashboard buttons |
+
+---
+
+## 6. Header Bar (TopBar)
+
+**Screenshot:** `22-header-bar-detail.png`
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| **Critical** | **Server-specific controls shown on platform pages** -- the TopBar always renders: (1) Search (Ctrl+K), (2) Status filters (OK/Warn/Error/Running), (3) Time range pills (1h/3h/6h/Today/24h/7d), (4) Auto-refresh toggle (MANUAL/AUTO). None of these are relevant to the platform dashboard or license page. They are observability controls designed for the server's exchange/route monitoring. | Entire TopBar filter area |
+| Important | **Search button does nothing** -- clicking "Search..." on the platform does not open a search modal. The CommandPaletteProvider is likely not configured for the platform context. | Search button |
+| Important | **Status filter buttons are interactive but meaningless** -- clicking OK/Warn/Error/Running on platform pages toggles state (global filter provider) but has no effect on the displayed content. | Status filter buttons |
+| Important | **Time range selector is interactive but meaningless** -- similarly, changing the time range from 1h to 7d has no effect on platform pages. | Time range pills |
+| Important | **Auto-refresh toggle is misleading** -- shows "MANUAL" toggle on platform pages where there's nothing to auto-refresh. | Auto-refresh button |
+
+---
+
+## 7. User Menu
+
+**Screenshot:** `02-user-menu-dropdown.png`
+
+### What works well
+- User name "admin" and avatar initials "AD" displayed correctly
+- Dropdown appears on click with Logout option
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| Important | **User menu only has "Logout"** -- there's no "Profile", "Settings", "About", or "Switch Tenant" option. For a SaaS platform, users should at minimum see their role and tenant context. | User dropdown menu |
+| Nice-to-have | **Avatar shows "AD" for "admin"** -- the Avatar component appears to use first 2 characters of the name. For "admin" this produces "AD" which looks like initials for a different name. | Avatar component |
+
+---
+
+## 8. Dark Mode
+
+**Screenshots:** `08-dashboard-dark-mode.png`, `09-license-dark-mode.png`
+
+### What works well
+- Dark mode toggle works and applies globally
+- Background transitions to dark brown/charcoal
+- Text colors adapt appropriately
+- Cards maintain visual distinction from background
+- Design system tokens handle the switch smoothly
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| Nice-to-have | **Dark mode is warm-toned (brown)** rather than the more common cool dark gray/charcoal. This is consistent with the design system's cameleer branding but may feel unusual to users accustomed to dark mode in other apps. | Global dark theme |
+| Nice-to-have | **The same label/value collision issues appear in dark mode** -- these are layout bugs, not color bugs, so dark mode doesn't help or hurt. | Card content |
+
+---
+
+## 9. Responsiveness
+
+**Screenshots:** `13-responsive-tablet.png`, `14-responsive-mobile.png`
+
+### Issues found
+
+| Severity | Issue | Element |
+|----------|-------|---------|
+| **Critical** | **Mobile layout is broken** -- at 375px width, the sidebar overlaps the main content. The KPI strip cards are truncated ("LO...", "AC..."). The header bar overflows. Content is unreadable. | Full page at mobile widths |
+| Important | **Tablet layout (768px) is functional but crowded** -- sidebar takes significant width, header bar items are compressed ("Se..." for Search), but content is readable. KPI strip wraps correctly. | Full page at tablet widths |
+| Important | **Sidebar doesn't collapse on mobile** -- there's no hamburger menu or responsive sidebar behavior. The sidebar is always visible, eating screen space on narrow viewports. | Sidebar |
+
+---
+
+## 10. Cross-cutting Concerns
+
+### Loading States
+- Dashboard and License pages both show a centered `Spinner` during loading -- this works well.
+- `EmptyState` component used for "No tenant associated" and "License unavailable" -- good error handling in components.
+
+### Error States
+- Login page error handling is good (alert banner)
+- No visible error boundary for unexpected errors on platform pages
+- Admin route fails silently with HTTP error -- no user-facing error message
+
+### Toast Notifications
+- No toast notifications observed during the audit
+- License token copy should trigger a toast confirmation (if a copy button existed)
+
+### Confirmation Dialogs
+- No destructive actions available on the platform (no delete/deactivate buttons) so no confirmation dialogs needed currently
+
+---
+
+## Summary of Issues by Severity
+
+### Critical (5)
+1. **Label/value collision** throughout Tenant Information card, License Validity, and License Limits sections -- labels and values run together without spacing
+2. **"Open Server Dashboard" appears 3 times** on the dashboard page -- excessive redundancy
+3. **No active state on sidebar navigation items** -- users can't tell which page they're on
+4. **Server-specific header controls shown on platform pages** -- search, status filters, time range, auto-refresh are all meaningless on platform pages
+5. **Mobile layout completely broken** -- sidebar overlaps content, content truncated
+
+### Important (17)
+1. No password visibility toggle on login
+2. Branding says "cameleer3" instead of product name on login
+3. Breadcrumbs always empty on platform pages
+4. Massive empty space below dashboard content
+5. Tier badge color mapping inconsistent between Dashboard and License pages
+6. Status shown redundantly in 3 places on dashboard
+7. No clipboard copy button for license token
+8. Feature badge text mismatch between source and deployed build
+9. "Disabled" badge uses red-ish color (implies error, not "not in plan")
+10. Admin page returns HTTP error with no graceful fallback
+11. Admin section invisible in sidebar despite being admin user
+12. Sidebar collapse button doesn't work (no-op handler)
+13. No clear platform vs server level distinction
+14. Search button does nothing on platform
+15. Status filters and time range interactive but meaningless on platform
+16. User menu only has Logout (no profile/settings)
+17. Sidebar doesn't collapse/hide on mobile
+
+### Nice-to-have (8)
+1. No "Forgot password" link on login
+2. Login page title uses "cameleer3" branding
+3. No external link icon on "Open Server Dashboard"
+4. Avatar shows "AD" for "admin"
+5. No units on limit values
+6. Dark mode warm-toned (not standard cool dark)
+7. No Enter-key submit hint
+8. No tenant ID in breadcrumb/subtitle
+
+---
+
+## Overarching Assessment
+
+The platform UI currently feels like a **thin shell** around the server dashboard. It has only 2 functioning pages (Dashboard and License), and both suffer from the same fundamental layout bug (label/value collision in Card components). The header bar is entirely borrowed from the server observability UI without any platform-specific adaptation, making 70% of the header controls irrelevant.
+
+**Key architectural concerns:**
+1. The TopBar component from the design system is monolithic -- it always renders server-specific controls (status filters, time range, search). The platform needs either a simplified TopBar variant or the ability to hide these sections.
+2. The sidebar uses `Sidebar.Section` (expandable groups) as navigation links, which prevents active-state highlighting. It should use `Sidebar.Link` or a similar component.
+3. The platform provides very little actionable functionality -- a user can view their tenant info and license, but can't manage anything. The "Server Management" card is just a link to another app.
+
+**What works well overall:**
+- Design system integration is solid (same look and feel as server)
+- Dark mode works correctly
+- Loading and error states are handled
+- Login page is clean and functional
+- KPI strip component is effective at summarizing key info
+
+**Recommended priorities:**
+1. Fix the label/value collision bug (affects 3 cards across 2 pages)
+2. Hide or replace server-specific header controls on platform pages
+3. Add sidebar active state and fix the collapse behavior
+4. Add clipboard copy for license token
+5. Fix mobile responsiveness
diff --git a/audit/source-code-findings.md b/audit/source-code-findings.md
new file mode 100644
index 0000000..04f6679
--- /dev/null
+++ b/audit/source-code-findings.md
@@ -0,0 +1,433 @@
+# Cameleer SaaS UI — Source Code Audit Findings
+
+**Audit date:** 2026-04-09
+**Scope:** `ui/src/` (platform SPA) + `ui/sign-in/src/` (custom Logto sign-in)
+**Design system:** `@cameleer/design-system@0.1.38`
+
+---
+
+## 1. Layout and Styling Patterns
+
+### 1.1 Container Padding/Margin
+
+All three page components use an identical outer wrapper pattern:
+
+```tsx
+// DashboardPage.tsx:67, LicensePage.tsx:82, AdminTenantsPage.tsx:60
+
+```
+
+**Verdict:** Consistent across all pages. However, this padding is applied by each page individually rather than by the `Layout` component. If a new page omits `p-6`, the layout will be inconsistent. Consider moving container padding to the `Layout` component wrapping ``.
+
+### 1.2 Use of Design System Components vs Custom HTML
+
+| Component | DashboardPage | LicensePage | AdminTenantsPage |
+|-----------|:---:|:---:|:---:|
+| Badge | Yes | Yes | Yes |
+| Button | Yes | - | - |
+| Card | Yes | Yes | Yes |
+| DataTable | - | - | Yes |
+| EmptyState | Yes | Yes | - |
+| KpiStrip | Yes | - | - |
+| Spinner | Yes | Yes | Yes |
+
+**Issues found:**
+
+- **LicensePage.tsx:166-170** — Raw `