Inline edit fields

Four different answers to “is this field live?” ship on one screen today, and two surfaces answer it with nothing at all. The fix is not a fourth invention — it is one signal whose fill inverts with the ground it sits on, plus one named exemption. Columns two and three are live CSS, not screenshots: what you see is what the declarations beneath them do.

Treatment A — field on page background

The ground is already white, so the field tints up to be seen.

--bn-field-edit-fill-on-page
--bn-field-edit-edge at 1px

Treatment B — field on a tinted surface

The ground is already coloured, so the field blanks to neutral to be seen.

--bn-field-edit-fill-on-tint
--bn-field-edit-edge at 1px

Exempt — quote crop and trim

Not “edit this text” but “move this boundary”. Custom by design, one signal with the burnt-amber brackets. Keeps its yellow, now honestly named --bn-colour-crop-bg. Do not restyle it to match, and do not borrow that yellow.

Scenario
Before
After — shipped 20 Sep 2026
Treatment and why

Theme heading

Quotes lens · ground page

changed
page background

Onboarding friction

.editable-text.editing {
  background: --bn-colour-editing-bg;
  outline:    --bn-colour-editing-border;
}
/* never matches: React adds no
   .editing class — only theme/js
   does, in the static byproduct */
page background

Onboarding friction

.editable-text[contenteditable="true"] {
  outline: 1px solid --bn-field-edit-edge;
  outline-offset:    --bn-field-edit-offset;
  background:        --bn-field-edit-fill-on-page;
  border-radius:     --bn-field-edit-radius;
}

Keys on the attribute, not a class, so it needs no co-operation from the component and cannot fall out of sync again. Resting padding plus equal negative margin means entering the field moves no text.

Theme description

Quotes lens · ground page

changed
page background

Where people stall in the first run

page background

Where people stall in the first run

Same rule, same class, no second selector. The heading and its description were always siblings in the markup; they are now siblings in the CSS too.

Participant name

Sessions lens · ground page

unchanged — now tokenised
page background p3Sarah Chen
.bn-speaker-editable-name[contenteditable] {
  outline: 1px solid --bn-colour-accent;
  outline-offset: 1px;
  background: --bn-colour-quote-bg;
}
page background p3Sarah Chen

Pixel-identical. This one was already right, which is what made it the model — the tokens were reverse-engineered from it rather than invented. Its declarations are deleted from person-badge.css and the class now joins the shared selector, so there is one rule, not two that happen to agree.

Code group title

Codes lens · ground tinted card

changed
group-tinted card
Navigation
how people move around
group-tinted card
Navigation
how people move around
.group-title-text[contenteditable="true"] {
  outline: 1px solid --bn-field-edit-edge;
  outline-offset:    --bn-field-edit-offset;
  background:        --bn-field-edit-fill-on-tint;
  border-radius:     --bn-field-edit-radius;
}

A tint on a tint reads as nothing — the same 1.01:1 wall the code cursor hit. Blanking to page background is what the code chips three inches below already do: one card, one idiom, whether you are naming the group or naming a code inside it.

The card's own selection edge stands down via :focus-within as this one lights, so exactly one accent edge is on screen and it is around the thing taking the keystrokes.

Code group subtitle

Codes lens · ground tinted card

changed
group-tinted card
Navigation
how people move around
group-tinted card
Navigation
how people move around

Shares the selector with the title. Keeps its existing display:inline-block and min-width:12ch — the fix that stopped a three-word subtitle getting a field four times its length, and that keeps an empty one from collapsing to a caret with no box.

New code

Codes lens · ground tinted card

unchanged — now tokenised
group-tinted card wayfinding back-b
.tag-input-box {
  border: 1px solid --bn-colour-accent;
  background: --bn-colour-bg;
}
group-tinted card wayfinding back-b

Pixel-identical, and the second model the tokens were read off. Border rather than outline because this chip already owns a box — that is a layout mechanism, not a second meaning, and the set deliberately leaves the choice open. Outline is for a span in running prose, where a border would reflow the line.

Rename a code

Codes lens · ground tinted card

already aligned
as it was two weeks ago wayfinding
.tag-edit-inline {
  /* .badge metrics dragged in the
     grey fill; the ring was
     --bn-focus-ring at 12% alpha */
  box-shadow: --bn-focus-ring;
}
group-tinted card wayfinding

This one you already fixed by eye — “whatever you're doing for the brand new tag on first edit feels right”. All that changes now is that it reads the tokens instead of repeating their values, so re-editing and first-typing cannot drift apart again.

Worth keeping as the cautionary specimen: twelve per cent alpha on a tinted card is a ring that technically exists and cannot be seen.

Crop / trim a quote

Quotes lens · ground quote card

exempt — do not touch
quote card

[it just kept spinning and I had no idea if it had worked]

quote card — identical

[it just kept spinning and I had no idea if it had worked]

Untouched, deliberately. The verb is different — you are moving a boundary, not retyping a string — and the yellow was designed to read as a single signal with the brackets. A different verb is allowed a different look.

Not one declaration changed. What changed is the name: --bn-colour-editing-bg is now --bn-colour-crop-bg, because a token named for a state it must not be used in is how three other surfaces came to borrow it in the first place. Same hex, same rules, same pixels.

Search, filters, settings

Everywhere · ground page

not in the set
page background
page background — identical

A different animal, and the distinction is worth stating so nobody “aligns” these next. A real <input> has a box at rest: it is visibly a field before you touch it, so focus only needs to promote the resting border to accent. An inline edit has no box at rest — it is prose until you click it — so focus has to conjure the field, which is why it needs a fill as well as an edge.

Rule of thumb: if the reader can see it is a field before interacting, use the resting-border pattern. If they cannot, use the --bn-field-edit-* set.