CI & Build / Python lint (push) Successful in 7s
CI & Build / Plugin hooks (push) Successful in 36s
CI & Build / TypeScript typecheck (push) Successful in 49s
CI & Build / integration (push) Successful in 2m16s
CI & Build / Python tests (push) Successful in 2m51s
CI & Build / Build & push image (push) Successful in 1m15s
SettingsView and UserManagementView had near-identical button vocabularies — btn-delete, btn-cancel-delete, btn-confirm-delete, btn-toggle/-open/-close — defined separately in each. Parallel duplication (#2278's shape), and it had already diverged twice: - .btn-confirm-delete used --color-danger in UserManagement and --color-action-destructive in Settings. Those are different colours on purpose: the house style keeps error (something went wrong) distinct from destructive (something is about to). A delete confirmation is destructive. UserManagement was showing the error colour for a button nothing had failed in yet. - .btn-remove-slot's hover reached for --color-danger for the same reason, and is the same correction. It turned out to be dead anyway — style rules only, no template reference anywhere in the app — so it is gone. .btn-danger-outline was defined TWICE inside SettingsView, at 0.4rem 0.9rem and 0.45rem 1rem. One file, one class, two geometries, ~1200 lines apart. That is the clearest single argument for this whole task that I have found: the drift does not need two files, only enough distance that nobody sees both at once. The registration toggle keeps .btn-toggle-close, and only that. It is bound dynamically (:class="registrationOpen ? … : …"), so a name-based scan reads it as unused — checked before deleting. .btn-toggle-open went, because btn-primary now says the same thing; the close state stays because it must NOT read as the primary action it sits on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs