/* ==========================================================================
   SKMovies Premium — v6.4.0 · Production Polish Layer
   File: ui-polish-v64.css   (loads LAST — after styles.css + ui-polish.css)
   --------------------------------------------------------------------------
   Scope: styles the v6.4.0 feature layer only, plus low-risk polish passes.
     0 · Thumb positioning guard (fixes fragile abs-pos containing block)
     1 · Card quick actions            (.card-qa / .card-qa__btn)
     2 · Source provider badges        (.src-badge + per-provider hues)
     3 · Cast real photos              (.skm-cast-avatar.has-photo)
     4 · Direct download trigger       (.skm-dl-btn__direct)
     5 · "All Sources" sheet button    (.source-select-btn--all)
     6 · No-overlap / wrap guarantees  (hero actions, chips, meta, split, cast row)
     7 · Anti-lag / performance        (content-visibility upgrades)
     8 · Hover capability guards       (sticky-hover fix for touch)
     9 · Focus & a11y                  (rings, selection)
    10 · Scrollbars                    (sheet scroll areas)
    11 · Skeleton / empty refinements
    12 · Mobile safe areas
    13 · Reduced motion (scoped)
    14 · Responsive sanity (≤480px)

   Rules of engagement:
   - Reuses design tokens from styles.css :root (--red, --border, --radius-*,
     --ease, --shadow-card-*, --font-*, --text*, --card-bg*) — no redefinition.
   - Additive only: nothing here removes or globally resets existing styles.
   - All new @keyframes animate transform/opacity only.
   - backdrop-filter only on small pills/buttons (<40px) — never large surfaces.
   - No new z-index above 3 inside cards (site ladder: 40/50/80/100/120/150+).
   ========================================================================== */


/* ══════════════ 0 · THUMB POSITIONING GUARD ══════════════
   styles.css never sets `position` on .thumb; its absolutely-positioned
   children (.badges, .thumb::after) only anchor correctly because
   `content-visibility: auto` applies layout containment (which creates an
   abs-pos containing block). Make it explicit + clip the poster zoom so
   hover scaling can never bleed onto .post-desc. */

.thumb {
  position: relative;
  overflow: hidden;
}


/* ══════════════ 1 · CARD QUICK ACTIONS (.card-qa) ══════════════
   Two 38px circular buttons pinned bottom-right of the poster thumb.
   JS handles taps via delegated listener + stopPropagation (app.js v6.4.0);
   CSS only guarantees positioning and that hidden buttons can't be hit.
   Bottom-LEFT corner stays free for .badges (top-left) + .src-badge. */

.card-qa {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 3;                       /* above .thumb::after gradient (z2 badges) */
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;             /* container never traps card clicks */
}

.card-qa__btn {
  box-sizing: border-box;
  -webkit-appearance: none;
  appearance: none;
  width: 38px;
  height: 38px;
  padding: 0;
  margin: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.28);
  font-size: 14px;
  line-height: 1;
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  pointer-events: auto;
  background: rgba(15, 23, 42, 0.55);   /* secondary glass (download) */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
  transition: transform 0.2s var(--ease),
              opacity 0.2s var(--ease),
              background-color 0.2s var(--ease),
              border-color 0.2s var(--ease),
              box-shadow 0.2s var(--ease);
}

/* Play = accent gradient, matching .hero-btn--primary / .skm-split__btn--stream */
.card-qa__btn--play {
  border-color: rgba(255, 30, 66, 0.55);
  background: linear-gradient(135deg, var(--red) 0%, var(--red-dark) 100%);
  box-shadow: 0 4px 14px rgba(255, 30, 66, 0.45);
}

/* Solid-glass fallback when backdrop-filter is unsupported */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .card-qa__btn { background: rgba(15, 23, 42, 0.85); }
}

/* Blurred glass upgrade for the secondary button (small surface — cheap) */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .card-qa__btn {
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }
}

/* --- Pointer devices: hidden until the card is hovered / focused --- */
@media (hover: hover) {
  .card-qa__btn {
    opacity: 0;
    transform: translateY(8px) scale(0.9);
    pointer-events: none;           /* invisible buttons must not be hit */
  }
  .single-post:hover .card-qa__btn,
  .single-post:focus-within .card-qa__btn,
  .card-qa__btn:focus-visible {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
  }
  .card-qa__btn--play:hover {
    transform: translateY(-2px) scale(1.06);
    box-shadow: 0 6px 18px rgba(255, 30, 66, 0.55), var(--red-glow);
  }
  .card-qa__btn--dl:hover {
    background: rgba(15, 23, 42, 0.8);
    border-color: rgba(255, 255, 255, 0.5);
    transform: translateY(-2px) scale(1.06);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  }
}

/* --- Touch devices: always visible, slightly translucent --- */
@media (hover: none) {
  .card-qa__btn {
    opacity: 0.94;
    transform: none;
    pointer-events: auto;
  }
  .card-qa__btn:active {
    transform: scale(0.92);
    opacity: 1;
  }
}

/* Press feedback (declared after hover rules so :active wins the cascade) */
.card-qa__btn:active {
  transform: scale(0.92);
}

/* Keyboard ring — also force-reveals the row when tabbing to it */
.card-qa__btn:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 2px;
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}


/* ══════════════ 2 · SOURCE PROVIDER BADGES (.src-badge) ══════════════
   Tiny uppercase glass pill, bottom-left of .thumb (opposite corner from
   .badges which owns top-left). Non-interactive: pointer-events none, so it
   can never intercept the card's own click. Each provider gets a distinct
   600-level dot hue (roughly matched to the Sources sheet chip colors). */

.src-badge {
  position: absolute;
  left: 8px;
  bottom: 8px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: calc(100% - 16px);
  padding: 3px 8px 3px 6px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(10, 12, 18, 0.66);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #ffffff;
  font-family: var(--font-primary);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.6px;
  line-height: 1.4;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
}

/* Provider dot — default neutral, then one hue per source id */
.src-badge::before {
  content: '';
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #94a3b8;                          /* unknown provider */
}

.src-badge[data-src-badge="mlsbd"]::before      { background: #2563eb; }  /* blue-600  (Primary)   */
.src-badge[data-src-badge="hdhub4u"]::before    { background: #d97706; }  /* amber-600             */
.src-badge[data-src-badge="hdhubmain"]::before  { background: #ea580c; }  /* orange-600            */
.src-badge[data-src-badge="cinedose"]::before   { background: #65a30d; }  /* lime-600              */
.src-badge[data-src-badge="southfreak"]::before { background: #0d9488; }  /* teal-600              */
.src-badge[data-src-badge="nongor"]::before     { background: #e11d48; }  /* rose-600              */
.src-badge[data-src-badge="moviebox"]::before   { background: #db2777; }  /* pink-600              */
.src-badge[data-src-badge="lockedin"]::before   { background: #ca8a04; }  /* yellow-600            */
.src-badge[data-src-badge="fibwatch"]::before   { background: #0891b2; }  /* cyan-600              */
.src-badge[data-src-badge="fojik"]::before      { background: #0284c7; }  /* sky-700               */
.src-badge[data-src-badge="fdm"]::before        { background: #059669; }  /* emerald-600           */
.src-badge[data-src-badge="krx18"]::before      { background: #7c3aed; }  /* violet-600            */
.src-badge[data-src-badge="all"]::before        { background: #4f46e5; }  /* indigo-600            */

/* Opaque fallback where blur is unsupported (badge is tiny — no perf cost) */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .src-badge { background: rgba(10, 12, 18, 0.82); }
}


/* ══════════════ 3 · CAST REAL PHOTOS (.skm-cast-avatar.has-photo) ══════════════
   enrichCastPhotos() appends an <img> + .has-photo. The photo must fill the
   circle, get a subtle inner ring, and the gradient initial letter must be
   hidden while a photo is present. Non-photo avatars keep their gradient. */

.skm-cast-avatar {
  position: relative;                /* anchor for the injected <img> */
  overflow: hidden;                  /* hard-clip to the circle */
  flex: 0 0 auto;
}

.skm-cast-avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;          /* head-and-shoulders framing */
  border-radius: 50%;
  animation: skmPhotoIn 0.35s var(--ease) backwards;   /* transform+opacity only */
}

.skm-cast-avatar.has-photo {
  color: transparent;                /* hide the fallback initial letter */
  text-shadow: none;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25),
              inset 0 2px 6px rgba(0, 0, 0, 0.28),
              inset 0 -6px 12px rgba(0, 0, 0, 0.16);
}

/* If the photo 404s, JS removes the <img> and .has-photo → initial returns. */

@keyframes skmPhotoIn {
  from { opacity: 0; transform: scale(1.08); }
  to   { opacity: 1; transform: scale(1); }
}


/* ══════════════ 4 · DIRECT DOWNLOAD TRIGGER (.skm-dl-btn__direct) ══════════════
   A <span role="button"> inside every .skm-dl-btn anchor. Rendered as a
   compact corner tab at the top-right of the download card: hairline
   left/bottom borders act as the divider separating it from the host label.
   Visual 28px; an invisible ::before expands the hit area to ~40px. */

.skm-dl-btn {
  position: relative;                /* anchor for the corner tab */
  padding-top: 14px;                 /* breathing room under the tab */
}

.skm-dl-btn__host {
  max-width: calc(100% - 26px);      /* keep long host names clear of the tab */
}

.skm-dl-btn__direct {
  position: absolute;
  top: 0;
  right: 0;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
  color: var(--red);
  background: rgba(255, 30, 66, 0.07);
  border-left: 1px solid var(--border);      /* divider vs host label */
  border-bottom: 1px solid var(--border);    /* divider vs size/quality */
  border-radius: 0 9px 6px 0;                /* nests inside card's 10px corner */
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  transition: background-color 0.2s var(--ease),
              color 0.2s var(--ease),
              border-color 0.2s var(--ease),
              transform 0.15s var(--ease);
}

/* Invisible hit-area expander → ~40px touch target without layout shift */
.skm-dl-btn__direct::before {
  content: '';
  position: absolute;
  inset: -6px;
}

@media (hover: hover) {
  .skm-dl-btn__direct:hover {
    background: var(--red);
    border-color: var(--red);
    color: #ffffff;
  }
}

.skm-dl-btn__direct:active {
  transform: scale(0.9);
}

.skm-dl-btn__direct:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}

.dark-ui .skm-dl-btn__direct {
  background: rgba(255, 30, 66, 0.16);
  border-color: var(--card-border-dark);
  color: #fda4af;
}
.dark-ui .skm-dl-btn__direct:hover {
  background: var(--red);
  border-color: var(--red);
  color: #ffffff;
}


/* ══════════════ 5 · "ALL SOURCES" AGGREGATE BUTTON (.source-select-btn--all) ══════════════
   The button carries inline gradient styles in index.html. We only ADD
   refinements: hover lift + blue/purple glow + a 1px inset highlight ring.
   No !important needed — inline styles set border/background, we layer
   box-shadow + transform on top. */

.source-select-btn--all {
  position: relative;
  overflow: hidden;
  transition: transform 0.2s var(--ease),
              box-shadow 0.25s var(--ease);
}

/* Soft tinted sheen that fades in on hover (opacity only) */
.source-select-btn--all::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(135deg, rgba(96, 165, 250, 0.10), rgba(168, 85, 247, 0.10));
  opacity: 0;
  transition: opacity 0.25s var(--ease);
  pointer-events: none;
}

@media (hover: hover) {
  .source-select-btn--all:hover {
    transform: translateY(-2px);
    box-shadow: inset 0 0 0 1px rgba(191, 219, 254, 0.6),   /* 1px highlight border */
                0 10px 28px rgba(37, 99, 235, 0.22),        /* blue glow          */
                0 0 18px rgba(168, 85, 247, 0.22);          /* purple glow        */
  }
  .source-select-btn--all:hover::after { opacity: 1; }
}

.source-select-btn--all:active {
  transform: translateY(0) scale(0.985);
}

.source-select-btn--all:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}


/* ══════════════ 6 · NO-OVERLAP / WRAP GUARANTEES ══════════════ */

/* Hero action row: already flex-wrap in styles.css — tighten small screens
   so 360px never overflows or clips. */
.movie-hero__actions > * {
  max-width: 100%;
  min-width: 0;
}
@media (max-width: 400px) {
  .movie-hero__actions {
    gap: 7px;
  }
  .movie-hero__actions .hero-btn {
    padding: 8px 11px;
    font-size: 11.5px;
  }
}

/* Hero chips: never blow out the row; wrap instead */
.movie-hero__chips .chip {
  max-width: 100%;
  min-width: 0;
}

/* Card meta row: wrap cleanly instead of overflowing narrow cards */
.post-meta {
  flex-wrap: wrap;
  row-gap: 2px;
  min-width: 0;
}
.post-meta-item {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
}

/* Modal split buttons: equal height via grid stretch + touch-friendly min */
.skm-split {
  align-items: stretch;
}
.skm-split__btn {
  min-width: 0;
  min-height: 52px;
}
@media (max-width: 480px) {
  .skm-split {
    gap: 10px;
  }
  .skm-split__btn {
    padding: 13px 10px;
    font-size: 13.5px;
  }
}

/* Cast row: already scrollable with hidden scrollbar (ui-polish v6.3) —
   add the trailing fade mask so the cut-off chip reads as "scrollable". */
.skm-cast-row {
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 calc(100% - 28px), transparent 100%);
          mask-image: linear-gradient(90deg, #000 0%, #000 calc(100% - 28px), transparent 100%);
}


/* ══════════════ 7 · ANTI-LAG / PERFORMANCE ══════════════ */

/* Upgrade the card's intrinsic-size hint with the `auto` keyword
   (remember-last-rendered-size → no reflow jump when re-entering viewport).
   Parsers that don't know `auto <length>` drop this declaration and keep the
   valid base value (200px 300px) from styles.css — safe progressive win. */
.single-post {
  content-visibility: auto;
  contain-intrinsic-size: auto 200px auto 300px;
}

/* Shimmer sweeps read better (and cost less) with linear timing */
.skeleton__poster,
.skeleton__line,
.skeleton-modal,
.skeleton-card {
  animation-timing-function: linear;
}

/* NOTE: no new will-change and no new backdrop-filter on large surfaces.
   All new @keyframes (skmPhotoIn) animate transform/opacity only. */


/* ══════════════ 8 · HOVER CAPABILITY GUARDS ══════════════
   Touch devices keep "sticky" :hover state after a tap. Neutralize the card
   hover effects on non-hover devices (styles.css applies them unconditionally),
   and keep the refined glow on hover-capable devices only. */

@media (hover: none) {
  .single-post:hover {
    transform: none;
    box-shadow: var(--shadow-card);
    border-color: var(--border);
  }
  .dark-ui .single-post:hover {
    box-shadow: var(--shadow-card);
    border-color: var(--card-border-dark);
  }
  .single-post:hover .thumb img {
    transform: none;
  }
  .single-post:hover .post-title {
    color: var(--text);
  }
  .dark-ui .single-post:hover .post-title {
    color: #f1f5f9;
  }
}

@media (hover: hover) {
  .single-post:hover {
    box-shadow: var(--shadow-card-hover), 0 0 0 1px rgba(255, 30, 66, 0.22);
  }
  .dark-ui .single-post:hover {
    box-shadow: var(--shadow-card-dark-hover);
  }
}


/* ══════════════ 9 · FOCUS & A11Y ══════════════ */

/* Consistent 2px accent ring, 2px offset (matches the global :focus-visible) */
.card-qa__btn:focus-visible,
.skm-dl-btn__direct:focus-visible,
.source-select-btn--all:focus-visible,
.source-select-btn:focus-visible,
.skm-split__btn:focus-visible,
.nav-link:focus-visible,
.pill:focus-visible,
.skm-cast-chip:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}

/* Accent selection (re-affirm base + kill inherited text-shadow) */
::selection {
  background: var(--red);
  color: #ffffff;
  text-shadow: none;
}


/* ══════════════ 10 · SCROLLBARS (sheet scroll areas) ══════════════
   #modalCard already got a slim themed scrollbar in ui-polish v6.3.
   The bottom sheets scroll via their inner grids (inline overflow-y:auto)
   — give those the same treatment. .sheet__panel itself intentionally keeps
   its hidden scrollbar (established v6.2 design; not fought here). */

#categoriesGrid,
#sourcesGrid {
  scrollbar-width: thin;
  scrollbar-color: rgba(148, 163, 184, 0.55) transparent;
}
#categoriesGrid::-webkit-scrollbar,
#sourcesGrid::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
#categoriesGrid::-webkit-scrollbar-track,
#sourcesGrid::-webkit-scrollbar-track {
  background: transparent;
}
#categoriesGrid::-webkit-scrollbar-thumb,
#sourcesGrid::-webkit-scrollbar-thumb {
  background: rgba(148, 163, 184, 0.45);
  border-radius: 9999px;
}
.dark-ui #categoriesGrid::-webkit-scrollbar-thumb,
.dark-ui #sourcesGrid::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.16);
}


/* ══════════════ 11 · SKELETON / EMPTY REFINEMENTS ══════════════ */

/* Gentle entrance for the empty state (reuses the skmFadeUp keyframes
   already shipped in ui-polish.css — no new keyframes). */
#empty {
  animation: skmFadeUp 0.4s var(--ease) backwards;
}


/* ══════════════ 12 · MOBILE SAFE AREAS ══════════════ */

/* Bottom sheets + modal + toast already handle env() insets in styles.css.
   The floating go-to-top button did not — lift it above the home indicator. */
#go-top {
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
}


/* ══════════════ 13 · REDUCED MOTION (scoped to v6.4 components) ══════════════
   ui-polish.css already kills all animation/transition globally under this
   media query; these scoped rules keep the guarantee self-contained even if
   that global block is ever edited. */

@media (prefers-reduced-motion: reduce) {
  .card-qa,
  .card-qa__btn,
  .skm-dl-btn__direct,
  .source-select-btn--all,
  .src-badge,
  .skm-cast-avatar img,
  #empty {
    animation: none !important;
    transition: none !important;
  }
  /* The photo fade-in is animation-driven — ensure the photo still shows. */
  .skm-cast-avatar img {
    opacity: 1;
    transform: none;
  }
  /* Card QA hover/focus reveal still works — it snaps instead of easing. */
}


/* ══════════════ 14 · RESPONSIVE SANITY (≤480px) ══════════════
   At 360px a 2-col grid thumb is ~158px wide: a horizontal QA row (~80px)
   plus a provider pill (~70px) could collide. Stack the QA buttons
   vertically bottom-right (YouTube-style) and slim the badge. */

@media (max-width: 480px) {
  .card-qa {
    flex-direction: column;
    right: 6px;
    bottom: 6px;
    gap: 6px;
  }
  .card-qa__btn {
    width: 36px;
    height: 36px;
    font-size: 13px;
  }
  .src-badge {
    left: 6px;
    bottom: 6px;
    max-width: calc(100% - 12px);
    font-size: 9.5px;
    padding: 2px 7px 2px 5px;
    letter-spacing: 0.5px;
  }
  /* Direct-download tab: slightly larger visual on touch-first widths */
  .skm-dl-btn__direct {
    width: 30px;
    height: 30px;
  }
  .skm-dl-btn__host {
    max-width: calc(100% - 30px);
  }
}

/* ≥768px / desktop: nothing further needed — all v6.4 components are
   absolutely positioned INSIDE overflow-clipped cards, so no horizontal
   scroll or floating-button overlap is possible at any width. */
