Skip to content

fix(ui): drop the stylesheet selectors that can never match an element - #332

Merged
argszero merged 1 commit into
mainfrom
fix/css-orphan-selectors
Sep 30, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/css-orphan-selectors

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

ui/css/style.css carried four rules whose names no longer appear on any element — not in the markup, not in the scripts, and not in the design baseline the stylesheet itself declares (ui/css/style.css:4 → docs/prototype/aitokenpool-console.html):

selector status
.demo-hint (:754) element removed with the demo-seed cleanup (#90 35291b3); the rule stayed, and its i18n key was already retired
.login-divider + ::before + ::after (:757/:759) #159 f46882c moved the markup to the prototype's own name, .divider; the old rules kept a "historic alias" comment and nothing else
.wallet-note (:909) #156 41bb6d1 rewrote the element as .wallet-hero-note; the old rule was left behind
.sidebar #toggle-mode-btn (:1242, inside the mobile media query) the button it hides never reached the product; the #logout-btn beside it in the same selector list is live

A rule nobody carries still applies — writing class="wallet-note" today still gets its 12px — which is what makes these misleading: they read as live component rules for elements that no longer exist. Each of the four was introduced as a rename or a removal elsewhere, and the rule was left in place.

.delta (three rules) is deliberately kept: the prototype's statCard() really does emit <div class="delta ok">, so it is design-baseline vocabulary, not a leftover.

Related Issue

None — this came out of a repo-internal audit of selector/element correspondence, and there is no open issue for it.

Changes

  • Delete the four orphan rules; the one inside the media query is removed from the selector list only (its sibling #logout-btn stays). No behaviour change: nothing renders these names.
  • src/layout_gate.rs: new rule R4 every_selector_lands_on_an_element — every .class / #id in a selector prelude must occur on an identifier boundary in the app corpus (ui/index.html + ui/js/*.js) or the design-baseline corpus. Token roster derived from the selector text; script roster borrowed from js_gate so a new ui/js/*.js cannot slip past it; ⛔ no hand-written name list.
  • ui/README.md: convention section stating the invariant, why a still-applying orphan rule is worse than a deleted one, and the gate's scope.
  • ui/index.html: cache-bust token style.css?v=20260924-4 → -5.
  • No config / data-structure change.

Gate scope (lexical, deliberately wide): it proves a name has a landing site, not that the landing site is the element the rule was written for (a same-name occurrence in a comment, a string, or dead code counts; mentioning a name ≠ wearing it). The baseline corpus is an intentional escape hatch — anything the prototype mentions passes.

Tests

  • cargo test — 446 passed, 0 failed (baseline b59999b: 442) — the gate brings 4 new tests.
  • cargo fmt --check — clean.
  • cargo clippy --all-targets -- -D warnings — clean.
  • Unit tests added/updated: every_selector_lands_on_an_element plus four companions — a self-proof that the scanners see something and do not read comments/strings, a nested-rule + two-corpus negative control (.delta clears only via the prototype; #toggle-mode-btn is unseen by both), a per-leg mutation test, and a leg-reading printer.
  • A/B on the real tree: re-adding .wallet-note / .demo-hint to style.css makes every_selector_lands_on_an_element fail (restored byte-identical afterwards). Run against the pre-fix tree it fails naming exactly these four.

Checklist

  • Branch name follows convention (fix/…)
  • Conventional Commits format, no (#N) in the title
  • Single responsibility, minimal change

`ui/css/style.css` carried four rules whose names no longer appear on any
element — in the markup, in the scripts, or in the design baseline the file
itself declares (`ui/css/style.css:4`, `docs/prototype/aitokenpool-console.html`):

- `.demo-hint` — the element went away with the demo-seed cleanup (#90
  `35291b3`); the rule stayed, and its i18n key was already retired.
- `.login-divider` (+ `::before` / `::after`) — #159 `f46882c` moved the
  markup to the prototype's own name, `.divider`; the old rules kept a
  "historic alias" comment and nothing else.
- `.wallet-note` — #156 `41bb6d1` rewrote the element as
  `.wallet-hero-note`; the old rule was left in place.
- `.sidebar #toggle-mode-btn` (inside the mobile media query) — the button it
  hides never reached the product; the `#logout-btn` next to it in the same
  selector list is live.

A rule nobody carries still applies — writing `class="wallet-note"` today
still gets its 12px — which is why these read as live component rules for
elements that no longer exist. `.delta` (three rules) is deliberately kept:
the prototype's `statCard()` really does emit `<div class="delta ok">`, so it
is design-baseline vocabulary, not a leftover.

The rules are deleted; the one inside the media query is dropped from the
selector list only (the sibling `#logout-btn` stays). No behaviour changes:
nothing renders these names.

`src/layout_gate.rs` gains a fourth rule, `every_selector_lands_on_an_element`,
so the next such rule is caught when it appears. The token roster is derived
from the selector text and the script roster is borrowed from `js_gate`, so a
new `ui/js/*.js` cannot slip past it; there is no hand-written name list. The
read is deliberately wide (a name mentioned anywhere, even in a comment,
counts as a landing site) and the baseline corpus is an intentional escape
hatch — the gate proves a name has a landing site, not that the landing site
is the element it was written for.
@argszero
argszero merged commit f63dd66 into main Sep 30, 2026
2 checks passed
@argszero
argszero deleted the fix/css-orphan-selectors branch September 30, 2026 05:09
@argszero argszero mentioned this pull request Sep 30, 2026
12 tasks done
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.

1 participant