Switch the TransitionGroup animation from in-flow opacity+translate to
the grid-template-rows 1fr → 0fr pattern so a leaving row's height
shrinks during the transition. Avoids the post-animation snap that
happened when the DOM nodes were removed and the surrounding gap
suddenly closed.
If a user filters by a project/context/priority and then edits tasks until
that value no longer exists, the chip is gone but the active set still
contains it — leaving the list filtered to empty with no chip to toggle
off. Watch each available-list and prune orphaned entries from the
matching active set. Also tightens the task-input placeholder and reflows
some template whitespace.
Adds a Priorities filter column with toggleable (A)/(B)/(C)/(D)/no-priority
chips. Reflows the filter section from a two-column grid into single-line
strips so each filter type (Priorities · Projects · Contexts) reads on one
row with a fixed-width label and wrap-only-on-overflow chips.
Replace the markdown _todo/todo.md view with a structured todo.txt UI at the
repo root: priority dropdown, inline body edit, project/context/due/rec chips
with Tabler icons, add input as a join-suffix, project/context filter columns
with TransitionGroup animation, priority-sorted list. Drops the now-unused
.todo-notes markdown checkbox styles from app.css.
Fetch the viewer's push permission via GET /repos/{owner}/{repo} when
entering a repo and gate every write affordance behind it: edit and
image-upload buttons in StackedNote, new-fleeting-note and YouTube
buttons in FleetingNotes, and interactive checkboxes in TodoNotes
(rendered disabled when read-only). Anonymous viewers get the same
treatment because the permissions field is absent without auth, which
collapses to canPush = false.
Previously every write button was visible regardless of role, so
read-role collaborators and anonymous viewers could enter edit mode and
type before the save failed with 401/403.