#2533. theme.css claimed "removing this block is a rename sweep across the
components, tracked separately" — written in 67a529a, never filed, which made
the comment itself an instance of the survey's presence-without-reference
pattern. This is that sweep.
73 alias declarations deleted; 69 files rewritten; every --color-*-style name
now references its --fs-* token directly. Mechanical by construction: the map
IS the alias block, applied longest-name-first with a boundary guard so
--color-text never matched inside --color-text-muted. Zero survivors outside
theme.css, verified by grep rather than assumed.
One deliberate survivor: --color-shadow stays DECLARED, because it was never
an alias — it is a literal value the design system has no token for. Marked
in place as a recorded gap: promote it to an --fs-* token when a second app
needs it, don't copy the line.
Nothing is lost mode-wise: the aliases' resolve-at-use-time trick (which
absorbed 48 dark-mode overrides) lives one layer down in the --fs-* tokens'
own derivations, which is why the sweep is a pure rename. Both CSS checkers
green.
Why now rather than never: check_snippets_against_design_system reports every
--color-* reference as "unknown — renders as NOTHING", and nine recipe
snippets recorded from components.css carried the deprecated names, making
them prior art pointing the wrong way. With the sweep in, the checker's
report over re-recorded snippets should be EMPTY — the acceptance test that
proves the checker was right all along (#2517's correction).
Refs #2533
#2277 counted ~150 "raw colour literals bypassing the tokens". Measuring them
told a different story: 184 sat in `var(--token, #fallback)` position, and a
check against theme.css shows every one of those tokens IS declared. So the
fallbacks could not render. Not drift — vestigial.
They were also not this palette. The most common were Tailwind and Flat-UI
defaults — #6366f1 indigo, #22c55e green, #f59e0b amber, #3b82f6 blue,
#e74c3c and #27ae60 — a second, unsanctioned colour scheme sitting in the
codebase looking like the app's colours to anyone reading it.
Removing them is not tidying. #2319's lesson is that a fallback is WORSE than a
missing token: a missing token renders as nothing and someone eventually
notices, while a fallback renders something plausible forever. These 184 were
one token rename away from silently repainting the app in Tailwind. The design
token check would catch the rename — but the fallback is precisely the thing
that would make it invisible if the check were ever bypassed.
Literal count 152 -> 45, which matters beyond the number: a report that is
mostly unreachable noise is one people stop reading, and then it stops working
while still passing. What remains should be genuinely worth looking at.
Done with a paren-aware transform, not a regex — `var(--x, rgba(0,0,0,.5))`
nests parens and `[^)]+` would cut at the first one and leave `))` behind.
Verified after: every changed line is a fallback strip and nothing else, and
every var() reference still resolves.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
Replaces every hand-inlined SVG in the chrome (60 across 15 files)
with Lucide components. Snaps icon sizes to the doc's 16/24 scale —
all icons in this pass land at 16. AppLogo wordmark stays as the
legitimate "custom app icon" exception per the doc; GraphView's <svg>
mount point for D3 stays as well.
Replaces emoji-as-icons in clear button-affordance cases with their
Lucide equivalents: ✕ → X (close/dismiss buttons across 8 files), ✓ →
Check (ProjectView task-advance button), 🎤 → Mic (ChatPanel voice
CTA), 📎 → Paperclip (ChatView context toggle), ↑ → ArrowUp
(ChatInputBar Send), × → X (ChatPanel context-note remove), ☀/☾
→ Sun/Moon (AppHeader theme toggle).
Inline emoji punctuation in textual confirmation copy ("Saved ✓",
"Created ✓", `done: "✓"` status maps, `'✓' : '📄'` interpolations)
is left for surface-phase voice/tone touchups — replacing requires
structural template changes and is best done per-component.
Stroke weight stays at Lucide's default 2px; tightening to the doc's
1.5/1 is deferred per the surface-phase spec (option ii: drop-in +
scale enforcement).
Adds lucide-vue-next ^0.469.0 to frontend/package.json. Docker
rebuild handles the install.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- New /graph route with D3 force simulation (GraphView.vue)
- Tag nodes as first-class graph nodes (string IDs "tag:name") — clicking
navigates to /notes?tags=name; tags shown by default
- Invisible project hub nodes attract project members into clusters
- Physics panel with live sliders: repulsion, link distance, link strength,
project pull, gravity (forceX/forceY, not forceCenter)
- Wikilink edges retain directed arrowheads; tag edges are thin, no arrowhead
- Graph nav link in AppHeader; `g` shortcut in App.vue
- Backend: build_note_graph() emits tag nodes + note→tag edges instead of
O(n²) note→note shared-tag mesh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>