LifeLab · lens · aesthetics + workspace

The view is a lens. So depth is the wrong thing to draw.

Three aesthetic directions for lenses, all built on one move: stop encoding nesting depth and start encoding what a keystroke will do. Nested-darker was a nice trick that answers a question nobody asks — how deep am I? — while spending the loudest visual channel in the app, and it bottoms out at mud by depth three. The questions people actually ask a lens are where will this block land, what does × mean here, and where do my keys go.

0 · the argumentwhat the pixels should be paid to say

01

Darker = heavier = more important. That's backwards: a nested lens is usually less important than the river it sits in. Recede by fading ink, not by stacking surfaces — the terminal move, not the card move. Paper stays one continuous sheet.

02

Depth is free from indentation already. A gutter rule plus 18px of indent tells you depth at any level. Spend colour and weight on contract instead: solid = owned here, dashed = a window onto elsewhere, dotted = a predicate's result.

03

If the view is a lens, the title is an expression. project/LifeLab + {todo :urgent:} is the page header. Editing the header re-frames the workspace in place — which is exactly the job tabs were doing badly.

04

Zoom replaces navigation. Press on any lens header and that lens becomes the whole view; the frame you were in stays as a gutter breadcrumb, esc drops back. No history stack, no tab bar — one canvas, one focus.

contract

What ×, drag and typing do. Never ambiguous.

gutter rule style

focus

Where the keys land. Exactly one lens is hot.

ink contrast

home

The block's canonical page. Survives every sort.

right-margin path

depth

Interesting to the renderer, not the reader.

indent only

A · apertureone sheet · lenses are cuts, not cards · unfocused lenses fade in ink

home·dayweekmonthfind/goSPCdo:·context

project /

LifeLab{todo:urgent:deadline:..+1w}⋎ +

the view is a lens · 5 of 31 blocks · reframe · p pin

page2
*TODOFinalize release notes:urgent:jul 24
*TODOSign the macOS build:urgent:jul 25

+ Add to project/LifeLab — TODO and :urgent: applied

[−]LifeLab/frontendreferenced1 of 6
*TODORecord the Lens walkthrough:urgent:
[−]:blocked:computed · 2mark on drop
*TODOWait on the notarisation ticketperson/Ada
*TODOScreen recording rightsproject/LifeLab/docs
[+]LifeLab/docsreferenced1 of 4
[−]linkedcomputed · 1journal
*TODOVerify the Windows installerjournal/2026-07-22

What changed: subpages and linked stopped being two fixed footer sections and became ordinary lenses in the river — you can fold them, filter them, reorder them, or delete them like anything else. Depth costs nothing but indent, so depth six still reads. The dim isn't decoration: only the full-contrast region takes your keystrokes, and hovering any dim lens brings it to 80% so you can read without committing. Gutter tells you the deal — solid you own, dashed is a window onto another page, dotted is a predicate.

costCheapest to build (opacity + border-style), scales infinitely, and it's the most honest to the app's text-first character. Risk: at 45% ink the dim lenses may read as disabled rather than unfocused — needs a real contrast pass, and probably a floor of 60% for anything containing a TODO.

B · aperture platenesting goes lighter, not darker — light through a cut, with crop marks

home·dayweekmonthfind/goSPCdo:·context

project /

LifeLab{todo:urgent:}⋎ +

the view is a lens · 5 of 31 blocks · plates are apertures, one tint deep

*TODOFinalize release notes:urgent:jul 24
*TODOSign the macOS build:urgent:jul 25
[−]LifeLab/frontendtodoreferenced1 of 6
*TODORecord the Lens walkthrough:urgent:
[−]:blocked:computed2
*TODOWait on the notarisation ticketperson/Ada
*TODOScreen recording rightsLifeLab/docs

+ Add to LifeLab/frontend — TODO applied

[−]linkedcomputed1
*TODOVerify the Windows installerjournal/2026-07-22

+ Add to project/LifeLab

The inversion: the page surface drops half a step (#f2f1e8) and every lens plate goes lighter (#fdfcf8) — so a transcluded page reads as light coming through a hole in the sheet rather than a card set on top of it. Depth alternates paper/light rather than accumulating, so it never muddies; past two levels only the gutter and label distinguish. Crop-mark corners say "this is a framing of something that exists elsewhere" without a heavy border. Focus is a 2px olive cap on the plate's left edge, not a change of fill.

costMost legible boundary of the three, and the one that best survives a lens with mixed content (code blocks, tables, images) — a plate contains them, ink-fade doesn't. Risk: plates are boxes, and boxes creep toward the card-app look this design has been carefully avoiding. Also fights dark theme, where "lighter = nested" means glow.

C · spinethe lens header moves into a 19px rail — so lenses can sit side by side in the flow

home·dayweekmonthfind/goSPCdo:·context

review /

Launch week{todo:urgent:}render:cols

4 lenses summoned · ⌥← ⌥→ move focus · zoom · q dismiss

*One project, wherever the work lives
*Every lens keeps its rows on their canonical home page.
[−]owned2
project/LifeLabtodo
TODOFinalize release notes
TODOSign the macOS build

+ Add…

[−]ref2
…/docstodo
TODOReplace the README hero
DONEScreenshot pass
[−]comp1
:urgent:..+1w
TODOVerify installerjournal/07-22
[+]ref6
…/frontendtodofolded
+

+ Summon a page or tag into this row…

Why a spine: once the fold, contract, and count live in a vertical rail instead of a horizontal header, a lens no longer needs full width — so render:cols can lay two or three lenses across the river and they still read as part of one document. This is the tab-killer in its most literal form: the things you'd have opened in tabs are all on screen, in the flow, at the position you put them, with drag-reparent working between them.

costHighest information density and the strongest "workspace" feel, but it's also the most machinery: a rail is a widget, rotated labels are hard to scan, and narrow columns break the long-line text editing that block content actually needs. Best read as a moderender:cols on a review page — layered on A, not a replacement for it.

the tab-killersummon → pin → zoom → drop back · four states, no navigation

1 · summon. on any reference
*TODOVerify the installer:project/LifeLab:
project/LifeLabtodoesc drop · . keep
TODOFinalize release notes
TODOSign the macOS build

A flash lens: dashed, transient, never written to the file. Reading a linked page costs one keystroke and zero navigation.

2 · keepwrites ![[…]]{todo}
*TODOVerify the installer:project/LifeLab:
[−]project/LifeLabtodo2
TODOFinalize release notes
TODOSign the macOS build

The dashes solidify into a referenced gutter. The transient becomes text — and text is the durable definition.

3 · zoom on the header
injournal/2026-07-22{todo}esc
LifeLab{todo}

now the whole view · same lens, same state

TODOFinalize release notes
TODOSign the macOS build

Zoom is not navigation: the lens didn't change, its frame did. The breadcrumb is the lens you were inside, one esc away.

drop targets — drag means three different things

TODORenew renter insurance
▾ body of project/LifeLabre-home the block
▾ onto the chips :urgent:make it match — tags it, leaves it home
▾ onto a folded spinere-home without opening

"Make it match" is the gesture the computed contract has been missing: dropping onto a predicate's chips edits the block until it qualifies rather than moving it. Same drag, two outcomes, disambiguated by the pixel you release on.

why this removes the need for tabs

reframe
The header is an expression. Changing your question doesn't need a second window — it's an edit.
summon
Any reference opens in place. Peeking never costs you your position.
zoom
Any lens can become the view and drop back. Depth of attention without a history stack.
compose
Several lenses live in one document, arranged by you. That arrangement is the saved workspace — no session state, just text.
one focus
Exactly one lens is hot. Tabs exist to hold context you can't see; here the context is the page.

recommendationnot a pick-one

Ship A as the substrate. It's the only one that scales to arbitrary depth, it removes machinery rather than adding it, and it re-founds the model correctly: subpages and linked stop being special footers and become ordinary lenses you can fold, filter, and reorder. Borrow B's plate for one case only — a lens containing non-text content (code, table, image), where ink-fade can't establish a boundary; keep it lighter-not-darker so depth never muddies. Keep C as render:cols, an opt-in mode for review pages, not the default river.

The open question I'd want to test first: whether ink-fade reads as unfocused or as disabled. If the second, the fallback is fading only the chrome (labels, counts, gutters) and leaving block text at full contrast — quieter than dimming everything and still unmistakable about where the keys go.