For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: On the document detail view, collapse the sidebar to its 60px icon rail (no expansion) and cap the PDF pane at 720px so the data panel grows to fill the remaining width.
Architecture: Pure CSS-driven. Add a :compact-sidebar? option to app.ui.layout/base that toggles a compact-sidebar-mode class on <body>. New CSS rules scoped to body.compact-sidebar-mode mirror the existing @media (max-width: 1023px) collapse rules. The PDF panel max-width changes from 100% to 720px; flexbox redistributes the leftover space to the data panel automatically. The detail page passes :compact-sidebar? true when calling layout/base. No JS, no new markup beyond the body class.
Tech Stack: Clojure (Hiccup2), CSS (custom properties, flexbox).
Spec: docs/superpowers/specs/2026-04-09-document-view-layout-design.md
src/com/getorcha/app/ui/layout.clj — add :compact-sidebar? option and body class composition in base.resources/app/public/css/style.css — add new body.compact-sidebar-mode rule block; change .pdf-panel max-width from 100% to 720px.src/com/getorcha/app/http/documents/view/shared.clj — pass :compact-sidebar? true from detail-page into layout/base.No new files. No tests added — app.ui.layout has no existing unit tests, and the changes are verified visually in the browser plus via clj-kondo linting.
:compact-sidebar? option to layout/baseAdd a new option to com.getorcha.app.ui.layout/base that composes a compact-sidebar-mode class onto the <body> element alongside the existing super-admin-mode class. No visual effect yet — just the plumbing.
Files:
Modify: src/com/getorcha/app/ui/layout.clj:189-231
Step 1: Update the base function's docstring, destructuring, and body-class composition
Replace the current base function (lines 189–231) with this version. Three edits in one: (a) document the new :compact-sidebar? option, (b) destructure it with a default of false, (c) replace the inline (when (and is-super-admin? …) "super-admin-mode") with a let-bound body-class that composes both classes via a cond.
(defn base
"Wraps content in base HTML structure with nav and scripts.
Arguments:
- request - Ring request map (identity and router extracted)
- opts - Options map with:
- :title - Page title (appended to 'Orcha - ')
- :active-nav - Keyword for active nav item (:documents, :settings)
- :show-sidebar? - Whether to show the sidebar (default true)
- :compact-sidebar? - Whether to render the sidebar as a 60px icon rail
with labels hidden (default false). No hover-expand;
used on pages where the user is deep-focused on
content (e.g. the document detail view).
- :tenants - List of all tenants (for super admin dropdown)
- :current-tenant-name - Name of currently selected tenant (for super admin banner)"
[{:keys [identity :reitit.core/router] :as _request}
{:keys [title active-nav show-sidebar? compact-sidebar? tenants current-tenant-name]
:or {show-sidebar? true
compact-sidebar? false}}
& content]
(let [is-super-admin? (:identity/is-super-admin identity)
super-admin-mode? (and is-super-admin?
current-tenant-name
(not= "Orcha" current-tenant-name))
body-class (cond
(and super-admin-mode? compact-sidebar?) "super-admin-mode compact-sidebar-mode"
super-admin-mode? "super-admin-mode"
compact-sidebar? "compact-sidebar-mode")]
(hiccup/html (hiccup.util/raw-string "<!DOCTYPE html>")
[:html {:lang "en"}
[:head
[:meta {:charset "UTF-8"}]
[:meta {:name "viewport" :content "width=device-width, initial-scale=1.0"}]
[:title (str "Orcha" (when title (str " - " title)))]
[:script {:src "https://unpkg.com/htmx.org@2.0.4"
:integrity "sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+"
:crossorigin "anonymous"}]
[:script {:src "https://unpkg.com/htmx-ext-sse@2.2.2/sse.js"}]
[:script {:src "https://code.iconify.design/iconify-icon/2.1.0/iconify-icon.min.js"}]
[:link {:rel "icon" :href "/public/images/orcha-icon.png" :type "image/png"}]
[:link {:rel "stylesheet" :href (str "/public/css/style.css?v=" assets-version)}]]
[:body {:class body-class
:hx-headers "{\"Accept\": \"text/html\"}"}
[:div.app-container
(when show-sidebar? (nav router active-nav identity tenants))
[:main.content
(when super-admin-mode?
(super-admin-banner current-tenant-name))
content]]
(when show-sidebar? (footer))]])))
Notes on what changed from the original:
Docstring gains a :compact-sidebar? entry.
Destructuring adds compact-sidebar? with default false.
The outer let now binds super-admin-mode? and body-class (previously only is-super-admin?).
The [:body {:class …}] attribute uses body-class instead of the inline when.
The super-admin-banner check inside .content reuses the super-admin-mode? binding — a small consistency cleanup that removes the duplicated (and is-super-admin? …) expression. No behavior change.
Step 2: Lint
Run:
clj-kondo --lint src/com/getorcha/app/ui/layout.clj
Expected: linting took Xms, errors: 0, warnings: 0. Fix any issues before committing.
If the REPL is running, reload namespaces:
(require 'com.getorcha.app.ui.layout :reload)
Open any app page in the browser (e.g. /app/ap). Confirm:
<body class="super-admin-mode"> (when in super-admin mode) or <body> (otherwise) — i.e., the new code path produces the same output as before when :compact-sidebar? is not passed.If the REPL is not running, this is deferrable to the end-to-end verification in Task 5.
git add src/com/getorcha/app/ui/layout.clj
git commit -m "feat(app/layout): add :compact-sidebar? option to base"
body.compact-sidebar-modeAdd a new CSS rule block that mirrors the existing @media (max-width: 1023px) collapse rules but triggers on the compact-sidebar-mode body class instead of viewport width. Standalone commit: at this point no page uses the class, so the only visible effect is that a browser DevTools "Add class" experiment on <body> collapses the sidebar.
Files:
Modify: resources/app/public/css/style.css — insert a new block after the @media (max-width: 1023px) block (which ends at line 346 in the current file)
Step 1: Insert the compact-sidebar-mode rule block
Find this closing brace of the @media (max-width: 1023px) block (around line 346):
/* Content adjusts */
.content {
margin-left: 60px;
}
}
Immediately after it, insert the following new block (before the /* Page header */ comment on line 348):
/* Compact sidebar mode — forced icon rail regardless of viewport.
Applied via body.compact-sidebar-mode on pages where the user is
deep-focused on content (e.g. the document detail view). No hover-expand;
users click an icon to navigate away. Mirrors the @media (max-width: 1023px)
collapse rules above — the two triggers are intentionally independent. */
body.compact-sidebar-mode {
--sidebar-width: 60px;
}
body.compact-sidebar-mode .sidebar {
width: 60px;
padding-bottom: 12px;
overflow: visible;
}
body.compact-sidebar-mode .logo {
display: flex;
justify-content: center;
padding: 16px 0 10px;
}
body.compact-sidebar-mode .logo-full { display: none; }
body.compact-sidebar-mode .logo-icon {
display: block;
width: 28px;
height: 28px;
}
body.compact-sidebar-mode .nav-items li a {
justify-content: center;
padding: 12px 0;
gap: 0;
}
body.compact-sidebar-mode .nav-items li a span { display: none; }
body.compact-sidebar-mode .nav-items li a iconify-icon { font-size: 20px; }
body.compact-sidebar-mode .nav-items li.active a {
padding-left: 0;
border-left: 2px solid #58a6ff;
}
body.compact-sidebar-mode .sidebar-user { padding: 8px 0; }
body.compact-sidebar-mode .user-trigger {
justify-content: center;
padding: 8px;
}
body.compact-sidebar-mode .user-name,
body.compact-sidebar-mode .user-chevron { display: none; }
body.compact-sidebar-mode .user-menu { display: none; }
body.compact-sidebar-mode .content {
margin-left: 60px;
}
Hard-refresh any app page (the CSS is cache-busted by assets-version, but use Cmd/Ctrl-Shift-R to be safe).
In DevTools, select the <body> element and add compact-sidebar-mode to its class list. Confirm:
.logo-icon), not the full word mark (.logo-full)..content left margin shrinks to 60px (content shifts left to meet the narrower sidebar).Remove the class from <body>; the sidebar returns to 300px (or its responsive width).
git add resources/app/public/css/style.css
git commit -m "feat(app/css): add body.compact-sidebar-mode rule block"
.pdf-panel at 720pxReplace the .pdf-panel max-width: 100% with max-width: 720px. On its own this already affects every document detail page — flex redistribution means the data panel grows on wide viewports even before the compact sidebar lands.
Files:
Modify: resources/app/public/css/style.css — the .pdf-panel rule (find by content match below; line number may have shifted after Task 2)
Step 1: Change .pdf-panel max-width
Find:
.pdf-panel {
flex: 1;
min-width: 300px;
max-width: 100%;
background: #161b22;
border: 1px solid #30363d;
border-radius: 8px;
overflow: hidden;
resize: horizontal;
Change the max-width line to:
max-width: 720px;
So the block becomes:
.pdf-panel {
flex: 1;
min-width: 300px;
max-width: 720px;
background: #161b22;
border: 1px solid #30363d;
border-radius: 8px;
overflow: hidden;
resize: horizontal;
Leave all other declarations in the block untouched (including resize: horizontal — users who manually drag the resize handle past 720px will still be clamped by the new cap).
Hard-refresh and open any document detail page. Expected:
On a wide viewport (≥1564px), the PDF pane is visibly narrower than half the container; it's capped near 720px and the data panel has grown to absorb the extra width.
On a narrower viewport (<1564px), the panels split roughly 50/50 as before (both panels have flex: 1; the max-width only kicks in when half-width would exceed 720px).
No horizontal scrollbar inside the panels.
PDF still renders via view=FitH (the PDF scales to fit the narrower pane automatically).
Step 3: Commit
git add resources/app/public/css/style.css
git commit -m "feat(app/css): cap .pdf-panel max-width at 720px"
:compact-sidebar? true on the detail pagePass the new option into layout/base from view.shared/detail-page. This is the task that activates the compact sidebar on the document view.
Files:
Modify: src/com/getorcha/app/http/documents/view/shared.clj:766-771 (the app.ui.layout/base call inside detail-page)
Step 1: Add :compact-sidebar? true to the options map
Find (around line 766):
(app.ui.layout/base
request
{:title page-title
:active-nav (if is-ap? :documents :document-management)
:tenants tenants
:current-tenant-name current-tenant-name}
Change to:
(app.ui.layout/base
request
{:title page-title
:active-nav (if is-ap? :documents :document-management)
:compact-sidebar? true
:tenants tenants
:current-tenant-name current-tenant-name}
(One new line added. The rest of the detail-page function is unchanged.)
Run:
clj-kondo --lint src/com/getorcha/app/http/documents/view/shared.clj
Expected: errors: 0, warnings: 0.
In the REPL:
(require 'com.getorcha.app.http.documents.view.shared :reload)
Navigate to a document detail page (e.g. open any invoice from the AP list). Expected:
Sidebar is 60px icon rail.
Logo shows the icon only.
Nav items show icons only (hover an icon and the browser native title tooltip reveals the label).
Clicking any sidebar icon navigates away (the compact mode is per-page, not persisted).
PDF pane caps at 720px.
Data panel fills the rest of the horizontal space.
Clicking "Back" (or navigating to the AP list) restores the full 300px sidebar — only the detail page is compact.
Step 4: Commit
git add src/com/getorcha/app/http/documents/view/shared.clj
git commit -m "feat(app/view): compact sidebar on document detail page"
Final manual verification across the dimensions called out in the spec's Testing section. Catches interactions between the compact class and the existing media queries, the super-admin banner, and the list pages.
Files: none.
Resize the browser to ~1800px wide. Open a document detail page. Confirm:
Sidebar is 60px icon rail.
PDF pane visibly caps around 720px (eyeball it against a window ruler or DevTools).
Data panel is noticeably wider than it was before this change — at ~1800px viewport it should be roughly ~900px wide (1800 − 60 sidebar − 48 content padding − 16 gap − 720 PDF ≈ 956px).
Scrolling inside the data panel works normally.
Step 2: Medium viewport (1024–1599px) — detail page
Resize to ~1280px wide. Expected:
Sidebar is 60px icon rail (from body.compact-sidebar-mode, not the media query — the @media (max-width: 1023px) breakpoint hasn't triggered yet).
PDF and data panels split roughly 50/50. PDF is below 720px (at ~1280px viewport, each panel is ~580px).
Step 3: Small viewport (≤1023px) — detail page
Resize to ~900px wide. Expected:
Sidebar is 60px icon rail (both triggers now fire — the media query and the body class — with identical visual result).
PDF and data panels split roughly 50/50 at ~390px each; PDF is well below 720px.
Step 4: List pages unaffected
Navigate to the AP list (/app/ap). Resize back to a wide viewport (≥1400px). Expected:
.pdf-panel on this page, so the max-width change doesn't apply.Repeat for Document Management, Workflows, Settings. All should render with the full sidebar.
If you have a super-admin account locally, switch to a non-Orcha tenant and open a document detail page. Expected:
.content as usual.<body class="super-admin-mode compact-sidebar-mode"> (both classes composed).If you don't have a local super-admin account, verify this by inspecting the rendered HTML: the body-class cond branch is covered by unit-reading the code (the (and super-admin-mode? compact-sidebar?) branch produces "super-admin-mode compact-sidebar-mode").
No code changed in this task — it's pure verification. If any step failed, go back and fix the offending task.