The closeup studio cello shot (now atmosphere 2 after the swap)
had too much empty ceiling above the head. Recropped from
1440x2560 to 1440x1920 (3:4) with top offset 450px so the head sits
near the top of the frame and the full upper body is visible.
TOS upload: portraits/014-2.webp (overwrite).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
14号 gallery atmospheres 1 & 2 swapped + atmosphere 1 recropped to 3:4
to frame the upper body. Same TOS URLs with new content, version bump
forces CDN/browsers to refetch.
TOS uploads: portraits/014.webp (overwrite, now wide-orchestra cropped
to 3:4), portraits/014-2.webp (overwrite, now closeup studio shot).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
019 氛围图3 was pre-cropped from 9:16 (1440x2560) to 3:4 (1440x1920)
to remove the empty bamboo decoration above the head and frame the
upper body. Same URL with new content, so version bump forces CDN +
browsers to refetch.
TOS upload: portraits/019-3.webp (overwrites).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Navigation: removed top-left <Logo />, NavLinks now sit at the
left edge. Logo component itself kept (still used by Footer /
LoginForm / LoginModal).
- HeroBanner: restored simple "default muted + autoplay" behavior.
The earlier try-unmuted-fallback flow was working but produced
unpredictable first-paint audio depending on browser autoplay
policy; muted is the safer default.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Hero eyebrow: "Top 12 · Virtual Idol Debut Project"
→ "Top 12 · Cyber Star Debut Survival"
- Hero video: attempt unmuted autoplay first, fall back to muted on
browser autoplay-policy block (sound button reflects actual state).
- Logo: replace with cropped v2 art, drop purple drop-shadow glow.
- ArtistCard: drop non-top12 opacity dim AND the top dark gradient
overlay — new high-quality portraits look better fully exposed.
- mock-data: 003/010/017/027/033 solo videos are present in v2,
cleared MISSING_VIDEO set so the video section renders for them.
- tos: bump TOS_VERSION to 3 — videos/portraits overwritten on TOS,
this cache-busts older URLs in browsers and CDNs.
TOS uploads (handled separately): hero-pv.mp4, 5 solo videos
(003/010/017/027/033), 7 cover images, 6/036 atmosphere images.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 021 (温景然) enName RYAN → KINGSTON
(fixes duplicate: 006 stays RYAN, 021 was a typo)
- 002/003/005/012/014/019/025 now use portraits/{no}-cover.webp
for the cover (chosen from v2 atmospheres per 调整.xlsx). Gallery
remains {no}/{no}-2/{no}-3 as before.
- 036 third atmosphere image is now expected (v2 provides it),
removed MISSING_ATMOSPHERE_3 set.
- tosUrl now appends ?v=2 cache-buster so overwritten TOS files
refresh immediately instead of waiting on CDN/browser cache.
Note: this commit is paired with TOS uploads (handled separately).
Two adjacent backdrop-filter elements (nav at y=0-80, filter at y=80+)
always show a visible seam at their boundary because each filter clips
its own blur kernel, so the edge pixels sample slightly different
neighborhoods. Same recipe doesn't help — it's a structural issue.
Fix: when filter is stuck, render an absolutely-positioned glass child
inside the filter that extends from -top-20 to bottom-0 (i.e. covers
nav area + filter area as ONE element). Nav reads filterStuck from a
tiny shared zustand UI store and disables its own glass layer in that
state, so only the shared band is visible. Single element, single
backdrop-filter, no seam.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Navigation: fixed + transparent over Hero (home) / at page top (other routes);
fades to glass-on-scroll. Glass uses surface tone matching site cards.
- Filter bar sticky glass synced to nav recipe (no seam between layers).
- HeroBanner: full-viewport video, center title removed, bottom dim overlay
removed, eyebrow/countdown repositioned below the nav.
- ArtistDetail: removed portrait shadow; added FloatingBackButton that uses
router.back() with internal-history fallback to /.
- Floating buttons (back + vote) translateY upward to avoid footer rather
than disappearing, via useFooterPush.
- Home: useScrollRestore preserves scroll position on return from detail
pages; temporarily disables scroll-snap during restore.
- PerformanceVideo: max-w capped by 85svh*16/9 so small viewports never crop.
- ArtistFilters: hide horizontal scrollbar thumb in tag container.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Matches the AirGate convention of putting infra credentials directly in
the deploy yaml — no Gitea Secrets configuration required, push-to-deploy
just works.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous commit scoped too broadly. Other env vars (TOS/SMS/WECHAT/etc.)
already have application-level fallbacks and aren't required to make the
deploy work, so they don't need to be in the workflow yet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously cyberstar-env had to be created manually with kubectl, which
broke the "git push = full deploy" expectation. Workflow now derives the
runtime Secret from Gitea repo secrets each deploy, so DATABASE_URL,
AUTH_SECRET, TOS/SMS/WECHAT credentials etc. are kept in one place and
applied transactionally with the rest of the manifests.
Repo secrets that need to exist in Gitea Settings:
DATABASE_URL, REDIS_URL, AUTH_SECRET,
TOS_ENDPOINT, TOS_REGION, TOS_BUCKET, TOS_ACCESS_KEY, TOS_SECRET_KEY,
NEXT_PUBLIC_TOS_DOMAIN,
WECHAT_APP_ID, WECHAT_APP_SECRET,
SMS_ACCESS_KEY, SMS_SECRET_KEY, SMS_SIGN_NAME, SMS_TEMPLATE_CODE,
HCAPTCHA_SITE_KEY, HCAPTCHA_SECRET
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root cause (from build log):
1. Prisma 6 generates client into @prisma/client package dir (not .prisma/client)
2. pnpm default isolated linker puts everything in .pnpm/ store with symlinks
at top-level — Docker COPY of @prisma followed broken/incomplete symlinks
3. node:22-alpine needs linux-musl-openssl-3.0.x engine binary
Fixes:
- .npmrc: node-linker=hoisted → flat node_modules, COPY behaves like npm
- schema.prisma: add linux-musl-openssl-3.0.x to binaryTargets
- Dockerfile: drop dead .prisma/client checks, copy only @prisma (where
Prisma 6 actually writes the client) plus standalone output
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root cause: pnpm 10+ skips lifecycle scripts in root/CI environments by
default, so the project's postinstall (prisma generate) never ran. The
runner stage then failed to COPY node_modules/.prisma because builder
never produced it.
Fix: install with --ignore-scripts, then call `pnpm exec prisma generate`
explicitly in both deps and builder stages, with ls assertions to surface
any future regression early.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
corepack-installed pnpm 11 requires node:sqlite (Node 22+).
Build was failing in deps stage with ERR_UNKNOWN_BUILTIN_MODULE.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>