diff --git a/src/renderer/src/features/settings/ui/ThemePickerRow.tsx b/src/renderer/src/features/settings/ui/ThemePickerRow.tsx
index da8202d2..92cda1e6 100644
--- a/src/renderer/src/features/settings/ui/ThemePickerRow.tsx
+++ b/src/renderer/src/features/settings/ui/ThemePickerRow.tsx
@@ -27,6 +27,22 @@ export function ThemePickerRow({ settings, onSelect, onCreate, onEdit, onDelete
// gap-px over a bg-panel-border parent draws the grid lines as gaps rather
// than per-cell borders, which keeps the double-border seams out and
// respects the codebase's no-border-radius rule.
+ //
+ // THE CELLS MUST BE OPAQUE for this to work, and that is not a style
+ // preference — it is what the trick depends on. The parent is painted with
+ // the BORDER colour; only the 1px gaps are meant to show it. Any cell that
+ // is transparent (or semi-transparent) lets that border colour flood the
+ // cell, and the whole picker renders as a grey block with the border colour
+ // used as a fill.
+ //
+ // That is exactly what happened: the cells used `bg-row-bg` and
+ // `bg-row-selected-bg`, and BOTH of those tokens are deliberately
+ // see-through (`transparent`, and a 15% accent mix against `transparent`).
+ // They are correct defaults for an ordinary row sitting on a panel — they
+ // are simply wrong here. So this component names opaque tokens explicitly
+ // rather than depending on tokens whose own definition documents them as
+ // transparent. `bg-row-hover-bg` was always opaque (`--theme-surface-hi`),
+ // which is why hover was the one state that looked right.