Skip to content

Rebuild the left column, and put the map's controls on the map - #136

Merged
khagele merged 4 commits into
mainfrom
column-redesign
Sep 10, 2026
Merged

khagele merged 4 commits into
mainfrom
column-redesign

Conversation

@khagele

@khagele khagele commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Four issues, four commits, in the order they can be reviewed. Everything here came out of measuring a real run — 8 first-hop prefixes near Delft, cluster locked, commit 3885428 — rather than from reading the markup.

The starting numbers: the left column was 2145px beside a 792px map, Step 2 alone was 1587px, and the card holding the map's own controls sat at y=1852, 973px below the bottom of the map. On a phone the map started at y=2297 of a 2776px page.

1 · Step 1 had four text roles in one voice (#132)

Role Size Colour
Field label 13.44px rgb(158,182,192)
Explanation under it 12.48px, opacity .85 rgb(158,182,192)
Incident toggle 13.44px rgb(158,182,192)
km unit label 13.44px rgb(158,182,192)

The hierarchy was also inverted: p.hint had no colour of its own, inherited --text at .85 opacity, and rendered brighter than the --muted label above it.

Now three roles, three treatments: the label leads, a new .field-help carries the static explanation in a quieter --faint and is never overwritten, and p.hint becomes the app's reply channel — monospaced with an accent rule, so "Parsed observers: …" can no longer be read as the next field's opening words.

Two bugs fell out of it: no rule styled a inside the panels, so links rendered in the browser default #0000EE on a dark teal card; and `PREFIX` or `PREFIX:count` shipped with literal backticks as UI text.

2 · Two ways into Step 1 (#133)

The spam-detector importer is the other way to start, not a footnote — it was a <details> above the main field, so the exception route opened the panel. It is now a segmented control, and loading an incident fills the prefix field, switches back to it, and says where the values came from.

Second-hop prefixes fold away by default, with 2nd-hop km travelling with them since it governs nothing else. A deep link carrying second-hop clues opens the fold, so a shared scene never hides part of itself.

3 · Observer rows, and a number that was missing (#134)

Rows spent three lines on 51.99951, 4.39375 — one-metre precision in a list where you choose between candidates kilometres apart — and never showed distance to the cluster centre, which is the figure dedupeByPrefix() actually falls back to when proven links do not separate a prefix (#54).

Rows now read centre 0.1 km · reach 4.3 km, with the exclusion reason as a tag beside the name. Distance is computed at render, so dragging an observer (#33b) moves it too. Coordinates stay in the map popup.

Chasing the row height found the real cause: .step-panel input (0,1,1) outspecified .observer-weight (0,1,0), so the weight field kept the panel's 12px padding and stood 48px tall while its own text was 30px. The field, not the content, set the 60px row.

The cluster status concatenated six caveats into one paragraph. Same six facts, one per line, count first; nothing dropped, per AGENTS.md. The two that are inference rather than measurement take the second accent (#54, #85).

4 · The map's controls, and folding steps (#135)

The strip moves into .map-col above .map-wrap: with the map, never over it, so there is no overlay against a light basemap and no z-index to maintain. Relief is a chip opening a popover, which keeps the strip one line at its widest. ? and 🔔 go to the topbar.

Step panels get a clickable head with a summary, so a folded step reads Step 1 · 8 prefixes and can be reopened — Step 1 already folded itself when a cluster locked, with no way back and nothing said. On a narrow screen Step 2 folds once an estimate exists. An automatic fold never fires on a panel opened by hand.

Result

before after
Left column, desktop 2145px 1726px
Observer row 60px 42px
Observer list 949px 711px
Map controls 973px below the map above it
Phone: map starts at y=2297 y=742
Phone: page height 2776px 1221px

Verified

Driven against the running page at 1440×900 and 375×812: full discovery → lock → estimate, both entry tabs, a real incident import (#2148, 8 entry hops), deep links with and without second-hop prefixes, the relief popover, folding by hand and automatically, and that a hand-opened panel stays open through a second estimate.

One bug was introduced and caught here: removing the concatenated notes in commit 3 left a reference to hullNote, which threw when activating a cluster. Fixed in commit 4 and re-verified with a full run.

Changelog entry per commit, per AGENTS.md §7.

Closes #132
Closes #133
Closes #134
Closes #135

🤖 Generated with Claude Code

khagele and others added 4 commits September 10, 2026 11:11
Four text roles in the panel shared one voice: field label, the explanation
under it, the incident toggle and the km unit labels were all rgb(158,182,192)
within a pixel of each other. The hierarchy was inverted too — p.hint had no
colour of its own, so it inherited --text at .85 opacity and rendered brighter
than the --muted label above it. The explanation outshouted the field it
explained.

Three roles, three treatments. The label leads (--text, semibold). A new
.field-help carries the static explanation in --faint, a step below --muted,
and is never overwritten, so it survives typing. p.hint becomes the app's reply
channel: monospaced with an accent rule down the left, so "Parsed observers:
..." can no longer be read as the opening words of the next field's label,
which is what happened when it replaced the help text mid-panel.

Also: panels had no rule for `a`, so the browser default #0000EE landed on a
dark teal card; links take the accent now. The literal backticks in "`PREFIX`
or `PREFIX:count`" shipped as UI text and become real inline samples. And three
status branches that told you to click the button you were looking at are gone
— that is instruction, it lives in .field-help now, and the reply channel is
for what the app did.

Closes #132

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The spam-detector importer is the other way to start a run, not a footnote to
the first one, but it shipped as a <details> above the prefix field: collapsed
it read as a stray grey line, expanded it pushed the primary field down ~120px,
and either way the exception route opened the panel.

It becomes a segmented control — Prefixes | Spam incident — with the same shape
in both panes: label, field, help, one primary button. Loading an incident
fills the prefix field and switches back to Prefixes, and says where the values
came from in the reply channel next to them ("From incident #2148: 8 entry
hops, weighted by packets"), because the pane that used to carry that message
is hidden by then. Nothing arrives invisibly and it is still editable before
the search runs.

Second-hop prefixes fold into a disclosure, closed by default: a run is
first-hop only most of the time. 2nd-hop km travels with them, since it governs
nothing else; Cluster km stays out, since it governs every run. A deep link
carrying second-hop clues opens the fold, so a shared scene never hides part of
itself.

Closes #133

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rows spent three lines on `51.99951, 4.39375` — one-metre precision in a list
where you choose between candidates kilometres apart — and never showed the
number the automatic pick is actually made on. dedupeByPrefix() falls back to
"nearest the cluster centre" when proven links do not separate a prefix (#54),
the status says so, and the list gave you no way to see it.

Rows now carry `centre 0.1 km · reach 4.3 km`, with the exclusion reason as a
short tag beside the name (full wording in its title) instead of a third line.
Distance is computed at render, so dragging an observer (#33b) moves it too.
Coordinates stay in the node's map popup, where a position belongs.

Chasing the row height turned up the real cause: `.step-panel input` (0,1,1)
outspecified `.observer-weight` (0,1,0), so the weight field kept the panel's
12px padding and stood 48px tall while its text was 30px. The field, not the
content, set the 60px row. Measured on the same 8-prefix run near Delft: row
60px → 42px, editor 949px → 711px, left column 2145px → 1797px.

The cluster status concatenated six caveats into one paragraph — eight
sentences of prose in a 300px column. Same six facts, one per line, count
first; nothing dropped, per AGENTS.md. The two that are inference rather than
measurement take the second accent (#54, #85).

Closes #134

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The controls card sat at the bottom of the left column, after all three steps.
Measured on an 8-prefix run near Delft at 1440x900: the map ran y=87 to y=879
and the card sat at y=1852 — 973px below the bottom of the map it acts on. To
switch off the range polygons because the map had gone pink, you scrolled the
map completely out of view.

It becomes a strip inside .map-col, above .map-wrap: with the map, never over
it, so there is no overlay against a light basemap and no z-index to keep in
step. Relief is a chip that opens its slider in a popover, which keeps the
strip one line at the widest state (Clear Map, Resolve on map, Show + 4 chips,
Share). ? and the bell move to the topbar, where about-the-app controls belong.
The "enter prefixes first" line moves onto the disabled Share button rather
than standing in the strip and making it two rows tall before anything has
happened.

Step panels get a clickable head with a summary of what they hold, so a folded
step reads "Step 1 · 8 prefixes" and can be opened again — Step 1 already
folded itself when a cluster locked, with no way back and nothing said. On a
narrow screen Step 2 folds once an estimate exists: at 375x812 that moves the
map from y=1822 to y=742 and the page from 2301px to 1221px. An automatic fold
never fires on a panel the operator opened by hand.

Two specificity traps found on the way: `.step-panel button` (0,1,1) painted
the new heads with the accent fill, the same way it had been inflating the
observer weight field.

Closes #135

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@khagele
khagele merged commit 8bfcc8e into main Sep 10, 2026
2 checks passed
@khagele
khagele deleted the column-redesign branch September 10, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment