* chore(themes): drop the dead installs field from RegistryTheme
The store no longer reads install counts (the themes registry stopped
emitting them), so this optional field on RegistryTheme was unused.
* fix(themes): give dropdown border/shadow tokens a cascade default
--border-dropdown and --shadow-dropdown were set by only two themes and had
no base fallback, so dropdown/popover borders rendered without a themed value
in every other theme. Default them in the semantic cascade next to the other
menu tokens; themes that set them explicitly still override.
* fix(themes): unify input focus rings, drop the double border
Text inputs draw their own border + box-shadow focus ring, but the global
:focus-visible outline stacked a second ring outside it — a double border on
every field. Suppress the outline for text inputs centrally; the specificity
(0,1,1) beats the global ring but loses to the colour-blind-safe themes'
[data-theme] *:focus-visible (0,2,0), so those keep their stronger AAA ring on
every field by design — the header search now carries that ring on its cluster
there too. Align the few input classes that had a weaker or missing ring to the
shared border + 3px accent-dim standard.
* docs(changelog): add #1052 input/dropdown focus border fixes
* fix(focus): keyboard focus ring no longer clipped by overflow or cover
The global :focus-visible ring used a positive outline-offset, so it was
drawn outside the element and clipped by any ancestor with overflow:hidden
or a scroll container (cards, rails, player bar, queue strip). Draw it inset
instead via shared --focus-ring-* variables (single source). Cards draw the
ring as an overlay above the cover, since a cover's own stacking context
(transform/contain for render stability) would otherwise paint over an inset
outline. Dracula now only sets --focus-ring-color.
* refactor(focus): fold scattered focus-ring overrides onto shared knob
Six components declared their own :focus-visible outline (mostly an exact copy
of the old global ring). Remove the redundant ones so they inherit the global
inset ring; keep the custom-coloured ones (genre pill, playback-delay modal)
but source width/offset from --focus-ring-*; move the because-card ring to the
central card focus ring (it has a cover and needs the lifted treatment).
* fix(settings): round theme accordion inner box to match its section
The theme picker's inner accordion had square corners, so the first (open)
group header ran flush into the rounded Theme card. Give .theme-accordion a
border-radius + overflow:hidden so its top/bottom corners continue the parent
card's rounding, matching the other settings sections.
* fix(search): unify search fields to one look
Live-search, Help and Settings search differed (pill vs rounded-rect, glow vs
plain border-change, mismatched backgrounds). Align them on the canonical input
look: radius-md, ctp-base background, accent border + soft accent-dim focus
glow. Drop the live-search pill radius, and suppress the input's own inset ring
so only the outer cluster glow shows (no double ring).
* fix(tracklist): column picker menu no longer clipped on short lists
The column-visibility dropdown was an absolutely-positioned menu inside the
tracklist, so a short list (e.g. a one-song Favorites view) clipped it via the
ancestor's overflow box. Render the menu in a portal to <body> with fixed
positioning anchored to the trigger (flips above when there's no room below),
following on scroll/resize. Outside-click + Escape close now live in the shared
TracklistColumnPicker (the menu is portalled out of the wrapper, so the old
wrapper-only check would have closed it on every in-menu click). Fixes albums,
playlists and favorites in one shared place. Adds a behaviour test.
* docs(changelog): UI/CSS fixes pass (#954)
theme.css (16138 LOC) → 122 per-section files in src/styles/themes/ +
an index.css that imports them in original cascade order.
Concatenating all files via index.css reproduces the original byte stream
(+1 trailing newline, cosmetic).
Each top-level section header in theme.css (matching /^\/\* ─{3,}/)
becomes its own file, slugged from the header text (or the [data-theme]
selector found in the body when the header was a banner). Pure-separator
headers fold into the previous section so they don't create empty files.
Generated via /tmp/split-theme-css.mjs.