# Story Markup The story stream supports plain paragraphs plus a small set of structural and media cues. ## Inline Text Markdown emphasis is supported inside paragraphs and headings: - `*italic*` or `_italic_` - `**bold**` or `__bold__` - `***bold italic***` or `___bold italic___` SmartyPants processing still runs after markup parsing, so straight quotes, apostrophes, and dashes are converted typographically before layout and hyphenation. ## Paragraphs And Sections Plain narrative is rendered paragraph by paragraph. Each ordinary paragraph uses the normal first-line indent, and adjacent paragraphs are not separated by a blank line. Use an explicit section marker when the next paragraph should begin a new text block: ```text ::section The first paragraph of the section begins here. The second paragraph begins here. ``` - The first paragraph after `::section` is not horizontally indented. - It gets one line of vertical separation from previous content. - Following paragraphs use the normal first-line indent. Paragraphs are separated by one or more blank lines. Single newlines inside a paragraph are normalized to spaces. ## Chapters Use: ```text ::chapter[The House on the Hill] The first paragraph begins here. The second paragraph begins here. ``` The chapter heading is rendered in the same font and size as block text, centered and italic. The first following paragraph is unindented and marked for a three-line drop cap. Following paragraphs are indented normally. ## Images Image blocks are parsed, queued, and emitted as future media blocks, but image rendering is not implemented yet. ```text ::image[widescreen](mansion-rain.jpg) ::image[portrait](portrait-letter.jpg) ``` `widescreen` means 100% page width and 50% page height. `portrait` means 100% page width and 100% page height. Filenames are relative to the future image directory. ## Sound Effects Sound effects can appear inside regular paragraphs: ```text The door opens {{sfx:door-creak.ogg}} and the hall exhales. ``` The marker is removed from displayed text and TTS text. It is preserved as a timed cue and emitted when the word animation reaches the marker position. Actual preload and playback are not implemented yet. The animation engine emits `story:media-cue` with `type: "sfx"`, `filename`, `wordIndex`, and `delay`. ## Music Music can be queued as a block: ```text ::music[crossfade, loop, lead=4](rain-theme.ogg) ``` It can also be placed inline: ```text The candles gutter. {{music:cut:danger.ogg}} Something moves upstairs. ``` Supported modes are: - `queue`: play after the current track finishes. - `crossfade`: crossfade from the current track to the new one. - `cut`: stop the current track and start the new one immediately. - `loop` or `once`: whether the track repeats. - `lead=`: how long the music plays alone before the next text/TTS paragraph starts. Inline music markers emit `story:media-cue`. Block music directives emit `story:media-block`; block directives also delay the following paragraph when `lead` is set.