**Scene heading demotion on continuation (fountain.c TODO)**

When a scene heading is immediately followed by more text with no blank line, the Fountain spec says the scene heading should be demoted to action and the lines merged. The C++ parser handles this by retroactively changing the element type. The SAX parser emits the scene heading before seeing the next line, so it can't un-emit. The fix is to buffer one non-dialogue block before emitting, checking if the next line is a continuation. This is rare in well-formed Fountain (scene headings are always followed by blank lines in practice), but it's a correctness gap.

**Paginator (not yet implemented)**

The paginator distributes body elements across pages of a given size (default US Letter, 612x792 PostScript points). It handles page-break logic for scene headings (keep with following element), dialogue splitting across pages with MORE/CONT'D insertion, and parenthetical break rules. It requires a caller-provided text measurement callback (`(text, max_width, line_height) -> height_px`) since font metrics are platform-specific.

The recommended design is a second-pass approach: the consuming application uses `fn_parse()` to collect elements into a flat array, then passes that array to a separate pagination utility (analogous to `fountain-html.c` being a separate helper). This keeps the core parser streaming and allocation-free. The paginator itself needs random access (lookahead for scene headings, accumulating dialogue blocks, sentence-boundary splitting), which is why it can't be a pure SAX consumer. The second pass adds negligible cost because the element array is small (a typical screenplay is a few hundred elements) and the work is dominated by the measurement callback, not the iteration. The existing C++ `Paginator` class (in the project knowledge) has the complete logic that would be translated.

**IDE memory warnings**

Two unreviewed memory-related warnings from the IDE (green lines). Unknown location. Likely worth investigating once the library is confirmed working in Fernanda.

**Performance gap vs md4c on large documents (carry-forward)**

On a 26k-word document (Big Fish), the C Fountain parser chokes slightly more than md4c at 0ms debounce. Some of this may be the Prime Document pattern affecting both parsers, but some is likely ours. Probable bottleneck areas, roughly ordered by expected impact:

**Output callback overhead.** The current Fernanda integration creates a new `QString::fromUtf8()` for every tiny HTML fragment (each open tag, text chunk, close tag). On a large document this means thousands of small QString allocations and conversions. md4c-html uses an internal growing buffer and flushes in larger chunks. Fix: either add internal buffering to `fountain-html.c`, or change the Fernanda-side callback to append to a `QByteArray`/`std::string` and convert to `QString` once at the end.

**Input copy.** We `malloc` + copy + normalize the entire input up front. md4c works directly on the caller's buffer. For a 150k-char screenplay this is a non-trivial allocation. Could be avoided by normalizing line endings during the scan instead of in a separate copy pass.

**Line table.** We build a complete array of line offsets before parsing begins. md4c processes lines on the fly. This is an extra allocation and an extra pass over the input.

**Multi-pass inline processing.** For every block, we run 8 passes over the text (7 marker types + notes), each scanning for opener/closer pairs, plus a `memset` of the consumed array and a `qsort` of the marks array. md4c uses a more sophisticated single-pass mark stack. Most screenplay blocks have no inline formatting at all, so an early-exit check (scan for any `*`, `_`, or `[` before entering the multi-pass logic) would skip the vast majority of blocks entirely.

**Dialogue group buffering.** Small dynamic arrays with `realloc` for each dialogue group. Minor compared to the above, but contributes to allocation pressure.