Two related bugs in fontconvert_sdcard.py:
1. SMP filter for ligatures was post-pack, which only checked the
already-masked low half (always ≤ 0xFFFF), didn't check `lc`, and
couldn't catch SMP cps that already had bits truncated by the
mask. Filter at source instead — inside extract_ligatures_fonttools
when building the `filtered` dict — so any seq with an SMP
component or any lig_cp > 0xFFFF is dropped before packing. The
chained 3+ char path is naturally covered because
`intermediate_cp = filtered[prefix].lig_cp` reads from the same
already-filtered table.
2. GPOS kern dispatch checked `actual.LookupType` after unwrapping an
Extension subtable. Format-specific subtables (PairPosFormat1/2)
don't carry `LookupType`, so this fails for any Extension-wrapped
PairPos lookup — i.e. how every modern font (Inter, Source Serif,
Bitter, …) ships kern. Use the effective type instead:
effective_type = getattr(st, "ExtensionLookupType", lookup.LookupType)
so non-Extension lookups read the outer type and Extension lookups
read the inner ExtensionLookupType, and Type-2 PairPos lookups
actually reach _extract_pairpos_subtable in either case.