/* style.css
 * ------------------------------------------------------------------
 * Dipindah dari <style> inline di user/components/head.php supaya jadi
 * aset statis sungguhan yang bisa di-cache browser (lihat header Cache-
 * Control/Expires untuk *.css di assets/.htaccess). Isinya TIDAK diubah,
 * cuma dipindah lokasinya.
 * ------------------------------------------------------------------ */

html {
    overflow-x: hidden;
    max-width: 100%;
}
body {
    font-family: 'Inter', sans-serif;
    transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
    max-width: 100%;
}
.font-title {
    font-family: 'Plus Jakarta Sans', sans-serif;
}
/* ==========================================================
   SKELETON SHIMMER & STAGGER FADE-UP KARTU (roadmap.md Fase 3, Agustus 2026)
   ----------------------------------------------------------
   .skel-shimmer: dipakai skeletonCardHTML() di helpers.js -- placeholder
   kotak yang tampil SELAMA grid/kartu belum siap (bukan grid kosong tanpa
   indikator apa pun). .card-stagger-in: dipakai staggerRevealCards() di
   helpers.js -- begitu kartu asli siap, tampil fade-up bertahap per kartu
   (delay dihitung dari --stagger-index yang di-set inline per elemen),
   bukan muncul mendadak sekaligus.
   ========================================================== */
:root {
    --skel-a: #e7e9f1;
    --skel-b: #f4f5f9;
}
body.dark {
    --skel-a: #10182b;
    --skel-b: #17233f;
}
.skel-shimmer {
    background: linear-gradient(100deg, var(--skel-a) 30%, var(--skel-b) 50%, var(--skel-a) 70%);
    background-size: 220% 100%;
    animation: skeletonShimmer 1s ease-in-out infinite;
}
@keyframes skeletonShimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -20% 0; }
}
.card-stagger-in {
    opacity: 0;
    transform: translateY(8px);
    animation: cardStaggerIn 0.28s ease-out forwards;
    animation-delay: calc(var(--stagger-index, 0) * 25ms);
}
@keyframes cardStaggerIn {
    to { opacity: 1; transform: translateY(0); }
}
/* Orang yang mengaktifkan "reduce motion" di OS-nya tidak perlu lihat
   animasi ini -- kartu langsung tampil penuh tanpa delay/gerakan. */
@media (prefers-reduced-motion: reduce) {
    .card-stagger-in {
        animation: none;
        opacity: 1;
        transform: none;
    }
    .skel-shimmer {
        animation: none;
    }
}

/* Scrollbar kustom premium */

::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
::-webkit-scrollbar-track {
    background: #0a0f1d;
}
body:not(.dark) ::-webkit-scrollbar-track {
    background: #f1f5f9;
}
::-webkit-scrollbar-thumb {
    background: #1e293b;
    border-radius: 4px;
}
body:not(.dark) ::-webkit-scrollbar-thumb {
    background: #cbd5e1;
}
::-webkit-scrollbar-thumb:hover {
    background: #334155;
}
body:not(.dark) ::-webkit-scrollbar-thumb:hover {
    background: #94a3b8;
}

/* Slim Scrollbar untuk filter box agar rapi */
.scrollbar-slim::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}
.scrollbar-slim::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.02);
    border-radius: 10px;
}
body:not(.dark) .scrollbar-slim::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.03);
}
.scrollbar-slim::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 10px;
}
body:not(.dark) .scrollbar-slim::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.1);
}
.scrollbar-slim::-webkit-scrollbar-thumb:hover {
    background: #ff2a5f;
}

/* ============================================================
   BOTTOM NAVBAR MOBILE — "BUBBLE TAB"
   ------------------------------------------------------------
   Tiap tombol (#mobileBottomNav .mobile-navitem) punya ikon di
   dalam .mobile-navitem-bubble + label di bawahnya. Saat tombol
   itu berstatus aktif (class .is-active, diberikan lewat JS oleh
   setMobileNavActive() di user/components/scripts.php), bubble
   ikonnya membesar & "melompat" ke atas bar dengan cincin (ring)
   yang warnanya menyamai background halaman -- menciptakan efek
   ikon mengambang lepas dari bar, seolah "dipotong" dari baris.
   Warna ring beda untuk mode terang vs gelap (lihat variabel
   --mobile-nav-ring di bawah).
   ============================================================ */
#mobileBottomNav {
    --mobile-nav-ring: #f8fafc; /* menyamai bg-slate-50 (mode terang) */
}
.dark #mobileBottomNav {
    --mobile-nav-ring: #060913; /* menyamai brandDark (mode gelap) -- sama dgn body */
}

#mobileBottomNav .mobile-navitem {
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    position: relative;
    z-index: 1;
}

/* Slot ikon berukuran TETAP (tidak pernah berubah baik aktif maupun tidak).
   Bubble di dalamnya di-posisikan `absolute`, jadi saat dia membesar/naik
   ke atas bar, itu murni visual saja -- tidak menambah tinggi apa pun di
   alur layout, sehingga label di bawahnya (Home/Search/Menu/dst) TIDAK
   pernah ikut turun/naik dan selalu sejajar dengan label tombol lain. */
#mobileBottomNav .mobile-navitem-iconslot {
    position: relative;
    width: 2.15rem;
    height: 2.15rem;
}

#mobileBottomNav .mobile-navitem-bubble {
    position: absolute;
    top: 50%;
    left: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.15rem;
    height: 2.15rem;
    border-radius: 9999px;
    color: inherit;
    border: 0 solid transparent;
    background-color: transparent;
    transform: translate(-50%, -50%);
    transition: width .3s cubic-bezier(.34, 1.56, .64, 1),
                height .3s cubic-bezier(.34, 1.56, .64, 1),
                transform .3s cubic-bezier(.34, 1.56, .64, 1),
                background-color .2s ease,
                border-color .2s ease,
                border-width .2s ease,
                box-shadow .2s ease,
                color .2s ease;
}

#mobileBottomNav .mobile-navitem-label {
    transition: color .15s ease;
}

/* Tombol aktif: bubble membesar & naik cukup tinggi supaya SETENGAH badannya
   menembus keluar dari tepi atas pill (persis pola "ikon mengambang lepas
   dari bar" pada desain referensi), dengan cincin selebar warna background
   halaman + bayangan lembut. Karena bubble ini `position:absolute` di dalam
   slot berukuran tetap, perubahan lebar/tinggi/posisinya di sini TIDAK
   pernah menggeser label di bawahnya. */
#mobileBottomNav .mobile-navitem.is-active {
    z-index: 2;
}
#mobileBottomNav .mobile-navitem.is-active .mobile-navitem-bubble {
    width: 3.5rem;
    height: 3.5rem;
    transform: translate(-50%, -50%) translateY(-1.75rem);
    background-color: #060913;
    color: #ffffff;
    border: 4px solid var(--mobile-nav-ring);
    box-shadow: 0 10px 20px rgba(0, 0, 0, .3), 0 2px 6px rgba(0, 0, 0, .15);
}

/* Override khusus DARK MODE saja untuk tombol navbar mobile yang aktif.
   Versi LIGHT MODE (rule di atas) tidak diubah sama sekali. */
body.dark #mobileBottomNav .mobile-navitem.is-active .mobile-navitem-bubble {
    border: 4px solid #0e1629;
    box-shadow: 0 10px 20px rgba(0, 0, 0, .5), 0 2px 6px rgba(0, 0, 0, .15);
}

/* ==========================================================================
   Download Batch (Satu Paket) -- tombol host per resolusi
   Sedikit efek "lift" saat hover, senada dengan desain referensi baru,
   tanpa mengubah warna dasar tombol (tetap mengikuti token light/dark site).
   ========================================================================== */
.host-download-btn {
    transition: transform .2s cubic-bezier(0.4, 0, 0.2, 1),
                background-color .2s ease,
                border-color .2s ease,
                box-shadow .2s ease,
                color .2s ease;
}

.host-download-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 18px -6px rgba(255, 42, 95, 0.18);
}

body.dark .host-download-btn:hover {
    box-shadow: 0 8px 20px -4px rgba(245, 158, 11, 0.15);
}

/* ==========================================================================
   FITUR "AVATAR FRAME" (Agustus 2026)
   --------------------------------------------------------------------------
   Dipakai bareng oleh avatarFrameOverlayHTML() di assets/helpers.js --
   dipasang di SEMUA tempat avatar ditampilkan (navbar profil, komentar,
   dst) supaya perilakunya konsisten:
     - .avatar-frame-slot   wrapper terluar, ukurannya = ukuran avatar asli
       (supaya tidak mengganggu layout flex/grid di sekitarnya), tapi
       overflow visible supaya bingkai yang lebih besar tidak terpotong.
     - .avatar-frame-photo  lingkaran avatar asli (inisial/foto), tetap
       persis di tengah slot.
     - .avatar-frame-overlay gambar bingkai (.webp beralpha), diposisikan
       absolute & di-center lewat transform, LEBIH BESAR dari avatar-nya
       sendiri, dan pointer-events:none supaya tidak menghalangi klik ke
       tombol avatar/dropdown di baliknya.
   ========================================================================== */
.avatar-frame-slot {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: visible;
    flex-shrink: 0;
}

.avatar-frame-photo {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    overflow: hidden;
}

.avatar-frame-overlay {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    /* Jaga-jaga kalau ada gambar bingkai (upload admin nanti) yang ternyata
       tidak persegi -- object-fit:contain mencegahnya "digepengkan" paksa
       ke kotak persegi, beda dengan bug lonjong yang pernah terjadi karena
       file sumbernya sendiri yang di-resize tanpa jaga rasio. */
    object-fit: contain;
    pointer-events: none;
    user-select: none;
    z-index: 2;
}

/* Efek "mengkilap" (glossy shine) di atas bingkai avatar. Elemen terpisah
   (bukan ditempel ke <img> bingkainya) yang di-mask pakai GAMBAR BINGKAI ITU
   SENDIRI (mask-image = url yang sama dengan avatar-frame-overlay, diisi
   lewat inline style oleh JS) -- jadi sapuan cahayanya otomatis mengikuti
   bentuk asli bingkai (cincin/sayap/permata dsb) dan TIDAK menutupi foto
   avatar di tengah yang transparan, berlaku untuk bingkai apapun tanpa
   perlu pengaturan khusus per-bingkai. */
.avatar-frame-shine {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    user-select: none;
    z-index: 3;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: 100% 100%;
    mask-size: 100% 100%;
    -webkit-mask-position: center;
    mask-position: center;
    background-image: linear-gradient(115deg,
        transparent 30%,
        rgba(255, 255, 255, 0.85) 47%,
        rgba(255, 255, 255, 0.95) 50%,
        rgba(255, 255, 255, 0.85) 53%,
        transparent 70%);
    background-size: 300% 300%;
    background-position: -220% -220%;
    background-repeat: no-repeat;
    mix-blend-mode: overlay;
    animation: avatarFrameShineSweep 3.4s ease-in-out infinite;
}

/* Beberapa avatar sekaligus di layar (mis. daftar komentar) sengaja diberi
   jeda animasi acak lewat --avatar-frame-shine-delay (diisi JS per elemen)
   supaya kilaunya tidak "berkedip" bersamaan dan terlihat lebih natural. */
.avatar-frame-shine {
    animation-delay: var(--avatar-frame-shine-delay, 0s);
}

@keyframes avatarFrameShineSweep {
    0%, 12% { background-position: -220% -220%; }
    55%, 100% { background-position: 220% 220%; }
}

@media (prefers-reduced-motion: reduce) {
    .avatar-frame-shine { animation: none; background-position: 0% 0%; opacity: 0; }
}

/* ==========================================================================
   TEMPLATE "USERNAME BANNER" (Fase 7 Item Shop, Agustus 2026 - kerangka saja)
   --------------------------------------------------------------------------
   Standar aset: video .mp4 (H.264, TANPA audio), 448x84px, durasi pendek
   (contoh dari FT: 3 detik) -- diputar loop terus-menerus sbg latar,
   username ditulis DI ATASNYA. Dipakai bareng oleh usernameBannerHTML() di
   assets/helpers.js. BELUM disambungkan ke data shop_items/user_active_cosmetics
   (tabel itu bagian checklist Fase 7 yang belum dibuat) -- ini baru
   komponen render-nya, siap dipasang begitu data pembelian item sudah ada.
     - .username-banner        wrapper, rasio TETAP 448:84 (~5.33:1) lewat
       aspect-ratio, lebar mengikuti container (responsive).
     - .username-banner video  mengisi penuh wrapper, object-fit:cover
       (lihat catatan "safe zone" di usernameBannerHTML()).
     - .username-banner-label  teks username, di-overlay dengan text-shadow
       ganda supaya tetap terbaca di atas video apapun (terang/gelap).
   ========================================================================== */
.username-banner {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 100%;
    max-width: 224px;
    aspect-ratio: 448 / 84;
    border-radius: 10px;
    overflow: hidden;
    background: #0a0f1d; /* fallback kalau video gagal load */
}

.username-banner video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
}

.username-banner-label {
    position: relative;
    z-index: 2;
    padding: 0 10px;
    font-weight: 800;
    font-size: 0.75rem;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.9), 0 0 6px rgba(0,0,0,0.6);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ==========================================================================
   TAB SORTIR KOMENTAR (Fase 8, Agustus 2026)
   -------------------------------------------------------------------------
   .comment-sort-tab       state tidak aktif (default).
   .comment-sort-tab.active state lagi dipilih -- class "active" ditoggle
   oleh switchCommentSort() di user/components/comment-box.php.
   ========================================================================== */
.comment-sort-tab {
    color: #64748b;
    background: transparent;
}
.comment-sort-tab:hover {
    background: rgba(100, 116, 139, 0.1);
}
.comment-sort-tab.active {
    background: #ff2a5f;
    color: #fff;
}
html.dark .comment-sort-tab {
    color: #94a3b8;
}
html.dark .comment-sort-tab:hover {
    background: rgba(255, 255, 255, 0.06);
}
html.dark .comment-sort-tab.active {
    background: #ff2a5f;
    color: #fff;
}

/* Petisi (Fase 9) -- tab sortir Terpopuler/Terbaru/Terlama, gaya SAMA
   PERSIS dgn .comment-sort-tab (Fase 8) supaya konsisten, cuma nama class
   beda krn dipakai di halaman terpisah (petitions.php vs comment-box.php). */
.petition-sort-tab {
    color: #64748b;
    background: transparent;
}
.petition-sort-tab:hover {
    background: rgba(100, 116, 139, 0.1);
}
.petition-sort-tab.active {
    background: #ff2a5f;
    color: #fff;
}
html.dark .petition-sort-tab {
    color: #94a3b8;
}
html.dark .petition-sort-tab:hover {
    background: rgba(255, 255, 255, 0.06);
}
html.dark .petition-sort-tab.active {
    background: #ff2a5f;
    color: #fff;
}

/* ==========================================================================
   SLOT IKLAN (Backlog, Agustus 2026)
   -------------------------------------------------------------------------
   Sengaja sesederhana mungkin -- 1 link+gambar per slot, di-stack vertikal
   kalau lebih dari 1 slot aktif di zona yang sama (lihat
   render_ad_slot_zone() di includes/AdSlots.php). Gambar TIDAK dipaksa
   rasio tertentu (ukuran beda-beda tiap zona, admin atur sendiri lewat
   ukuran file yang diunggah) -- cuma dibatasi lebar penuh + tinggi maks
   supaya tidak mendominasi halaman kalau adminnya upload gambar raksasa.
   ========================================================================== */
.ad-slot-banner {
    display: block;
    width: 100%;
    max-width: 1280px;
    margin: 12px auto;
    border-radius: 12px;
    overflow: hidden;
    text-align: center;
}
.ad-slot-banner img {
    display: inline-block;
    max-width: 100%;
    max-height: 200px;
    width: auto;
    height: auto;
    border-radius: 12px;
}
