Interaction
What a reader can move: parameters, a fit they drive, editable panes, and the state that follows them between scenes.
#Parameters
A parameter is a named quantity with a slider in the pane footer. Its var is a single letter, and every expression in the pane that mentions that letter re-evaluates as the reader moves it.
canvas.graph{
parameter#a{steepness}(var: a; range: [0, 4]; step: 0.25; default: 2)
curve(expression: a * x^2)
point(x: 1; y: a; label: $a$)
}The body is what the parameter is called in front of the reader; without one the slider is labelled with its letter. hidden: true keeps it out of the footer — the expressions still use it, the reader cannot move it — and lock: true keeps it out of their reach on an editable pane. Its current position is derived as #a.value, readable in prose with !value.
#Giving fit a parameter for its degree
fit takes its degree as a number or as an expression of parameters. A parameter in that position hands the degree to the reader: the parameter's slider is the control, and the fit recomputes as it moves.
canvas.graph{
scatter(data: (1, 2.0), (2, 2.4), (3, 3.1), (4, 4.8), (5, 7.4))
parameter#d{fit degree}(var: d; range: [1, 4]; step: 1; default: 1)
fit#f(model: polynomial; degree: d)
}#f.slope, #f.intercept and #f.r2 are derived from whatever the reader has chosen, so prose that reads them stays true at every degree.
#editable: panes and lock:
editable: true on a canvas.graph lets the reader add their own elements and pan or zoom the frame; on a canvas.code it lets them edit the text, which still runs nothing. Any mark takes lock: true to stay out of their reach — and does nothing at all on a pane that is not editable.
#continue: and session state
A later pane written as continue: #projectile inherits what the reader did in the earlier one: where they left the sliders, the degree they chose, the view they zoomed to. Only that state carries — the content is the new pane's own.