BRIEF-v2 step 2 · 2026-10-10 · surface only, nothing in here changes
the engine. Page: approaches/B/index.html (fragment:
<title>, charset + viewport metas, Google-Fonts link,
<style>, markup, <script>). QA
round 1 fixes applied (2026-10-10):
<meta charset="utf-8"> added after the title; drum
neighbour rows raised 38 → 44 px so the ± tap rows meet the 40-px
minimum (fade 30 → 20 px); §1 / §6 touch-size statements corrected; the
three qa/round1-*.png re-taken. Reference for every
contract not repeated here: CONTROL-MAP.md §0 (common
contracts) and the [F] column of §1, §2, §5.
Idea in one sentence. The panel is a Swiss form: a typographic ledger with numbered rubrics, hairline rules and no boxes. Read-outs are ledger rows (label left, tabular value right, a 3-px rule in the left margin as the state). Inputs are tap-only — flat text stops, drums, a notched rail — never a dragged carriage.
Numbers in «» are the hard-coded values on the page. "Touch" and "Keys" state the product behaviour the coder builds; §5 says which of it the mockup actually does.
| # (CONTROL-MAP) | Original (as observed) | Einsatzblatt control | Range · step · precision · unit | Touch | Keys | State colours / wording |
|---|---|---|---|---|---|---|
| C1 | Bold title «Löschwasser» · × | Running head: title in sentence case, «‹» collapse key (44 × 44) at the left; the panel slides shut | — | tap | Enter/Space | — |
| C2 | Tab strip Details · Werkzeuge · Netzwerk · Warnungen with red count circle | Register: the four views are collapsible section heads stacked in one scroll. «Warnungen (3)» writes the count into the heading, gets a 3-px orange rule in the left margin and sorts to the top when count > 0; «Details» is open by default; «Werkzeuge» and «Netzwerk» sit below the object's foot row. Head = chevron «›» (rotated 90° when open) + label, ≥ 52 px tall | count whole; four views | tap a head toggles it | Enter/Space toggles · ↑/↓ moves between heads · Ctrl+1…4 jumps | orange rule when count > 0, red when any warning is critical (owner's severity rule); the count is a plain numeral, never a circle; a heading reads the state in words |
| C3 | Small-caps grey uppercase labels | Numbered rubrics «1 Pumpentyp», «2 Maschinisten-Tafel», «3 Wasserbezug der Pumpe», «4 Tankinhalt», «5 Pendelbetrieb (Wassertransport im Kreisverkehr)»: bold sentence case 18 px, number in the 14-px margin, 1.5-px top rule, no fill | — | — | — | — |
| C6 / A1 / B1 | Coloured letter tile «MS» / «TLF», bold name, grey «Typ | Höhe», dotted rule | Ledger head: the standard symbol (48-px line drawing, placeholder — see §4) at the left, name 30 px bold, type and altitude stacked in the value column. TLF: «565 m ü. M. · 100 %» (tank % after the altitude) | altitude whole m ü. M.; tank % whole | — | — | no colour on the head; the pump state is read in rubric 1 |
| A2 / B2 | Native <select>, caret right, text truncated |
Picker row that expands in place: full-width row «Pumpentyp», value right-aligned in plain text (wraps to two lines, never truncated), disclosure «›». Tap/Enter grows the ledger in place by n rows (radio mark on the current, option text on one line); Esc collapses. On phone the same list may open as a bottom sheet docked to the panel's edge — never a popover under the row | list of ~6 classes; «MS Typ 2 (1600 l/min, 8 bar)» / «FPN 10-2000 (2000 l/min, 10 bar)» | tap row, tap option (2 taps) | ↑/↓ move, Enter selects, Esc closes, letter jumps | — (the chosen row's radio mark is teal) |
| A3 / B3 | iOS-style pill toggle | Two-segment control in the ledger row: «In Betrieb» · «Aus» (Aus: wording owner) as two adjoining square-cornered segments with a 1.5-px outline; the chosen segment is filled teal and carries a check glyph + the word | on / off | tap a segment (1 tap); build each segment ≥ 56 × 56 pt (mockup draws 56 × 44 px at desktop scale) | ←/→ or Space/Enter | chosen = teal fill + check + word; never colour alone |
| A4 / B4 | Horizontal range slider with round thumb, «8.0 bar» text at right | Tap-rail + tenths drum + flat stops (three parts, one value): (a) the big set numeral «8.0 bar» (32 px) in the row's value column; (b) four flat text stops «6 · 8 · 10 · 12» (≥ 56 × 48 px, underline rule, the stop equal to the set value highlighted teal); (c) a vertical tenths drum showing «.9 / .0 / .1» (current row framed, 24 px); (d) a notched tap-rail 0 – 16 bar: ticks every 0.5 bar (short), whole bars long, every 2 bar labelled; a printed flag «8.0 ▾» above the rail at the set value. No carriage, no drag, no fill along the rail (§0 rail contract) | 0 – 16 bar · 0.1 · one decimal · bar; presets 6 / 8 / 10 / 12 | tap a flat stop = whole value in 1 tap (10 bar = 1 tap) · tap a tick column = that 0.5 stop (tenths become .0 or .5) · drum: flick-and-snap, or tap the upper/lower row = ± 0.1 with carry (7.9 → 8.0, 8.0 → 7.9), clamped 0.0 … 16.0 · tap the big numeral = typed entry, Enter commits, Esc reverts | rail focused: ←/→ ± 0.1 · Shift ± 1.0 · PgUp/PgDn next/previous flat stop · Home/End 0 / 16 · digits open typed entry. Drum focused: ↑/↓ ± 0.1 | set value and read-out (A6) are kept apart: this block is the input only. Glove note (honest): a tick column is rail-width / 32 (~11 px at 360 px, ~20 px at 640 px) and is not glove-sized; the glove path is the four stops + the drum (64 × 44-px neighbour rows for ± 0.1, 64 × 48-px framed current row). Owner may ask for whole-bar stops only on phone |
| A5–A10 / B5–B10 | 2 × 3 grey tile grid, small-caps label over big number | Ledger column under «2 Maschinisten-Tafel», rows in this order: Eingangsdruck · Ausgangsdruck · Erforderliche Einstellung · (group rule) · Ist-Durchfluss · Max. Leistung · (group rule) · Leistungsreserve as a sum line (bold, 1.5-px top rule). Columns: label 17 px · value 24 px tabular right-aligned · unit in a fixed 3.3-rem column so decimals align · delta printed in 14 px under the value when present («+0.8 bar») | bar 0.1 · l/min whole; «7.5 · 8.0 · 400 · 1'600 · – · 1'200» (MS 4); «0.0 · 8.0 · 800 · 2'366 · 8.8 (+0.8) · 1'566» (TLF 8 bar); «0.0 · 12.0 · 800 · 1'549 · 12.0 · 749» (TLF 12 bar) | read-only | read-only | 3-px left-margin rule: green = live value ok (Eingangsdruck, Ausgangsdruck, Ist-Durchfluss); orange = attention (Erforderliche > set) plus the printed delta «+0.8 bar»; none = neutral computed value (Max. Leistung, Leistungsreserve); «–» printed when the pump governs no nozzle. Null outlet (KEIN_ZULAUF, not drawn): value «–», red rule |
| B11 | Native <select> «aus eigenem Tank (Zulauf»
truncated |
Picker row + inline list, component of A2; value «aus eigenem Tank (Zulauf …)» | list ≥ 2 (full texts owner) | 2 taps | as A2 | — |
| B12 | Borderless number «2400», unit «l» floated far right | Drum with flat stops: one coarse 100-l wheel in a 3-row window («2'300 / 2'400 / 2'500», current row 24 px framed by two rules), unit beside the window; flat stops «1'800 · 2'400» under the label (list from owner) | whole l · ≥ Füllstand · unbounded above | tap a stop (1 tap) · flick the wheel or tap the upper/lower row ± 100 · tap the window = typed entry (unbounded) | ↑/↓ ± 100 · Shift ± 1'000 · digits typed entry | — |
| B13 | As B12, «2400 l» | Drum with stops «0 % · 50 % · 100 %» (computed from Tankinhalt), 100-l wheel capped at Tankinhalt (the next row is blank at 100 %) | whole l · 0 … Tankinhalt | as B12 | as B12 | drives the litre scale (B15), «Leer in» (B16) and the map chip % |
| B14 | «400», «l/min» far right | Drum with stops «400 · 800», 50-l/min wheel («350 / 400 / 450») | whole l/min · unbounded above | as B12 (± 50) | ↑/↓ ± 50 · Shift ± 500 | — |
| B15 | Grey card, flat teal progress bar, «2400 / 2400 l (100%)» | Litre scale (read-out only): a horizontal ruler 0 … Tankinhalt with 13 ticks (every 200 l; 600-l majors labelled «0 · 600 · 1'200 · 1'800 · 2'400 l»); ticks up to the Füllstand are drawn teal, beyond it hairline; a printed flag «Füllstand 2'400 l · 100 %» with a teal pointer at the fill. No bar, no fill, no drag; the compound «x / y l (z %)» string is never printed (the litres are rows B12/B13) | l whole · % whole | none (read-out) | none | teal = the scale's fill marks (accent is allowed on a read-out mark); low-tank warning: owner's thresholds (25 % / 10 % proposed) turn the pointer and the «Leer in» rule orange / red |
| B16 | «Leer in 06:00» at the right end of the bar | Ledger row «Leer in … 06:00 min» (printed time, 24 px tabular mm:ss) | mm:ss | read-only | read-only | B16 state rule (CONTROL-MAP): net < 0 → «mm:ss», green rule; Füllstand = 0 and net < 0 → «00:00», red rule; net ≥ 0 → «–», no rule; pump off → «–». «Voll in» from fullInSec only if the owner wants it (§8) |
| B17 | «▶ Start · Tempo: 1x · 11:18» inside the tank card | removed from the panel → C5 | — | — | — | — |
| B18 | Pill toggle, off | Two-segment control «Aktiv» · «Inaktiv» (wording owner), component of A3; «Inaktiv» chosen | on / off | 1 tap | ←/→, Space | chosen = teal fill + check + word |
| B19 | «15», «min» far right | Drum, 1-min wheel («14 / 15 / 16»), no stops | whole min · floor 1 (0 refused) · unbounded above | flick / tap rows ± 1 · typed entry | ↑/↓ ± 1 · Shift ± 10 | — |
| B20 | «800», «l/min» far right | Drum with stops «400 · 800», 50-l/min wheel, component of B14 | whole l/min · unbounded above | as B14 | as B14 | — |
| B21 | Grey status card «PENDELBETRIEB AKTIV / inaktiv (stationär)» | Ledger row «Pendelbetrieb … inaktiv (stationär)», value 19 px, grey rule in the margin | two states (active text from owner) | read-only | read-only | grey rule = off; green rule + active text when on |
| A11 / B22 / C4 | Pale-red outlined «Entfernen» button, bottom-left | Foot action row under the ledger (1.5-px top rule): left slot = object name «MS 4 · Motorspritze»; right slot = the word «Entfernen» in grey, no glyph, nothing red at rest. Tap arms in place: a filled red «Entfernen» with trash glyph + an outlined «×» (44 × 44) cancel; second tap removes | — | 2 taps by design; focus moves to the red key when armed and back to the word when disarmed | Enter arms · Enter confirms · Esc or × disarms | red only in the armed state |
| C5 | Start button, native Tempo select, boxed clock (three copies in the app) | One ledger foot row for the module (drawn once under both sheets; in the product it is the panel's foot): two-segment «Start» · «Pause» (the filled segment = current mode; shown paused at 11:18 as in the frame), «Tempo» as a small drum («1x» current, «2x» next; list from owner), clock 30 px tabular «11:18» | Tempo from the engine's list; clock mm:ss | tap | Space = Start/Pause · ←/→ Tempo | — |
Rule-zero check against the frames: no range slider, no pill toggle, no native select, no tile grid, no tab strip or count circle, no progress bar, no unit floated at the far right of a plain field, no red Entfernen at rest, no small-caps grey section labels.
| Row | CONTROL-MAP [F] option | Built here | Why |
|---|---|---|---|
| A4 / B4 | Drum pair «bar · tenths» + flat stops | Tap-rail with 0.5-bar stops + tenths drum + flat stops | The step-2 design seed for approach B asks for a notched rail with 0.5-bar stops and a drum for tenths. The rail is tap-only (no carriage, no drag, no fill), so the §0 rail contract (nothing dragged along a straight track) holds; the tenths drum is the second wheel of the drum pair. The glove caveat is stated in §1 |
| B15 | Ledger row «Füllstand … 100 %» with a ten-block column in the margin | Horizontal litre scale with a marker flag | Seed: "the tank is a horizontal litre scale with a marker". The % and litres stay printed (flag + rows B12/B13) |
| B16 | Timeline rail in elapsed mm:ss with a marker at 17:18 | Printed time in a ledger row «Leer in … 06:00» | Seed: "the countdown as a printed time". The B16 state rule is unchanged |
| C5 | Ledger foot row in the panel | Ledger foot row drawn once under both sheets | The page shows two panels at once; the product has one panel and one foot row |
Everything else follows the [F] cell verbatim (register, numbered rubrics, ledger head, picker rows, two-button pairs drawn as a joined two-segment control, drums with flat stops, ledger column with sum line, foot action row).
Tokens on :root, redefined under
@media (prefers-color-scheme: dark) for
:root:not([data-theme="light"]) and under
:root[data-theme="dark"]; component rules use only
var(--…).
| Token | Light | Dark | Use |
|---|---|---|---|
--bg / --fg |
#f6f6f3 / #161717 | #131516 / #ebebe6 | page, text |
--fg-2, --fg-3 |
#585c5f, #8b8f92 | #a6aaad, #787c80 | secondary labels, notes |
--rule, --rule-2,
--rule-strong |
#d8d8d2, #b9bab4, #161717 | #2c3033, #454a4e, #ebebe6 | hairlines, group rules, rubric/sum rules |
--accent / --accent-ink |
#0c7a84 / #fff | #3cb6c0 / #0b1517 | chosen segment, highlighted stop, radio mark, scale marks — never a state |
--ok |
#1e7a3e | #52c474 | green margin rule (value ok) |
--attn |
#c25800 | #f29b40 | orange margin rule + delta (required > set), Warnungen rule |
--crit / --crit-ink |
#b3221b / #fff | #ef6157 / #170a09 | armed Entfernen; red rule for 00:00 / null outlet |
--well |
#eaeae6 | #1c1f21 | drum window recess |
A state is never colour alone: the orange row also prints «+0.8 bar»; the segment prints its word and a check; the Warnungen head prints the count; the armed Entfernen changes its shape (filled key + ×).
Type: Archivo 400/500/600/700 (Google Fonts) with fallback «Helvetica
Neue», Helvetica, Arial, system-ui. Sizes: rubric 18 bold · label 17
medium · ledger value 24 semibold · set value 32 bold · object name 30
bold · drum current row 24 bold · stops 20 · rail/scale labels 13 ·
clock 30. font-variant-numeric: tabular-nums on every
numeral. Swiss grouping «1'566», decimal point «8.0», units bar · l/min
· l · min · m ü. M.
Layout: one outer wrapper, 16–40 px side gutter; sheets side by side from 960 px, stacked below; ledger rows carry a 14-px left margin (3-px state rule + 11-px gap) so the rubric numbers, state rules and the Warnungen rule share one column.
Live: Pumpentyp and Wasserbezug rows expand/collapse in place (Esc closes; picking a row collapses without changing the value); the «Details» register head collapses its sheet; Entfernen arms into the red pair and Esc/× disarms; the TLF stops 8 / 12 and rail ticks 8.0 / 12.0 switch the two precomputed states (PgUp/PgDn on the focused rail does the same). Inert (drawn, focusable, documented above, no handler): the MS rail and stops, every drum, the two-segment controls, the Simulation row, «Werkzeuge» / «Netzwerk» heads, the collapse key.
ms-pumpentyp, ms-betrieb,
ms-druck (rail), ms-tenths,
ms-stop-6…12, ms-remove;
tlf-pumpentyp, tlf-betrieb,
tlf-druck, tlf-tenths,
tlf-stop-6…12, tlf-wasserbezug,
tlf-tankinhalt, tlf-fuellstand,
tlf-befuellung, tlf-pendel,
tlf-umlaufzeit, tlf-ablade,
tlf-remove, tlf-ro-* (read-outs),
tlf-warn; sim-run, sim-tempo,
sim-clock.role="spinbutton" with
aria-valuemin/max/now/text; two-segment controls and picker
lists are radiogroup / radio; picker rows and
the Details head carry aria-expanded +
aria-controls; the litre scale is role="img"
with a full-sentence label.prefers-reduced-motion: reduce.<meta charset="utf-8"> and
<meta name="viewport"> after the title so a locally
opened file (file://, Safari does not sniff) or a raw serve without a
charset header decodes the German correctly and lays out at phone width;
the artifact host's own head makes both redundant there.