diff --git a/src/help/05-window.txt b/src/help/05-window.txt
new file mode 100644
index 0000000..c1d2d21
--- /dev/null
+++ b/src/help/05-window.txt
@@ -0,0 +1,30 @@
+Time window
+
+The window is how much time the plot shows. Every row shares one window: the figure has a
+single x link group, so the rows cannot drift apart. The trigger's event span follows it, and
+the pre-trigger share is a share of this window.
+
+How to reach it
+
+The header bar's window button opens a popover: type a number, pick a unit under it, or step a
+decade with the arrows. The button's own label is a reading of the current window in a natural
+unit, width-locked so a change of window cannot widen the header bar.
+
+Worth knowing
+
+• A window too long to store at the wire rate is decimated, not refused. The shared clock
+ takes a power-of-two stride, and each group of samples is averaged rather than strided,
+ so a tone above the stored Nyquist is attenuated instead of aliasing to a false low frequency.
+• The stamp stored for a group is the group's mean, which is where the averaging puts the
+ value. Stamping at the end of a group would shift every trace half a stored sample late.
+• Moving the window across a decimation boundary rebuilds the buffer and drops the history.
+ Walking it inside one decade is free.
+• The trigger sees the stored (filtered) signal, not the wire signal, because an edge
+ found on a sample that is not in the buffer could not be cut out of it.
+
+Example
+
+1 MS/s with 200 MB of buffer. A 2 s window stores every sample (time x1). Widen it to
+600 s and the stride becomes x16: 625 S/s stored, anti-aliased at 312.5 Hz. A 2 kHz
+sine seen through that window reads y=[-0.059, 0.079] — attenuated to about 6%, not
+folded down to a full-amplitude 125 Hz one.
diff --git a/src/help/06-navigate.txt b/src/help/06-navigate.txt
new file mode 100644
index 0000000..f073948
--- /dev/null
+++ b/src/help/06-navigate.txt
@@ -0,0 +1,34 @@
+Navigating the plot
+
+The plot pans and zooms with the mouse and with the keyboard. Every gesture acts on the row the
+pointer is over, and because the rows share one time axis, an x change moves all of them.
+
+How to reach it
+
+Wheel zooms both axes · Shift+wheel zooms x only · Ctrl+wheel zooms y only.
+Drag pans · Ctrl+drag is a box zoom on x · Alt+drag a box zoom on y.
++ and - zoom both axes; Ctrl with them restricts to x, Alt to y.
+Arrow keys pan, f fits, Escape cancels a gesture in progress.
+The full table is in the shortcut overview (Ctrl+/).
+
+Worth knowing
+
+• The keyboard zoom's modifiers are not the wheel's, and that is deliberate: on common
+ layouts + is shift+=, so a bare zoom-in already arrives with Shift
+ set and Shift could not mean anything. Ctrl/Alt mirror the box-zoom drags instead.
+• A pinned view is navigable within its own data but cannot leave it. While an event is
+ held, a capture is filling, or the view is paused, a zoom in works normally — "not
+ outside the event" is not "not readable" — but a pan or a zoom out is clamped to the data.
+• A live view is clamped to the window you asked for, not to what the ring happens to hold.
+ That is why a buffer that has only just started filling leaves its left-hand side empty
+ instead of squeezing the window down to the first few samples.
+• Zooming hard into a held capture is exact. The renderer finds the visible samples by binary
+ search over the real timestamps, never over a nominal sample grid, so a capture whose clock
+ wandered does not drift away from its axis as you zoom.
+
+Example
+
+Pause a live view, then press Ctrl++: x narrows and y does not move. Press
+Alt++: y narrows and x does not. Eight doublings into a held 2 s capture, the trace
+still reaches both margins — the zoom probe reports gap_px and end_px within
+a pixel or two at every step.
diff --git a/src/help/07-pause.txt b/src/help/07-pause.txt
new file mode 100644
index 0000000..41942f4
--- /dev/null
+++ b/src/help/07-pause.txt
@@ -0,0 +1,29 @@
+Pause and play
+
+Pause freezes the display, not the acquisition. The producer keeps filling the ring at
+full rate; the view binds an immutable snapshot of the window that was on screen, and the axis
+is pinned to it.
+
+How to reach it
+
+The pause button in the toolbar, or Space. Press it again to resume, which rebinds the
+live ring and puts the window back on the newest data.
+
+Worth knowing
+
+• Nothing is lost while paused. Because the producer never stops, resuming shows current data
+ with no hole in the history behind it.
+• The axis is pinned to the snapshot's own stamps, not to the window that was requested.
+ A window reaching back past the oldest retained sample yields a shorter snapshot, and the
+ pinned axis is that shorter span — so you see a narrower view rather than an empty margin.
+• A paused view is pinned exactly as a held trigger event is: zoom in freely, but a pan or a
+ zoom out is clamped to the snapshot's data.
+• Pausing is the easiest way to measure a layout or read a cursor precisely, because nothing
+ under the pointer moves between frames.
+
+Example
+
+Pause with a 2 s window over a ring holding 1.4 s: the frozen axis reads
+[-1.40 .. 0.00] rather than [-2.00 .. 0.00] with 0.6 s of blank. The pause
+probe reports ring_produced still growing across the pause and
+event_size non-zero exactly while paused.
diff --git a/src/help/08-trigger.txt b/src/help/08-trigger.txt
new file mode 100644
index 0000000..f4f0ebf
--- /dev/null
+++ b/src/help/08-trigger.txt
@@ -0,0 +1,35 @@
+Trigger
+
+The trigger watches one signal for an edge through a level and captures a window around it.
+The captured window is frozen on screen until you re-arm.
+
+How to reach it
+
+The trigger button in the toolbar (t) reveals the trigger panel: the signal, the level,
+the edge (rising, falling, either), the mode (Normal or Single) and the pre-trigger share.
+Arm starts watching; a arms and disarms from the keyboard.
+
+Worth knowing
+
+• Arming enables the signal if it was off, because a trigger on a signal nobody acquires
+ can never fire.
+• The pre-trigger share is a share of the display window, not of the ring. A 2 s window
+ at 50% captures 1 s before the edge and 1 s after.
+• There are four display states, and the status bar names each: armed (watching,
+ nothing drawn yet), capturing (the edge was accepted and the post window is filling
+ in view, with the marker at x = 0), event held (the frozen capture) and
+ disarmed. A held capture is never quietly replaced by live data.
+• The first edge after arming is only accepted once the history reaches back a full pre-trigger
+ window, so a capture may legitimately be shorter than you asked for. The axis is pinned to
+ what the capture actually got.
+• Disarming during a capture publishes what the capture got to, so the picture on screen
+ at that moment stays on screen. No event fired, so the event count does not move.
+• The trigger reads the stored signal — decimated and averaged — not the wire signal.
+ A spike narrower than one decimation group is filtered away rather than triggering on data
+ the buffer does not contain.
+
+Example
+
+A 1 Hz sine, level 0, rising, 2 s window at 50%, Single. The capture spans
+[-1.000 .. 1.000] with n=20001 samples at 10 kS/s — the span times the real
+rate, plus one — and the marker sits at x = 0 throughout.
diff --git a/src/help/udpscope-help.gresource.xml b/src/help/udpscope-help.gresource.xml
index e48cef4..7df6621 100644
--- a/src/help/udpscope-help.gresource.xml
+++ b/src/help/udpscope-help.gresource.xml
@@ -13,5 +13,9 @@
02-source.txt
03-signals.txt
04-layout.txt
+ 05-window.txt
+ 06-navigate.txt
+ 07-pause.txt
+ 08-trigger.txt
diff --git a/src/help_window.cpp b/src/help_window.cpp
index 70bb9e1..a9153f7 100644
--- a/src/help_window.cpp
+++ b/src/help_window.cpp
@@ -34,6 +34,10 @@ constexpr HelpPage kPages[] = {
{"Getting started", "Choosing a source", "/org/udpscope/help/02-source.txt"},
{"Getting started", "Signals and calibration", "/org/udpscope/help/03-signals.txt"},
{"Getting started", "Rows, layout and drag & drop", "/org/udpscope/help/04-layout.txt"},
+ {"Viewing", "Time window", "/org/udpscope/help/05-window.txt"},
+ {"Viewing", "Navigating the plot", "/org/udpscope/help/06-navigate.txt"},
+ {"Viewing", "Pause and play", "/org/udpscope/help/07-pause.txt"},
+ {"Viewing", "Trigger", "/org/udpscope/help/08-trigger.txt"},
};
constexpr int kPageCount = static_cast(sizeof(kPages) / sizeof(kPages[0]));