{{/* present — GET /p/{session}, the fullscreen surface, and the audience's follow view (GET /s/{token}?follow=1), which is the same page with nothing to press. One template for both because they ARE the same screen: a slide filling the viewport, where in the deck it is, and a way to move — forms for whoever holds the remote, links for whoever is only watching, nothing at all for an audience following along. Nothing here needs the script. With it, static/present.js swaps the slide when the session moves; without it, the follow view has a meta refresh and the presenter has next and previous. */}} {{define "page-head"}} {{if .Refresh}}{{/* The scriptless heartbeat: an audience with no JavaScript still moves with the presenter, five seconds behind. Only on the follow view — a refresh on the presenter's own screen would blink the projector mid-sentence. */}} {{end}} {{end}} {{define "main"}}
{{template "content" .}}
{{end}} {{define "content"}} {{/* The two URLs the script reads come DOWN rather than being built up there: which capability this surface reads under is the handler's decision (presentation.go's surfaceOptions), and the audience's follow view deliberately carries no session sqid at all. */}}
{{if .HasSlide}}
{{.Slide}}

{{.BlackoutLabel}}

{{if .Controls}}{{template "present-controls" .Controls}}{{end}} {{if .PrevHref}}{{end}} {{if .NextHref}}{{end}} {{/* "3 / 12" alone is terse read aloud, so the counter carries what the number means in a line only a screen reader gets. The bar beside it is the same fact as a picture, and is hidden from assistive tech rather than announced twice. */}}

{{.ProgressLabel}} {{.Counter}}

{{if .NotesHref}}{{.NotesLabel}}{{end}} {{if .BackHref}}{{.BackLabel}}{{end}}
{{else}}
{{template "empty-state" dict "Title" .EmptyTitle "Body" .EmptyBody}}
{{end}}
{{end}}