diff --git a/web-player/CLAUDE.md b/web-player/CLAUDE.md
index a61cf1b..7651a13 100644
--- a/web-player/CLAUDE.md
+++ b/web-player/CLAUDE.md
@@ -79,7 +79,7 @@ The shell in `src/routes/(app)/+layout.svelte` is a fixed `h-dvh` frame: Sidebar
## Motion
-Every animation follows one scale of three durations and one easing curve, all defined in `theme.css`. Fast (`--mf-motion-fast`, 150ms) is for hover, focus and press feedback: color, opacity and small scale changes. Plain `transition` or `transition-colors` already uses it because it is the Tailwind default, so never write `duration-150`. Base (`--mf-motion-base`, 200ms) is for things that appear on top of the page or move inside a control: modals, menus, the queue panel, `animate-pop`, `animate-fade` and the segmented control thumb. Slow (`--mf-motion-slow`, 300ms) is for content entering the page and larger movement: `animate-enter`, cover zoom on hover.
+Every animation follows one scale of three durations and one easing curve, all defined in `theme.css`. Fast (`--mf-motion-fast`, 150ms) is for hover, focus and press feedback: color, opacity and small scale changes. Plain `transition` or `transition-colors` already uses it because it is the Tailwind default, so never write `duration-150`. Base (`--mf-motion-base`, 200ms) is for things that appear on top of the page or move inside a control: modals, menus, the queue panel, `animate-pop`, `animate-fade` and the segmented control thumb. Slow (`--mf-motion-slow`, 300ms) is for content entering the page and larger movement: `animate-enter`. Media cards have no cover zoom: hovering one only fades in its background (`hover:bg-hover`) and reveals the play button.
Entrances and movement always use `--mf-ease` (`ease-snappy` in Tailwind, `expoOut` in Svelte transitions), which feels immediate because most of the motion happens at the start. Color transitions keep the Tailwind default curve. Overlays must feel instant: the modal backdrop uses `transition:fade={{ duration: 200 }}` and the panel uses a local `pop` transition (opacity + scale + translateY, `expoOut`, 200ms) mirroring `animate-pop`'s keyframes — both directives so the modal fades and pops on close too, not just on open, and the whole thing settles in 200ms. Staggered lists use `--i` with 40ms steps capped at ten items.
diff --git a/web-player/scripts/check-tokens.mjs b/web-player/scripts/check-tokens.mjs
index 4f2e14e..928ab06 100644
--- a/web-player/scripts/check-tokens.mjs
+++ b/web-player/scripts/check-tokens.mjs
@@ -15,6 +15,7 @@ const ARBITRARY_WHITELIST = [
/^my-\[\d+d?vh\]$/, // +error.svelte: centrado vertical de página de error
/^py-\[\d+d?vh\]$/, // Explorar: centrado vertical de "sin resultados"
/^transition-\[filter\]$/, // Explorar: genre-tile hover
+ /^transition-\[transform,width\]$/, // Tabs: indicador deslizante
/^bg-\[image:var\(--mf-[\w-]+\)\]$/
];
diff --git a/web-player/src/lib/components/music/GenrePicker.svelte b/web-player/src/lib/components/music/GenrePicker.svelte
new file mode 100644
index 0000000..350b2fb
--- /dev/null
+++ b/web-player/src/lib/components/music/GenrePicker.svelte
@@ -0,0 +1,58 @@
+
+
+ {help}
+ {inAlbum.length > 0 ? plural(inAlbum.length, 'canción', 'canciones') : 'Sin canciones'} +
+ + {#if available.length > 0} +{item.file.name}
-{item.file.name}
+{details(item)}