/* YOUKAY FASHION — Custom Styles */
html { scroll-behavior: smooth; }
body { font-family: 'Inter', system-ui, -apple-system, sans-serif; -webkit-font-smoothing: antialiased; }

/* ── Mobile layout safety net ──
   Nothing on the site should ever be wider than the viewport. Without this,
   a single oversized element (a fixed-width table, an un-constrained image,
   a long unbroken string, etc.) makes the ENTIRE page horizontally
   scrollable — which is what caused the "whole website shakes when you
   swipe left/right" report: a left/right swipe was actually scrolling the
   page sideways instead of doing nothing, and on some browsers that manifests
   as a visible jolt/shake. It's also what made pages "look zoomed out /
   desktop-sized on mobile": the browser has to shrink everything to fit an
   effective page width wider than the device, so text and buttons that were
   already mobile-sized render even smaller and the layout gets cut off. */
html, body { max-width: 100%; overflow-x: hidden; }
* { min-width: 0; }
img, video, svg, canvas, table { max-width: 100%; height: auto; }
img { object-fit: cover; }

/* Broken/failed image placeholder (paired with the small error-handler
   script in includes/header.php + includes/admin-footer.php) so a missing
   or still-uploading image shows a clean grey box instead of the browser's
   default broken-image icon + alt text spilling out of its container. */
img.img-broken { object-fit: contain !important; padding: 14%; background: #f3f4f6; opacity: 0.6; }

/* Hide scrollbar */
.hide-scrollbar::-webkit-scrollbar { display: none; }
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

/* Line clamp */
.line-clamp-1 { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.line-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Bottom sheet slide-up */
@keyframes youkaySlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.animate-slide-up { animation: youkaySlideUp 0.25s ease-out; }

/* Homepage banner fade-in (hero slider crossfade + new-product-launch banner) */
@keyframes youkayFadeIn { from { opacity: 0; } to { opacity: 1; } }
.animate-fade-in { animation: youkayFadeIn 0.7s ease-out; }

/* Desktop admin sidebar - hide on mobile via lg: */
@media (max-width: 1023px) {
    aside.w-64 { display: none; }
}

/* Shop by Category carousel — flex-basis per breakpoint controls how many
   cards are visible (2 on mobile/tablet, 3 on desktop). Written by hand
   instead of Tailwind arbitrary-value classes because assets/css/tailwind-build.css
   is a purged production build (only pre-scanned classes exist in it), so
   one-off bracket values like w-[46%] silently render with no styling. */
.cat-carousel-item { flex: 0 0 46%; }
@media (min-width: 1024px) { .cat-carousel-item { flex-basis: calc(33.333% - 11px); } }

/* Prev/Next arrows for the category carousel — desktop (mouse) only;
   touch devices scroll the strip directly, same as Featured Collection above it. */
.cat-nav-group { display: none; gap: 8px; }
@media (min-width: 1024px) { .cat-nav-group { display: flex; } }
.cat-nav-btn {
    width: 36px; height: 36px; border-radius: 9999px;
    border: 1px solid #d1d5db; background: #fff; color: #4b5563;
    display: flex; align-items: center; justify-content: center;
    font-size: 18px; line-height: 1; cursor: pointer;
    transition: border-color 0.15s, color 0.15s;
}
.cat-nav-btn:hover { border-color: #111827; color: #111827; }

.cat-shop-btn {
    display: inline-block; margin-top: 10px;
    font-size: 11px; font-weight: 600;
    background: rgba(255,255,255,0.92); color: #111827;
    padding: 6px 12px; border-radius: 9999px;
}

/* Announcement bar marquee — a single continuous line that starts fully off
   the right edge, scrolls left at a constant speed, and exits fully off the
   left edge before restarting. padding-left:100% pushes the content off-screen
   at rest (translateX(0)); the animation then moves it left by exactly the
   track's own width (padding + content) via translateX(-100%), so by the time
   it resets to translateX(0) the content is already fully hidden again —
   no visible jump, clipping, or flicker. JS in includes/header.php sets
   animation-duration from the track's actual rendered width so the scroll
   speed stays constant no matter how long the message text is. */
.hb-marquee { width: 100%; }
.hb-marquee__track {
    display: inline-block;
    white-space: nowrap;
    padding-left: 100%;
    will-change: transform;
    animation-name: hbMarqueeScroll;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
.hb-marquee__item { display: inline-block; }
@keyframes hbMarqueeScroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-100%); }
}
/* Pause on hover — desktop (hover-capable, precise-pointer) devices only,
   so a tap on mobile/tablet doesn't get "stuck" paused. */
@media (hover: hover) and (pointer: fine) {
    .hb-marquee:hover .hb-marquee__track { animation-play-state: paused; }
}