mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
20c8fb0898
Introduce user-reported-issues and Goodreads shelf sync features and wire them into notifications. Adds Prisma migrations and schema changes (ReportedIssue, GoodreadsShelf, GoodreadsBookMapping), API endpoints for reporting (POST /audiobooks/[asin]/report-issue) and admin management (list, resolve/dismiss, replace), and an admin UI section to view/dismiss/replace reported issues. Adds a new notification event (issue_reported) with updates to notification schemas, docs and provider handling, plus a notification-events constants file. Refactors request creation to use createRequestForUser service, adds a Goodreads sync processor/service/hooks/UI modals, a scrape-resilience util, and related tests and minor integration updates.
208 lines
3.8 KiB
CSS
208 lines
3.8 KiB
CSS
@import "tailwindcss";
|
|
|
|
:root {
|
|
--background: #ffffff;
|
|
--foreground: #171717;
|
|
}
|
|
|
|
@theme inline {
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--font-sans: var(--font-geist-sans);
|
|
--font-mono: var(--font-geist-mono);
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--background: #0a0a0a;
|
|
--foreground: #ededed;
|
|
}
|
|
}
|
|
|
|
body {
|
|
background: var(--background);
|
|
color: var(--foreground);
|
|
font-family: Arial, Helvetica, sans-serif;
|
|
}
|
|
|
|
@keyframes slide-in-right {
|
|
from {
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.animate-slide-in-right {
|
|
animation: slide-in-right 0.3s ease-out;
|
|
}
|
|
|
|
/* BookDate Card Stack Animations */
|
|
|
|
/* Exit animations - card swipes away */
|
|
@keyframes card-exit-left {
|
|
0% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
transform: translate(-150%, 50px) rotate(-25deg);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
@keyframes card-exit-right {
|
|
0% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
transform: translate(150%, 50px) rotate(25deg);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
@keyframes card-exit-up {
|
|
0% {
|
|
transform: translate(0, 0) scale(1);
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
transform: translate(0, -120%) scale(0.8);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
/* Advance animations - cards move forward in stack */
|
|
@keyframes card-advance-to-top {
|
|
0% {
|
|
transform: scale(0.95) translateY(-12px);
|
|
opacity: 0.95;
|
|
}
|
|
100% {
|
|
transform: scale(1) translateY(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes card-advance-to-middle {
|
|
0% {
|
|
transform: scale(0.90) translateY(-24px);
|
|
opacity: 0.90;
|
|
}
|
|
100% {
|
|
transform: scale(0.95) translateY(-12px);
|
|
opacity: 0.95;
|
|
}
|
|
}
|
|
|
|
/* Enter animation - new card enters from bottom of stack */
|
|
@keyframes card-enter {
|
|
0% {
|
|
transform: scale(0.85) translateY(-36px);
|
|
opacity: 0;
|
|
}
|
|
100% {
|
|
transform: scale(0.90) translateY(-24px);
|
|
opacity: 0.90;
|
|
}
|
|
}
|
|
|
|
/* Animation classes */
|
|
.animate-exit-left {
|
|
animation: card-exit-left 400ms ease-in-out forwards;
|
|
}
|
|
|
|
.animate-exit-right {
|
|
animation: card-exit-right 400ms ease-in-out forwards;
|
|
}
|
|
|
|
.animate-exit-up {
|
|
animation: card-exit-up 400ms ease-in-out forwards;
|
|
}
|
|
|
|
.animate-advance-to-top {
|
|
animation: card-advance-to-top 350ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
}
|
|
|
|
.animate-advance-to-middle {
|
|
animation: card-advance-to-middle 350ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
}
|
|
|
|
.animate-enter {
|
|
animation: card-enter 350ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
}
|
|
|
|
/* Stack positioning classes */
|
|
.card-stack-position-0 {
|
|
z-index: 50;
|
|
transform: scale(1) translateY(0);
|
|
opacity: 1;
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.card-stack-position-1 {
|
|
z-index: 40;
|
|
transform: scale(0.95) translateY(-12px);
|
|
opacity: 0.95;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.card-stack-position-2 {
|
|
z-index: 30;
|
|
transform: scale(0.90) translateY(-24px);
|
|
opacity: 0.90;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Performance optimizations */
|
|
.card-stack-container {
|
|
perspective: 1000px;
|
|
transform-style: preserve-3d;
|
|
}
|
|
|
|
.card-stack-item {
|
|
will-change: transform, opacity;
|
|
backface-visibility: hidden;
|
|
-webkit-backface-visibility: hidden;
|
|
transform-origin: center center;
|
|
}
|
|
|
|
/* Premium Shimmer Animation for Skeletons */
|
|
@keyframes shimmer {
|
|
0% {
|
|
transform: translateX(-100%);
|
|
}
|
|
100% {
|
|
transform: translateX(100%);
|
|
}
|
|
}
|
|
|
|
/* Smooth Toast Slide In */
|
|
@keyframes toast-slide-in {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translate(-50%, 20px);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translate(-50%, 0);
|
|
}
|
|
}
|
|
|
|
.animate-toast-in {
|
|
animation: toast-slide-in 0.3s ease-out;
|
|
}
|
|
|
|
/* Hide scrollbar while keeping scroll functional */
|
|
.scrollbar-hide {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
.scrollbar-hide::-webkit-scrollbar {
|
|
display: none;
|
|
}
|