Split card design into front+back, add sound effects & background music

Card design:
- Separate cardFront + cardBack (each own/equip independently)
- Fronts: classic (free), ivory/rosegold (buy), parchment/mint (earned)
- Backs: classic (free), sapphire/emerald (buy), ruby/royal (earned)
- PlayingCard `front` prop; table applies front to all faces, back to opponents
- Profile has front + back pickers; shop has both sections

Audio:
- Web Audio synth engine (no asset files): SFX for card/deal/trump/trick,
  win/lose, message, notify, award, levelup, purchase, kot + ambient music
- Toggles in profile (Audio) + mute button in game HUD; prefs persisted
- Wired across game-store, rewards, daily, shop, chat

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-04 11:49:19 +03:30
parent db4eade619
commit ae239f4c51
18 changed files with 579 additions and 72 deletions
+15 -1
View File
@@ -17,6 +17,12 @@ interface CardBack {
accent: string;
}
interface CardFront {
bg1: string;
bg2: string;
border: string;
}
interface Props {
card?: Card;
faceDown?: boolean;
@@ -24,6 +30,7 @@ interface Props {
className?: string;
dimmed?: boolean;
back?: CardBack;
front?: CardFront;
}
export function PlayingCard({
@@ -33,6 +40,7 @@ export function PlayingCard({
className,
dimmed,
back,
front,
}: Props) {
const s = SIZES[size];
@@ -76,7 +84,13 @@ export function PlayingCard({
dimmed && "opacity-45",
className
)}
style={{ width: s.w, height: s.h }}
style={{
width: s.w,
height: s.h,
...(front
? { background: `linear-gradient(160deg, ${front.bg1}, ${front.bg2})`, borderColor: front.border }
: {}),
}}
>
<div className={cn("absolute top-1 left-1.5 leading-none font-bold", color, s.rank)}>
<div>{rankLabel(card.rank)}</div>