# Board UI

The board window: layout, lanes, cards, and styling. Interaction mechanics (selection, drag, keyboard) are in 04-interactions.md.

## Layout — full visibility

- **Every lane is always on screen.** The window width divides across the lanes' width units — no horizontal scroll, no enforced minimum lane width. Resizing the window is the width control. (Settled emphatically in the old app: horizontal scroll strays from what kanban is for.) The degenerate case is accepted, not floored: enough lanes/units in a small window compress every lane, titles and cards truncate gracefully, and the remedy is the user's (fewer units, bigger window). A minimum-width setting that reintroduces scroll was considered in the pathfinder and deliberately rejected. **Lane-count changes re-divide, never resize**: new lane (⇧⌘N), lane paste or cross-board lane drop, lane delete (and its undo), and Show/Hide Trash (the trash lane's fixed unit joins and leaves the division — Trash below) all re-divide the existing window width across the new unit total — window-growing behavior belongs to the right-edge drag alone (Lane below).
- A lane spans a **whole number of width units** (`width` frontmatter, ≥ 1, no cap). Cards stay standard width; a wide lane flows them into as many interior masonry columns as it has units.
- **Zoom scales the ruler, never the strip** (settled 2026-08-02 — View ▸ Zoom In / Zoom Out / Actual Size, 11-command-nexus.md). The board's whole geometry is already derived from the body font's point size (10-accessibility.md ▸ Full relative scaling — every figure an em multiple, no fixed point sizes), and macOS supplies no text-size control to move it, so the zoom commands *are* that control: a rung on the level ladder raises the effective body size, and type, card chrome, lane chrome and card heights grow together off it. **Full visibility above is untouched, and that is the whole design constraint**: a canvas magnification would have to widen the strip and reintroduce the horizontal scroll this section rejects, so zoom does not do that — lane *width* stays the window's division at every rung. Zoom does move the inter-lane gap (an em multiple like everything else), so lanes narrow by a few percent across the ladder's whole range; the felt effect is the intended one — zoom in for bigger, more legible cards and fewer per screen, out for a denser board. **The level is app-wide, persisted, and never a property of a board**: it lives beside Show Comments in the app's preferences, not in any lane's or board's frontmatter, because it describes how a user likes to read rather than what a board is. **Zoom never moves the window** — the minimum content size stays pinned to the *system* body size, since window-growing behavior belongs to the right-edge drag alone (Lane below).
- New lanes are created via a **File-menu item** (the one committed surface; ⇧⌘N — 11-command-nexus.md); new cards from the lane (see 04-interactions.md for creation flows). **The created lane becomes the sole selection** (settled): ⇧⌘N → Board ▸ Rename is a pure keyboard path — the create-then-act texture (Return-creation re-selects its lane, ⌫ picks a successor).

## Toolbar (board + card windows)

Toolbars are **pure enhancement**: every function they host already has a menu item + shortcut (04-interactions.md's contract), so nothing below is anyone's only path. Both windows' toolbars are **user-customizable, macOS-native** (right-click ▸ Customize Toolbar…, drag to rearrange, system overflow and icon/text display options) — the sets below are shipped defaults, not verdicts. Toolbar item labels match their menu-item titles exactly (Show Trash, Edit Body, Raw Source, …), minus any trailing ellipsis (macOS convention: "Add Attachment…" labels as Add Attachment) — one vocabulary everywhere, and the customize palette self-documents against the menus. One exception: the Undo/Redo toolbar items keep static labels — NSUndoManager rewrites their menu titles dynamically ("Undo Move Card…", 04-interactions.md ▸ Configurable bindings), which a toolbar label doesn't track.

- **Board window default: the search field and Appearance** — both **centered** (ratified 2026-08-06 off the 2026-08-01 live try-out, reversing the earlier trailing ruling; Appearance joined the default set 2026-08-07 — 11-command-nexus.md ▸ View ▸ Appearance): the titlebar reads as a placement grammar — leading is board identity (the title widget), center is view controls (search and the app's Auto/Light/Dark override today, the filter family if one ever grows), trailing remains the user's catalog space. The mechanism is `NSToolbar.centeredItemIdentifiers`, deliberately not a flexible-space sandwich: it centers against the window rather than leftover space, holds as catalog items install, and sits outside the autosaved configuration, so it takes effect on machines with a saved arrangement — and `defaultItems` is unchanged, keeping the pinned default-set tests standing. The known tensions were weighed and accepted at ratification: the 400pt leading widget and a centered field share the titlebar's budget in narrow windows (the squeezed field's expand-in-place answer below is the relief), and HIG's trailing-edge convention yields to the grammar. The titlebar stays clean. ⌘F always summons search: with the field removed from the toolbar, invoking it surfaces the field transiently until the search clears. **A squeezed field expands in place; the strip answers only genuine unreachability** (blessed 2026-08-06): a space-constrained `NSSearchToolbarItem` collapses to a magnifying-glass button still in the window, and ⌘F expands and focuses it — the toolbar's own field, a better surface than the fallback — so the transient strip fires only for a truly windowless field (true overflow, or the item removed from the toolbar). **The item's overflow row is the platform's own second answer, and the duality is blessed** (2026-08-06): AppKit's overflow menu row carries a live action that widens the window until the field is usable, and suppressing it would destroy the honest overflow presentation — so a squeezed toolbar reaches search two ways with two honest resolutions: ⌘F expands the item or surfaces the strip (ours), the overflow row grows the window (the platform's) — different gestures, reasonable respective outcomes, no contradiction to resolve. **The field is the platform's own search toolbar item and grows on focus** (2026-08-01): the em-derived width is the *focused* width — applied when the field takes the keyboard, expanding via the item's own animation — and the resting width is AppKit's natural one, not the app's to set. **The two-homes width rule is focused-width parity** (ruled 2026-08-01): the width the user *types in* is the same em-derived figure whichever home the field is in — the toolbar item focused, or the transient strip; the toolbar field's resting width is outside the invariant (the strip never rests — it exists only while a search is live or focused, so it has no collapsed state to mirror). **Catalog** (available via Customize): New Card, New Lane, Zoom In, Zoom Out (the zoom pair is catalog-only, unlike Appearance below — the titlebar's default is the search field plus Appearance, nothing more; each disables at its end of the ladder, and both disable mid-drag like their menu rows — Layout ▸ zoom above), Undo, Redo (the pair disabled only under locks and on empty stacks — re-ruled 2026-07-31, twice: the provider follows the board, so boards without app-managed git — repo-nested included — bind 13-native-undo.md's native stack in **every** tier and Pro git boards bind the git provider — 06-history-undo.md), Show Trash (toggle state matching the View menu checkmark), Appearance (a pull-down of Auto/Light/Dark — 11-command-nexus.md ▸ View ▸ Appearance; the one catalog command that also ships as a default item, centered beside search rather than reached through Customize). The board popover deliberately has **no toolbar item** — the window-title widget is its committed home (below), and a second entry would muddy it.
- **Card window default: Edit Body · Raw Source · Add Attachment** — the window's three committed functions, all discoverable from its toolbar; the catalog is the same trio. Edit Body is a **single toggle button** (on-state in Edit — mirroring the View ▸ Edit Body checkmark and the ⌘E/Return/Escape grammar; the pathfinder's segmented Preview|Edit is retired). Raw Source is likewise a toggle showing on-state; while source mode is active, Edit Body disables (Cancel/Apply own the exits — 05-card-window.md). Add Attachment stays enabled in every mode — attachment operations never touch `index.md`, so they're safe alongside a raw edit (the sidebar's feedback returns on exit).

## Lane

- Title bar: leading SF Symbol (the lane's `icon`), title, **card-count badge** (quiet, secondary styling), the collapse chevron (below). The whole title bar is the lane's drag surface — no separate grip; a plain click (no movement) on it selects the lane (04-interactions.md ▸ Selection). **No header card-creation control** (removed): the header carried a "+" new-card button through m5; it is gone, and every other creation path — ⌘N, Return on a selected lane, double-click on lane empty space — is unchanged. **The lane has one context menu** (settled), invoked on the header or on lane empty space alike — Rename, Style…, the quick-style recents row, the Width stepper, Delete (inventory normative in 11-command-nexus.md ▸ Context menus); a full lane still has its header, so the menu is always reachable. The count reads the search filter like every other surface (04-interactions.md): during a search it shows the visible count, not the total.
- Body: vertical card stack (masonry grid when wide — settled, the pathfinder's masonry works), scrolls vertically.
- Right-edge **drag-to-resize** between integer widths (1×, 2×, 3×, … — no cap): shadow snaps at the inter-column gap with 10pt release hysteresis; the window grows/shrinks by one standard width per snap so other lanes keep their exact size. **At the screen's visible frame the window stops and the drag degrades to the re-divide** (settled 2026-08-08, superseding the pathfinder's hard stop): further snaps re-divide the now-fixed width across one more unit each — siblings compress, exactly the stepper's mechanism — so a lane keeps growing at the siblings' expense once the screen is spent; a window with no headroom to begin with (already at the edge, or full screen) re-divides from the first snap. The two regimes meet without a pixel jump — the re-divided standard at the screen fit *is* the frozen standard. Shrinking mirrors it: re-divide back down to the screen fit, then window shrinking resumes (and shrinking is always allowed). The rubber-band feedback (the dragged edge gives a fraction of the overshoot and snaps back, signalling the bound) moves to the true end of travel — the strip's own capacity — and the window still never overflows the screen. The header context menu's Width control (stepper, uncapped) remains the precise control: it never touches the window, it **re-divides** the existing width across the new unit total (siblings compress); the drag now reaches those widths too, but the stepper stays the exact, accessible path. The **Increase/Decrease Lane Width menu items (⌥⌘→/⌥⌘← — 11-command-nexus.md) are this stepper's keyboard face** — same re-divide semantics, never the window's size; window-growing behavior belongs to the drag alone — and they **batch over a multi-lane selection** (settled, the styling precedent): each selected lane steps one unit, one gesture, one commit; the context-menu stepper itself stays single-lane by nature. **A width write landing on 1 removes the `width` key** (settled — the remove-at-default family: the empty rename removes `title`, the None well removes `background`): a default lane's frontmatter stays clean, drag, stepper, and menu items alike; a hand-written `width: 1` is legal and preserved until the app itself next edits width. **A failed width commit at drag release rolls the window back** (settled): the failure surfaces as the ordinary one-shot banner and the window animates back by the uncommitted delta — 02-architecture.md's write-failure honesty (the action visibly doesn't happen) applied to the one control that moves the window.
- **Collapsed lanes** (settled 2026-08-08): a lane folds to a **fixed slim vertical strip** — its `icon`, its card-count badge, its title rotated a quarter turn **counterclockwise so it reads bottom-up** (the book-spine orientation) and **justified to the top** of the room below that chrome (ruled by the owner 2026-08-08, reversing the top-down reading of the first pass), and its accent band, at a fixed width (~44pt, an em multiple like every other figure) — and **the strip is not part of the width re-division**: the window's width divides across the *expanded* lanes' units alone, with each collapsed strip's fixed width taken off the top, so folding a lane is a re-divide trigger of the Show/Hide Trash family (the window never moves and the siblings grow into what the lane gave up). Persistence is a first-class lane frontmatter key, `collapsed: true` — **document state exactly like `width`**, because the files are the board and an agent must be able to fold a lane by editing frontmatter; absent means expanded, expanding **removes** the key (never writes `false` — the remove-at-default family), and the lane's `width` is preserved untouched while collapsed so expanding restores the lane the user had. **Toggling**: the header's trailing collapse chevron (always visible, not hover-revealed — the header has no hover chrome to match), the lane context menu's single **Collapse Lane** / **Expand Lane** row (single-lane like the width stepper, not batched), and a plain click anywhere on the collapsed strip, which expands it; a modified click on the strip stays the ordinary selection grammar, so a folded lane is still selectable by pointer. Rename and the expanded header's double-click behaviours are unchanged. **While collapsed**: no resize handle (the width stepper and ⌥⌘→/⌥⌘← still edit the preserved key), and the lane's cards are **not rendered at all** — which is what excludes them from the marquee sweep, from spatial keyboard navigation, and from the ⌥-arrow jumps (↓ from a folded lane is inert, like an empty one), and what makes ⌘N skip the lane for creation (a selection inside a folded lane falls through to the last-active lane rather than refusing). A drop on the strip **appends at the lane's end**, like an end-of-lane drop, with an accent edge standing in for the shadow the strip has no masonry to open; there is no hover-to-auto-expand in v1 (future work). Lane reorder drag works on the strip, and a folded lane's replica and drop shadow are the strip rather than its units. **Search still matches cards in collapsed lanes** — the badge and the flatten lists count them, since collapse is a presentation fold rather than a filter — but the lane stays folded and shows no match: pointing into a folded lane is not something the current search presentation can do, and the honest minimum is that the query does not fold or unfold anything. The **trash quasi-lane is not collapsible**; multi-select styling and the Style editor are unaffected.

## Card face

- Leading icon + title. Two face chips are in scope, both present-only and the same secondary-tinted, decorative styling family: **attachments** (a quiet glyph when the card has files — the title dominates) and **comments** (ruled 2026-08-09, card e729e30a — a quiet bubble glyph plus its count when the card has one or more, joining the attachments chip at the row's trailing edge). Metadata chips (labels/assignees/due) went to the enhanced schema with their fields — out of scope.
- **No body excerpt, but not "closed with no growth"** (re-settled 2026-08-09 — that old phrasing is retired as stale): the face still never draws a preview of the card's own prose, and that stays closed for good. What *has* grown since is exposure of facts the card already carries structurally, never content: the hero banner (below) and the comments chip both draw from a fact — a named attachment, a folder count — that a sighted glance or a screen reader already had another way to learn, not from anything a body excerpt would have shown.
- **Hero image** (ruled 2026-08-09): a card whose `hero` key names one of its own attachments (a bare filename — 01-storage-format.md § Frontmatter's card table) draws it as a **banner across the full plate width above the icon-and-title row**, aspect-fill cropped to a fixed em-scaled band (2.75 em — 36pt at the standard body, so it scales with system text size and board zoom like every other face figure). Set from the card window's **attachment row context menu** — "Set as Hero" on any image row, "Remove Hero" on the current one (re-ruled 2026-08-09, promoting the day-one "future work" note; 05-card-window.md ▸ Attachments) — and hand-written or agent-written exactly as before. One hero per card: Set on a card that already has one **replaces** it, and the row that holds it shows Remove Hero instead, so there is no Remove-then-Set dance. Image rows only, by extension: offering the row on a `.zip` would let a user set a hero that can never draw. A key that is absent, malformed, or names a file that is missing, unreadable or not an image renders **exactly as no key at all** — the band has no height until a picture actually decodes, so the degrade is structural rather than a branch. Everything else the face draws is unchanged and sits outside the band: the accent stripe runs the plate's full leading edge over it, the selection and file-hover strokes ring the whole plate, the cut/drag dims cover it, and the drop model registers the plate's real height — a hero card is simply a taller card. The trash draws it too (the one-face rule). The drag replica carries the band when the picture is already decoded, which it is for any card the user can see to drag.
- **Titles are optional at every level.** On cards and lanes, a missing `title` renders as a quiet placeholder ("Untitled", secondary styling) wherever the title would appear. On boards, the fallback is the folder name (sans extension), never "Untitled" — see 01-storage-format.md's board-naming rule; window title and welcome recents show `title` when present, folder name otherwise.
- Attachments on the face: **the chip only — there is no face carousel** (resettled 2026-07-28, reversing the carry-over): the pathfinder's selection-keyed in-place expansion — compact unselected, media carousel when sole-selected — **proved undesirable and does not carry over**. A card has **one presentation**: selection changes styling (the selection treatment), never geometry, so the masonry never reflows on click and a card face is the same object whatever the selection state. The attachment chip above is the face's whole attachment story; viewing media is the card window's job (⌘↩ / double-click — the attachments section and QuickLook, 05-card-window.md). The earlier 2026-07-28 carousel settlements (metrics, tick paging, clamp, dots, marquee suppression, trash exclusion) are superseded with it — recorded on their Resolved cards.

## Styling

### Capabilities (settled)

- **`background`** on board / lane / card: a mapping, `{color: …, image: …}`, and only a mapping (settled 2026-08-06 — 01-storage-format.md § Frontmatter; a bare scalar has no reading and paints nothing). `color` is a palette name (kebab-case, hand-editable) or a `#RRGGBB[AA]` hex; either subkey may stand alone. Board color paints the board window's content background (the surface behind and between lanes). **A board's background may also carry an image**: the `image` path is relative to the board root so the picture travels with the document. Color and image both paint the **full window** — the content runs under a transparent title bar, with a frosted strip across the title-bar/toolbar band keeping the chrome legible over them; the extended chrome applies only while the board has a background of its own, and a board without one keeps the standard chrome unchanged. The image draws over the color, scaled to fill and cropped, with the color standing in while it loads or if it can't be read; an unresolvable path paints nothing, the lenient degrade an unrecognized color already gets. **The image has exactly one in-app control, and it writes a file rather than browsing for one**: Edit ▸ Paste as Board Background (ruled 2026-08-09) writes the pasteboard's picture into the board folder as `Pasted Background.<ext>` and points `image` at it — the generated-background gesture's shape, minus the colour, because a picture off the pasteboard carries no ground colour to degrade to, so `color` is left exactly as it was. Re-pasting overwrites the board's own file; a file of that name the app did not write is stepped around, Finder-style. There is still **no image picker** — naming a picture that is already somewhere in the folder is the raw file's job, and it stays the escape hatch (the stance custom hex held until the 2026-08-06 combo reversal; for browsing it stands) — and **the board-level ink rule still derives from the color reading alone**: an image makes no AA claim (10-accessibility.md), since a picture has no single luminance to threshold against. Lane and card color are **edge accents, not fills** (settled in the pathfinder's treatment shootout — its settings matrix of C-series lane / K-series card variants landed on **C7 · full-column top edge** and **K1 · left edge stripe**): a lane's color paints a full-width band along its top edge, a card's a stripe along its left edge; the surfaces themselves keep the standard chrome, so colored title text never sits on a colored fill.
- **The standard chrome is the pathfinder's surface stack** (settled 2026-08-06): the window keeps the neutral system background; every lane wears a quiet quaternary-wash plate (the trash plate's own figure — translucent, so a board-chosen color shows through and the board-level ink rule keeps its premise; opaque under Reduce Transparency, the trash precedent); every card sits on an opaque `controlBackgroundColor` plate — white over the washed lane in light appearance, a step *darker* than the window in dark. One plate value for every face a card draws (resting, replicas, placeholder, arriving), so a card is the same object wherever it renders.
- **`icon`**: SF Symbol per item with per-level defaults (board `rectangle.split.3x1`, lane `square.stack`, card `doc.text`).
- **`iconColor`**: resolved — **schema yes, control no**. The field renders when hand-written (tint palette name or hex); the app offers no control for it (Controls below).
- The pathfinder's palettes (12 icon tints, 12 backgrounds; grown to 16+16 on 2026-08-09 — the hue ring's four widest gaps filled at lime 64°, jade 158°, indigo 238°, magenta 312°, S/B set per table's own statistics) carry over as the starting point. **The 12+12 split is a picker split, not a name split** (settled): color resolution searches foregrounds then backgrounds, so a hand-written `background: carnation` (an icon-tint name) resolves and paints — the split governs what the grids offer, never what a name means.

### Controls (settled)

One **style editor** component — a background palette grid and a curated symbol grid — presented as a **popover** opened by Style… from a card/lane context menu or the menu bar (Board ▸ Style…, ⌥⌘S — 11-command-nexus.md; selection-aware: it styles the selected cards or lane, and with nothing selected, the board). One component, one behavior — replacing the pathfinder's swatch-row-plus-Style-popover split, whose functions were right and whose form wasn't. **The card window sidebar now styles through the compact `SymbolPicker` instead of this component** (2026-08-06 anchor-ownership rule for the background half; the symbol half followed the same way on 2026-08-08): the sidebar pairs the **color combo** (below) — standing in for the background half, the narrow context the combo was built for — with the picker's own well and popover-hosted grid, fed `CuratedSymbols`' card-level set, so this component now has exactly one anchor left, the Style… popover, which alone carries both grids in full. (The board popover was briefly a third anchor — the background half embedded in its Theme tab — until the 2026-08-07 Theme rework made that tab preset-only; Style… with nothing selected is the board's manual grid now, and the popover's symbol picker beside the rename field still owns the board glyph — the same `SymbolPicker` the card sidebar now uses.)

- **Curated-first, panel-backed** (re-ratified 2026-08-06, reversing 2026-07-29's palette-only ruling): the background grid offers the 16 palette colors (12 until 2026-08-09) — every one AA-verified through one code path (ratified 2026-07-29: palette names route through the same runtime ink-selection seam as hand-written hex — the appearance flip picks the readable label vocabulary — and PaletteContrastTests pins that the chosen ink meets AA in both appearances for all 16 backgrounds, so palette drift can never silently break it) — plus a leading **None** well that removes the `background` key. Beside the grid the vocabulary now has a second, compact form: the **color combo** — a swatch-faced popup listing None, the role's twelve, the current off-palette value verbatim when there is one, and **Other…**, which opens the system Colors panel. The panel is the in-app escape hatch the 2026-07-29 ruling withheld: a pick landing exactly on a palette color stores the *name* (so a re-pick never drifts to a hex spelling), anything else stores the hex — the same unlimited vocabulary hand-editing always had, now pickable. An arbitrary pick changes no contrast story (it lands on the identical runtime ink computation hand-written hex already gets — 10-accessibility.md), and the quick-style recents stay palette-vocabulary: a panel pick never enters them.
- **Curated symbol grid**: three hand-picked, level-specific sets (~30–40 SF Symbols each, one for boards, one for lanes, one for cards — split 2026-08-09 from an original single ~65-entry list); the grid draws from whichever set matches the target's level, or the three combined for a target spanning more than one (unreachable today under 04-interactions.md's cards-XOR-lanes rule, kept as a real fallback rather than an assumption). Its leading well is the level's default symbol and removes the `icon` key. Any other SF Symbol name works written by hand — named symbols the running OS knows, that is: inventories grow per macOS release, so a newer-OS name renders the level default on an older Mac, value preserved on disk — the palette stance again. **The full-browser stance reversed 2026-08-09** (Pipeline card 5004c540 — the pickers-rhyme pass): the symbol combo's face opens a standalone searchable, categorized browser panel — the Colors-panel move, made for symbols, once the browser could be *derived* rather than hand-curated: the catalog reads the OS's own `CoreGlyphs` plists (categories, order, search terms, restrictions), so it inventories exactly what the running OS renders, drops trademark-restricted glyphs, and grows per macOS release with no app-side list to maintain. The raw file remains the escape hatch for names the browser doesn't surface.
- **Off-palette values display leniently**: a hand-written hex background or uncurated symbol shows as the current value in the editor (labeled verbatim, outside the grids); choosing any well replaces it.
- **Batch edits**: a multi-selection shows per-dimension mixed state (no well selected, "—" where a value would read); choosing a well applies to the whole selection — one gesture, one commit on git boards.
- **The Style… popover tracks its target set live and dismisses when it empties** (settled): its target is the selection, re-resolved across reloads by 02-architecture.md's UUID rule — a member that vanishes or flips liveness leaves the set and the mixed-state display recomputes; a set emptied by a foreign reload dismisses the popover (the inline-rename discard applied here) — it never silently retargets to the board, and nothing writes into a vanished folder (a member moved to the trash leaves the set like any other departure). **The read-only lock instead disables its wells in place** (settled): a popover open when the lock lands stays open, content disabled — the banner names why, and the lock never yanks a surface (the Edit buffer's keeps-its-place posture). The embedded anchors need no rule of their own: the card sidebar dismisses with its card's window, and the board popover's target is the board itself.
- **Quick-style row, recents only**: card and lane context menus carry one compact row of recently used backgrounds plus the Style… item — one-click recolor for the common case; the pathfinder's second full-palette tier is gone. Before any background has ever been applied, the row is omitted entirely — never an empty strip. Recents are app-wide and persist app-side (user preference, never board data).
- **Keyboard path**: Style… is a menu item with a shortcut (04-interactions.md's contract); inside the editor the grids are arrow-navigable and every well Tab-reachable (10-accessibility.md).

## Board popover

**The tabbed popover (2026-08-07, restructure complete — all three tab sessions settled).** The symbol/name header stays at the top — the board's glyph with its tint row beside the rename field; below it sit tabs — **Info**, **Theme**, **Git** — each the settings surface for one aspect of board configuration, each settled in its own dedicated session. **Tab membership is the git posture's** (the Git session's ruling): the Git tab joins the strip only when the git section has something true to say — `BoardGitSection` resolves to anything but absent — so a free-tier board with no `.git` shows Info | Theme alone. This carries 12-editions.md's "absent, no placeholder" rule up to the tab strip: a standing Git tab on every free board would be the standing ad for Pro that 12 forbids. *(Pivot 2026-08-07, same day — 12: git left the paywall, so the absent posture is unreachable and every board carries all three tabs. The membership rule stands structurally — the strip still asks the posture — it just never hears "absent" anymore.)* **Selection resets to Info on every open** (ruled in the Git session, closing the question the earlier tab sessions deferred): the popover is transient and Info is the board's face — and a remembered tab could strand selection on a tab the next posture doesn't offer. *(Added 2026-08-07, the same night the settings sheet retired: a fourth tab, **Sync** — a standing placeholder, last in the strip, rendering one honest "Nothing here yet." caption. It claims the position where the remote half of the git story will live — tracking, Pull/Push, the badges, and whatever home 07-sync-collab.md's setup surfaces are ruled into — without ruling any of that: the open Redesign card owns the question, and the placeholder is deliberately empty rather than a greyed-out preview.)*

**The Theme tab** (settled 2026-08-07, its dedicated session; reworked same day from the first "Background" cut — the style-editor embed was in, then ruled out): a **preset-only** surface — no palette grid, no "Board" subtitle, no manual controls (the manual surface is Style… with nothing selected; the raw file remains the image escape hatch). One **Solid color / Pattern** segmented choice at the top, then the filters that apply to the chosen kind, then one carousel of the eight wheel hues with tall skinny chevrons flanking it (compact-chevron paging buttons, ~three swatches per press, each disabling at its end of the strip). **Solid color** shows Tone (defaults to the current appearance) and Saturation only; the carousel holds flat swatches — each hue at the selected tonality's base saturation and lightness, exactly the primary color the matching facets recipe would write — and clicking one sets `background.color` and *removes* `background.image` in one write (the generated PNG stays on disk so undo can restore the field that pointed at it). **Pattern** is the faceted-background picker (DESIGN/explorations/board-backgrounds.md ▸ Faceted gallery, the reviewed recipe): four filters — Tone and Saturation shared with Solid, plus Colors mono/duo/trio and Mesh coarse/medium/fine — over rendered previews, one seed per hue, plus a Reroll button that re-mints the seeds (filters change the treatment, Reroll the geometry; preview and file share a seed, so what's clicked is what lands). Clicking a pattern swatch renders the recipe at the 3072 px decode ceiling off-main and lands it in one write: the PNG into the board root as `facets.png` (Finder-ladder rename only when a foreign file owns the name), `background.image` pointed at it, and `background.color` set to the recipe's primary color — the underlay that stands in while the image decodes or if the file ever goes missing. The mode opens on whichever kind the board currently wears (Pattern when `background.image` is the generated file, Solid otherwise). **Backgrounds ship as static pixels, never live-rendered views** (the perf/sync ruling, 2026-08-07): the generator runs at pick time, the render loop only ever composites a decoded bitmap. Native undo restores the two fields, not overwritten bytes — regenerating over our own PNG is destructive, documented, and accepted. The whole tab disables under the read-only lock as one surface.

### Info tab (settled 2026-08-07)

The board's vital statistics, read-only, in two registers with one honest split: **model facts** off the live snapshot — Lanes, Cards, Attachments — counting *the board you see* (the welcome-count live-only rule; the Cards row grows a quiet "· N in Trash" tail only when the trash holds anything, counting freight the way the purge confirms do — never a standing "0 in Trash"); and **disk facts** off one background whole-folder walk — File (the `.board` folder's name), Files, Size, Created, Modified — counting *everything*, `.git` and `.trash/` included, because their job is to agree with Finder's Get Info about the same folder (a size that quietly excluded the repository would send a user hunting for missing gigabytes). Disk facts are honest-as-of-appearance, refreshed per tab visit, never live — `FolderWatcher` filters `.git` churn out of the reload stream by design, so there is no event they could honestly hang off, and a ticking size is motion without meaning on a settings surface; an em dash holds each disk row until the walk answers. Modified is the tree's newest content-modification date, directories included (a deletion-only change moves no file's mtime, only its parent folder's); Created is the folder's filesystem birth date, not frontmatter — the folder may predate any stamp in it. A **Reveal in Finder** link closes the tab — the rows describe the folder, and this is the door to it; not disabled under the read-only lock, since revealing is not a mutation.

### Git tab (settled 2026-08-07)

The pre-tab closing git section rehomed whole — and, later the same day, **the retired settings sheet's contents with it**: this tab is where a board's repository is both operated and set up (a repository-facts dossier in the Info register was considered this session and declined — the popover's git surface is for operating, and per-item history is the card History section's). The postures (06-history-undo.md ▸ Rules; 12-editions.md) render one tab surface each, with the tab's own label doing the work the section's "Git" header used to:

- **No repository** → one caption stating the fact, then **add-git** directly under it — the fact-then-offer posture blessed 2026-08-06, whose middle term was a **Board Settings…** door for the week the sheet existed *(amended 2026-08-07: the split reversed, so the offer is the control itself again)*. *(Pivot 2026-08-07 — 12: this is every tier's posture now, and git stays opt-in per board: the button is an offer, never an auto-init.)*
- **Repo-nested** and **unverifiable** → their settled prose, no action (nothing setup-shaped can apply).
- **Git mode** → the branch display with the **switch picker**, the abnormal-state notes (paused, unreadable, switch failure — 06), and a **Commit Identity** block under a heading VoiceOver navigates by *(rehomed 2026-08-07 from the sheet; withheld when the repository won't open, since writing an identity is a write into a repository the app can't open — the branch surface's own unreadable sentence stands alone there)*; on remote-backed boards, remote tracking (ahead/behind) with **Pull/Push** controls and the status badges (Authentication needed, queued pushes, last error) join as one more block under the branch controls (07-sync-collab.md's cards, whose own setup half needs a home now that the sheet is gone — open).
- **Free + inert `.git`** and **absent** — *retired by the 2026-08-07 pivot (12: git left the paywall)*: the Pro pointer described a gate that no longer exists, and with no free-only postures every board resolves one of the three families above, so the tab is always in the strip.

**Branch creation is the switch menu's again** *(2026-08-07, reversing the 2026-07-31 relocation to the sheet)*: below the switch targets sits a divider and a **New Branch…** entry that reveals an inline name field with Create under the branch row — the shape creation had before the split, restored when the sheet retired. Escape steps outward one layer per press (a dirty field clears, an empty one closes the reveal, then the popover dismisses); create-and-switch runs 06's identical settle sequence, and its failures answer at the section's own caption.

**A single-branch board's picker opens onto a disabled explanatory row** (ruled 2026-08-06, built with the tab): the menu's upper half holds only the *other* local branches, and an unexplained gap above the divider reads as a menu that lost something — a disabled "No other branches" row says why there is nothing to pick. *(Amended 2026-08-07: the row taught a second thing while creation lived in the sheet — that creation was no longer here — and that half retires with the reveal's return.)* The popover is now the one configuration home; each control keeps exactly one home within it.

The window-title widget opens the **board popover** — the one board-level surface. **The widget is a two-line identity block** (reworked 2026-08-07): the board's glyph at roughly double its drawn text height, sized to span both lines, beside a stack whose first line is the board's name (titlebar weight, the string the window title would show) and whose second — **git-mode boards only** — is the current branch, smaller and secondary; then the disclosure chevron. It was one line reading `glyph  Name — branch  ⌄`, and the em-dash retired with the rework: a separator was doing a hierarchy's job, and the branch was competing for width with the name it qualifies. Both lines truncate at the tail inside the widget's 400pt cap; a board with no branch is the same block with one line, centered against the same glyph. Its header hosts, on every board:

- **Board rename** (settled: this function stays in-app, unlike the pathfinder which dropped it with the inspector). Rename edits the board's frontmatter `title` only — the folder is never renamed by the app; the Finder document name is Finder's to change (01-storage-format.md's board-naming rule). A foreign rename landing while the popover is open resyncs the field from the snapshot only while the field is unfocused — a focused field keeps the user's keystrokes, the dirty-buffer courtesy applied here (settled).
- **The board glyph** — the symbol picker with its tint row beside the rename field owns the board's `icon`/`iconColor` (Styling ▸ Controls above); manual board styling beyond the glyph is Style… ⌥⌘S with nothing selected, and the Theme tab owns the preset backgrounds.

## Board settings sheet — RETIRED 2026-08-07

**The surface is gone, and the 2026-07-31 popover/sheet split with it.** The split's promise was one home per control across two committed surfaces; a week of it showed the cost — setup a user could only reach through a door, a second surface whose existence had to be validated before either door could point at it, and a menu command that did nothing but open it. So the popover is the board's **one configuration home** again: **add-git** and **commit identity** render inline in the Git tab's postures (▸ Git tab above), **branch creation** went back into the switch menu's New Branch… reveal, the sheet's **availability rule** retires with the surface it gated, and **Board ▸ Board Settings…** leaves the menu bar (11-command-nexus.md). Board Info ⌘I is the door to all of it. The mechanical arguments the split rested on stand as *unfinished business*, not as a case for the sheet: 07-sync-collab.md's credential and SSH surfaces still want confirmation alerts, inline network probes and drag-in key import, and where those live is that card's to rule — the popover is not obviously wrong for them (an alert can present over it), but nothing here decides it.

The retired ruling, kept for its reasoning:

**The setup home** (ruled 2026-07-31 — the popover/sheet split, 04-interactions.md's configuration carve-out): a board-scoped, titled, sectioned sheet on the board window, opened from the popover's Board Settings… row and from Board ▸ Board Settings… (11-command-nexus.md). It hosts everything setup-shaped: **add-git** (mode none; opt-in init — 06), **add/change remote** with the inline verify probe (07 ▸ Setup verifies right there), **credentials** — HTTPS username/token fields and the whole SSH surface (machine key Copy + Verify, key import by paste or **drag** — the sheet's stable frame is part of why it exists — the per-host key picker, unreferenced-import removal, confirm-gated machine-key regeneration), the TOFU first-connect confirm and mismatch block, **commit identity** name/email (06 — the visibility-scoped 2 s config re-read rides with the fields), **branch creation** (switching stays in the popover; create-and-switch runs 06's identical settle sequence from here), and **push-on-commit**. The mechanics that forced the split live comfortably here: confirmation alerts present over the sheet without dismissing the flow that owns them, network probes and their spinners survive focus changes, and typed-but-unverified credentials are never discarded by a stray click. Under the read-only lock the sheet's mutating controls disable in place (the Style-popover rule); every control is Tab-reachable and labeled (10-accessibility.md). Each control has exactly one home — the popover never duplicates a sheet control, the sheet never hosts the daily surface.

## Trash

**Resettled 2026-07-28 — the materialized trash.** The tombstone model (a `deleted:` flag on items left in place, rendered by a pure-view quasi-lane) is **retired**: it generated a standing tax of nesting rules — ancestor walks, effective liveness, entry-vs-universe splits, kind-homogeneous selection — that this design replaces wholesale. Deletion is now a **move**: deleting a card moves its folder into **`<board-root>/.trash/`**, a reserved, materialized container (01-storage-format.md). A trashed card is an ordinary card in a special place — search, selection, rendering, styling, and clipboard all treat it exactly like any other card, and `.trash/` is self-describing in Finder and to agents.

- **Lanes trash too** (re-ruled 2026-07-29, retiring "cards only" and with it the design's sole destructive delete): deleting a lane moves its folder — subtree intact — into `.trash/`, exactly as a card moves; `kind: lane` in its frontmatter is what tells a trashed lane from a card in the flat container (01-storage-format.md ▸ Deletion), stamped on the way in when absent. The no-dialog posture survives for a better reason: the move is recoverable, so nothing needs confirming. Native undo's inverse is the ordinary move back (13-native-undo.md — the capture/recreate machinery retires). **A trashed lane is an opaque unit**: one distinct dimmed row showing its title and held-card count ("Doing — 5 cards"), no styling accents, never expandable; its cards are invisible to search and not individually addressable — it restores whole or purges whole. The row matches the search filter by lane title only. **The held count is a load-time disk fact** (pinned 2026-07-31): counted from a subtree the snapshot deliberately does not hold — the model's one number not derivable from the model — refreshed by reload like every snapshot field (its changes speak in the digest, 10-accessibility.md); the freight confirm's "…and its 5 cards" is thereby the design's one confirmation counting unrendered content, honest as of the latest reload — the opaque-unit trade, deliberate. Lane rows and cards interleave in the one trash column by `modified` descending (the trash's sort — Entry below).
- **Entry is always at the top — the trash sorts by `modified` descending** (re-ruled 2026-07-31, retiring the arrival rank mint): every arrival, card or lane — ⌫/⌘⌫ delete and drag-to-trash alike — lands at the top because the move **stamps `modified`** (a container-changing move — 01's `modified` scope; deletion is an edit to the card's story), and that stamp is the position: newest-first with no `order` rewrite, no rank minting, the item's `order` key riding along untouched for its eventual restore. Ties break by title (case-insensitive), then folder name. **Undated entries sort after every dated one** (blessed 2026-07-31 — the comments rule's rung applied here: malformed sorts after dated siblings), then fall to the same tail. **Whole-second stamps make batch deletes tie deliberately** (blessed 2026-07-31): `modified` serializes at second granularity, so a multi-item delete bracket — and any two deletes inside one wall-clock second — carries identical stamps and orders by the tail; "newest first" reading as title-order within a second is the accepted consequence, not worth a schema-wide move to fractional stamps. **The merged order is one derivation** (both kinds interleaved — the column, the keyboard grammar, and the path resolver all read the same sequence; a second implementation of "the row below this one" is a bug by definition). The stamp is also what a future age-based auto-purge will read (deferred, 01-storage-format.md).
- **Rendering**: trailing (rightmost) position when shown, visually distinct — dimmed/hatched header, trash SF Symbol, count badge — **the badge counts rows** (blessed 2026-07-31): its one invariant is matching what the column draws, so a trashed lane counts as one whatever its freight; card-level totals surface where consequences are decided — the freight confirm and the spoken accessibility value; no new-card button; not draggable, not resizable, excluded from lane reordering. Fixed one width unit, consumed only while shown; Show/Hide Trash is a re-divide trigger (Layout above). **Visibility**: hidden by default; View ▸ Show Trash toggles (no default chord — ⇧⌘T belongs to the system's Show Tab Bar, 11-command-nexus.md); per-open transient state, resets to hidden, never persisted. Hidden, the trash is invisible to every gesture and to search; shown, its cards participate in the filter **exactly like any other card** — the point of the pivot.
- **No Put Back** (settled): the valuable item is the card (or lane); where it goes on the way out is the user's cheap decision. Restoring is an ordinary move out: **drag** a trash card into any lane at any position — or a trashed lane row to a lane-strip slot — or **⌘X in the trash, ⌘V** — into a lane for cards, after the anchor lane for a trashed lane (04-interactions.md's lane-paste rule verbatim); the clipboard works on trash items like on any item, which is also the keyboard-native restore path (10-accessibility.md). Dropped on another board it follows the drag locality model (04-interactions.md).
- **No editing in the trash**: trash cards don't open — double-click stops at selection; move it out first — and a trashed lane row never expands. Moving a card to the trash dismisses its open card window (05-card-window.md), and an external move-in observed by reload does the same; a lane entering the trash dismisses the open card windows of every card it carries (they entered the trash with it).
- **Permanent deletion**: on a trash selection, **Delete (⌫/⌘⌫) is permanent** — one delete vocabulary, staged by place: on the board it moves to the trash, in the trash it removes the folder. **Delete Immediately is deliberately absent** (removed 2026-07-30): Finder's ⌥⌘⌫ answers disk-space pressure boards don't have, and it was the one gesture reaching unrecoverable straight from the board — permanence is only reachable inside the trash, where the staging makes the loss visible. The trash-side Delete **confirms exactly where the loss is real** (carried over): on boards without app-managed git history the alert stands between one keystroke and unrecoverable deletion; on git boards it acts immediately (delete-never-forgets). Confirms name the freight honestly — a trashed lane's alert counts its cards ("Permanently delete lane 'Doing' and its 5 cards"). **Empty Trash…** (⇧⌘⌫) confirms everywhere and purges the whole `.trash/`, lane subtrees walked, search-independent, the confirmation naming the full count ("Permanently delete 41 cards", "… 41 cards and 2 lanes containing 9 more cards" — 06-history-undo.md's plural folding); menu validation's "non-empty" reads `.trash/`, not the filtered view.
- Every trash operation is an ordinary file operation — auto-committed and undoable on git boards; native undo restores a delete-to-trash in-session on any board (a trash move undoes as a move back — durable across relaunch, since it is just a move), while a permanent delete registers no step (13-native-undo.md: the confirm is the safety).
- **Naming constraint** (carried over): attachment Remove moves files to the *system* Trash (05-card-window.md); board deletion says "Delete" and this container is "Trash" / "Show Trash" — Finder's "Move to Trash" phrasing stays reserved for the system Trash.
- **Materialized reserved lanes are a pattern, not a one-off**: `.trash` is the first; an **archive lane** (`<root>/.archive`, intake criteria to be designed) is the anticipated second (WISHLIST) — same mechanics, ordinary cards in a reserved dot-named container, different entry semantics. Nothing beyond `.trash` is committed yet.

## Welcome screen & templates

The welcome window carries over from the pathfinder unchanged — confirmed, it works well.

- Welcome: resizable, no title bar (background drag); recents list with board icon, name, location, counts; single click selects, double click opens; context menu Open / Reveal in Finder / Forget.
- **Templates**: New Board (⌥⌘N — ⌘N is new *card*; 11-command-nexus.md) opens a Pages-style chooser with a mini per-lane preview per template. Inventory and definition format: 09-templates.md.
- File menu: Open Recent (with Clear Menu; available everywhere), and Duplicate (⇧⌘S) — **board window only** (11-command-nexus.md), duplicating the frontmost open board to a Finder-style "copy" sibling; it never acts on a welcome-selected recent. **A sandbox refusal of the sibling write falls back to a save panel** (settled — the board's security-scoped bookmark grants its subtree, not its parent, so the sibling destination may be unwritable): the silent Finder-style sibling is attempted first; on a permission refusal a save panel opens pre-filled with the parent folder and the "copy" name — the panel's grant is the sandbox's own answer, and it doubles as a choose-another-location affordance. Cancelling the panel cancels the duplicate quietly (no banner — the user declined, nothing failed); non-permission failures (disk full, …) keep the ordinary one-shot banner. **The copy itself is cancellable** (settled — 02-architecture.md's in-progress banner promises Cancel on copy-shaped work, and Duplicate honors it): the copy runs as a per-item file walk that checks cancellation between items — never one monolithic `copyItem` — and Cancel removes the partial sibling before dismissing the banner (the attachment partial-cleanup precedent): a cancelled duplicate never happened. The copy is preceded by the close flush (02-architecture.md ▸ Windows; the rule and its Edit-session exception are stated at 09-templates.md ▸ Save as Template), so neither the tree nor the copied history misses pending work; under the read-only lock Duplicate disables in every state (02-architecture.md — the flush can't run and the sibling destination shares the board's fate). The duplicate **opens in its own board window** once copied — macOS Duplicate convention; the original stays open too. On a git board, the duplicate **keeps `.git` but has its remote configuration stripped** — remotes only: the repo-local `user.name`/`user.email` (06-history-undo.md's identity home) survives, so the fork keeps its commit identity. The copy keeps every GUID — a whole-board copy is 01-storage-format.md's explicit carve-out from the copies-remint rule (a new identity namespace, no collision possible), and keeping them is what keeps the copied history true: its commits name paths that still exist. **The trash is carried too** (settled, re-grounded 2026-07-28): Duplicate is a full fork, `.trash/` included — dropping it would leave the copy's working tree disagreeing with its own copied HEAD (the trash folders are tracked), where keeping it means the duplicate is born exactly matching its history; Empty Trash in the copy is one command away. Save as Template makes the opposite choice — a template isn't a fork (09-templates.md). A fork of the board keeps its history (undo trail, delete-never-forgets — and it opens straight in git mode via 06-history-undo.md's adoption rule), but it must not silently push into the original's remote — sharing stays a deliberate per-board opt-in. (Push-on-commit lives app-side in the board registry and never carries to a new board path anyway.)

## Editing surfaces summary

| What | Where |
|---|---|
| Card title | Inline rename on the face; card window title field |
| Card body | Card window (05-card-window.md) |
| Lane title | Inline rename on the header |
| Colors / icons | The style editor — card sidebar Style section (05-card-window.md), board popover, or Style… (context menu / Board ▸ Style…) |
| Lane width | Edge drag + header context-menu stepper + Increase/Decrease Lane Width |
| Board title, board styling | Board popover |
| Board/lane descriptions (bodies) | File-only — hand-edit `index.md`; live-reload reflects it |

## Motion

The pathfinder's animation behavior carries over as the committed motion language — it grew call-site by call-site but is disciplined enough to state as rules. The rewrite gives the vocabulary the one thing the pathfinder lacked: a single named home (one animation-constants surface), so curves and durations stop being per-site literals.

- **Two curves, semantically split.** Snappy springs are the structural/positional voice: drag reflow (~0.18 s), drop commit, paste, and delete (~0.25 s), keyboard nudges, scroll-into-view, and lane resize (~0.2 s). A smooth spring (~0.28 s) is the content-reflow voice: search filtering and undo/redo restore, deliberately paired so a restore reads like the search filter — leavers and arrivers run their transition, survivors reflow under one gentle spring. Named system presets only; no hand-tuned spring parameters.
- **User-initiated structural changes animate; foreign changes snap.** Everything the user does through the app — drag, delete, paste, nudge, resize, search — lands in an animated transaction regardless of entry point (the pathfinder enforced this by routing every deletion/move through the same animated store methods; keep that shape). Changes arriving through the watcher — agent edits, hand edits, sync, external git — apply instantly with no transition: live-reload is the board becoming what's on disk, not an event to perform. The one deliberate crossover is app-initiated undo/redo restore — a git checkout, but *ours*, so it animates in the search-filter language (06-history-undo.md).
- **Equivalent operations share one dialect.** Paste animates exactly like a drop commit (same curve, same duration) so the clipboard's move story *feels* like drag landing; keyboard one-slot moves slide for the same reason a drop does — an item that teleports is harder to follow than one that slides; cut dims the card in place, Finder-style, until paste moves it (04-interactions.md).
- **Appear/disappear is scale + fade** (cards scale from ~0.8, lanes ~0.9, combined with opacity). A restore that moves a card across lanes flies it from old frame to new via matched geometry. Search-hiding rides the same structural transition — hiding is removal, not a special fade.
- **Some things deliberately never animate**: the rubber-band marquee tracks the cursor 1:1 (an eased band visibly lags the mouse), and the selection highlight rides whatever transaction is active rather than easing on its own.
- **Animated transactions are keyed narrowly** — on the search query (filter reflow) and on the drag's **drop proposal** (the reflow-to-make-room above animates under it, ~0.18 s) — never on broad state like the selection set (selection changes styling only, never geometry — Card face above, the no-carousel resettlement). What stays animation-free by construction rather than by suppression: the drag replica's tracking and the marquee rectangle (1:1 cursor following — animating input echo would be lag), and multi-select churn. **The replica's bracketing transitions do animate** (settled): the pickup lift (scale + shadow as it detaches from the card) and the cancel fly-back are the system drag session's own behaviors and match the spec verbatim; only the tracking between them is verbatim input echo. **The drop settle is the board's, not the replica's** (resettled 2026-07-28 — drags are system `NSItemProvider` sessions, required for cross-board transfer and the copy badge, and a successful drop's drag image has no fly-to-slot hook, only AppKit's brief fade): at release the held overlay (below) renders the dropped arrangement instantly while the system fade dissolves the drag image over it — the item is in its slot the moment the mouse releases, which is the promise that matters. A custom fly-to-slot animator (shadow-window replica, masked system fade) remains a deliberate later upgrade, not a commitment (WISHLIST). **The settle holds the drop proposal until the echo lands** (settled — the one-way flow means the write is still in flight at release, and a snapshot-order re-render would glide the dragged item back before the reload animates it forward again): the proposal survives release as overlay state in the app-wide DragSession (02-architecture.md — the placeholder's kin in semantics; app-wide in home because a drag crosses boards), the board keeps rendering the proposed arrangement under the system fade (the drop settle above) — **the release presentation is an open question** (reopened 2026-07-28): the first treatment — swapping the shadow for the dropped card(s) drawn in place immediately at release — was implemented and backed out on user review; the pause between release and the card's appearance still wants a designed answer, revisited separately (Redesign board ▸ Issues to Resolve). Until then the shadow holds through the gap and the card appears at the echo — and the proposal discards itself when the bracket's echo reload lands — positions already match, so the handoff moves nothing. A **failed write discards the proposal** and the board animates back to snapshot order with the ordinary one-shot banner — the width-drag rollback posture (the action visibly doesn't happen); a foreign reload that vanishes the dragged item discards it too (02-architecture.md's constraint rule).
- **Motion never feeds back into logic** (the pathfinder's animation-proof-inputs rule, kept as a hard constraint): drop-proposal math reads analytically computed resting zones, the physical mouse position, and item sizes frozen at drag start — never mid-flight measured frames, which are garbage precisely during the ~0.2 s reflow they trigger.
- **Reduce Motion is a rewrite obligation, not an inheritance**: the pathfinder ships zero reduced variants; 10-accessibility.md's commitments (crossfade or instant for reflow, search animate-out, the drag replica's lift and settle, the lane-resize rubber-band feedback, trash) are new work.

## Changes from Kanban

- Terminology: lane throughout the UI (menus, dialogs, agent guide).
- Lane and card colors render as edge accents (C7 top edge / K1 left stripe — Styling above), fixed rather than the pathfinder's configurable treatment matrix; the pathfinder's full-surface painting is gone.
- The motion language is named and centralized (Motion above); Reduce Motion variants are new work the pathfinder never had.

## Open questions

- Board rename is settled (board popover, above). Board/lane *descriptions* (bodies) remain file-only — keep that stance, or does the card window pattern (a "lane window"?) deserve to exist for them? Current lean: keep file-only; descriptions are edited rarely.
