Match the official-recommendation and popular cards to the message bubble
surface color (#272632) used on the browse/all page and the latest section,
so homepage content cards and the browse page share one background. Also
align the popular card border with the official card (#27292E).
Categories tiles are intentionally left unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Size the banner and the popular rank list to the same responsive widths as
the latest section's message bubbles (680/900/1120), so the banner, latest
cards and popular cards line up at one consistent content width on desktop.
Desktop-scoped; mobile stays full-width.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Wrap the Categories and Popular sections in the same responsive
max-width container (820/1080/1180) used by Official and Latest, so all
four section titles line up vertically on desktop.
- Official carousel arrows: hide the arrow at the edge already reached, and
snap one card per click (reveal the next/previous card fully, keeping a
small peek) instead of a fixed-pixel scroll.
- Show the pagination dots on desktop too (was mobile-only).
- RecommendedCard download button icon: text-ark-gold -> text-white to match
the file bubble / popular / video download buttons.
Desktop-scoped; mobile layout unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Banner: scale down and center on desktop (md:max-w-[680px] lg:max-w-[800px])
so it no longer fills the whole screen.
- Align section widths to one responsive container (820/1080/1180): wrap the
Official row and match Popular to Latest, fixing left-edge/width mismatches.
- RecommendedCard: stop the carousel card from shrinking back to 246.4px at xl.
- Popular download button now matches the file bubble's filled round
DownloadCloud button for visual consistency.
- Header nav vertical padding py-1 -> py-0.5; swap Favorites before Popular
across desktop nav and mobile menu to match the bottom tab order.
- Official carousel: hide the left arrow at the start and the right arrow at
the end instead of always showing both.
All changes are md/lg/xl-scoped; mobile layout is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entering /browse via a popular-section card carried ?post=, which made
ScrollToTop skip the reset entirely. The window stayed at the previous
page's bottom scroll, so the deep-link animation visibly scrolled UP from
the bottom to the target post.
Now any pathname change jumps to the top first (even with ?post=), letting
the destination align to the post by scrolling down from the top. Hash
anchors and same-page ?post= changes are still left alone.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mobile sections had no vertical rhythm (space-y only at md+) and
inconsistent header-to-content gaps. Add uniform 10px spacing between
sections and header-to-content so each section header sits symmetric.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `select-none` to the sticky header, the type filter chips row, and the
mobile bottom nav so their labels and icons can't be highlighted/selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- FigmaBanner: route same-app linkUrl through SPA navigation so the stream's
scroll-to-post runs without a full reload; defer pointer capture until a real
drag starts, fixing plain clicks being swallowed by setPointerCapture
- PopularRankList: rank rows navigate straight to /browse?sort=popular&post=<id>
- MessageStream: ?post= deep links jump directly to the target instead of
resetting to the top and animating through the stream
- ScrollToTop: skip the top-reset for ?post= navigations so the target page
handles its own alignment
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously the file bubble wrapped JS middle-ellipsis in CSS truncate,
so narrow containers silently clipped the tail+extension, leaving
e.g. "25cb264a-e06…." instead of "25cb264a-e06…811a.jpg".
Split the displayed name into a shrinking head (with CSS truncate)
and a non-shrinking tail (last 4 base chars + extension). The browser
now decides how much head to clip while the suffix is always visible.
Clarify that compact browsing surfaces should receive short post title fields
from the backend even if some frontend pages do not display them yet. Separate
the product requirement from current frontend implementation status so backend
can implement the API contract first and frontend can opt in per surface later.
Route resource card clicks to /browse?post=<id> instead of relying on hash
anchors, then manually calculate the sticky filter offset when scrolling to
the target bubble. Start from the top and smooth-scroll to the card for a
clear transition, with delayed auto realignments after media above the target
settles.
Add optional post-level and localized title fields, and use a new
postTitleText helper for Resource.title so card/list surfaces prefer short
backend-provided titles instead of full body text. When title is missing,
fallback to the first non-empty body line, then filename, then post id.
Document the backend handoff in docs/posts-title-api.md alongside the other
backend task docs.
Use object-fill for compact preview thumbnails so rank-list covers and
file previews fill their fixed boxes without cropping or black bars. This
keeps the list layout stable while matching the desired compressed-ratio
thumbnail treatment.
Clamp goPrev / goNext instead of wrapping the index, and hide the
left chevron on the first image and the right chevron on the last
one. Arrow keys, swipe gestures, and the on-screen buttons all
behave like a linear gallery now, so users get a clear cue that
they have reached the end instead of unexpectedly looping back.