Skip to content

feat(chat): a font-independent wordmark for the empty state - #85

Merged
ndemianc merged 2 commits into
developfrom
feat/wordmark-font-independent
Aug 17, 2026
Merged

feat(chat): a font-independent wordmark for the empty state#85
ndemianc merged 2 commits into
developfrom
feat/wordmark-font-independent

Conversation

@ndemianc

Copy link
Copy Markdown
Contributor

Installs the mark that #84 was meant to carry. #84 merged with only its revert commit, so develop currently has the original figlet art back — correct, but not the new design. This is the other half.

╭──────────────────────────────╮
│                              │
│  ▁▃▅█  L E V E L C O D E     │
│                              │
╰──────────────────────────────╯

Why this survives where #82's mark did not

That one drew letterforms out of , which only works where the font fills the character cell — a property of the font, not the character, and one Monaco does not have. I had claimed the opposite and verified it in a harness running SF Mono, so it looked perfect everywhere I checked and none of those checks were the editor.

This mark asks for neither property:

  • the frame is box-drawing rules — connector glyphs designed to join across cells in every monospace family
  • the letters are real text, not pixels
  • ▁▃▅█ is the only block run left, and it is decorative — an ascent, "level" made literal — so a font that renders it slightly short costs nothing

Verified before shipping this time. Rendered in Monaco, SF Mono, Menlo, Courier New, Andale Mono, Consolas and the generic fallback, plus the real empty state in Monaco in both themes. Legible in all seven; Monaco leaves hairline gaps at the frame corners and nothing else.

The two numbers are one number

The mark is 32 columns where the old one was 41, so the container-query factor moves with it: clamp(5px, 3.6cqi, 13px)clamp(5px, 4.6cqi, 13px).

41 × 3.6 and 32 × 4.6 both land the mark at ~88% of its container. The test pins that relationship rather than either number, because changing the art without the factor is exactly how this breaks — widen it and it overflows, narrow it and it becomes a stamp floating in white space. The failure message reports the computed fill percentage.

The old guard is deleted, not adjusted

It required "full blocks only", encoding the false belief as a rule. It would have blocked this fix while waving through the bug it was written for — worse than no test. The replacement records the Monaco finding and says plainly that ASCII art has to be looked at in the target font, because a static test cannot do it.

Guards

Each bypass-verified by reverting the fix:

bypass caught
cqi left at the old 41-column value (69% fill — a stamp)
cqi raised too far (115%)
art widened without touching the cqi (127%)
sizing no longer container-relative at all
role="img" dropped
the accessible name dropped

33 tests in webviewCss, 34 suites green.

Replaces the pixel-art mark from #82, which shattered into disconnected bars in the editor.

WHY THIS ONE SURVIVES WHERE THAT ONE DID NOT. The old mark drew letterforms out of `█`,
which only works where the font FILLS the character cell — a property of the font, not the
character, and one Monaco does not have. This mark asks for neither: the frame is built
from box-drawing rules, which are CONNECTOR glyphs designed to join across cells in every
monospace family, and the letters are real text rather than pixels. The `▁▃▅█` ramp is the
only block run left, and it is a decorative ascent — "level" made literal — so a font that
renders it slightly short costs nothing.

Verified before shipping this time, which is the part I skipped last time: rendered in
Monaco, SF Mono, Menlo, Courier New, Andale Mono, Consolas and the generic fallback, plus
the real empty state in Monaco in both themes. Legible in all seven. Monaco leaves hairline
gaps at the frame's corners and nothing else.

The mark is 32 columns where the old one was 41, so the container-query factor moves with
it: clamp(5px, 3.6cqi, 13px) -> clamp(5px, 4.6cqi, 13px). Those two numbers are halves of
one value — 41 x 3.6 and 32 x 4.6 both land the mark at ~88% of its container — and the
test now pins the RELATIONSHIP rather than either number, because changing the art without
the factor is the way this breaks: widen it and it overflows, narrow it and it becomes a
stamp floating in white space. The failure message reports the computed fill percentage.

The old guard, which required full blocks only, is gone. It encoded a false belief as a
rule and would have blocked this fix while waving through the bug it was written for.

Guards, each bypass-verified by reverting the fix:
  - the cqi left at the old 41-column value (69% fill — a stamp)
  - the cqi raised too far (115%) and the art widened without it (127%)
  - sizing no longer container-relative at all
  - role="img" dropped; the accessible name dropped

33 tests in webviewCss, 34 suites green.
Copilot AI lite review requested due to automatic review settings August 17, 2026 20:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the LevelCode AI chat webview’s empty-state wordmark to a font-independent design (box-drawing frame + real-text letters), and adjusts the container-relative sizing guard so the logo remains correctly scaled within the #empty container.

Changes:

  • Replaces the empty-state <pre class="lc-ascii"> figlet-style art with a box-drawing framed wordmark.
  • Updates the .lc-ascii font-size container query scaling from 3.6cqi to 4.6cqi to match the new mark’s width.
  • Reworks the webviewCss test to validate the “mark width ↔ cqi factor” agreement rather than asserting specific glyph composition.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
extensions/levelcode-ai/media/chat.html Replaces the empty-state wordmark art and updates its container-sized cqi scaling factor.
extensions/levelcode-ai/test/webviewCss.test.js Updates the wordmark sizing guard test to enforce the intended scaling invariant.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +605 to +611
const cqi = /\.lc-ascii[^{]*\{[^}]*font-size:\s*clamp\(\s*\d+px\s*,\s*([\d.]+)cqi/.exec(css);
assert.ok(cqi, 'the wordmark is no longer sized from its container');
// A monospace cell is ~0.6em wide, so the mark occupies cols * 0.6 * (cqi/100) of the container.
const fill = cols * 0.6 * Number(cqi[1]) / 100;
assert.ok(fill > 0.8 && fill < 0.95,
'the mark would fill ' + Math.round(fill * 100) + '% of its container — ' + cols + ' columns at '
+ cqi[1] + 'cqi. Below ~80% it reads as a stamp; above ~95% it touches the edges and can overflow.');
…a proxy

Review on #85, two distinct points and both correct.

THE SELECTOR COULD DRIFT TO THE WRONG RULE. `.lc-ascii-wrap` is declared BEFORE `.lc-ascii`
and `.lc-ascii-sub` immediately after it, and the old pattern —
`\.lc-ascii[^{]*\{[^}]*font-size:…cqi` — matched the right one only because -wrap happens to
declare no font-size. Luck of content, not construction.

Demonstrated rather than asserted: giving .lc-ascii-wrap a `clamp(5px, 9.9cqi, 13px)`, the
old regex reads 9.9 and the new one still reads 4.6. The rule is now anchored with a
negative lookahead so a hyphenated sibling cannot match, and the cqi is read from the
captured body rather than from a span that could cross rules.

THE FILL PERCENTAGE WAS FAKE PRECISION. It multiplied in a hard-coded 0.6em cell width to
report a tidy "88% of its container", but that factor is a property of whatever font the
editor resolves — it differs between Monaco and SF Mono — so the number dressed the real
invariant in an accuracy it does not have.

The contract is `cols x cqi`: the art's width in columns and the font size as a percentage
of the container are two halves of one value, and their product is what stays constant.
41x3.6 and 32x4.6 both land on ~147. That is what the test asserts now, and what the
failure message reports.

Guards, each bypass-verified by reverting the fix:
  - the decoy cqi on .lc-ascii-wrap, which the old pattern read and this one ignores
  - the cqi left at the old 41-column value (115.2); raised too far (192.0)
  - the art widened without the cqi (193.2)
  - sizing no longer container-relative at all

33 tests in webviewCss, 34 suites green.
@ndemianc

Copy link
Copy Markdown
Contributor Author

Both correct. Fixed in cfdd4dc.

The selector could drift to the wrong rule

Real, and worse than "if selector order changes" — the order is already against me:

766:  #empty .lc-ascii-wrap { … }     ← declared FIRST
770:  #empty .lc-ascii      { … }     ← the one we want
771:  #empty .lc-ascii-sub  { … }

The old pattern matched the right rule only because -wrap happens to declare no font-size. Luck of content, not construction.

Demonstrated rather than argued — giving .lc-ascii-wrap a clamp(5px, 9.9cqi, 13px):

clean with the decoy
old regex 4.6 9.9
new regex 4.6 4.6

Now anchored with a negative lookahead so a hyphenated sibling can't match, and the cqi is read from the captured body rather than from a span that could cross rules.

The fill percentage was fake precision

Also right. It multiplied in a hard-coded 0.6em cell width to report a tidy "88% of its container" — but that factor is a property of whatever font the editor resolves, and it differs between Monaco and SF Mono. Given this PR exists because I assumed a font property was universal, reporting a font-dependent number as the contract was the same mistake in miniature.

The contract is cols × cqi: the art's width in columns and the font size as a percentage of the container are two halves of one value, and their product is what stays constant. 41 × 3.6 and 32 × 4.6 both land on ~147. That's what the test asserts now, and what the failure message reports:

cols x cqi is 115.2 (32 columns at 3.6cqi). It must stay near 147 — the value both
shipped marks share (41x3.6, 32x4.6). Lower and the mark shrinks to a stamp in white
space; higher and it touches the edges and can overflow.

Guards

Each bypass-verified:

bypass caught
decoy cqi on .lc-ascii-wrap — old pattern read it, this one ignores it
cqi left at the old 41-column value (115.2)
cqi raised too far (192.0)
art widened without the cqi (193.2)
sizing no longer container-relative

33 tests in webviewCss, 34 suites green.

@ndemianc
ndemianc merged commit bec3377 into develop Aug 17, 2026
1 check passed
@ndemianc
ndemianc deleted the feat/wordmark-font-independent branch August 17, 2026 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants