The lists exist to answer "what ends soonest", so a rule contributes the
occurrence that has not finished and the one after it — no more, however
often it repeats. A weekly rule would otherwise put thirteen rows into the
list F1 is built to keep short.
occurrencesIn answers the timeline's different question and covers a whole
range. It skips non-repeating events deliberately: those are already in
rows, and returning them twice would double every plain event on the board.
useCustom takes the clock as an argument now, because the rows have to
change as time passes — the occurrence on screen rolls to the next one when
the current finishes.
CustomForms.tsx now passes repeat: null when saving a draft — EventDraft
gained the field but the form has no repeat control yet, so every event it
saves stays a single occurrence.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>