Bundles the backend+frontend delta-upload (content-dedup) feature with a
batch of frontend fixes from this session.
Upload / dedup:
- Client-hashed delta & instant upload (deltaUpload, hashWasm vendor shim)
- Backend dedup batch endpoint (dedup_service, dedup_handler, routes)
- session store owned-hash helpers; unit tests + upload-strategy bench
Frontend UI/UX:
- Colour file-type icons in grid/list (per-type tinted tiles + glyph hue)
- Robust thumbnail fallback; PDFs now show their type icon (backend
generates no PDF thumbnails) instead of a blank tile
- Fix PDF preview: load via a same-origin blob: iframe — the API URL is
blocked by the global X-Frame-Options: DENY in the browser's framed
PDF viewer, matching the existing CSP `frame-src blob:` design
- Groups: localized virtual-group description (no DB schema-note leak),
add nav.groups to the 15 missing locales, fix primary-button contrast
- Repoint --color-text-light → --color-on-accent (was faint grey on accent)
- Nudge the admin role badge off the user-menu header divider
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The three tiers had collapsed to one identical value (#5e6a78 / #9fadbe),
so hints, metadata, timestamps and placeholders were all indistinguishable.
Re-separate them into three perceptibly distinct steps, each verified WCAG
AA >=4.5:1 on every page/surface/hover/muted background in both light and
dark mode. Emphasis maps to contrast: muted is strongest (general secondary
text), faint the weakest (timestamps/placeholders) sitting on the AA floor;
secondary stays clearly stronger than all three. The dark floor is binding,
so the dark steps separate upward (lighter = more emphasis).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013J5koaCrHDMvS7uwpawLBN
- About modal overlay used a raw z-index: 1200, below the semantic
--z-modal (3000)/--z-toast (4000) layers, so token-based surfaces would
cover it. Consume var(--z-modal) instead.
- .btn-primary and .search-button sit on the accent gradient but coloured
their text with --color-danger-text (only correct by coincidence, #fff).
Use the purpose-built --color-on-accent so retinting danger can't break
them. The other --color-danger-text uses are white-on-red and stay.
- --color-item-hover-blue/--color-item-hover-sky were light-only literals
that would read wrong in dark mode; wrap them in light-dark().
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013J5koaCrHDMvS7uwpawLBN