@@ -97,27 +97,57 @@ export const BookCard = memo(function BookCard({
9797 { /* Cover — 28:41 aspect ratio */ }
9898 < View style = { s . coverWrap } >
9999 { resolvedCoverUrl && ! imageError ? (
100- < Image
101- source = { { uri : resolvedCoverUrl } }
102- style = { s . coverImage }
103- resizeMode = "cover"
104- onError = { ( ) => setImageError ( true ) }
105- />
100+ < >
101+ < Image
102+ source = { { uri : resolvedCoverUrl } }
103+ style = { s . coverImage }
104+ resizeMode = "cover"
105+ onError = { ( ) => setImageError ( true ) }
106+ />
107+ { /* Book spine crease overlay — matches desktop .book-spine */ }
108+ < View style = { s . spineOverlay } pointerEvents = "none" >
109+ { /* Left edge dark line */ }
110+ < View style = { s . spineStrip1 } />
111+ { /* Spine shadow dip */ }
112+ < View style = { s . spineStrip2 } />
113+ { /* Highlight reflection */ }
114+ < View style = { s . spineStrip3 } />
115+ { /* Transition bright */ }
116+ < View style = { s . spineStrip4 } />
117+ { /* Crease dark */ }
118+ < View style = { s . spineStrip5 } />
119+ { /* Deep fold */ }
120+ < View style = { s . spineStrip6 } />
121+ { /* Subtle bright transition */ }
122+ < View style = { s . spineStrip7 } />
123+ { /* Right edge subtle shadow */ }
124+ < View style = { s . spineEdgeRight } />
125+ </ View >
126+ { /* Top highlight */ }
127+ < View style = { s . spineTopHighlight } pointerEvents = "none" />
128+ { /* Bottom shadow */ }
129+ < View style = { s . spineBottomShadow } pointerEvents = "none" />
130+ </ >
106131 ) : (
107132 < View style = { s . fallbackCover } >
108- < View style = { s . fallbackTitleWrap } >
109- < Text style = { s . fallbackTitle } numberOfLines = { 3 } >
110- { book . meta . title }
111- </ Text >
112- </ View >
113- < View style = { s . fallbackDivider } />
114- { book . meta . author ? (
115- < View style = { s . fallbackAuthorWrap } >
116- < Text style = { s . fallbackAuthor } numberOfLines = { 1 } >
117- { book . meta . author }
133+ { /* Simulate gradient: stone-100 top half, stone-200 bottom half */ }
134+ < View style = { s . fallbackGradientTop } />
135+ < View style = { s . fallbackGradientBottom } />
136+ < View style = { s . fallbackContentOverlay } >
137+ < View style = { s . fallbackTitleWrap } >
138+ < Text style = { s . fallbackTitle } numberOfLines = { 3 } >
139+ { book . meta . title }
118140 </ Text >
119141 </ View >
120- ) : null }
142+ < View style = { s . fallbackDivider } />
143+ { book . meta . author ? (
144+ < View style = { s . fallbackAuthorWrap } >
145+ < Text style = { s . fallbackAuthor } numberOfLines = { 1 } >
146+ { book . meta . author }
147+ </ Text >
148+ </ View >
149+ ) : null }
150+ </ View >
121151 </ View >
122152 ) }
123153
@@ -261,19 +291,117 @@ const makeStyles = (colors: ThemeColors) => StyleSheet.create({
261291 borderRadius : radius . sm ,
262292 overflow : "hidden" ,
263293 position : "relative" ,
294+ // Book cover shadow
295+ shadowColor : "#000" ,
296+ shadowOffset : { width : 0 , height : 2 } ,
297+ shadowOpacity : 0.15 ,
298+ shadowRadius : 4 ,
299+ elevation : 3 ,
264300 } ,
265301 coverImage : {
266302 width : "100%" ,
267303 height : "100%" ,
268304 borderRadius : radius . sm ,
269305 } ,
306+ // Book spine crease effect — simulates desktop .book-spine linear-gradient overlay
307+ spineOverlay : {
308+ position : "absolute" ,
309+ top : 0 ,
310+ left : 0 ,
311+ bottom : 0 ,
312+ width : "8%" ,
313+ flexDirection : "row" ,
314+ zIndex : 2 ,
315+ } ,
316+ spineStrip1 : {
317+ width : "6%" ,
318+ height : "100%" ,
319+ backgroundColor : "rgba(0,0,0,0.10)" ,
320+ } ,
321+ spineStrip2 : {
322+ width : "8%" ,
323+ height : "100%" ,
324+ backgroundColor : "rgba(20,20,20,0.20)" ,
325+ } ,
326+ spineStrip3 : {
327+ width : "5%" ,
328+ height : "100%" ,
329+ backgroundColor : "rgba(240,240,240,0.40)" ,
330+ } ,
331+ spineStrip4 : {
332+ width : "18%" ,
333+ height : "100%" ,
334+ backgroundColor : "rgba(215,215,215,0.35)" ,
335+ } ,
336+ spineStrip5 : {
337+ width : "12%" ,
338+ height : "100%" ,
339+ backgroundColor : "rgba(150,150,150,0.25)" ,
340+ } ,
341+ spineStrip6 : {
342+ width : "20%" ,
343+ height : "100%" ,
344+ backgroundColor : "rgba(100,100,100,0.18)" ,
345+ } ,
346+ spineStrip7 : {
347+ width : "31%" ,
348+ height : "100%" ,
349+ backgroundColor : "rgba(175,175,175,0.12)" ,
350+ } ,
351+ spineEdgeRight : {
352+ position : "absolute" ,
353+ top : 0 ,
354+ right : - coverWidth * 0.92 ,
355+ bottom : 0 ,
356+ width : coverWidth * 0.02 ,
357+ backgroundColor : "rgba(30,30,30,0.12)" ,
358+ } ,
359+ spineTopHighlight : {
360+ position : "absolute" ,
361+ top : 0 ,
362+ left : 0 ,
363+ right : 0 ,
364+ height : "3%" ,
365+ backgroundColor : "rgba(240,240,240,0.15)" ,
366+ zIndex : 3 ,
367+ } ,
368+ spineBottomShadow : {
369+ position : "absolute" ,
370+ bottom : 0 ,
371+ left : 0 ,
372+ right : 0 ,
373+ height : "8%" ,
374+ backgroundColor : "rgba(15,15,15,0.15)" ,
375+ zIndex : 3 ,
376+ } ,
270377 fallbackCover : {
271378 flex : 1 ,
272- padding : 8 ,
379+ borderRadius : radius . sm ,
380+ overflow : "hidden" ,
381+ position : "relative" ,
382+ } ,
383+ fallbackGradientTop : {
384+ position : "absolute" ,
385+ top : 0 ,
386+ left : 0 ,
387+ right : 0 ,
388+ height : "50%" ,
389+ backgroundColor : colors . stone100 ,
390+ } ,
391+ fallbackGradientBottom : {
392+ position : "absolute" ,
393+ bottom : 0 ,
394+ left : 0 ,
395+ right : 0 ,
396+ height : "50%" ,
397+ backgroundColor : colors . stone200 ,
398+ } ,
399+ fallbackContentOverlay : {
400+ flex : 1 ,
401+ padding : 10 ,
273402 alignItems : "center" ,
274403 justifyContent : "center" ,
275- backgroundColor : colors . stone200 ,
276- borderRadius : radius . sm ,
404+ zIndex : 1 ,
277405 } ,
278406 fallbackTitleWrap : {
279407 flex : 1 ,
@@ -284,14 +412,15 @@ const makeStyles = (colors: ThemeColors) => StyleSheet.create({
284412 textAlign : "center" ,
285413 fontSize : fontSize . sm ,
286414 fontWeight : fontWeight . medium ,
415+ fontFamily : "serif" ,
287416 color : colors . stone500 ,
288- lineHeight : 16 ,
417+ lineHeight : 18 ,
289418 } ,
290419 fallbackDivider : {
291- width : 24 ,
420+ width : 32 ,
292421 height : 1 ,
293- backgroundColor : "rgba(168,162,158,0.4)" ,
294- marginVertical : 4 ,
422+ backgroundColor : ` ${ colors . stone300 } 99` ,
423+ marginVertical : 6 ,
295424 } ,
296425 fallbackAuthorWrap : {
297426 height : "25%" ,
@@ -300,7 +429,8 @@ const makeStyles = (colors: ThemeColors) => StyleSheet.create({
300429 } ,
301430 fallbackAuthor : {
302431 textAlign : "center" ,
303- fontSize : 8 ,
432+ fontSize : 10 ,
433+ fontFamily : "serif" ,
304434 color : colors . stone400 ,
305435 } ,
306436 progressBarBg : {
@@ -347,48 +477,48 @@ const makeStyles = (colors: ThemeColors) => StyleSheet.create({
347477 paddingVertical : 2 ,
348478 } ,
349479 vecBadgeText : { fontSize : 7 , fontWeight : fontWeight . medium , color : "#fff" } ,
350- infoWrap : { paddingTop : 6 } ,
480+ infoWrap : { paddingTop : 6 , paddingHorizontal : 1 } ,
351481 bookTitle : {
352482 fontSize : 11 ,
353483 fontWeight : fontWeight . semibold ,
354484 color : colors . foreground ,
355485 lineHeight : 14 ,
356486 } ,
357- tagsRow : { flexDirection : "row" , flexWrap : "wrap" , gap : 2 , marginTop : 2 } ,
487+ tagsRow : { flexDirection : "row" , flexWrap : "wrap" , gap : 3 , marginTop : 3 } ,
358488 tagBadge : {
359- backgroundColor : "rgba(245,245,244,0.1)" ,
489+ backgroundColor : ` ${ colors . muted } ` ,
360490 borderRadius : radius . full ,
361- paddingHorizontal : 5 ,
491+ paddingHorizontal : 6 ,
362492 paddingVertical : 1 ,
363493 } ,
364494 tagText : { fontSize : 8 , color : colors . mutedForeground } ,
365495 tagBadgeUncategorized : {
366- backgroundColor : "rgba(245,245,244,0.05)" ,
496+ backgroundColor : ` ${ colors . muted } 80` ,
367497 borderRadius : radius . full ,
368- paddingHorizontal : 5 ,
498+ paddingHorizontal : 6 ,
369499 paddingVertical : 1 ,
370500 } ,
371- tagTextUncategorized : { fontSize : 8 , color : "rgba(124,124,130,0.6)" } ,
372- tagOverflow : { fontSize : 8 , color : "rgba(124,124,130,0.6) " } ,
501+ tagTextUncategorized : { fontSize : 8 , color : ` ${ colors . mutedForeground } 99` } ,
502+ tagOverflow : { fontSize : 8 , color : ` ${ colors . mutedForeground } 99` , alignSelf : "center " } ,
373503 statusRow : {
374504 flexDirection : "row" ,
375505 alignItems : "center" ,
376506 justifyContent : "space-between" ,
377- marginTop : 2 ,
378- minHeight : 12 ,
507+ marginTop : 3 ,
508+ minHeight : 14 ,
379509 } ,
380510 progressText : { fontSize : 9 , color : colors . mutedForeground , fontVariant : [ "tabular-nums" ] } ,
381511 completeText : { fontSize : 9 , fontWeight : fontWeight . medium , color : "#16a34a" } ,
382512 newBadge : {
383- backgroundColor : "rgba(224,224,230,0.08)" ,
513+ backgroundColor : ` ${ colors . primary } 14` ,
384514 borderRadius : radius . full ,
385- paddingHorizontal : 4 ,
515+ paddingHorizontal : 5 ,
386516 paddingVertical : 1 ,
387517 } ,
388518 newText : { fontSize : 8 , fontWeight : fontWeight . medium , color : colors . primary } ,
389519 formatText : {
390520 fontSize : 8 ,
391- color : "rgba(124,124,130,0.4)" ,
521+ color : ` ${ colors . mutedForeground } 99` ,
392522 textTransform : "uppercase" ,
393523 letterSpacing : 0.5 ,
394524 } ,
0 commit comments