From a6d655048390d3b09ca76d121b881023472d8099 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 5 Aug 2026 09:26:35 -0400 Subject: [PATCH] =?UTF-8?q?fix(ui):=20walk=20the=20eleven=20dangling-style?= =?UTF-8?q?=20reports=20=E2=80=94=20two=20were=20real?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #2444. Each needed reading rather than a batch fix, and the split was 2 real losses, 4 false reports, 5 wrappers that are bare on purpose. REAL: .system-card was a flex row, and every child still says so — .system-swatch and .system-actions are flex-shrink: 0, .system-body and .system-form--inline are flex: 1. align-items: flex-start is why the swatch carries margin-top: 0.3rem: nudged onto the first line of text. .systems-list no rule AT ALL, so the systems list rendered with browser bullets and indent. Invisible to the check — see below. .graph-embed the panel is a flex column whose header is flex-shrink: 0, so this is the item that takes the remaining height. Without it the `height: 100%` on the line below resolves against auto and does nothing, which left the comment above it specifying a rule that could not work. FALSE REPORTS, and the checker was wrong rather than the code: `.pane.empty` and `td.num` are base rules for the element that carries those classes — the check read any compound with more than a lone class as a modifier. It now records a compound's whole class SET and clears an element carrying all of them, which is exact: recording the classes individually would have cleared `.pane` everywhere on the strength of a rule that only applies alongside `.empty`. Four reports gone, and a check with false reports is one that gets skimmed. BARE ON PURPOSE — .rb, .topic-group, .new-topic, .sub-list, .dash-head, and both .detail-row rows. Each namespaces descendant rules and assumes nothing about layout, which is the tell that separates them from a deleted base. All seven now carry a comment saying so, so the next reader doesn't re-litigate them and a NEW entry in the report means something actually changed. Also recorded in the script: it cannot see a class with no rule anywhere, since that is indistinguishable from a semantic-only hook. `.systems-list` was found by reading the file beside a class that WAS half-styled. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs --- frontend/src/components/SystemsSection.vue | 35 ++++++++++++ .../src/components/rules/PlanRulesPanel.vue | 6 ++ .../src/components/rules/ProjectRulesTab.vue | 4 ++ .../components/rules/RulebookDetailPane.vue | 5 ++ frontend/src/views/DashboardView.vue | 3 + frontend/src/views/KnowledgeView.vue | 11 ++++ frontend/src/views/LogsView.vue | 2 + frontend/src/views/SettingsView.vue | 2 + scripts/check_dangling_styles.py | 57 ++++++++++++++----- 9 files changed, 111 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/SystemsSection.vue b/frontend/src/components/SystemsSection.vue index b7b963d..4a4274d 100644 --- a/frontend/src/components/SystemsSection.vue +++ b/frontend/src/components/SystemsSection.vue @@ -387,6 +387,41 @@ async function confirmDelete() { .system-textarea { resize: vertical; } .system-form-actions { display: flex; gap: 0.4rem; } + +/* RESTORED (#2444). Both lost their base rule to a CSS sweep; only the + `--archived` modifier and the `:hover .system-actions` reveal survived. + The card WAS a flex row and every child still says so — `.system-swatch` + and `.system-actions` are `flex-shrink: 0`, `.system-body` is `flex: 1`, + and `.system-form--inline` is `flex: 1`. `align-items: flex-start` is why + the swatch carries `margin-top: 0.3rem`: it is nudged onto the first line + of text rather than centred against the whole card. + + The list had no rule at all, so it rendered with browser bullets and + indent — invisible to the dangling-style check, which can only see a class + that is PARTLY styled. A class with no rules anywhere looks exactly like a + semantic-only hook. + + Surface values match `.system-form` above, which is the same card shape in + this file and the reason they can be recovered rather than guessed. */ +.systems-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.system-card { + display: flex; + align-items: flex-start; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + background: var(--color-bg-card); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); +} + .system-card--archived { opacity: 0.6; } .system-swatch { diff --git a/frontend/src/components/rules/PlanRulesPanel.vue b/frontend/src/components/rules/PlanRulesPanel.vue index 1796b87..0610745 100644 --- a/frontend/src/components/rules/PlanRulesPanel.vue +++ b/frontend/src/components/rules/PlanRulesPanel.vue @@ -53,6 +53,12 @@ watch(() => props.projectId, load); font-size: 0.9em; opacity: 0.7; text-transform: uppercase; letter-spacing: 0.05em; } +/* `.rb` is deliberately bare — it exists to namespace the two heading rules + below, and its children carry their own spacing (the h4 keeps the UA + margin-top that separates one rulebook group from the next). Nothing here + assumes a flex or grid parent, which is the tell that distinguishes this + from a base rule someone deleted (#2444). Stated so the next reader doesn't + re-open the question. */ .rb h4 { font-family: Fraunces, serif; font-style: italic; margin-bottom: 0.25rem; } .rb h5 { font-size: 0.8em; opacity: 0.7; diff --git a/frontend/src/components/rules/ProjectRulesTab.vue b/frontend/src/components/rules/ProjectRulesTab.vue index ad7040e..039c3c5 100644 --- a/frontend/src/components/rules/ProjectRulesTab.vue +++ b/frontend/src/components/rules/ProjectRulesTab.vue @@ -349,6 +349,10 @@ select { .applicable { margin-top: 2rem; } .rb-group { margin-bottom: 1.5rem; } .rb-group h4 { font-family: Fraunces, serif; font-style: italic; margin-bottom: 0.5rem; } +/* `.topic-group` is deliberately bare — a namespace for the two h5 rules (this + one and the flex row further down), with the h5's own margin-top doing the + separating. Its children assume nothing about it, which is what tells it + apart from a base rule someone deleted (#2444). */ .topic-group h5 { font-size: 0.85em; opacity: 0.7; text-transform: uppercase; letter-spacing: 0.05em; margin-top: 0.75rem; diff --git a/frontend/src/components/rules/RulebookDetailPane.vue b/frontend/src/components/rules/RulebookDetailPane.vue index fecf4e4..a89b560 100644 --- a/frontend/src/components/rules/RulebookDetailPane.vue +++ b/frontend/src/components/rules/RulebookDetailPane.vue @@ -135,6 +135,11 @@ ul { list-style: none; padding: 0; margin: 1rem 0; } li { padding: 0.5rem; cursor: pointer; border-radius: 6px; } li.active { background: var(--color-primary-bg); } li:hover { background: var(--color-hover); } +/* `.new-topic` and `.sub-list` are deliberately bare (#2444). The first wraps a + button-or-form whose children style themselves; the second is a `