/* =====================================================================
   Gaya homepage.

   Sebelumnya satu blok <style> 29 KB di dalam views/default/pages/default.ejs,
   dikirim ulang setiap kali homepage dimuat. Dipisah ke sini supaya bisa
   di-cache; <link>-nya sengaja tetap berada di dalam [system-wrapper], di
   posisi persis blok <style> yang lama, agar Pjax tetap membawanya saat
   menavigasi kembali ke homepage.

   Seluruh selektor berawalan .pv-/.oka-, jadi tidak ada yang bocor ke halaman
   lain. NAIKKAN versi aplikasi setelah menyunting file ini.
   ===================================================================== */

    /* =========================================================
       Prototype styles — fully self-contained.
       Deliberately NOT relying on Tailwind utilities: the site's
       default.min.css is prebuilt and does not contain arbitrary
       values (w-[46%], row-span-2, snap-x, …) used here.
       ========================================================= */
    /* LIGHT is the default; the site adds `.dark` to <html> via its theme toggle.
       Everything below is expressed through these tokens, so the page follows the
       visitor's preference exactly like the rest of the site — no chrome overrides. */
    .pv-root {
        --bg:        #ffffff;
        --surface:   #eef1f7;
        --line:      rgba(15,23,42,.10);
        --text:      #0f172a;
        --muted:     #64748b;
        --title:     #1e293b;
        --chip:      rgba(15,23,42,.05);
        --chip-hov:  rgba(15,23,42,.09);
        --arrow-bg:  #ffffff;
        --arrow-fg:  #0f172a;
        --scrim-1:   rgba(255,255,255,.55);
        --scrim-2:   rgba(255,255,255,.88);
        --shadow:    rgba(15,23,42,.16);
        --kicker:    #b45309;        /* amber, darkened for contrast on light */

        --brand:     #6d4aff;
        --brand-2:   #ff4d6d;
        --radius:    14px;
        --gap:       14px;
        --cols:      7;              /* cards visible per rail */
    }

    :root.dark .pv-root {
        --bg:        #0a0b12;
        --surface:   #141826;
        --line:      rgba(255,255,255,.08);
        --text:      #f7f8fc;
        --muted:     #8e97b3;
        --title:     #cfd5e6;
        --chip:      rgba(255,255,255,.07);
        --chip-hov:  rgba(255,255,255,.12);
        --arrow-bg:  rgba(18,20,32,.92);
        --arrow-fg:  #ffffff;
        --scrim-1:   rgba(10,11,18,.55);
        --scrim-2:   rgba(10,11,18,.88);
        --shadow:    rgba(0,0,0,.55);
        --kicker:    #ffd166;

        --brand:     #7c5cff;
    }

    .pv-root {
        background: var(--bg);
        color: var(--text);
        font-synthesis-weight: none;
        overflow-x: hidden;
    }

    .pv-root *, .pv-root *::before, .pv-root *::after { box-sizing: border-box; }

    /* The sidebar footer block and its styles now live in modules/sidebar.block.ejs,
        so they render on every page rather than only here. */

    /* The footer is now hidden site-wide from modules/sidebar.block.ejs, so the
        homepage-only rule that used to live here is gone. */

    .pv-img { width: 100%; height: 100%; object-fit: cover; display: block; }
    .pv-root picture { display: block; width: 100%; height: 100%; }

    /* ---------------- hero ---------------- */
    .pv-hero { position: relative; isolation: isolate; padding: 22px 0 26px; }
    /* Purely decorative. The negative top bleeds this layer ~130px above the hero, right
       over the "Continue playing" rail; without pointer-events:none it swallows the touch
       gesture there and the rail can't be swiped on mobile. */
    .pv-hero-bg {
        position: absolute; inset: -10% -5% 0; z-index: -2;
        filter: blur(60px) saturate(1.6); opacity: .40;
        pointer-events: none;
    }
    .pv-hero::after {
        content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
        background: linear-gradient(180deg, var(--scrim-1) 0%, var(--scrim-2) 62%, var(--bg) 100%);
    }
    /* Single column: the recommended header stacks above its own grid. */
    .pv-hero-inner { max-width: 1400px; margin: 0 auto; padding: 0 20px; display: block; }
    .pv-hero-main {
        position: relative; display: block; border-radius: 20px; overflow: hidden;
        aspect-ratio: 21 / 9; text-decoration: none;
        box-shadow: 0 18px 50px var(--shadow);
        transition: transform .35s cubic-bezier(.2,.7,.3,1);
    }
    .pv-hero-main .pv-img { transition: transform .6s cubic-bezier(.2,.7,.3,1); }
    .pv-hero-main:hover .pv-img { transform: scale(1.06); }
    .pv-hero-scrim {
        position: absolute; inset: 0;
        background: linear-gradient(90deg, rgba(6,7,12,.92) 0%, rgba(6,7,12,.55) 45%, rgba(6,7,12,.05) 100%),
                    linear-gradient(0deg, rgba(6,7,12,.85) 0%, rgba(6,7,12,0) 55%);
    }
    .pv-hero-copy { position: absolute; left: 0; bottom: 0; padding: 26px 28px; display: block; max-width: 62%; }
    .pv-kicker {
        display: inline-flex; align-items: center; gap: 6px;
        font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
        color: var(--kicker); margin-bottom: 8px;
    }
    .pv-kicker svg { width: 13px; height: 13px; }
    .pv-hero-title {
        display: block; font-size: clamp(22px, 2.6vw, 40px); line-height: 1.06;
        font-weight: 800; letter-spacing: -.02em; color: #fff;
        text-shadow: 0 2px 20px rgba(0,0,0,.6);
    }
    .pv-cta {
        display: inline-flex; align-items: center; gap: 8px; margin-top: 16px;
        background: linear-gradient(135deg, #d946ef 0%, #06b6d4 100%);
        color: #fff; font-weight: 800; font-size: 14px;
        padding: 11px 22px; border-radius: 999px;
        box-shadow: 0 8px 26px rgba(217,70,239,.42);
        transition: transform .2s ease, box-shadow .2s ease;
    }
    .pv-hero-main:hover .pv-cta { transform: translateY(-2px); box-shadow: 0 12px 34px rgba(6,182,212,.55); }
    .pv-cta svg { width: 16px; height: 16px; }

    /* Media is taken out of flow so it never drives the hero's height:
       the 21/9 main card alone defines the row, and the side column stretches to match. */
    .pv-hero-main > picture, .pv-hero-main > img,
    .pv-hero-mini > picture, .pv-hero-mini > img { position: absolute; inset: 0; }

    .pv-hero-side { display: grid; grid-template-rows: 1fr 1fr; gap: var(--gap); min-width: 0; min-height: 0; }
    .pv-hero-mini {
        position: relative; display: block; border-radius: 16px; overflow: hidden;
        text-decoration: none; min-height: 0;
        box-shadow: 0 10px 30px var(--shadow);
    }
    .pv-hero-mini .pv-img { transition: transform .5s cubic-bezier(.2,.7,.3,1); }
    .pv-hero-mini:hover .pv-img { transform: scale(1.07); }
    .pv-hero-mini-title {
        position: absolute; left: 16px; right: 16px; bottom: 13px;
        font-weight: 700; font-size: 15px; color: #fff;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }

    /* ---------------- continue playing ---------------- */
    .pv-continue { padding: 20px 0 2px; }
    .pv-continue-inner { max-width: 1400px; margin: 0 auto; padding: 0 20px; }

    /* ---------------- recommended block ---------------- */
    .pv-rechead { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
    .pv-rechead-l { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    .pv-rechead .pv-kicker { margin-bottom: 0; font-size: 12px; }
    .pv-rechead-sub { font-size: 13px; color: var(--muted); }

    .pv-reroll {
        display: inline-flex; align-items: center; gap: 7px; flex: none; cursor: pointer;
        font-size: 13px; font-weight: 700; color: var(--title);
        background: var(--chip); border: 1px solid var(--line);
        padding: 8px 15px; border-radius: 999px;
        transition: background .18s, color .18s, transform .18s;
    }
    .pv-reroll svg { width: 15px; height: 15px; transition: transform .5s cubic-bezier(.2,.7,.3,1); }
    .pv-reroll:hover { background: var(--brand); color: #fff; border-color: transparent; }
    .pv-reroll:hover svg { transform: rotate(-180deg); }
    .pv-reroll[disabled] { opacity: .55; cursor: default; }

    .pv-recgrid {
        display: grid;
        grid-template-columns: repeat(6, minmax(0, 1fr));
        grid-auto-rows: minmax(0, 1fr);
        gap: var(--gap);
    }
    /* Cards stretch to their grid row so both rows align flush with the lead tile. */
    .pv-recgrid > .pv-card { display: flex; flex-direction: column; min-height: 0; }
    .pv-recgrid > .pv-card .pv-card-art { flex: 1 1 auto; aspect-ratio: auto; min-height: 0; }

    /* Lead pick takes a 2x2 block; the other eight fill the remaining 4x2. */
    .pv-card--lead { grid-column: span 2; grid-row: span 2; }
    .pv-card--lead .pv-card-art { height: 100%; aspect-ratio: auto; border-radius: 18px; }
    .pv-lead-copy { position: absolute; left: 0; bottom: 0; z-index: 3; padding: 20px 22px; display: block; }
    .pv-card--lead .pv-hero-title { font-size: clamp(18px, 1.6vw, 26px); }
    .pv-card--lead .pv-cta { margin-top: 12px; padding: 9px 18px; font-size: 13px; }
    .pv-card--lead:hover .pv-cta { transform: translateY(-2px); }
    .pv-card--lead .pv-play::before { width: 46px; height: 46px; }

    /* ---------------- pick a vibe ---------------- */
    .pv-vibes { padding: 26px 0 4px; }
    .pv-vibes-inner { max-width: 1400px; margin: 0 auto; padding: 0 20px; }

    .pv-vibegrid {
        display: grid;
        grid-template-columns: repeat(6, minmax(0, 1fr));
        gap: 10px;
    }
    .pv-vibe {
        display: flex; align-items: center; gap: 11px; min-width: 0;
        padding: 11px 13px; border-radius: 14px; text-decoration: none;
        background: var(--surface);
        box-shadow: inset 0 0 0 1px var(--line);
        transition: transform .18s cubic-bezier(.2,.7,.3,1), box-shadow .18s ease, background .18s ease;
    }
    .pv-vibe:hover {
        transform: translateY(-3px);
        background: color-mix(in srgb, var(--vc) 14%, var(--surface));
        box-shadow: inset 0 0 0 1px var(--vc), 0 10px 24px var(--shadow), 0 0 20px -6px var(--vc);
    }

    /* White glyph on a coloured tile.
       The heroicon sources are stroke-only with stroke="currentColor"; as a CSS mask
       that yields no alpha (currentColor has no host context), so the icon vanished.
       Rendering them as <img> and forcing white via filter is the approach already
       used elsewhere in this codebase, and it always paints. */
    /* The tile is shaded as a physical object rather than a flat swatch:
       a top-lit gradient, a bright rim along the top edge and a dark inner
       bottom edge (the bevel), then a cast shadow in the category colour.
       All of it derives from --vc, so every category keeps its own identity. */
    .pv-vibe-ico {
        flex: none; width: 34px; height: 34px; border-radius: 11px;
        display: flex; align-items: center; justify-content: center;
        position: relative;
        background:
            linear-gradient(160deg,
                color-mix(in srgb, var(--vc) 78%, #fff) 0%,
                var(--vc) 44%,
                color-mix(in srgb, var(--vc) 52%, #000) 100%);
        box-shadow:
            inset 0 1.5px 0 0 color-mix(in srgb, var(--vc) 40%, #fff),   /* lit top rim */
            inset 0 -2px 3px -1px color-mix(in srgb, var(--vc) 30%, #000), /* bevel underside */
            0 4px 10px -3px color-mix(in srgb, var(--vc) 70%, #000),      /* contact shadow */
            0 8px 18px -8px var(--vc);                                    /* colour bloom */
        transform-style: preserve-3d;
        transition: transform .22s cubic-bezier(.2,.7,.3,1), box-shadow .22s ease;
    }
    /* Specular sheen across the upper face. Sits above the gradient, below the glyph. */
    .pv-vibe-ico::after {
        content: ''; position: absolute; inset: 0; border-radius: inherit;
        background: linear-gradient(160deg, rgba(255,255,255,.42) 0%, rgba(255,255,255,.10) 38%, transparent 62%);
        pointer-events: none;
    }
    .pv-vibe-ico img {
        width: 19px; height: 19px; display: block;
        position: relative; z-index: 1;
        filter: brightness(0) invert(1)                       /* force the glyph to pure white */
                drop-shadow(0 1px 0 rgba(0,0,0,.32));         /* lifts it off the face */
        transform: translateZ(6px);
    }
    /* Tilt toward the cursor's side of the row and push the glyph further out,
       so the tile reads as a solid object catching the light. */
    .pv-vibe:hover .pv-vibe-ico {
        transform: perspective(140px) rotateX(9deg) rotateY(-11deg) scale(1.06);
        box-shadow:
            inset 0 1.5px 0 0 color-mix(in srgb, var(--vc) 46%, #fff),
            inset 0 -2px 3px -1px color-mix(in srgb, var(--vc) 30%, #000),
            0 7px 14px -4px color-mix(in srgb, var(--vc) 70%, #000),
            0 12px 26px -8px var(--vc);
    }
    .pv-vibe:hover .pv-vibe-ico img { transform: translateZ(10px); }

    /* The shading is static and stays; only the tilt is motion, so only it is dropped. */
    @media (prefers-reduced-motion: reduce) {
        .pv-vibe-ico, .pv-vibe-ico img { transition: none; }
        .pv-vibe:hover .pv-vibe-ico { transform: none; }
        .pv-vibe:hover .pv-vibe-ico img { transform: none; }
    }

    /* Clears the sticky site header when a rail is scrolled into view. */
    .pv-sec[id] { scroll-margin-top: 104px; }

    /* Brief highlight so it is obvious where the page landed. */
    @keyframes pvLand {
        0%   { box-shadow: 0 0 0 0 rgba(124,92,255,.55); background: rgba(124,92,255,.10); }
        100% { box-shadow: 0 0 0 14px rgba(124,92,255,0); background: rgba(124,92,255,0); }
    }
    .pv-sec.pv-landed { animation: pvLand 1.1s ease-out; border-radius: 16px; }
    @media (prefers-reduced-motion: reduce) { .pv-sec.pv-landed { animation: none; } }

    .pv-vibe-txt { display: flex; flex-direction: column; min-width: 0; }
    .pv-vibe-name {
        font-size: 13.5px; font-weight: 700; color: var(--text);
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .pv-vibe-count { font-size: 11.5px; color: var(--muted); white-space: nowrap; }


    /* Ad slots. An unfilled placement renders a `hidden` wrapper, so :empty-ish slots
       collapse to nothing — the layout must not reserve space for an ad that never
       arrives (that is what leaves a dead gap on pages with no active campaign). */
    .pv-adslot {
        display: flex; justify-content: center;
        max-width: 1400px; margin: 0 auto; padding: 6px 20px 18px;
    }
    .pv-adslot:not(:has(.ad-wrapper:not(.hidden))) { padding: 0; }

    /* Mid-feed slot sits between rails: a little breathing room and a hairline above,
       so it reads as a break in the content rather than part of the previous rail. */
    .pv-adslot--infeed {
        padding: 22px 20px 26px;
        margin-bottom: 8px;
        border-top: 1px solid var(--line);
    }
    .pv-adslot--infeed:not(:has(.ad-wrapper:not(.hidden))) { border-top: 0; margin-bottom: 0; }

    /* ---------------- sections ---------------- */
    .pv-main { max-width: 1400px; margin: 0 auto; padding: 0 20px 56px; }
    .pv-sec { margin-bottom: 34px; }

    .pv-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 12px; }
    .pv-head-l { display: flex; align-items: center; gap: 10px; min-width: 0; }
    .pv-head-bar { width: 4px; height: 20px; border-radius: 999px; flex: none; }

    /* Category mark: same treatment as the browse-row chips, one size down. */
    .pv-head-ico {
        flex: none; width: 28px; height: 28px; border-radius: 9px;
        display: flex; align-items: center; justify-content: center;
        position: relative;
        background:
            linear-gradient(160deg,
                color-mix(in srgb, var(--vc) 78%, #fff) 0%,
                var(--vc) 44%,
                color-mix(in srgb, var(--vc) 52%, #000) 100%);
        box-shadow:
            inset 0 1.5px 0 0 color-mix(in srgb, var(--vc) 40%, #fff),
            inset 0 -2px 3px -1px color-mix(in srgb, var(--vc) 30%, #000),
            0 3px 8px -3px color-mix(in srgb, var(--vc) 70%, #000),
            0 7px 15px -8px var(--vc);
    }
    .pv-head-ico::after {
        content: ''; position: absolute; inset: 0; border-radius: inherit;
        background: linear-gradient(160deg, rgba(255,255,255,.42) 0%, rgba(255,255,255,.10) 38%, transparent 62%);
        pointer-events: none;
    }
    .pv-head-ico img {
        width: 16px; height: 16px; display: block;
        position: relative; z-index: 1;
        filter: brightness(0) invert(1) drop-shadow(0 1px 0 rgba(0,0,0,.32));
    }
    .pv-h2 {
        font-size: 19px; font-weight: 800; letter-spacing: -.015em; color: var(--text);
        margin: 0; white-space: nowrap;
    }
    .pv-head-sub {
        font-size: 13px; color: var(--muted); white-space: nowrap;
        overflow: hidden; text-overflow: ellipsis; padding-top: 2px;
    }
    .pv-viewall {
        display: inline-flex; align-items: center; gap: 3px; flex: none;
        font-size: 13px; font-weight: 700; color: var(--muted); text-decoration: none;
        padding: 6px 10px; border-radius: 999px; transition: color .18s, background .18s;
    }
    .pv-viewall svg { width: 13px; height: 13px; transition: transform .18s; }
    .pv-viewall:hover { color: var(--text); background: var(--chip); }
    .pv-viewall:hover svg { transform: translateX(2px); }

    /* ---------------- rails ---------------- */
    .pv-railwrap { position: relative; }
    .pv-rail {
        display: flex; gap: var(--gap);
        overflow-x: auto; overflow-y: hidden;
        scroll-snap-type: x mandatory; scroll-behavior: smooth;
        scrollbar-width: none; -ms-overflow-style: none;
        padding-bottom: 2px;
    }
    .pv-rail::-webkit-scrollbar { display: none; }
    .pv-rail > .pv-card {
        flex: 0 0 calc((100% - (var(--cols) - 1) * var(--gap)) / var(--cols));
        scroll-snap-align: start;
    }

    /* Placeholder for a rail whose cards are still being fetched. It mirrors a real
       card's box exactly — same flex sizing from the rule above, same 16/10 art — so
       swapping the real cards in changes nothing about the rail's height. */
    .pv-card--ghost { pointer-events: none; }
    .pv-ghost-art {
        display: block; aspect-ratio: 16 / 10;
        border-radius: var(--radius); background: var(--surface);
    }
    .pv-ghost-title {
        display: block; height: .95em; margin-top: 9px; width: 72%;
        border-radius: 6px; background: var(--surface);
    }

    /* ---------------- card ---------------- */
    /* .pv-card is the grid/flex child (a wrapper); .pv-card-link is the anchor inside it,
       so the preview button can sit alongside the link rather than nested within it. */
    .pv-card { display: block; min-width: 0; position: relative; }
    .pv-card-link {
        display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
        text-decoration: none; color: inherit;
    }

    .pv-preview {
        position: absolute; top: 7px; right: 7px; z-index: 4;
        width: 28px; height: 28px; border: 0; border-radius: 999px; cursor: pointer;
        display: flex; align-items: center; justify-content: center;
        background: rgba(8,9,15,.55); color: #fff;
        backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
        /* Always visible, matching the previous homepage — hiding it until hover would
           lose the feature for anyone who already relies on it. Held at partial opacity
           so 100+ tiles don't turn into a wall of badges, full strength on hover/focus. */
        opacity: .6; transform: scale(1);
        transition: opacity .18s ease, transform .18s ease, background .18s ease;
    }
    /* Icon is painted by a pseudo-element instead of an inline <svg><path>.
       At ~286 tiles per page the inline eye icon cost 3 DOM nodes each (858
       total); a ::before costs zero, because pseudo-elements are not DOM nodes.
       Stroke is hard-coded white — currentColor does not resolve inside a
       background-image data URI. */
    .pv-preview::before {
        content: ""; display: block; width: 15px; height: 15px;
        background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>') center / contain no-repeat;
    }
    .pv-card:hover .pv-preview,
    .pv-preview:focus-visible { opacity: 1; }
    .pv-preview:hover { background: rgba(8,9,15,.85); transform: scale(1.12); opacity: 1; }
    .pv-preview:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
    @media (hover: none) { .pv-preview { opacity: .85; } }
    .pv-card--lead .pv-preview,
    .pv-card--big .pv-preview { width: 34px; height: 34px; top: 10px; right: 10px; }
    .pv-card--lead .pv-preview::before,
    .pv-card--big .pv-preview::before { width: 18px; height: 18px; }
    .pv-card-art {
        position: relative; display: block; overflow: hidden;
        aspect-ratio: 16 / 10; border-radius: var(--radius);
        background: var(--surface);
        transition: transform .22s cubic-bezier(.2,.7,.3,1), box-shadow .22s ease;
    }
    .pv-card-art::after {
        content: ""; position: absolute; inset: 0; border-radius: var(--radius);
        box-shadow: inset 0 0 0 1px var(--line);
        pointer-events: none;
    }
    .pv-card:hover .pv-card-art {
        transform: translateY(-5px) scale(1.02);
        box-shadow: 0 14px 32px var(--shadow), 0 0 0 2px var(--brand), 0 0 26px -4px var(--brand);
    }
    .pv-play {
        position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
        background: rgba(8,9,15,.45); opacity: 0; transition: opacity .2s ease;
    }
    /* Same treatment as .pv-preview::before — saves 2 DOM nodes per tile. */
    .pv-play::before {
        content: ""; display: block; width: 34px; height: 34px;
        background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23fff"><path d="M8 5v14l11-7z"/></svg>') center / contain no-repeat;
        filter: drop-shadow(0 2px 8px rgba(0,0,0,.6));
    }
    .pv-card:hover .pv-play { opacity: 1; }

    /* --- Pratinjau bergerak pada kartu ---------------------------------------
       Dua tingkat, dipilih otomatis per kartu oleh home.js:

         1. Kartu ber-`data-pv-video` menumpuk <video> senyap di atas gambarnya.
         2. Kartu tanpa video - mayoritas katalog, karena GameDistribution hanya
            memberi satu gambar diam per game - memakai gerak lambat pada gambar
            yang sudah dimuat. Nol byte tambahan, tapi kartunya tidak terasa mati.

       Hanya SATU kartu aktif dalam satu waktu, supaya daftar tidak berkedip dan
       tidak ada dua video berjalan bersamaan.

       <video> sengaja disisipkan tepat sesudah gambar, bukan di akhir: lencana,
       judul mosaik, scrim dan tombol putar datang belakangan dalam DOM sehingga
       tetap tergambar di atas video tanpa perlu satu pun z-index. */
    .pv-video {
        position: absolute; inset: 0; width: 100%; height: 100%;
        object-fit: cover; display: block;
        opacity: 0; transition: opacity .35s ease;
        pointer-events: none; background: var(--surface);
    }
    .pv-card.is-previewing .pv-video { opacity: 1; }

    .pv-card.is-previewing .pv-img { animation: pvKen 7s ease-out both; }
    @keyframes pvKen {
        from { transform: scale(1); }
        to   { transform: scale(1.1) translate3d(0, -1.5%, 0); }
    }

    /* Scrim tombol putar dibuat untuk gambar diam; di atas video yang berjalan ia
       terlalu gelap. Ikonnya tetap, gelapnya dikurangi. */
    .pv-card.is-previewing .pv-play { opacity: 1; background: rgba(8,9,15,.18); }

    @media (prefers-reduced-motion: reduce) {
        .pv-card.is-previewing .pv-img { animation: none; }
        .pv-video { transition: none; }
    }

    .pv-card-title {
        display: block; margin-top: 7px; font-size: 12.5px; font-weight: 600;
        color: var(--title); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
        transition: color .18s;
    }
    .pv-card:hover .pv-card-title { color: var(--text); }

    .pv-badge {
        position: absolute; top: 7px; left: 7px; z-index: 2;
        font-size: 9.5px; font-weight: 900; letter-spacing: .07em;
        padding: 3px 7px; border-radius: 999px; color: #fff;
        box-shadow: 0 2px 8px rgba(0,0,0,.45);
    }
    .pv-badge--hot { background: linear-gradient(135deg,#ff4d6d,#ff8a3d); }
    .pv-badge--new { background: linear-gradient(135deg,#12c98f,#25e39a); }
    .pv-badge--top { background: linear-gradient(135deg,#ffb020,#ffd166); color: #2a1c00; }

    /* ---------------- arrows ---------------- */
    .pv-arrow {
        position: absolute; top: calc(50% - 22px); transform: translateY(-50%);
        z-index: 5; width: 38px; height: 38px; border-radius: 999px; border: 0;
        display: none; align-items: center; justify-content: center; cursor: pointer;
        background: var(--arrow-bg); color: var(--arrow-fg);
        box-shadow: 0 6px 20px var(--shadow), inset 0 0 0 1px var(--line);
        opacity: 0; transition: opacity .18s ease, transform .18s ease, background .18s;
    }
    .pv-arrow svg { width: 17px; height: 17px; }
    .pv-arrow--prev { left: -14px; }
    .pv-arrow--next { right: -14px; }
    .pv-railwrap:hover .pv-arrow { opacity: 1; }
    .pv-arrow:hover { background: var(--brand); transform: translateY(-50%) scale(1.09); }
    .pv-arrow[disabled] { opacity: 0 !important; pointer-events: none; }
    @media (min-width: 1024px) { .pv-arrow { display: flex; } }

    /* ---------------- mosaic (real 2x2 spans) ---------------- */
    .pv-mosaic {
        display: grid;
        grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
        grid-auto-rows: auto;
        /* dense: a 2x2 tile that cannot fit the remaining columns would otherwise
           leave a hole; dense backfills it with later tiles. */
        grid-auto-flow: row dense;
        gap: var(--gap);
    }
    /* Tiles stretch to their row: the 2x2 tile sets the row height, and without this
       the shorter 16:10 tiles leave dead space beneath them. */
    .pv-mosaic > .pv-card { display: flex; flex-direction: column; min-height: 0; }
    .pv-mosaic > .pv-card .pv-card-art { flex: 1 1 auto; aspect-ratio: auto; min-height: 0; }

    .pv-card--big { grid-column: span 2; grid-row: span 2; }
    .pv-card--big .pv-card-art { aspect-ratio: 1 / 1; height: 100%; border-radius: 18px; }
    .pv-mosaic-title {
        position: absolute; left: 16px; right: 16px; bottom: 14px; z-index: 2;
        font-size: 17px; font-weight: 800; color: #fff;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .pv-card--big .pv-play::before { width: 48px; height: 48px; }

    /* ---------------- discover: load more ---------------- */
    .pv-more { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 26px 0 6px; min-height: 56px; }
    .pv-morebtn {
        cursor: pointer; font-size: 14px; font-weight: 700; color: var(--title);
        background: var(--chip); border: 1px solid var(--line);
        padding: 11px 26px; border-radius: 999px;
        transition: background .18s, color .18s, transform .18s;
    }
    .pv-morebtn:hover { background: var(--brand); color: #fff; border-color: transparent; transform: translateY(-2px); }
    .pv-morebtn[hidden] { display: none; }
    .pv-more-end { display: flex; flex-direction: column; align-items: center; gap: 12px; }
    .pv-more-end[hidden] { display: none; }
    .pv-more-end p { font-size: 13px; color: var(--muted); margin: 0; }
    .pv-morebtn--cta {
        text-decoration: none;
        background: linear-gradient(135deg, var(--brand), var(--brand-2));
        color: #fff; border-color: transparent;
        box-shadow: 0 8px 24px -8px var(--brand);
    }

    .pv-more-spin { display: flex; gap: 6px; }
    .pv-more-spin[hidden] { display: none; }
    .pv-more-spin span {
        width: 8px; height: 8px; border-radius: 999px; background: var(--brand);
        animation: pvBounce 1s infinite ease-in-out;
    }
    .pv-more-spin span:nth-child(2) { animation-delay: .15s; }
    .pv-more-spin span:nth-child(3) { animation-delay: .3s; }
    @keyframes pvBounce { 0%,80%,100% { opacity:.3; transform: translateY(0); } 40% { opacity:1; transform: translateY(-6px); } }

    /* Newly appended tiles fade in rather than popping. */
    @keyframes pvFadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
    .pv-mosaic > .pv-card.pv-new { animation: pvFadeIn .32s ease-out both; }
    @media (prefers-reduced-motion: reduce) {
        .pv-mosaic > .pv-card.pv-new { animation: none; }
        .pv-more-spin span { animation: none; }
    }

    /* ---------------- responsive density ---------------- */
    @media (max-width: 1500px) { .pv-root { --cols: 6; } }
    @media (max-width: 1180px) { .pv-root { --cols: 5; } }
    @media (max-width: 1180px) {
        .pv-recgrid  { grid-template-columns: repeat(5, minmax(0,1fr)); }
        .pv-vibegrid { grid-template-columns: repeat(4, minmax(0,1fr)); }
    }
    @media (max-width: 900px)  {
        .pv-root { --cols: 4; }
        .pv-recgrid  { grid-template-columns: repeat(4, minmax(0,1fr)); }
        .pv-vibegrid { grid-template-columns: repeat(3, minmax(0,1fr)); }
    }
    @media (max-width: 700px)  {
        .pv-root { --cols: 3; --gap: 10px; }
        .pv-recgrid { grid-template-columns: repeat(2, minmax(0,1fr)); grid-auto-rows: auto; }
        .pv-vibegrid { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 8px; }
        .pv-vibe { padding: 9px 10px; gap: 9px; }
        /* At 30px the full bevel turns muddy, so the inner edges are softened and
           the cast shadow tightened. Hover tilt is irrelevant on touch anyway. */
        .pv-vibe-ico {
            width: 30px; height: 30px; border-radius: 10px;
            box-shadow:
                inset 0 1px 0 0 color-mix(in srgb, var(--vc) 38%, #fff),
                0 3px 8px -3px color-mix(in srgb, var(--vc) 70%, #000);
        }
        .pv-vibe-ico::after {
            background: linear-gradient(160deg, rgba(255,255,255,.34) 0%, rgba(255,255,255,.08) 40%, transparent 64%);
        }
        .pv-card--lead { grid-column: span 2; grid-row: span 1; }
        .pv-card--lead .pv-card-art { aspect-ratio: 16/9; height: auto; }
        .pv-rechead { align-items: center; }
        .pv-hero-inner { grid-template-columns: 1fr; }
        .pv-hero-side { grid-template-rows: none; grid-template-columns: 1fr 1fr; }
        .pv-hero-mini { aspect-ratio: 16 / 9; }
        .pv-hero-main { aspect-ratio: 16 / 9; }
        .pv-hero-copy { max-width: 100%; padding: 18px; }
    }
    @media (max-width: 480px) {
        .pv-root { --cols: 2.3; }          /* peek: hints the rail scrolls */
        .pv-mosaic { grid-template-columns: repeat(2, minmax(0,1fr)); }
        .pv-card--big { grid-column: span 2; grid-row: span 1; }
        .pv-card--big .pv-card-art { aspect-ratio: 16/9; }
        .pv-h2 { font-size: 17px; }
        .pv-head-sub { display: none; }
    }

    @media (prefers-reduced-motion: reduce) {
        .pv-root *, .pv-rail { transition: none !important; scroll-behavior: auto !important; }
    }
