# PowerMD (pwmd) — authoring guide for AI assistants

PowerMD turns one Markdown file into a browser presentation (16:9 slides). Use this file when asked to write, edit, or review a PowerMD deck. The complete syntax reference follows the header below.

## Output rules

1. Produce **one Markdown file**. Optional flat frontmatter first (`title`, scale keys), then slides.
2. Separate **slides** with a line containing only `---` and **panels** with a line containing only `***`.
3. Put presentation behaviour in HTML-comment directives on their own line: `<!-- @name arguments -->`.
4. Put **slide-level directives** (`@slide`, `@layout`, `@grid`, `@slide-theme`, `@slide-bg`, `@slide-gradient`, `@slide-wallpaper`, `@sound`) at the very start of the slide, before any content.
5. Put **panel backgrounds** (`@bg`, `@gradient`, `@wallpaper`, `@cover`, `@contain`) at the start of the panel.
6. Keep each panel to one visual idea: a heading, 3–6 short bullets, or one media block. Do not write document-length prose.
7. Use `<!-- @note -->` before a blockquote for speaker notes. A plain blockquote is visible to the audience.
8. Do not use raw HTML for layout, and do not invent directives: unknown directives are ignored.

## Common mistakes

- A directive inside a fenced code block, or sharing a line with text, is not interpreted.
- A slide directive placed after content is ignored.
- `@layout` letters must match the number of `***` panels, form rectangles, and have equal row lengths; otherwise the layout falls back to automatic.
- `@wallpaper` / `@slide-wallpaper` consume the Markdown image that follows; `@youtube`, `@qr`, `@drawio`, and `@sound` need a Markdown link next; `@gallery` needs a Markdown list of images.
- `@align` and `@set-align` do not accept `reset`; use no argument to return to `center`. `@width` / `@set-width` accept `reset`.
- Hidden `@reveal` content still occupies space; check that the revealed slide fits.
- Browsers autoplay media only when `muted on`.
- Relative image paths resolve against the Markdown file's URL. For decks that may be opened locally, use absolute URLs.
- A leading `---` at the top of the file starts frontmatter, not a slide.

## Minimal example

````md
---
title: "Quarterly update"
---

<!-- @slide-theme slate amber zinc -->

# Quarterly update

A one-line subtitle.

---

<!-- @layout AB -->

# Highlights

- Revenue up 12%
- Churn down 2 points

<!-- @note -->
> Pause here and ask for questions.

***

<!-- @img 16:9 rounded -->
![Chart](https://example.com/chart.png)

---

# Thank you
````

## Syntax reference

# pwmd syntax

**pwmd** turns Markdown into a presentation. Regular Markdown remains the content format: headings, lists, links, tables, blockquotes, images, and fenced code blocks all work normally. Presentation features use standalone HTML-comment directives:

```md
<!-- @directive arguments -->
```

Prefer spaces just inside the comment delimiters: `<!-- @directive -->` or `<!-- @directive arguments -->`. This form is more compatible with Markdown renderers that handle compact comments differently; rendering behavior varies. pwmd also accepts compact comments for backward compatibility.

A directive is only interpreted on its own line and never inside a fenced code block. Invalid directives are left as ordinary hidden HTML comments.

## FRONTMATTER

An optional flat frontmatter block at the very beginning sets the presentation title and multiplicative text scales for every slide:

```md
---
title: "Product update"
text-scale: 120%
h1-scale: 150%
h2-scale: 110%
table-scale: 80%
---

# First slide

Presentation content.
```

`title` is a nonempty string naming the presentation independently of its filename. It appears in recent-presentation lists; it does not set or change slide headings or `@slide` titles. Omit it to use the filename or URL as the recent-list label.

### Document typography

Supported scale keys are `text-scale`, `h1-scale`–`h6-scale`, `table-scale`, `code-scale`, `quote-scale`, and `math-scale`. Element base ratios are built into the theme. For example, h1 uses `text scale × built-in h1 base × h1-scale`. Missing values use the built-in defaults.

## Slides and panels

A standalone `---` starts a new slide; a standalone `***` starts a new panel on the current slide. They are ignored inside fenced code blocks. A slide can contain up to 26 panels.

````md
<!-- @slide Introduction -->

# First panel

***

# Second panel

---

<!-- @slide Next slide -->

# New slide
````

## Slide metadata

Put slide directives at the beginning of a slide, before panel content. Slide-metadata parsing stops at the first non-empty, non-directive line.

### Title

```md
<!-- @slide Slide title -->
```

The title is editor metadata, used in the editor’s slide list and editing UI; the player does not currently render it. If omitted, the editor uses the slide’s first `#` heading and writes an `@slide` directive when saving.

### Layout and visible grids

```md
<!-- @layout AB/AC -->
```

```md
<!-- @grid AB/AC -->
```

Letters identify panel areas. Repeating a letter merges its cells into one rectangular area; `/` starts a new row. Panel order follows each letter’s first occurrence.

```text
AB/AC

+---+---+
| A | B |
+---+---+
| A | C |
+---+---+
```

- `@layout` hides panel dividers.
- `@grid` displays dashed panel dividers.
- `.` represents an empty cell.
- Rows must have equal length and every panel letter must form one contiguous rectangle.
- Layouts support at most 26 rows, columns, and panels. Invalid layouts fall back to an automatic grid.

Add `collapse` to reduce the grid’s outer and panel padding:

```md
<!-- @layout AA/BC collapse -->
```

### Slide theme

```md
<!-- @slide-theme stone blue gray -->
```

The three values are `BASE ACCENT FRAME`:

- `BASE`: background, surface, and text palette
- `ACCENT`: highlight color
- `FRAME`: frame and divider color

Colors are built-in Tailwind color-family names such as `slate`, `stone`, `blue`, `amber`, and `zinc`. A theme affects the whole slide.

### Slide background

A slide background can combine a wallpaper image, a color, and a gradient. Only the first directive of each kind takes effect.

````md
<!-- @slide-wallpaper -->
![Background](./images/background.jpg)

<!-- @slide-bg slate-900/70 -->
<!-- @slide-gradient down transparent -> slate-900/70 60% -> slate-950 -->

# Content above the background
````

- `@slide-wallpaper` consumes the following Markdown image; blank lines are allowed in between.
- `@slide-bg` accepts a Tailwind color with optional `-50`…`-950` shade and `/0`…`/100` opacity, for example `black/50`.
- `@slide-gradient` uses `down`, `up`, `left`, or `right`, with `->`-separated stops. A stop may have a position, such as `blue/60 45%`.

### Sound

Sound is slide-level YouTube audio. The directive must be followed by a Markdown link.

```md
<!-- @sound autoplay on muted on volume 5 -->
[Soundtrack](https://www.youtube.com/watch?v=VIDEO_ID)
```

Options are pairs in any order:

- `autoplay on|off` — default: `off`
- `muted on|off` — default: `off`
- `volume 1`…`10` — default: `7`

Browsers generally require `muted on` for autoplay.

## Panel backgrounds

Use the same three background directives without the `slide-` prefix:

````md
<!-- @wallpaper -->
![Panel background](./images/detail.jpg)

<!-- @bg black/55 -->
<!-- @gradient up black/80 -> transparent -->

# Panel content
````

Only a panel’s first `@bg`, `@gradient`, and `@wallpaper` are used. `@wallpaper` consumes its following image.

## Content layout

Persistent directives affect following content within the panel until changed. One-off `@width`, `@align`, and `@scale` target only the next content block.

### Alignment, width, and columns

```md
<!-- @set-align left -->
<!-- @set-width 60% -->

Narrow, left-aligned content.

<!-- @width 80% -->

Only this paragraph is 80% wide.

This paragraph returns to 60%.

<!-- @set-align center -->
<!-- @set-width reset -->

Full-width centred content again.
```

- `@align left|center|right|justify` sets alignment for the next content block only; without an argument it selects the default `center` for that block.
- `@set-align left|center|right|justify` sets the persistent panel alignment; without an argument it restores `center`. `reset` is not an accepted alignment argument.
- One-off overrides never change persistent defaults, even when a persistent directive follows a pending override. All three scopes reset at each new panel. For example, `<!-- @set-align left -->`, then `<!-- @align right -->` aligns the next block right and subsequent content left. Combine it with `<!-- @width 80% -->` and `<!-- @scale 120% -->` to independently style that block.
- `@width N%` sets only the next content block’s width, then the persistent width resumes. `@width reset` is a one-off `100%`.
- `@set-width N%` sets the persistent width for following blocks in this panel. `@set-width reset` restores `100%`.
- Width defaults to `100%` in each panel and is relative to that panel’s available content width, not the slide. Alignment defaults to `center`. Pending one-off width and alignment skips whitespace, layout directives, spacers, and hidden presenter notes; it applies to Markdown blocks (including headings, lists, code and tables), callouts, or media. Float/cover/contain retain their own explicit sizing.
- `@columns N [GAP]` sets CSS columns for Markdown text. `N` is 1–12; `GAP` is 0–999 `cqw` units.

```md
<!-- @columns 2 4 -->

Longer text in two columns.

<!-- @col-break -->

This paragraph starts in the next column.

<!-- @columns -->
```

`@col-break` starts the following Markdown content in the next CSS column. It only has an effect while `@columns` is active.

### Scale

```md
<!-- @set-scale 90% -->
This and the following content remain at 90%.

<!-- @scale 130% -->
Only this next content block is at 130%.
```

`@set-scale PERCENT` changes the persistent scale from that point onward. `@scale PERCENT` applies only to the next content block, then the persistent scale resumes. Both scale every text type after its document-level typography multipliers; they do not resize images or video. Use `@set-scale 100%` to restore the default block scale.

### Colors

```md
<!-- @color amber -->
This is amber.

<!-- @color reset -->
This uses the default text color.
```

`@color` accepts a color name or inline-color index `1`, `2`, or `3`.

```md
<!-- @set-colors cyan rose lime -->

_First color_, __second color__, ___third color___.

<!-- @color 2 -->
This uses the second color.
```

- `@set-colors COLOR1 COLOR2 COLOR3` overrides the inline palette for the rest of the panel.
- `@set-colors reset` restores the default palette.
- `@set-color-1`, `@set-color-2`, and `@set-color-3` override one palette entry; use `reset` to restore it.
- Defaults are `amber`, `violet`, and `emerald`.

### Spacing

```md
Top content.

<!-- @space -->

Bottom content.
```

`@space` fills the remaining panel height.

```md
First block.

<!-- @gap 4 -->

Second block.
```

`@gap N` inserts an empty block `N cqw` high (`N`: -999–999). A negative value reduces the space before the following block, pulling it upward.

```md
<!-- @set-gap 3 -->

# Heading

A paragraph.

<!-- @set-gap reset -->
```

`@set-gap N` changes the normal gap between panel content blocks. `reset`, or no argument, restores the default gap.

### Progressive reveal

```md
Visible immediately.

<!-- @reveal -->
Visible on the first next step.

<!-- @reveal 3 -->
Visible on step three.

<!-- @reveal end -->
Visible immediately again.
```

Reveal steps are shared across every panel on the slide. Hidden blocks retain their space and fade in. An unnumbered `@reveal` receives the next automatic step; blocks with the same explicit number appear together.

## Block content

### Callouts and notes

```md
<!-- @callout warning -->
# Attention
> Highlighted content.
> It may span multiple lines.
```

The heading is optional; at least one quoted (`>`) line is required. Built-in icons: `info`, `tip`, `success`, `warning`, `danger`, `error`, `question`, `quote`, `love`, `like`, `dislike`.

Markdown callouts also work:

```md
>[!warning] Attention
>Highlighted content.
```

Use `<!-- @note -->` directly before a blockquote to make it speaker-only; the audience will not see it. The paired mobile remote renders these notes as Markdown.

```md
<!-- @note -->
> **Presenter cue:** Explain the feature demonstrated on this slide.
> Mention the next step before advancing.
```

An ordinary blockquote without `@note` remains visible audience content.

### Images

A standalone Markdown image is normal Markdown content. `@img` turns the following image into a media block:

```md
<!-- @img 16:9 rounded -->
![Description](./images/hero.jpg)
```

The optional ratio is `WIDTH:HEIGHT`; optional shape is `rounded`, `square`, or `circle`.

### YouTube, QR, and draw.io

Each directive consumes the next Markdown link:

```md
<!-- @youtube autoplay on muted on volume 5 -->
[Demo](https://youtu.be/VIDEO_ID?t=1m30s)

<!-- @qr -->
[Open presentation](https://example.com/deck.md)

<!-- @drawio -->
[Architecture](./diagrams/architecture.drawio)
```

`@youtube` supports `autoplay on|off`, `muted on|off`, and `volume 1`…`10`; URL `t` or `start` sets its start time. `@qr` generates a clickable QR code. `@drawio` renders a diagrams.net file.

`@qr` and `@drawio` can consume a `data` fenced block instead of a link:

````md
<!-- @qr -->
```data
Any QR payload.
```

<!-- @drawio -->
```data
<mxfile>…</mxfile>
```
````

### Gallery

A gallery consumes the following contiguous Markdown list:

```md
<!-- @gallery 4s rows-2 -->
- ![First](./images/one.jpg) 6s
- ![Second](./images/two.jpg)
- ![Third](./images/three.jpg) 3s
```

The first duration (`ms` or `s`) is the default, with a default of `5s` and maximum of `60s`. Images may have individual durations. `rows-N` requests 1–12 rows; galleries support up to 100 images.

### `@cover`, `@contain`, and `@float`

`@cover` and `@contain` are panel-level display directives. Put one of them at the beginning of a panel, alongside panel background directives. They apply to the panel’s first supported content block, not merely to the line immediately following the directive. The directive may appear elsewhere in the source, but normalization moves it to the panel header.

```md
<!-- @cover -->

# Introductory heading

![Full-panel image](./images/hero.jpg)
```

In this example the heading remains normal content and the image is the first supported target, so it fills the panel. `@cover` crops an image when necessary; `@contain` fills the panel while preserving the image aspect ratio, which is useful for diagrams and SVGs.

```md
<!-- @contain -->

![System architecture](./diagrams/architecture.svg)
```

Only the first `@cover` or `@contain` in a panel takes effect. Supported targets are standalone Markdown images, tables, fenced code blocks, and `@img`, `@youtube`, `@qr`, `@gallery`, `@callout`, or `@space` blocks. If the panel has no supported target, the directive has no visual effect.

`@float` places its next block at one side so following content can flow next to it:

```md
<!-- @float right 40% 3 -->
<!-- @img rounded -->
![Illustration](./images/example.jpg)

This Markdown can flow beside the image.
```

Syntax: `@float left|right WIDTH [GAP]`; `WIDTH` is a percentage and `GAP` is in `cqw`. The target can be an image, table, fenced code block, or `@img`, `@youtube`, `@qr`, `@drawio`, `@gallery`, `@callout`, or `@space`.

## Markdown extensions

### Formulas

A `$$` pair on its own lines renders a KaTeX display formula:

```md
$$
\sum_{i=1}^{n} i = \frac{n(n+1)}{2}
$$
```

### Mermaid

```mermaid
flowchart LR
  A[Idea] --> B[Plan] --> C[Launch]
```

A fenced code block with language `mermaid` renders as a diagram.

## Frontmatter limits

The [frontmatter block](#frontmatter) supports flat `key: value` lines, not general YAML structures such as nested mappings, lists, or multiline values. Keep it at the very beginning of the document; outside that header, standalone `---` lines separate slides. Use slide and panel directives for their local presentation settings.

## Sizing guide

Use this section when planning a deck manually or asking an AI to author one. Values using `cqw` are proportional: `1cqw` is 1% of the slide container width, so a value scales with the presentation instead of being a fixed pixel size.

### Player baseline

| Element | Default size | Planning implication |
| --- | ---: | --- |
| Panel safe padding | `5cqw` on every side | Keep ordinary content inside this area. `@cover` and `@contain` intentionally remove it. |
| Body text | `1.25cqw`, `1.5` line-height | A full-width slide supports short, presentation-sized paragraphs rather than document-length prose. |
| Default block gap | about `0.8cqw` | Consecutive Markdown blocks already have breathing room. |
| H1 | about `4.5cqw` | Use for one primary statement, usually no more than one per panel. |
| H2 | about `2.75cqw` | Use for section labels or a secondary message. |
| H3 | about `1.8cqw` | Use for small subsections or grouped points. |
| H4–H6 | about `1.25`–`1.5cqw` | Use sparingly; body text, lists, or callouts are often clearer. |

The first heading in a Markdown block has no top margin. Later headings receive a section gap. A heading immediately after `@col-break` also starts without a top margin.

### Practical ranges

| Need | Recommended starting point | Notes |
| --- | --- | --- |
| Normal content width | `@set-width 100%` | Default in every panel; `@width 100%` is a one-block override. |
| Readable text measure | `@set-width 55%`–`75%`, or one-off `@width 60%` | Use persistent width for several blocks, one-off width for a statement, quotation, or compact explanation. |
| Side visual with flowing text | `@float left|right 30%`–`45% 2` | Keep the accompanying text short. |
| Deliberate vertical space | `@gap 2`–`6` | Use negative values only for small optical corrections, such as `@gap -1` or `@gap -2`. |
| Default gap between content blocks | `@set-gap 1`–`3` | Do not use a large panel-wide gap if only one relationship needs space; prefer `@gap`. |
| Two text columns | `@columns 2 2`–`4` | Best on a wide, single-panel slide; avoid columns in narrow grid panels. |
| Image/video ratio | `16:9`, `4:3`, or `1:1` | Choose a ratio that matches the source. Use `@cover` for edge-to-edge media and `@contain` for an uncropped full-panel diagram or SVG. |
| Dense material | `@set-scale 90%` or one-off `@scale 80%`–`90%` | Reduce scale before adding too much content, but avoid making presentation text document-sized. |

### Authoring rules for AI

1. Treat each panel as one visual idea. A multi-panel slide needs correspondingly shorter content per panel.
2. Start with one `#` heading or a short H2-level label; do not stack several large headings unless demonstrating typography.
3. Prefer 3–6 short list items over a long paragraph. Keep nested lists shallow.
4. Use `@columns` for parallel, scannable material—not to fit more prose. `@col-break` is for intentional column starts.
5. Use persistent `@set-width` or one-off `@width`, `@float`, `@cover`, and `@contain` to establish hierarchy before changing text scale.
6. Leave room for headings, images, tables, and reveal steps. Hidden reveal content still reserves its layout space.
7. Check the result at the intended aspect ratio and screen size; `cqw` preserves proportions, but it cannot make overloaded content readable.
