1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
//! What the pane spends its width on, and the measuring every line goes
//! through.
//!
//! Column widths are fixed rather than measured from content, the same
//! choice the flock table makes and for the same reason. The one variable
//! is whether the explanation panel fits beside the field list, which
//! [`panel_width`] decides once per frame and every layout below reads.
use Line;
use ApplyGroup;
use ;
use crateUNSET;
use crate;
/// The close dialog's own interior width, once it is boxed: what
/// [`super::close::close_dialog_lines`] lays its rows out to when [`super::close::draw_close_dialog`]
/// draws the boxed form.
pub const BOX_WIDTH: u16 = 86;
/// The KEY cell at its full width, flag character included. Twenty-six is
/// `exp_backoff_restart_delay` plus its flag, the longest key the Flockfile
/// schema declares, so no field name is truncated at a width that can
/// afford the whole column.
pub const KEY_W: u16 = 26;
/// The floor KEY shrinks to before the COST column is dropped instead.
pub const KEY_MIN: u16 = 8;
/// The floor VALUE shrinks to. Below this the pane drops COST, and below
/// that it draws KEY alone.
pub const VALUE_MIN: u16 = 8;
/// The position cell on the list sub-screen. Three columns holds an index
/// into an array longer than any Flockfile has, and no more: an element is
/// what the row is about.
pub const POSITION_W: u16 = 3;
/// The COST cell. Ten columns, which is exactly `next start`, the longest
/// word [`cost_label`] prints.
pub const COST_W: u16 = 10;
/// The narrowest body that still draws KEY, VALUE and COST.
pub const FULL_WIDTH: u16 = KEY_W + 2 + VALUE_MIN + 2 + COST_W;
/// The narrowest body that still draws a VALUE beside the KEY.
pub const VALUE_WIDTH: u16 = KEY_MIN + 2 + VALUE_MIN;
/// The blurb's own wrap width, independent of whatever width the panel
/// itself draws at: prose reads better narrower than the panel's outer
/// ceiling allows, the same way a magazine column is narrower than the
/// page.
pub const BLURB_WRAP: u16 = 66;
/// The narrowest left column that still draws a marker, a key and a value.
pub const LEFT_MIN: u16 = 40;
/// The narrowest panel that holds a wrapped blurb and a validation list.
pub const PANEL_MIN: u16 = 50;
/// The panel at the design target, and the ceiling everywhere else.
pub const PANEL_MAX: u16 = 72;
/// How wide the explanation panel is, and [`None`] when it does not draw.
///
/// 45% of 160 is 72, so the design target from
/// `docs/brainstorming/specs/2026-09-08-lookout-1e-editing-pane-design.md`
/// falls out of the formula rather than being special cased. Below it the
/// clamp to [`PANEL_MAX`] holds the panel at the design target's own width
/// rather than growing it to fill a wider terminal: the left column takes
/// the remainder instead, the same way [`super::super::flock`]'s own table grows.
/// Above [`LEFT_MIN`] short of `width` the panel cannot hold a wrapped
/// blurb and a validation list beside a left column with room for a
/// marker, a key and a value, and [`super::draw::pane_lines`] falls back to the single
/// column it always drew.
pub
/// The narrowest terminal that draws `LANDS` beside the panel rather than
/// giving way to it. The design target itself: at 160 the frame's own
/// `FIELD / VALUE / LANDS` header and the `FOCUSED` panel share a row, per
/// `docs/lookout/design-files/rulings.md`'s 1e ruling and
/// `docs/brainstorming/specs/2026-09-08-lookout-1e-editing-pane-design.md`'s
/// width table.
pub const LANDS_WITH_PANEL_MIN: u16 = 160;
/// Whether `LANDS` draws on a terminal `width` columns wide that also draws
/// the panel (`has_panel`).
///
/// `LANDS` and the panel do different jobs: the column is what an operator
/// scans to read every field's cost at once, the panel is a sentence about
/// only the field under the cursor. Where both fit, both draw. Where they
/// cannot, `LANDS` gives way first, since the panel's own impact sentence
/// already names the focused field's cost and nothing else on screen names
/// the column's.
///
/// Always `true` when the panel is absent: nothing else on screen carries
/// cost then, so `LANDS` has no reason to hide.
pub const
/// The width the rows are laid out in: the terminal minus [`GUTTER`].
pub const
/// What a change to a field in `group` costs, in an operator's words.
///
/// A prediction from the field's class, not the outcome of a specific
/// write: `watch` says `now` but can park, and `autostart` says `next
/// start` but takes effect at muster. The status bar reports what
/// actually happened; the row's `!` flag is the durable answer.
///
/// [`ApplyGroup`] is `#[non_exhaustive]`, so an untaught field falls back
/// to `respawn`, the most conservative of the four.
pub const
/// The three cell widths for a body of `width`: KEY, VALUE, COST. A zero
/// means the column is not drawn at all.
///
/// The three always sum, with their two-space separators, to exactly
/// `width`, so no line can overrun the terminal it was laid out for.
/// COST goes first when the terminal narrows: arming a field repeats its
/// cost verbatim in the status bar, which is the same reasoning
/// [`super::super::settings`] gives for dropping its own cost cell first.
///
/// `show_lands` is `false` only where the explanation panel is drawn and
/// the terminal is too narrow to hold both beside it (see
/// [`lands_fits_beside_panel`]): the panel still names the focused field's
/// own cost in its impact sentence, so nothing on screen goes unsaid.
/// `false` here behaves as if `width` had fallen under [`FULL_WIDTH`] on its
/// own, freeing what COST would have spent onto VALUE instead.
pub
/// Masks a secret field's rendered value: [`UNSET`] passes through, since
/// there is nothing to hide, and anything else becomes `<set>`.
///
/// The one rule every render path in this file applies to a secret before
/// its value reaches the screen, and every one of them calls this rather
/// than spelling the condition again: [`super::field_row::field_line`]'s stored cell and its
/// `old -> new` cell, `list::list_line`'s elements, and both halves of
/// [`super::chrome::pending_edit_line`]. Four inline copies of it agreed with each other
/// until they were routed through here, which is the state a fifth call
/// site would have had to keep up.
pub
/// The columns `line`'s spans occupy, added rather than measured against a
/// fixed cell: a blank separator or an unselected section header is
/// shorter than the left column's own width on its own, and only the
/// panel's own starting column cares where it ends.
pub
/// Wraps `text` at `width` columns, breaking on spaces. A single word
/// longer than `width` is placed on its own (overlong) line rather than
/// split mid-word: [`super::super::super::field::Field::help`] is prose, not data, and a rare overlong
/// word is a smaller wrong than a hyphen this module invented.
pub
/// `text`, truncated (never padded) to at most `width` columns, marking a
/// cut with a trailing `…` the way [`super::super::flock::fit`] does.
///
/// Not [`super::super::flock::fit`]: the panel's rows are prose, not a fixed-width table cell,
/// so a short value stays short rather than growing padded trailing spaces
/// across the column. This is the guard the panel's own width tests check:
/// a row built from a live value or a schema-authored sentence cannot push
/// the panel past its own column, even though nothing in today's schemas
/// is long enough to exercise the truncation itself.
pub