pipeline/crop.py
- Add CropRegion.frame_x2 / frame_y2 (exclusive right/bottom edges) and
pil_box (4-tuple for PIL.Image.crop()). The pattern
``(cr.frame_x, cr.frame_y, cr.frame_x + cr.frame_w, cr.frame_y + cr.frame_h)``
was reconstructed in 5+ places; ``cr.pil_box`` is now the single source.
Numpy slices like ``arr[cr.frame_y:cr.frame_y2, cr.frame_x:cr.frame_x2]``
read more cleanly than the previous ``+ cr.frame_h`` arithmetic.
Sites updated to use the new properties:
- pipeline/composite.py: composite_with_alpha numpy slicing (also drops
a redundant trailing .astype(np.uint8) on the already-uint8 result)
- pipeline/lama.py: _load_crop
- pipeline/vace.py: _load_chunk_crops
- pipeline/crop.py: build_inpaint_mask source-mask cropping
- app.py: _create_crop_preview rectangle + mask overlay
static/style.css (new file)
- The 100-line CSS string previously embedded in app.py now lives in its
own file so it gets proper editor syntax highlighting and shows up as
a…