+
+
+
+
+ ${/* column rendering stays the same */}
+
+ `;
+};
+```
+
+6. Add `@dragend` as a single stable handler on the virtualizer too (it's already `this.onTrackDragEnd` which is stable).
+
+**CRITICAL:** Event delegation must work through shadow DOM. Since the virtualizer and its children are all within the same shadow root, `event.target.closest('.track-row')` works correctly. But verify with `composedPath()` if needed.
+
+**queue-panel.ts — renderTrackItem:**
+
+Apply the same event delegation pattern:
+1. Add `data-index="${track.position}"` (or the loop index) to each `.track-item`
+2. Register delegated handlers on the virtualizer in firstUpdated
+3. Extract item index via `closest('.track-item')?.dataset.index`
+4. Remove all inline closures from the template
+
+**cover-grid.ts — renderAlbumCard/renderGridEntry:**
+
+The cover grid already uses some delegation (it reads `data-index` for some operations). Verify that all click handlers on album cards use delegation. If any inline closures remain in `renderGridEntry` or `renderAlbumCard`, convert them.
+
+**Key rule:** After this change, `renderTrackRow` and `renderTrackItem` should create ZERO new function objects. Every handler reference should be stable (either a bound class method or a property arrow function defined once in the class body).
+