Type ClipInstance.timeline_start/timeline_duration/loop_before as Beats and
thread Beats/Seconds through core so the compiler catches the seconds-vs-beats
mismatches behind the audio-clip placement/drag/trim bugs.
Fixes latent mixups surfaced by the types:
- add/remove/split clip instance: the audio "effective duration" fallback was
the content-seconds span treated as beats (clips stopped early off 60 BPM);
now converted via the tempo map at the clip's start.
- trim validation: extend-left/right clamped a content-seconds delta against a
timeline-beats gap (and moved trim_start + timeline_start by the same raw
amount, assuming 1:1). Now the gap is converted to content seconds and the
timeline moves by the beats-equivalent.
- split content-split point mixed beats into a seconds trim value.
- set_keyframe: visibility-start fallback returned beats where seconds expected.
- hit_test: timeline_time (s) compared against beats without conversion.
Typed backend boundaries that were passing beats/seconds as bare f64:
add_audio_clip (start/dur Beats, offset Seconds), move_clip/extend_clip (Beats),
set_offset (Seconds). Command enum transport stays f64.
Serialization is unchanged (Beats/Seconds are #[serde(transparent)]).
lightningbeam-core builds; 299 core tests pass. The editor call sites
(recording/drop/paste/drag placement) are updated in stage 2.