/* ==========================================
   SalmasFlix — Gallery · Card chrome
   Extracted from gallery.css in Phase 7 CSS refactor.

   Covers every surface on a Movies/Shows/Books card:
   grid layout, card container, thumbnail wrapper, card logo
   overlay, play/lock hover states, processing/failed badges,
   video-info + meta footer, comment badge, "new" badge,
   per-item progress chrome (watch-badge + watch-bar + book /
   show progress pills), pull-to-refresh indicator, and the
   book-card specific grid + thumbnail + read-overlay.

   Scoped entirely to .video-card / .book-card / .gallery-grid
   / .books-grid / .card-logo / .watch-* / .show-progress-badge
   / .book-progress-badge / .pull-refresh-* — zero cascade
   overlap with detail-modal or book-reader-modal.

   All accent colors use theme tokens (var(--primary),
   var(--secondary), rgba(var(--primary-rgb), X)) so retinting
   happens automatically across every preset + custom theme.
   ========================================== */

@layer features {

/* Gallery Grid */
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr));
    gap: var(--spacing-md);
    max-width: 1400px;
    margin: 0 auto;
}

/* breakpoint snap 900px -> 1024px (Phase 7.6 ladder) */
@media (min-width: 1024px) {
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    }
}

/* breakpoint snap 1200px -> 1280px (Phase 7.6 ladder) */
@media (min-width: 1280px) {
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    }
}

@media (max-width: 480px) {
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr));
        gap: var(--spacing-sm);
    }
}

.video-card {
    /* Flex column so .video-info can `flex: 1` to fill remaining space
     * after the thumbnail. That's what lets `.video-card-footer`'s
     * `margin-top: auto` actually pin to the bottom of the card —
     * across cards with shorter descriptions the footer would otherwise
     * sit right below the description text instead of at the card's
     * baseline. CSS Grid already gives every card in a row the same
     * height, so once flex is wired the meta line is locked at the
     * same Y on every card. */
    display: flex;
    flex-direction: column;
    background: var(--bg-card);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid rgba(var(--primary-rgb),0.15);
    transition: transform var(--transition-normal), border-color var(--transition-normal), box-shadow var(--transition-normal), opacity var(--transition-normal);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    /* Skip rendering cards that are scrolled off-screen — 20+ blurred cards
       all computing their backdrop at once was a major GPU hog. The browser
       will render each card lazily as it scrolls into view. */
    content-visibility: auto;
    contain-intrinsic-size: 320px 480px; /* rough estimate so scrollbar is accurate */
}

/* Processing / failed state — video is in the library but its HLS transcode
   isn't done yet. Dim the thumbnail, show a badge, make the card feel "not
   ready" but still browsable (can hover, can read title/year). */
.video-card.is-processing .video-thumbnail img,
.video-card.is-failed .video-thumbnail img {
    opacity: 0.55;
    filter: grayscale(0.25);
}
.video-card.is-processing,
.video-card.is-failed {
    cursor: not-allowed;
}
.video-card .status-badge {
    position: absolute;
    top: 12px;
    right: 12px;
    padding: 5px 10px 5px 8px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    z-index: 3;
    pointer-events: none;
}
.video-card .status-processing {
    background: rgba(var(--secondary-rgb), 0.75);
    color: #fff;
    border: 1px solid rgba(var(--secondary-rgb), 0.9);
}
.video-card .status-failed {
    background: rgba(200, 40, 40, 0.82);
    color: #fff;
    border: 1px solid rgba(200, 40, 40, 0.95);
}
/* Tiny pulse ring inside the processing pill */
.video-card .status-spinner {
    display: inline-block;
    width: 10px;
    height: 10px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: statusBadgeSpin 0.9s linear infinite;
}
@keyframes statusBadgeSpin { to { transform: rotate(360deg); } }

/* Cards without videos - fit content with minimum */
.video-card.coming-soon .video-info {
    padding: var(--spacing-sm);
    padding-bottom: var(--spacing-md);
}

.video-card:hover {
    transform: translateY(-5px);
    border-color: rgba(var(--primary-rgb),0.4);
    box-shadow: 0 6px 20px rgba(var(--primary-rgb),0.15), 0 0 30px rgba(var(--primary-rgb),0.06);
}

.video-card:active {
    transform: scale(0.97);
    border-color: rgba(var(--primary-rgb),0.4);
    transition-duration: 0.1s;
}

.video-thumbnail {
    position: relative;
    aspect-ratio: 16/9;
    background: linear-gradient(135deg, #1a1a2e, #2d1f3d);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

/* ==========================================
   CARD LOGO OVERLAY
   SalmasFlix branding auto-applied to every media card.
   Matches the main header logo style and swaps with the theme.
   Sized with container-query units (cqw) so it scales with the card,
   not the viewport — a big card gets a big logo, a small card a small one.
   Falls back to vw for older browsers.
   ========================================== */
.video-thumbnail,
.book-thumbnail {
    container-type: inline-size;
}

.card-logo {
    position: absolute;
    top: 6cqw;
    top: max(6px, 3cqw);
    left: max(6px, 3cqw);
    z-index: 4;
    font-family: 'Outfit', sans-serif;
    /* Fallback for browsers without container queries */
    font-size: clamp(0.72rem, 1.7vw, 0.95rem);
    /* Preferred: sized to the card itself */
    font-size: clamp(0.72rem, 6cqw, 1.15rem);
    font-weight: 800;
    letter-spacing: -0.4px;
    line-height: 1;
    text-transform: none;
    pointer-events: none;
    user-select: none;
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.7)) drop-shadow(0 0 4px rgba(0, 0, 0, 0.5));
    white-space: nowrap;
}
.card-logo .card-logo-main {
    background: linear-gradient(135deg, #fff 0%, #e0e0e0 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}
.card-logo .card-logo-accent {
    background: linear-gradient(135deg, var(--primary), var(--secondary), var(--secondary-dark));
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}
/* Book cards are portrait — taller than wide, so use a slightly larger cqw ratio */
.book-thumbnail .card-logo {
    font-size: clamp(0.78rem, 1.95vw, 1.05rem);
    font-size: clamp(0.78rem, 7cqw, 1.3rem);
}

.video-thumbnail img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.thumbnail-placeholder {
    font-size: 3rem;
}

/* Play / read overlay — centered affordance that materializes when
   the user shows intent. SOTA: Netflix shows a play button on hover
   (desktop) and on tap-down (mobile); Apple TV+ does the same.

   Centering: `inset: 0; margin: auto` with explicit width/height
   centers the element in the absolutely-positioned parent regardless
   of viewport. Works for any thumbnail aspect ratio (videos 16:9,
   shows 16:9, books 3:4) without re-tweaking per-type. */
.play-overlay,
.read-overlay {
    position: absolute;
    inset: 0;
    margin: auto;
    width: clamp(48px, 14vw, 64px);
    height: clamp(48px, 14vw, 64px);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    color: #fff;
    background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
    border-radius: 50%;
    opacity: 0;
    transform: scale(0.85);
    transition: opacity 220ms cubic-bezier(0.2, 0.9, 0.3, 1),
                transform 220ms cubic-bezier(0.2, 0.9, 0.3, 1);
    box-shadow: 0 8px 28px var(--accent-glow), 0 0 0 1px rgba(255, 255, 255, 0.18) inset;
    pointer-events: none; /* the card click handles the actual play action */
}

/* Desktop / fine-pointer: reveal on hover or focus. */
@media (hover: hover) and (pointer: fine) {
    .video-card:not(.coming-soon):hover .play-overlay,
    .video-card:not(.coming-soon):focus-within .play-overlay,
    .show-card:not(.coming-soon):hover .play-overlay,
    .show-card:not(.coming-soon):focus-within .play-overlay,
    .book-card:not(.coming-soon):hover .read-overlay,
    .book-card:not(.coming-soon):focus-within .read-overlay {
        opacity: 1;
        transform: scale(1);
    }
    /* Subtle thumbnail dim on hover so the overlay reads against any
       artwork — matches the streaming-app idiom. */
    .video-card:not(.coming-soon):hover .video-thumbnail::after,
    .show-card:not(.coming-soon):hover .video-thumbnail::after,
    .book-card:not(.coming-soon):hover .book-thumbnail::after {
        content: '';
        position: absolute;
        inset: 0;
        background: linear-gradient(180deg, transparent 40%, rgba(0, 0, 0, 0.35));
        pointer-events: none;
    }
}

/* Touch / coarse-pointer: reveal on :active (finger-down) but with
   a 120ms transition-delay on the IN state — a quick scroll-swipe
   passes finger across multiple cards in <50ms, so :active fires
   briefly on each but the delay defeats the reveal. A deliberate
   tap holds on one card for ~150-300ms, comfortably past the delay
   threshold. Net effect: scrolling = no flicker, deliberate tap =
   overlay shows centered before the navigation kicks in. */
@media (hover: none), (pointer: coarse) {
    .video-card:not(.coming-soon):active .play-overlay,
    .show-card:not(.coming-soon):active .play-overlay,
    .book-card:not(.coming-soon):active .read-overlay {
        opacity: 1;
        transform: scale(1);
        transition-delay: 120ms;
    }
}

.video-card.coming-soon .play-overlay,
.book-card.coming-soon .read-overlay {
    display: none !important;
}

.lock-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(10px);
    opacity: 0;
    transition: opacity var(--transition-normal);
}

.video-card.locked .lock-overlay {
    opacity: 1;
}

.video-card.locked .video-thumbnail {
    filter: blur(5px);
}

.video-card.locked .play-overlay {
    display: none;
}

.video-info {
    padding: var(--spacing-md);
    display: flex;
    flex-direction: column;
    flex: 1;
}

.video-info h3 {
    font-size: clamp(1rem, 2.5vw, 1.2rem);
    font-weight: 600;
    margin-bottom: var(--spacing-xs);
    color: var(--accent-primary);
}

.video-info p {
    font-size: 0.875rem;
    color: var(--text-muted);
}

.video-info .video-meta {
    display: flex;
    gap: var(--spacing-md);
    font-size: 0.75rem;
    color: var(--text-muted);
    flex-wrap: nowrap;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1;
}

.meta-icon {
    vertical-align: -2px;
    flex-shrink: 0;
}

/* Card footer with meta + comment badge */
.video-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: auto;
    padding-top: var(--spacing-sm);
}

.video-desc {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.comment-badge {
    font-size: 0.75rem;
    padding: 3px 8px;
    background: rgba(var(--secondary-rgb),0.15);
    border: 1px solid rgba(var(--secondary-rgb),0.25);
    border-radius: 12px;
    cursor: pointer;
    transition: background 0.2s;
    white-space: nowrap;
    flex-shrink: 0;
}

.comment-badge:hover {
    background: rgba(var(--secondary-rgb),0.3);
}

.comment-badge.empty {
    opacity: 0.5;
}

/* Show Cards now use .video-card styles for consistency */

.show-progress-badge {
    position: absolute;
    bottom: var(--spacing-sm);
    left: var(--spacing-sm);
    padding: var(--spacing-xs) var(--spacing-sm);
    font-size: 0.75rem;
    font-weight: 600;
    background: rgba(0, 0, 0, 0.8);
    color: var(--accent-primary);
    border-radius: var(--radius-sm);
    backdrop-filter: blur(10px);
}

.new-badge {
    position: absolute;
    top: var(--spacing-sm);
    right: var(--spacing-sm);
    padding: 3px 10px;
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.5px;
    background: linear-gradient(135deg, var(--secondary-dark), var(--secondary-alt));
    color: #fff;
    border-radius: 4px;
    text-transform: uppercase;
    box-shadow: 0 2px 8px rgba(var(--secondary-dark-rgb),0.4);
    z-index: 2;
    animation: newBadgePulse 2s ease-in-out infinite;
}

/* ────────────────────────────────────────────────────────────────
   Watch-progress badge for movies. Matches the existing
   .book-progress-badge and .show-progress-badge exactly — same
   position (bottom-left), same size, same dark-glass pill with
   primary-colored text, same backdrop blur. The user explicitly
   asked for "same look and position as the percentage read for books
   and latest episode in shows card from outside", so this badge is a
   sibling of those two.
   ──────────────────────────────────────────────────────────────── */
/* Continue / % read / % watched pill — same dark-glass style as the
   existing .book-progress-badge and .show-progress-badge. Sits slightly
   higher than the bar so both are visible together. */
.watch-badge {
    position: absolute;
    bottom: calc(var(--spacing-sm) + 6px);
    left: var(--spacing-sm);
    padding: var(--spacing-xs) var(--spacing-sm);
    font-size: 0.75rem;
    font-weight: 600;
    background: rgba(0, 0, 0, 0.8);
    color: var(--primary);
    border-radius: var(--radius-sm);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    z-index: 4;
    pointer-events: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    line-height: 1.15;
}
.watch-badge-finished {
    color: #7ed99c;
    bottom: var(--spacing-sm);
}
.watch-badge-finished svg { flex-shrink: 0; }

/* Thin primary progress bar pinned to the very bottom of the thumbnail.
   Universal for books + movies — shows visually how far you are at a
   glance (standard streaming convention: Netflix red, YouTube red, we
   use the theme's primary). Bar is 3px tall so it doesn't dominate. */
.watch-bar {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 3px;
    background: rgba(0, 0, 0, 0.55);
    z-index: 3;
    overflow: hidden;
    pointer-events: none;
}
.watch-bar-fill {
    height: 100%;
    background: var(--primary);
    box-shadow: 0 0 8px rgba(var(--primary-rgb), 0.55);
    transition: width 0.25s ease;
}
/* Hide the bar when the item is fully finished — no point showing a
   100%-full bar, the green "Read / Watched" pill tells the story. */
.video-thumbnail:has(.watch-badge-finished) .watch-bar,
.book-thumbnail:has(.watch-badge-finished) .watch-bar { display: none; }

@keyframes newBadgePulse {
    0%, 100% { box-shadow: 0 2px 8px rgba(var(--secondary-dark-rgb),0.4); }
    50% { box-shadow: 0 2px 16px rgba(var(--secondary-dark-rgb),0.7); }
}

/* ========== Pull to Refresh ========== */
.pull-refresh-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 0;
    opacity: 0;
    overflow: hidden;
    transition: height 0.25s ease, opacity 0.25s ease;
}

.pull-refresh-spinner {
    width: 24px;
    height: 24px;
    border: 3px solid rgba(var(--secondary-rgb),0.2);
    border-top-color: var(--accent-primary);
    border-radius: 50%;
}

.pull-refresh-indicator.ready .pull-refresh-spinner {
    transform: rotate(180deg);
}

.pull-refresh-indicator.refreshing .pull-refresh-spinner {
    animation: pullSpin 0.6s linear infinite;
}

@keyframes pullSpin {
    to { transform: rotate(360deg); }
}

/* ========== Book Card Styles ========== */

/* Phone-first: 2 columns, matching movies/shows. Books just have a
   taller card aspect ratio (book cover ≈ 2:3) — the WIDTH stays the
   same as movies/shows so card grid columns align across the three
   sub-tabs. Eliminates the "books are full-width single-column with
   black bars" complaint where books on phone read as a totally
   different layout from movies. */
.books-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--spacing-md);
    max-width: 1400px;
    margin: 0 auto;
}

/* Tablet+: multi-column like movies — auto-fill by min-width so wider
   viewports get more columns naturally. */
/* breakpoint snap 600px -> 768px (Phase 7.6 ladder) */
@media (min-width: 768px) {
    .books-grid {
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }
}

/* breakpoint snap 900px -> 1024px (Phase 7.6 ladder) */
@media (min-width: 1024px) {
    .books-grid {
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    }
}

/* breakpoint snap 1200px -> 1280px (Phase 7.6 ladder) */
@media (min-width: 1280px) {
    .books-grid {
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    }
}

.book-card {
    /* Flex column for the same reason as .video-card — pin the meta
     * footer to the bottom of the card via .video-card-footer's
     * `margin-top: auto`. */
    display: flex;
    flex-direction: column;
    background: var(--bg-card);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid rgba(var(--primary-rgb),0.15);
    transition: transform var(--transition-normal), border-color var(--transition-normal), box-shadow var(--transition-normal), opacity var(--transition-normal);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.book-card:hover,
.book-card:active {
    transform: translateY(-5px);
    border-color: rgba(var(--primary-rgb),0.4);
    box-shadow: 0 6px 20px rgba(var(--primary-rgb),0.15), 0 0 30px rgba(var(--primary-rgb),0.06);
}

/* book-card .video-meta inherits nowrap/overflow from base .video-meta */

/* Thumbnail: fixed 3:4 aspect ratio — slightly less tall than the
   classic 2:3 book-cover ratio so the card doesn't dominate the grid
   on phone. Card WIDTH matches movies/shows exactly (same grid track);
   only HEIGHT differs.

   Two-image stack (Apple Books / Spotify pattern) — the SOTA way to
   fit covers of varying aspect ratios into a fixed-aspect card
   without cropping or letterboxing:

     1. .book-thumbnail-blur (back layer): same image, object-fit:
        cover, heavily blurred + dimmed. Fills the entire card; reads
        as a soft ambient backdrop derived from the cover itself.
     2. .book-thumbnail-cover (front layer): same image, object-fit:
        contain. Full cover always visible — no titles cropped, no
        cut-off letters like the "a" / "c" in "Atomic Habits" the
        legacy `object-fit: cover` was clipping.

   Net effect: the WHOLE book cover shows, framed by a beautiful
   blurred wash of itself. No flat dark gaps, no cropping. */
.book-thumbnail {
    position: relative;
    background: rgba(13, 11, 30, 0.4);
    overflow: hidden;
    aspect-ratio: 3 / 4;
    width: 100%;
    display: block;
}

.book-thumbnail-blur {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
    /* Heavy blur + dim so the back layer is just an ambient color
       wash, not visually competing with the foreground cover. */
    filter: blur(28px) brightness(0.55) saturate(1.15);
    transform: scale(1.15); /* avoid blur-edge transparency at the corners */
    z-index: 1;
}

.book-thumbnail-cover {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    display: block;
    z-index: 2;
    /* Subtle drop shadow so the cover lifts off the blurred backdrop. */
    filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.45));
}

/* Legacy single-img selector (placeholder etc.) — keep working. */
.book-thumbnail > img:only-of-type:not(.book-thumbnail-blur):not(.book-thumbnail-cover) {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    display: block;
}

/* .read-overlay sizing + reveal logic moved into the shared
   .play-overlay,.read-overlay block above (single source of truth for
   centered overlay across video / show / book cards). The legacy
   :active rule fired on every touch-down — even mid-scroll — making
   the overlay flicker randomly. The new shared rule uses transition-
   delay to defeat scroll-swipe flicker. */

.book-progress-badge {
    position: absolute;
    bottom: var(--spacing-sm);
    left: var(--spacing-sm);
    padding: var(--spacing-xs) var(--spacing-sm);
    font-size: 0.75rem;
    font-weight: 600;
    background: rgba(0, 0, 0, 0.8);
    color: var(--accent-primary);
    border-radius: var(--radius-sm);
    backdrop-filter: blur(10px);
}

} /* end @layer features */
