Three changes from reviewing the panel against a real run.
Events are bracketed by the group they belong to. A coloured rail in the
group's own colour runs down the heading and every event under it, closed
by a foot where the group ends. This is the shape the rundown editor
already uses for a group, so the report reads with the same grammar as
the rundown it reports on, and an event can no longer be mistaken for
belonging to the group above it.
The show summary no longer reduces the run to one figure. Finishing time
and running time answer different questions and can point opposite ways:
a show which starts early and runs over still finishes early, and calling
that a single "total plan deviation" reported it as having come in under
when it had in fact overrun. The two are now separate: the headline is
the show against its planned duration, which is what the team controls
and what carries into the next run of the same rundown, and the finishing
time sits beside it as its own row alongside the start it inherited.
ShowOffsets gains plannedDuration, actualDuration and durationOffset,
replacing duringShow, which was the same figure under a name that
described neither.
Nothing is forced into upper case any more. The summary labels are
sentence case, and event rows carry their values in td rather than th:
the panel's th styling is meant for column headings, so every event
title in the report was being rendered small, bold and shouting.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nr3FbLbM8gB8Jm771YgTV
A group heading is a summary of the events inside it in the same way the
show summary is a summary of the groups, so both are now built on one
shell and read the same way: the conclusion at full weight on the left,
the workings beside it, and how much of it ran along the bottom. The
group's dense dot separated stat row is gone; it carries the same shape
at less weight so it belongs to the summary rather than competing with
it.
The show's headline becomes its total plan deviation, the figure a
producer is actually asked about afterwards, read back underneath as the
two parts it is made of: the lateness it inherited from its start and
the time the show itself lost or made up. The previous "recovered during
the show" phrasing named only the second part while showing a figure for
neither.
Drops the counts of events over, under and on time. Almost nothing lands
on the exact second, so those buckets described rounding rather than the
show. The single worst overrun, which was already computed but never
shown, replaces them: it names the event that blew the schedule.
Also:
- a group with events still to run no longer reports a variance, which
otherwise read as a large underrun for a block that had simply not
finished. This matches the guard already in place at show level.
- GroupReport.changeover becomes untimed. The same gap can be a
changeover, a timer started late, or an item run without a timer at
all, and in roll mode it is the scheduled gap. Naming it for what was
measured rather than for a cause avoids asserting a workflow.
- the summary names the rundown it reports on, since a project can hold
several.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019nr3FbLbM8gB8Jm771YgTV
* fix: issue where a count-to-end would lead to incorrect expected times
* fix: include add time in overtime when countToEnd
* fix: ui and server use same calculation for expected end
The server serves html/timer-legacy.html and html/login.html from disk
at runtime, relative to the bundled server. The Docker image copies
these files but the electron packaging did not, so the view 404ed in
all desktop distributions.
Additionally, AppImages mount at /tmp/.mount_*, a hidden directory.
Express sendFile refuses paths containing dot-segments by default
(returns 404 without touching disk), so the view failed on Linux even
with the file packaged. Allow dotfiles for this route; the request
path is fixed so no user input is affected.
The Stage Timer and PiP Timer views relied on `align-content: center` to
vertically center the timer digits inside `.timer-container`, which is a
plain block element. Aligning children of a block container via
`align-content` only works in Chromium 123+ (Firefox 125+, Safari 17.4+).
Embedded browsers such as vMix Browser Input (CEF V115) and other older
CEF/Chromium-based production tools ignore the property, so the digits
fall back to the top of the container while every other element renders
correctly.
Make `.timer-container` a real flex column and center with
`justify-content: center`, which is universally supported and matches the
centering approach used elsewhere in the codebase. The removed
`justify-self`/`align-self` were no-ops on a full-width flex item.
Fixes#2126
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014T6ENZ3r6JXZb1fpYw2oNY
Surface {{groupNow.*}} template variables (title, note, colour, times,
custom fields) in the automation template autocomplete so events inside a
group can reference their group. The runtime store already carries
groupNow, so substitution and filters worked already; this makes it
discoverable.
Extend the message-secondary action with an optional text field so an
automation can set the secondary message content, not just its source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZYPZVdZLWowU7DyzGkWyy