v0.3.1: upstream sync and a faster marker scanner
Closes #13, the scheduled upstream drift report. Checked against guillaumemeyer/watermarks-remover main 4a0fbc31.
Emoji presentation selectors after five more bases (upstream #200)
U+203C, U+2049, U+2139, U+2934 and U+2935 are Emoji=Yes but sit outside the block ranges the base test covered, so a VS16 after them was stripped and the emoji reverted to its text glyph. The parity suite was green on this only because no case reached those code points.
Benign JPEG comments survive keep mode (upstream #216)
A COM segment is unkeyed free text, so it is now dropped only when Remove all metadata is on or the comment actually carries a provenance marker. Generated by ImageMagick and Claude Monet are comment prose, not evidence.
The same change narrowed the whole-file C2PA byte scan for JPEG: jumb and the XMP InstanceID namespace occur in ordinary files, so neither promotes a JPEG to C2PA on its own any more. Inside a parsed APP segment they still count.
The marker scanner no longer builds a string of the whole file
containsAny walks the bytes behind a 256-slot first-byte dispatch table instead of turning the entire file into a latin-1 string and lowercasing it on every call. Same list, same order, same duplicate entries.
On a 24 MB HEIC, the inspect, clean and re-inspect pass the app performs went from 2936 ms to 121 ms, with byte-identical output across all 54 image fixtures in both strip modes. tests/test_contains_any_parity.py pins the scanner against upstream _contains_any.
Anchors
text_unicode.py ed86ed9715f4, image_meta.py 3bde868717f5. score_stylometry.py and detect_gumbel.py are unchanged.
Upstream 8e16b822 only passes creationflags to subprocess.run for Windows console suppression and has no counterpart in a browser; it is recorded in the manifest comment rather than ported.
Test suite: 584 passed, up from 483.