diff --git a/web-player/CLAUDE.md b/web-player/CLAUDE.md
index 7651a13..50fc2bf 100644
--- a/web-player/CLAUDE.md
+++ b/web-player/CLAUDE.md
@@ -108,6 +108,6 @@ Server helpers:
- `guards.ts` holds `requireUser`, `optionalUser` and `loginRedirect`. Keep them in pages and actions even though the `(app)` layout also redirects: page loads run in parallel with the layout load, and form actions skip it.
- `mappers.ts` (`toTrack`, `toAlbum`, `toPlaylist`, `toMix`, `toPage`, `toCount`, `toListeningStats`, ...) turn DTOs into the domain types. Every load and `/api` endpoint goes through them, so `Number()` conversions on DTOs never reach routes or the client.
- `actions/` holds `authedAction(handler)` (returns 401 without a token, reads the form and hands `{ api, form, params, locals, url }` to the handler) plus the shared `follow` and `playlist` actions.
-- `forms/` holds `fields.ts` (`formString`, `formFile`) and the form parsers (`parseAlbumForm`, `parsePlaylistForm`, `parseTrackUploadForm`); they validate with `LIMITS` from `$lib/validation`. `uploadOptionalCover` handles the optional cover upload.
+- `forms/` holds `fields.ts` (`formString`, `formFile`) and the form parsers (`parseAlbumForm`, `parsePlaylistForm`); they validate with `LIMITS` from `$lib/validation`. `uploadOptionalCover` handles the optional cover upload.
- `genres.ts` caches the genre list; `playbackConfig.ts` caches the anonymous listening setting.
- Page sizes come from `$lib/config`; do not hardcode them.
diff --git a/web-player/docs/paginas.md b/web-player/docs/paginas.md
index 737aeae..5d2b00f 100644
--- a/web-player/docs/paginas.md
+++ b/web-player/docs/paginas.md
@@ -17,7 +17,6 @@ src/routes/
new/ /library/albums/new Create an album
[id]/ /library/albums/:id Edit an album
uploads/ /library/uploads Upload queue
- upload/ /upload Upload a song
albums/ /albums Your albums
[id]/ /albums/:id Album detail
playlists/ /playlists Your playlists
@@ -36,8 +35,7 @@ Global chrome on every app page: sidebar (desktop) or tab bar (mobile), top bar
- **Home `/`**: a greeting, weekly listening stats, "continue listening" (recently played merged with the in-session history), the featured playlist with its first tracks (play and shuffle load the full list on demand), the user's mixes and playlists. Anonymous visitors are redirected to `/explore`.
- **Explore `/explore`**: genre tiles when there is no query, otherwise search results grouped by songs, albums, users and playlists with filter chips and counts taken from the API totals. Songs paginate with infinite scroll. Track and album context menus offer play next, add to queue and add to playlist.
- **Liked `/liked`**: the songs the user liked, newest first, with unlike per row.
-- **Library `/library`, `/library/albums`, `/library/uploads`**: the manage-music area, one route per section behind shared tabs. Songs lists the user's uploads with a confirmed delete; Albums lists the user's albums and edits them at `/library/albums/new` and `/library/albums/:id`; Uploads is the upload queue.
-- **Upload `/upload`**: audio, cover, title, genres (incompatible genres are blocked) and explicit flag. The server reserves presigned URLs, uploads both files and creates the track; processing happens asynchronously in the backend.
+- **Library `/library`, `/library/albums`, `/library/uploads`**: the manage-music area, one route per section behind shared tabs. Songs lists the user's uploads with a confirmed delete; Albums lists the user's albums and edits them at `/library/albums/new` and `/library/albums/:id`; Uploads is the upload queue: the browser sends each file straight to storage through presigned URLs (`/api/uploads`, with progress), `/api/uploads/complete` creates the track unpublished and optionally adds it to an album, and `/api/uploads/status` follows the processing. Genres and cover apply to the whole queue and the queue survives tab changes. `/upload` redirects here.
- **Albums `/albums`, `/albums/:id`**: list and create albums. The owner can edit, delete and add or remove tracks from their library.
- **Playlists `/playlists`, `/playlists/:id`**: list and create playlists. The owner can edit, delete and remove tracks; everyone else gets a read only view.
- **Mix `/mixes/:id`**: a generated mix with play, shuffle and a track menu.
diff --git a/web-player/scripts/check-tokens.mjs b/web-player/scripts/check-tokens.mjs
index 928ab06..b9fcd93 100644
--- a/web-player/scripts/check-tokens.mjs
+++ b/web-player/scripts/check-tokens.mjs
@@ -16,6 +16,7 @@ const ARBITRARY_WHITELIST = [
/^py-\[\d+d?vh\]$/, // Explorar: centrado vertical de "sin resultados"
/^transition-\[filter\]$/, // Explorar: genre-tile hover
/^transition-\[transform,width\]$/, // Tabs: indicador deslizante
+ /^transition-\[width\]$/, // cola de subida: barra de progreso
/^bg-\[image:var\(--mf-[\w-]+\)\]$/
];
diff --git a/web-player/src/lib/components/music/library/LibraryUploadsSection.svelte b/web-player/src/lib/components/music/library/LibraryUploadsSection.svelte
index b0ad180..4721699 100644
--- a/web-player/src/lib/components/music/library/LibraryUploadsSection.svelte
+++ b/web-player/src/lib/components/music/library/LibraryUploadsSection.svelte
@@ -1,68 +1,42 @@