Draw an occupied block as a flat red wash, not a hatch - #183
Merged
Merged
Conversation
Operator feedback: the hashing on an occupied block stands out too much. It does, and the diagram's own reasoning is why that matters. A hatch is the loudest non-colour mark the diagram has, and `unknown` is meant to be the most visually assertive of the three occupancy states because it is the one that refuses routes. Spending a hatch on `occupied` - the state a working railway sits in most of the time - put the busiest texture on the ordinary case and left the fail-safe state shouting over it. The rule that replaces it (`docs/diagram-encoding.md` D10): texture separates a fault from an operational state, never one operational state from another. `unknown` keeps its cross-hatch and is now the only hatch on the diagram; the `diag-occupied` pattern and its `<pattern>` def are gone. Two flat washes cannot be told apart by hue alone, and that is not rhetorical for this pair: composited over the `#1e1e2e` tile at the same opacity, `#f38ba8` and `#a6e3a1` land 6.9 apart in RGB under simulated deuteranopia - occupied and clear become the same colour for roughly 8% of men. So the flat wash carries its own non-colour distinction: `OCCUPANCY_WASH_OPACITY` draws occupied at 0.55 and the other two at the ordinary `BLOCK_TINT_OPACITY` (0.26). That is a 1.57:1 luminance step, taking deuteranope separation to 34.8 and protanope to 22.3. With colour removed entirely, occupied is the heavier block - the right direction, since it is also the one carrying a train - and the run label's glyph is unchanged on top of that. A deeper red is the instinct and is the wrong one: `#e64553` and `#ff6b6b` both read as more emphatically red to normal vision and worse to everyone else (`#ff6b6b` at 0.55 falls to 6.7 under protanopia, indistinguishable from clear). Red is intrinsically dark and green intrinsically light, so the only red wash that outweighs a green one is a light red. `#f38ba8` was already the state palette's red, so no new colour enters the system. `POINT_CONFIRMATION.mismatch` named `diag-occupied` and is nulled with it - nothing ever drew it (a confirmation is a badge, not an area, so its glyph has always been the carrier), and naming a pattern id that no longer exists is worse than naming none. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Operator feedback on the control view: "the hashing stands out a bit too much" on an
occupied block, and hashing on
unknownis fine because that reads as a fault rather thanan operational state. That is the right instinct, and the diagram's own reasoning agrees
with it.
Texture now marks a fault state, not an operational one
A hatch is the loudest non-colour mark the diagram has, and
docs/diagram-encoding.mdD2already said
unknownshould be the most visually assertive of the three occupancy states,because it is the one that refuses routes. Spending a hatch on
occupied— the state aworking railway sits in most of the time — put the busiest texture on the ordinary case and
left the fail-safe state shouting over it. D2's claim about
unknownwas half true at bestwhile the two were competing for the same channel.
So
occupiedis a flat red wash,clearstays a flat green wash, andunknownkeepsits cross-hatch and is now the only hatch on the diagram. The
diag-occupiedpattern andits
<pattern>definition are deleted. New rule, recorded as D10: texture separates afault from an operational state, never one operational state from another — which is also
the line #71's decorative track and #82's staleness will be measured against.
What the hatch was carrying, and what carries it now
#81's rule is not rhetorical for this pair. Composited over the
#1e1e2etile at the sameopacity,
#f38ba8and#a6e3a1land 6.9 apart in RGB under simulated deuteranopia —occupied and clear become the same colour for roughly 8% of men, which is exactly the
failure the whole document exists to prevent. Two flat washes separated only by hue would
have been the bug, not the fix.
So the flat wash carries its own non-colour distinction.
OCCUPANCY_WASH_OPACITYdrawsoccupiedat 0.55 andclear/unknownat the ordinaryBLOCK_TINT_OPACITY(0.26):#935a71#41514cWith colour removed entirely, occupied is the heavier block — the right direction, since
it is also the one carrying a train. The run label's
OCCUPANCY[…].glyph(■ □ ?) and thelegend on the status strip are unchanged, so weight is the second carrier, not the only one.
The resting layout is pixel-identical: only
occupiedmoved.Refused: a deeper, more saturated red
Tried and rejected.
#e64553and#ff6b6bboth read as more emphatically red to normalvision and worse to everyone else —
#ff6b6bat 0.55 falls to 6.7 under protanopia,essentially identical to clear. Red is intrinsically dark in luminance and green
intrinsically light, so the only way a red wash outweighs a green one is to be a light red.
#f38ba8was already the state palette's red (FAULT,SENSOR_OBSERVATION.occupied), sokeeping it means no new colour enters the system and nothing needs re-validating against the
four block tints.
Also
POINT_CONFIRMATION.mismatchnameddiag-occupiedand is nulled alongside it. Nothing everdrew it — a confirmation is a badge, not an area, so its glyph (
✗) has always been thatrecord's non-colour carrier — and naming a pattern id that no longer exists is worse than
naming none.
What this does not change
Occupancy remains a fill and a lock remains a line along the road (D2). The four validated
block tints are untouched (D4) — this changes the opacity of a state wash, and identity
still gives up the colour channel wherever state is drawn (D1). The sensor observation mark
keeps
OCCUPANCY.occupied's hue at its own scale (D8); it is a 7px circle-and-line, neveran area, so wash opacity does not reach it.
Tested
New tests in
diagram/encoding.test.tspin the rule rather than the pixels: only thefail-safe state carries a hatch,
OCCUPANCY_WASH_OPACITY.occupiedmust exceedclear's,clear/unknownstay atBLOCK_TINT_OPACITY, and every state still ships a distinct glyphand label.
Run in this session, from the repo root:
Docs
In the same commit: D10 added to
docs/diagram-encoding.mdwith the numbers and therejected alternatives, D2's "unknown is the most distinct" paragraph amended,
docs/liveness.mdM5's treatment table,
docs/track-editor.mdD18 (which narrated the retired hatch'salignment bug), plus the
docs/current-state.mdlong form and theCLAUDE.mdindex line.