- Resolve product cards from group endpoints (store-specials,
brand-groups) that only return a productId, not a slug, via a new
/products/id/[id] route backed by GET /products/by-id/{id} — clicking
these was previously falling back to a name search instead of the
detail page.
- Derive discount price/percent generically in normalizeProduct so any
source with real old/new prices shows it, even without an explicit
discount field from the API.
- Product cards and the detail page buy-box: show the discount badge
beside the old (struck-through) price, current price alone on its
own line, matching the reference design.
- Equalize product card heights within a carousel row (Swiper's own
CSS doesn't stretch slides to the tallest sibling in slidesPerView:
"auto" + freeMode mode) so the add-to-cart button lines up across
cards regardless of whether a card has a discount line.
- Featured categories: 110px images with no border/radius, matching
the site's other category card treatment.
- Replace Vazirmatn with the client's IRANYekan font files — light
weight for body text, bold weight for headings only.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
103 lines
1.8 KiB
CSS
103 lines
1.8 KiB
CSS
@import "tailwindcss";
|
|
@plugin "@tailwindcss/typography";
|
|
|
|
:root {
|
|
--background: #fafafa;
|
|
--foreground: #1a1a1a;
|
|
--surface: #ffffff;
|
|
--muted: #6b7280;
|
|
--border: #e5e7eb;
|
|
--red: #dc2626;
|
|
--red-dark: #991b1b;
|
|
--red-light: #fef2f2;
|
|
--red-muted: #fca5a5;
|
|
}
|
|
|
|
@theme inline {
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
--color-surface: var(--surface);
|
|
--color-muted: var(--muted);
|
|
--color-border: var(--border);
|
|
--color-red: var(--red);
|
|
--color-red-dark: var(--red-dark);
|
|
--color-red-light: var(--red-light);
|
|
--color-red-muted: var(--red-muted);
|
|
--font-sans: var(--font-iranyekan);
|
|
--font-sans-bold: var(--font-iranyekan-bold);
|
|
--font-display: var(--font-syne);
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
body {
|
|
background: var(--background);
|
|
color: var(--foreground);
|
|
font-family: var(--font-iranyekan), system-ui, sans-serif;
|
|
}
|
|
|
|
/* Titles use the bold face; everything else stays on the light one. */
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
font-family: var(--font-iranyekan-bold), var(--font-iranyekan), system-ui, sans-serif;
|
|
}
|
|
|
|
.font-display {
|
|
font-family: var(--font-syne), var(--font-iranyekan), sans-serif;
|
|
}
|
|
|
|
@keyframes fade-up {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(16px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
@keyframes slide-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(24px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.animate-fade-up {
|
|
animation: fade-up 0.6s ease-out both;
|
|
}
|
|
|
|
.animate-slide-in {
|
|
animation: slide-in 0.5s ease-out both;
|
|
}
|
|
|
|
.carousel-track {
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
}
|
|
|
|
.carousel-track::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.prose img {
|
|
width: 100%;
|
|
height: auto;
|
|
border-radius: 1rem;
|
|
}
|