**Accessibility pass** — secondary "faint" text now clears WCAG AA in both palettes (was ~2.8:1); accent-coloured text (links, *italic* emphasis) darkens on paper via a new `--bu-accent-ink` so it clears AA there too, while borders, fills and glow keep the vivid accent; and a `:focus-visible` keyboard ring marks focus for keyboard / assistive-tech users without showing on mouse clicks. **Phosphor terminal** — two new accent presets, **Amber** and **Green (P1)**, plus a **Phosphor terminal** toggle that tints the dark-mode body text to the accent for a monochrome vintage-CRT look. **Boot sequence** — the CRT power-on is a real tube switch-on now (collapse to a scan-slit, vertical bloom, phosphor settle), and a new **Boot sequence** toggle adds a beam-striking-the-glass flash on app launch, front-loaded so it lands as the window appears. **Accent caret** — the caret rides the accent in every mode (dark, paper, inverted) so it stops getting lost against the ink, and the Block caret pulses like a terminal cursor (stops under reduced-motion, the solid block stays). **Checkboxes** — a checked task box is a printed box: white field on dark, black on paper, with an accent mark; fixed the mark vanishing in the editor under Paper / Inverted-editor mode. **Coverage** — **notices / toasts**, **Canvas** (node cards + bevel, accent focus, themed edges and backdrop), **footnotes**, and **MathJax** are now styled instead of falling back to stock grey. **New Style Settings levers** — **Flat card edges** (bevel off, shadow kept), **Card shadow blur** + **spread** sliders, a **custom scrollbar grip colour** (decoupled from the accent), and an **Animation easing** select (Ease-out / Smooth / Linear). **Light-mode fixes** — the accent no longer reverts to red inside the inverted-editor pane (the accent palette moved to a zero-specificity `:where(body)` rule so the Style Settings choice always wins); focused property fields lift onto a visible surface instead of vanishing into the page, and resting property fields carry an accent border. **Under the hood** — removed all `:has()` selectors (selector-invalidation cost), consolidated the metadata-input rules from five overlapping blocks into one, tokenised the card drop-shadow, gave the graph-controls panel the theme's card material, and added a `CONTRIBUTING.md` plus a `test/kitchen-sink.md` regression note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.4 KiB
Contributing to Bureau
Thanks for prying the lid off. Bureau is a small, opinionated room, and it stays livable because the rules are few and held to. Here's how to file a report, send a change, and not break the lights on your way out.
Reporting a problem
Open an issue. The useful ones tell me:
- Obsidian version (Settings → About) and Bureau version (
manifest.json, or the What's new note in Style Settings). - Platform — desktop (and OS) or mobile.
- Whether the Style Settings plugin is installed, and which Bureau options you've changed.
- What you saw vs. what you expected. A screenshot is worth a paragraph.
- The smallest steps that reproduce it. "It's broken" is a mood, not a bug report.
If it only happens with a particular plugin or another theme element layered on top, say so — Bureau aims for a plugin-independent baseline, so those cases are worth knowing about.
Sending a change
- Fork, branch off
main. - Edit
theme.css. It's one file — there's no build step, no preprocessor, nosrc/to compile. What you edit is what ships. - Reload to see it. Obsidian caches the stylesheet and will lie to you about whether your change took — hard-reload, or toggle the theme off and back on.
- Open a pull request against
mainwith a short note on what changed and why. Before/after screenshots for anything visual.
Keep a PR to one idea. A focused diff gets read and merged; a grab-bag sits.
House rules
These aren't style preferences — they're what keeps the theme coherent and the reviewers happy. Hold to them:
- One accent, one palette. The whole UI reads from
--bu-accentand the token block at the top of the.theme-dark/.theme-lightsections. Retheme from there; don't hard-code colours mid-file. - No
!important. The theme ships with zero of them and clears every Obsidian linter warning. If you think you need one, you've usually lost a specificity fight that's better won another way — raise it in the PR. - Avoid
:has()and other broadly-invalidating selectors. They're flagged in review for the selector-invalidation cost — re-evaluating big swaths of the DOM on every mutation. Reach for a class, a combinator, or a small JS-set body class before a:has()that spans editor leaves or the workspace. - Atmosphere is opt-in. CRT, scanlines, glow, animation — all of it defaults to off-or-quiet and lives behind a slider. Nothing decorative should be load-bearing or on by default.
- Mobile stays sane. There's a hard plugin-independent mobile baseline with real touch targets. Don't regress it.
- Match the room. Comments in
theme.cssexplain the why, not the obvious what. If a rule is a workaround for an Obsidian quirk, leave a note saying so — there are plenty already; mirror their tone and density.
The @settings block
Every Bureau option lives in one @settings YAML block at the foot of
theme.css. It looks like a comment and it is not — it's parsed by the Style
Settings plugin, and a malformed block silently kills the whole panel. Two scars
worth not reopening:
- Never put a bare
:(colon-space) inside adescription:— it breaks the YAML and takes the entire panel down with it. Reword, or quote the string. - Set
quotes: falseonvariable-textinputs that take a URL (e.g. the wallpaper), or Style Settings wraps the value in quotes and the pastedurl()breaks.
If you add or rename an option, validate before you commit — ./release.py <ver> --dry-run runs the same brace + @settings YAML check the real release does, without touching anything.
Releasing (maintainer)
The ## Changelog in the README is the single source of truth. To
cut a release: add the new ### X.Y.Z entry to the top of it, then run
./release.py X.Y.Z. The script stamps manifest.json and the theme.css
header, regenerates the in-panel What's new note, prepends the entry to Release
history, validates the CSS, then commits, tags, pushes main + the tag, and
publishes the GitHub release with theme.css + manifest.json attached. Use
--dry-run to preview, --yes to skip the confirmation. Tags carry no v
prefix — Obsidian matches them to the manifest.
License
Bureau is MIT. By contributing, you agree your work ships under the same. Take it apart, build your own room.