# Deck format

> The native MakoDeck deck contract: markup, layout classes, the 1920×1080 frame, what MakoDeck does for you, slide titles, speaker notes, the manifest, running your own stage, and the other kinds of upload.

Write the slides as markup and CSS; MakoDeck runs them.

## Markup

A document is a native deck when both hold:

- its `<html>` element carries a `data-mako-deck` attribute (any value), and
- at least one `.slide` inside its FIRST `.deck` element has a layout class. Class names are case-sensitive.

Its slides are every `.slide` inside that `.deck`, in document order. So:

- Use one `.deck`, and one `<section class="slide slide--…">` per slide directly inside it.
- Never nest a `.slide` in another, or use the class `slide` for anything else inside the deck: it would count as a slide.
- Write the slides in the HTML. Titles, notes and search text come from the file as uploaded; slides added by script after the page loads get none, and the site gives a deck only a few seconds to be ready.

Layout classes: `slide--title`, `slide--section`, `slide--content`, `slide--closing`. `slide--title` opens the deck, `slide--section` divides it, `slide--content` carries the substance, `slide--closing` ends it (next steps, decisions, contact).

## What MakoDeck does for you

For a native deck that marks no slide `is-active`, MakoDeck:

- **shows** one slide at a time, and makes the others `inert`;
- **scales** the 1920×1080 frame to fit the window, centred;
- **moves** between slides with the left/right arrow keys, Space, Page Up/Down, Home/End, a click on either half of the slide, a sideways swipe, the page's own buttons and the presenter's window, and opens the slide `#n` names (`#3` is the third; `#orders` the slide holding the element with that `id`);
- **prints** every slide on a page of its own, at 1920×1080, for the PDF download and the thumbnails;
- **reads** each slide's title and speaker notes (below), and shows the notes to the presenter only.

So add no navigation script, no `is-active` class, and no stage, scaling or print CSS. Your CSS styles the slides — their padding, layout, colours and fonts all apply; MakoDeck sets only each slide's size and position. Then:

- Put every slide directly inside the `.deck`, and nothing else in `<body>` that prints: a wrapper around a slide, or a header outside the `.deck`, adds a page.
- Never hide a `.slide` with `display`, `visibility` or `opacity` (or a class of your own that does): MakoDeck hides and shows the slides itself, and a slide your CSS hides stays blank.
- Your own code may still move slides: an agenda button or a timer that marks a slide `is-active` is followed. It may write the URL's hash or query for its own state, except a `#<digits>` hash, which names a slide.
- Make a clickable part of a slide a control (a `<button>`, an `<a>`) or put it inside an element marked `data-interactive`; otherwise a click on it also counts as a click on the slide: MakoDeck moves one slide, or follows the slide your code jumps to. The same goes for a part that uses the arrow keys or Space itself, or a sideways swipe (a slider, a canvas you draw on): a swipe never also moves a slide when it starts on a control or a `data-interactive` element, in something that scrolls sideways or sets `touch-action: none` (or `pan-y`), or when your code answers it with a slide move of its own.
- In the presenter and audience windows, B or . and W or , (black or white screen), G (every slide), ? (shortcuts) and a slide number then Enter are the presenter's, also when pressed in the deck — unless your code uses the key (`preventDefault()`). Keys typed into a field are always yours.

To see the deck as the site shows it before you upload, preview it with the site's own script, `mako-preview.js` (https://makodeck.com/ai/interactive.md): opened on its own, the file shows every slide one after another.

## The frame

- Every slide is a 1920×1080 frame. Size everything in CSS pixels at that size; MakoDeck scales the whole frame to the window.
- The site records every native deck as 1920×1080, takes thumbnails in a 1920×1080 window with reduced motion, and shows decks on a 16:9 stage. Portrait and other shapes aren't supported.

## Slide titles and speaker notes

- **Title:** the element the slide's `aria-labelledby` names, else its first `.title`, `h1` or `h2` (at most 300 characters). The site shows it in the presenter view, the slide list and search.
- **Notes:** `<aside class="notes">…</aside>` inside the slide, or a `data-notes="…"` attribute on it. Plain text, at most 20,000 characters. The site removes them from what viewers get and shows them to the presenter only.
- Both are kept as text that reads the way it's written: bidi controls, zero-width, tag and other invisible characters are removed (an emoji keeps its own joiner), a title is one line, and notes keep their line breaks with at most one blank line in a row.

## The manifest

Optional, in the entry file's `<head>`; at most 64 KB; removed before the deck is served.

```html
<script type="application/json" id="mako-manifest">
{
  "title": "Quarterly review",
  "dataAsOf": "2026-09-30",
  "sources": [{ "system": "Order system", "detail": "Shipped orders, May–August", "asOf": "2026-09-30" }],
  "seed": 1234,
  "seedMathRandom": true
}
</script>
```

- `dataAsOf`: an ISO date; the deck's page shows it as "Data as of …".
- `title`, `sources` (at most 50 entries of `system`, optional `detail` and `asOf`): kept as a record of what the deck is built from.
- `seed` (a whole number from 0 to 4294967295) and `seedMathRandom` (`true`): see https://makodeck.com/ai/interactive.md.

Invalid values are ignored with a warning (https://makodeck.com/ai/warnings.md).

## Accessibility

Keep what the skeleton does: `<html lang="…">`; on each slide `aria-roledescription="slide"` and `aria-labelledby` naming its title's `id`; charts as `<svg role="img">` with `<title>` and `<desc>`; tables with real `<th>` headers; status written as a word, not shown by colour alone.

## Reserved

Never use: the `data-mako-template` or `data-business-case-deck` attributes (they belong to the built-in templates); the `data-mako-stage` attribute and the `--mako-stage-scale` custom property (MakoDeck's stage sets them); `id="mako-manifest"` on anything but the manifest; a top-level `_mako/` folder; the globals `Mako`, `MakoDeck` and `__mako`.

## Running your own stage

Rarely needed: only for a deck whose slides must move in ways MakoDeck's don't. A deck runs its own stage when it marks a slide `is-active` before DOMContentLoaded ends — in the HTML, from a classic or deferred script, or in a DOMContentLoaded listener. A deck that marks one later is run by MakoDeck until its own script moves a slide by exactly the step MakoDeck would take for a slide key or click; then MakoDeck steps aside. Such a deck does everything above itself:

- As the page loads, and on every `hashchange` (the site sets `#n`, 1-based, and fires the event), show the slide the hash names, else the first; keep `is-active` on exactly that slide, hide the others, and scale the 1920×1080 frame to the window.
- Move with its own keys and clicks, writing the hash with `history.replaceState` — never `location.hash =` or `href="#…"` links: Safari treats each as a reload of the frame, and the site stops the deck. Leave clicks and keys on controls and `data-interactive` alone; a plain `f` or `F` is the site's (fullscreen). A sideways swipe moves a slide through the hash, as the site's own buttons do, unless your code answers it first.
- Print every slide on a page of its own: `@page { size: 1920px 1080px; margin: 0 }`, and an `@media print` block that shows every slide, unscaled, with a page break between them. The site's PDF is printed from it.

## Other kinds of upload

Build the native format. The site also takes:

- **A reveal.js deck** (`.reveal .slides > section`). Bundle reveal.js in the folder (no CDN); give `Reveal.initialize({ width: 1920, height: 1080, … })` literal numbers (the site reads them; without them it assumes 960×700); set `pdfSeparateFragments: false` when slides are drawn by code. A `data-markdown` section may load a `.md` file from the folder: it is copied into the page, without its notes.
- **Any other HTML page:** shown as one scrolling page, with a warning that no slides were found — or, if it names its paper (`@page { size: letter }`), whole at that shape, with none.
- **A PDF** (at most 300 pages): each page becomes a slide image — no notes, links or code.

PowerPoint files are refused: export them to PDF, or rebuild the deck natively.
