/* ==========================================================
   watchwatch.store — stylesheet bersama untuk semua halaman
   Fondasi awal diambil dari prototipe statis, DIPERBARUI 2026-07-13 mengikuti
   referensi Figma "CONTOH BERANDA FIGMA.zip" -- palet biru marketplace (#0066CC)
   menggantikan navy gelap, font Inter menggantikan Nunito.

   REBRAND MERAH PUTIH (2026-08-13, PERMANEN -- bukan kampanye musiman, permintaan
   eksplisit pemilik "permanen ganti seterusnya", referensi "Ecommerce Design Merah
   Putih" Figma) -- palet biru diganti merah-putih ala Shopee/Blibli. Pola PERSIS
   sama seperti rebrand 2026-07-13 sebelumnya: --navy/--navy-dark/--accent
   DIPERTAHANKAN NAMANYA (bukan di-rename ke --merah dkk) supaya ratusan pemakaian
   var(--navy) di seluruh file CSS/inline style TIDAK perlu diubah satu-per-satu --
   cuma NILAI hex-nya yang berubah di SATU tempat ini, otomatis konsisten ke SEMUA
   halaman pelanggan begitu file ini di-load (topbar, tombol, badge, link, dst).
   Hanya berlaku untuk halaman pelanggan (file ini) -- assets/css/dashboard.css
   (admin/mitra, dashboard internal) SENGAJA TIDAK ikut diubah, sama seperti
   keputusan di rebrand 2026-07-13 sebelumnya ("di luar cakupan").

   REVISI (2026-08-13, hari yang sama) -- percobaan pertama menjadikan merah warna
   DASAR hampir semua komponen sekaligus (topbar+hero+badge+kartu semua merah
   jenuh tanpa jeda putih) dilaporkan pemilik "terlalu ngejreng, warna section lain
   ga sepadan". Konsep ulang dikonfirmasi lewat artifact pitch (lihat memori
   project) sebelum coding: MERAH JADI AKSEN, BUKAN CAT TEMBOK -- prinsip yang
   sama dipakai Shopee/Tokopedia/Blibli (warna brand cuma nutup sebagian kecil
   layar: tombol utama, harga, satu banner kampanye; sisanya netral). --bg diganti
   krem hangat (bukan putih dingin/abu kebiruan lama), --navy diredupkan jadi
   "merah anggur" (bukan merah-api), --accent jadi emas kuningan redup (bukan
   kuning terang). Komponen yang KEMARIN ikut memerah padahal seharusnya netral
   (kartu Koin Saya/Multi Game, topbar penuh) diperbaiki terpisah di
   beranda.php/style.css komponen masing-masing -- lihat memori project untuk
   daftar lengkap "ke mana merah boleh pergi". */

:root{
  --navy:#A32638;
  --navy-dark:#6B1420;
  --accent:#9C7A26;
  /* --navy-tint (2026-08-13, ditambah bareng rebrand Merah Putih) -- versi latar
     pudar dari --navy, dipakai badge/ikon "bertema navy" (.badge-verif,
     .verif-toggle.active, avatar toko, dst). SEBELUMNYA beberapa tempat ini
     hardcode hex biru literal (#e6f1fb dkk, lihat catatan bug dark-mode di atas)
     -- diseragamkan jadi 1 variable di sini sekalian supaya rebrand warna
     berikutnya (atau toggle dark-mode yang sudah lama jadi sumber bug serupa)
     otomatis ikut konsisten, tidak nyangkut biru lagi kalau navy berubah lagi.
     Dipakai SANGAT JARANG dgn sengaja (lihat revisi 2026-08-13) -- bukan lagi
     warna latar bebas pakai untuk "apa saja yang berbau navy". */
  --navy-tint:#F6E9E7;
  --bg:#ffffff;
  --card:#ffffff;
  --text:#241A16;
  --muted:#8A7F72;
  --border:#E8DFD3;
  --green:#2E7D46;
  --red:#C0392B;
  --amber:#B8860B;
  /* --amber-tint (2026-08-13, dipasang bareng restyle .promo-band Flash Sale/Tukar
     Koin) -- padanan --navy-tint di atas tapi untuk keluarga warna amber/emas,
     supaya section itu bisa punya latar pudar bertema tanpa hardcode hex baru. */
  --amber-tint:#FBF1DC;
  /* --lebar-phone (2026-08-07) -- lebar .phone SAAT INI, dideklarasikan ulang di
     SETIAP breakpoint yang mengubah .phone{max-width} (lihat @media di bawah).
     Dipakai .forum-fab/.cs-fab supaya posisinya OTOMATIS ikut lebar .phone di
     breakpoint MANAPUN tanpa perlu formula calc() terpisah per breakpoint --
     akar masalah yang ditemukan lewat laporan pemilik "hp dimiringin dan tablet
     dan ipad masih ga responsif ... masih tidak melebar": breakpoint tablet yang
     ditambahkan sebelumnya SENGAJA dikecualikan dari HP miring (syarat
     min-height:600px) semata-mata supaya formula calc(50vw-240px) FAB versi lama
     tidak salah hitung -- akibatnya HP miring tetap dikunci 480px selamanya,
     padahal layarnya sungguhan lebih lebar. Dengan variable ini, HP miring boleh
     ikut melebar sama seperti tablet (lihat @media 600-899px di bawah, syarat
     tinggi sudah dihapus) TANPA merusak posisi FAB, karena FAB tidak lagi perlu
     tahu breakpoint mana yang aktif -- cukup baca lebar .phone yang berlaku. */
  --lebar-phone:480px;
}

/* Tema gelap (2026-07-28, permintaan pemilik: "buat dan tambahkan tema gelap yang
   bisa di ubah di menu akun") -- diaktifkan lewat atribut data-theme="dark" di
   elemen <html>, diset oleh assets/js/theme.js (baca localStorage, dipasang paling
   awal di <head> supaya tidak sempat "kedip" tema terang sebelum berganti).
   Sebagian besar komponen situs SUDAH memakai var(--card)/var(--text)/var(--muted)/
   var(--border) (bukan warna hex langsung) sejak awal, jadi otomatis ikut berubah
   cuma dengan override variabel ini -- termasuk puluhan `background:#fff` yang
   sebelumnya hex literal, sudah dikonversi ke var(--card) di seluruh file supaya
   ikut tema (lihat riwayat 2026-07-28). Elemen yang SENGAJA dibiarkan putih literal
   (kolom pencarian topbar, tombol Google, tombol CTA di atas banner warna, titik
   kecil dekoratif, kenop toggle switch) TIDAK diubah -- itu memang harus putih di
   kedua tema, bukan terlewat. */
/* Tema gelap (2026-08-13, REVISI TOTAL bareng rebrand Merah Putih) -- permintaan
   eksplisit pemilik: "pastikan darkmode itu ga cuma sebagian yang gelap saya mau
   darkmode itu hitam putih yang elegan". Versi SEBELUMNYA (biru gelap #0d1220,
   lalu sempat jadi coklat-hitam hangat) diganti abu-abu netral SUNGGUHAN --
   --bg/--card/--border/--muted TIDAK ikut nada hangat krem seperti tema terang,
   murni skala hitam-putih (grayscale), supaya kesan "hitam putih" nyata bukan
   sekadar gelap. Merah tetap ada sebagai SATU-SATUNYA aksen warna (tombol/harga/
   status aktif) -- diredupkan lagi dari versi terang supaya tidak menyala di
   atas hitam, tapi TIDAK dihilangkan (identitas brand tetap kelihatan). */
[data-theme="dark"]{
  --bg:#0E0E0E;
  --card:#1A1A1A;
  --text:#F2F0ED;
  --muted:#9A9A9A;
  --border:#2A2A2A;
  --navy:#C2485A;
  --navy-dark:#7A2030;
  --accent:#C9A227;
  --navy-tint:rgba(194, 72, 90, 0.16);
  --green:#4CAF6D;
  --red:#E57373;
  --amber:#E0B04A;
  --amber-tint:rgba(224, 176, 74, 0.16);
}
/* Bayangan kartu di tema terang (rgba(0,0,0,...) tipis) nyaris tidak kelihatan di
   atas kartu yang sudah gelap -- garis tepi tipis dipakai sebagai pengganti supaya
   batas antar kartu tetap jelas tanpa perlu menulis ulang setiap box-shadow satu
   per satu di seluruh file. */
[data-theme="dark"] .card,
[data-theme="dark"] .product-card,
[data-theme="dark"] .auction-card,
[data-theme="dark"] .lelang-card,
[data-theme="dark"] .po-row,
[data-theme="dark"] .flash-card,
[data-theme="dark"] .koin-promo-card,
[data-theme="dark"] .promo-member-card,
[data-theme="dark"] .promo-section,
[data-theme="dark"] .section-card,
[data-theme="dark"] .trust-row,
[data-theme="dark"] .cat-row,
[data-theme="dark"] .spec-table,
[data-theme="dark"] .desc-box,
[data-theme="dark"] .seller-box,
[data-theme="dark"] .social-box,
[data-theme="dark"] .review-card,
[data-theme="dark"] .video-card,
[data-theme="dark"] .seller-group,
[data-theme="dark"] .pd-info-card{
  border:1px solid var(--border);
}
/* Bug ditemukan 2026-07-29 -- .icon-circle (tombol bulat kembali/wishlist/share
   melayang di atas foto produk) terlewat saat migrasi tema gelap 2026-07-28 karena
   background-nya hex literal #f0f0f0 (bukan #fff yang sudah dikonversi ke
   var(--card)) -- akibatnya di tema gelap warna ikon (var(--text), jadi terang)
   nyaris tidak kelihatan di atas lingkaran abu-abu terang yang sama sekali tidak
   ikut menggelap, ikon jadi nyaris tak terlihat (terang di atas terang). */
[data-theme="dark"] .icon-circle{
  background:var(--card);
}
/* Bug ditemukan 2026-07-30 -- .badge-verif, .seller-box .avatar, .pesanan-ic, dan
   .promo-member-strip (lencana/ikon/strip "bertema navy") sama-sama terlewat
   migrasi tema gelap: background-nya hex literal biru muda (#e6f1fb dkk, bukan
   var()), jadi tetap biru muda terang di tema gelap walau color-nya sendiri
   (var(--navy)) sudah benar ikut berubah -- elemen-elemen ini jadi terlihat
   "masih tema terang" mengambang di atas kartu gelap. DIPERBAIKI DI AKARNYA
   2026-08-13 (bareng rebrand Merah Putih) -- keempatnya sekarang pakai
   var(--navy-tint) di base rule (lihat masing-masing di bawah), yang SUDAH
   didefinisikan beda nilai untuk tema terang/gelap di :root/[data-theme="dark"]
   di atas -- override manual per-elemen di sini jadi tidak perlu lagi sama
   sekali, otomatis ikut kalau --navy berubah lagi suatu saat.

   .trust-chip.* SENGAJA TIDAK ikut pola ini -- warnanya (biru=terverifikasi,
   hijau=positif, oranye=info) adalah sistem semantik sendiri yang independen
   dari warna brand navy, bukan sekadar "tint dari navy" seperti elemen di atas. */
[data-theme="dark"] .trust-chip.blue{ background:rgba(59, 130, 246, 0.15); color:#60a5fa; }
[data-theme="dark"] .trust-chip.green{ background:rgba(34, 197, 94, 0.15); color:var(--green); }
[data-theme="dark"] .trust-chip.orange{ background:rgba(251, 191, 36, 0.15); color:var(--amber); }
/* .footer-box: latar abu-abu pucat (bukan warna aksen seperti di atas), jadi
   diganti var(--card) polos sama seperti .icon-circle -- teks di dalamnya
   (.footer-nama dkk) SUDAH var(--text)/var(--muted)/var(--navy), otomatis pas. */
[data-theme="dark"] .footer-box{ background:var(--card); }
[data-theme="dark"] img{ opacity:.92; } /* foto produk sedikit diredupkan -- putih polos di latar produk placeholder jadi tidak menyilaukan di tema gelap */

*{ box-sizing:border-box; margin:0; padding:0; }

/* overflow-x:hidden (jaring pengaman lama terhadap overflow horizontal dari
   trik full-bleed .banner-slider dkk) TERNYATA membuat SELURUH .topbar/
   position:sticky di situs ini tidak pernah benar-benar menempel saat scroll
   (bug ditemukan 2026-08-13 saat uji header baru beranda.php) -- akar masalah:
   spesifikasi CSS memaksa overflow-y yang "visible" jadi computed 'auto' kalau
   overflow-x TIDAK 'visible' (di sini 'hidden'), dan overflow-y:auto pada
   html/body itulah yang mematahkan position:sticky pada elemen turunan mana
   pun (termasuk .topbar yang sudah pakai position:sticky sejak awal, tidak
   pernah benar-benar sticky selama ini). overflow-x:clip (bukan hidden) tetap
   mencegah overflow horizontal SAMA PERSIS, TAPI dikecualikan dari aturan
   auto-konversi itu (tujuan clip memang dibuat utk kasus ini), jadi
   overflow-y tetap murni 'visible' dan position:sticky di seluruh situs
   akhirnya benar-benar berfungsi. */
html, body{
  overflow-x:clip;
  width:100%;
}

body{
  font-family:'Inter', sans-serif;
  background:var(--bg);
  color:var(--text);
  display:flex;
  justify-content:center;
}

a{ text-decoration:none; color:inherit; }

.phone{
  width:100%;
  max-width:480px; /* dinaikkan dari 430px (2026-07-15) -- di HP dengan viewport
    lebih lebar dari 430px (mis. Pro Max terbaru), 430px sisakan strip putih tipis
    di kiri-kanan. 480px aman untuk seluruh rentang lebar HP yang ada tanpa
    menabrak breakpoint desktop di 900px. */
  min-height:100vh;
  background:var(--bg);
  padding-bottom:76px; /* bottomnav rata menempel bawah (2026-07-14) -- lebih rendah dari versi pil mengambang sebelumnya */
  position:relative;
}

/* ---------- top bar ---------- */
/* Topbar putih + aksen merah (2026-08-13, REVISI setelah pemilik menilai versi
   solid-merah pertama "terlalu ngejreng") -- dulu gradient var(--navy) penuh
   satu layar, sekarang var(--card) polos + garis tipis bawah, merah cuma tersisa
   di logo mark/tombol/link aktif. Prinsip "merah aksen bukan cat tembok" --
   lihat memori project untuk konsep lengkapnya (artifact pitch yang sudah
   dikonfirmasi pemilik sebelum ini dikerjakan). */
.topbar{
  background:var(--card);
  color:var(--text);
  border-bottom:1px solid var(--border);
  display:flex;
  align-items:center;
  gap:12px;
  padding:14px 16px;
  position:sticky;
  top:0;
  z-index:20;
}
/* Versi 3-baris (search + strip lokasi) dipakai includes/topbar.php -- kelas TAMBAHAN
   di atas .topbar dasar (bukan pengganti), supaya halaman yang masih pakai .topbar
   versi sederhana (akun.php dkk: judul+tombol kembali) tidak ikut berubah jadi kolom.
   Lihat catatan lengkap di includes/topbar.php. */
.topbar.topbar-full{ flex-direction:column; align-items:stretch; gap:0; padding:10px 0 0; }
.topbar-row1{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:0 16px 8px; }
.topbar-full .search-wrap{ margin:0 16px 12px; }
.location-strip{
  display:flex; align-items:center; gap:6px; padding:8px 16px;
  background:var(--navy-tint);
}
.location-strip span{ color:var(--muted); font-size:11px; }
.location-strip b{ color:var(--navy); font-weight:700; }
.icon-btn{
  width:22px; height:22px; flex-shrink:0; cursor:pointer;
}
.topbar .icon-btn{ color:var(--text); }
.topbar h1{ font-size:17px; font-weight:700; flex:1; }
.topbar .logo{ height:22px; }
.wordmark{ font-size:15px; font-weight:800; letter-spacing:-.2px; white-space:nowrap; }
.wordmark .w1{ color:var(--text); }
.wordmark .w2{ color:var(--navy); }
.wordmark .dom{ color:var(--muted); font-size:10px; font-weight:600; display:block; }
.topbar .search-wrap{
  flex:1;
  min-width:0;
  background:var(--bg);
  border-radius:24px;
  display:flex;
  align-items:center;
  gap:0;
  padding:4px 4px 4px 14px;
  position:relative; /* jangkar untuk .search-saran (2026-07-27) */
}
.topbar .search-wrap input{
  border:none; outline:none; font-size:13px; font-family:'Inter',sans-serif;
  flex:1; min-width:0; width:100%; color:var(--text); background:transparent;
}
.topbar .search-wrap svg{ color:var(--muted); flex-shrink:0; }
/* Tombol cari bulat terintegrasi (2026-07-27, referensi Blibli -- sebelumnya cuma
   ikon kaca pembesar polos di kiri, sekarang tombol submit sungguhan bulat penuh
   warna aksen di ujung kanan pill, konsisten dengan pola marketplace besar). */
.search-submit{
  flex-shrink:0; width:34px; height:34px; border-radius:50%; border:none;
  background:var(--navy); color:#fff; display:flex; align-items:center; justify-content:center;
  cursor:pointer;
}
.search-submit svg{ color:#fff; }
/* Saran pencarian (2026-07-27, permintaan pemilik: "kolom search menetik satu dua
   huruf ... ada opsi kayak saran nama produk yang sudah ada") -- dropdown melayang
   di bawah kolom pencarian, muncul/hilang lewat JS di includes/topbar.php. */
.search-saran{
  position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:50;
  background:var(--card); border-radius:14px; box-shadow:0 10px 30px rgba(0,0,0,.15);
  overflow:hidden; max-height:280px; overflow-y:auto;
}
.search-saran-item{
  display:flex; align-items:center; gap:8px; padding:10px 14px;
  font-size:12.5px; color:var(--text); cursor:pointer; text-align:left;
}
.search-saran-item:hover, .search-saran-item.aktif{ background:#f0f2f5; }
.search-saran-item svg{ color:var(--muted); flex-shrink:0; }
.topbar .right-icons{ display:flex; align-items:center; gap:14px; flex-shrink:0; }
.topbar .cart-badge{ position:relative; }
.topbar .cart-badge .count{
  position:absolute; top:-6px; right:-8px;
  background:var(--red); color:#fff; font-size:9px; font-weight:700;
  width:15px; height:15px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
}
.topbar .btn-masuk{
  flex-shrink:0; display:flex; align-items:center; gap:6px;
  background:var(--navy); color:#fff; font-weight:800; font-size:13px;
  padding:8px 14px; border-radius:12px;
}

/* logo topbar (dipakai includes/topbar.php) -- menggantikan .wordmark bertulisan supaya
   kolom pencarian lebih lebar; .wordmark lama TETAP ada (masih dipakai akun.php,
   produk_detail.php, dan halaman auth yang tidak include topbar.php ini) */
.topbar-brand{ display:flex; align-items:center; flex-shrink:0; }
.topbar-logo{ height:30px; width:auto; display:block; border-radius:50%; }

/* menu horizontal khusus desktop (900px+), lihat topbar.php -- tersembunyi di mobile,
   pakai destinasi sama persis dengan includes/bottom_nav.php supaya konsisten */
.topbar-desktop-nav{ display:none; }
.topbar-desktop-nav a{ color:var(--muted); font-size:13px; font-weight:700; }
.topbar-desktop-nav a:hover{ color:var(--navy); }

/* icon kanan topbar bergaya "chip" bulat -- gaya marketplace besar (Blibli dkk).
   Latar var(--navy-tint)+ikon var(--navy) (2026-08-13, dulu semi-transparan putih
   di atas navy solid -- sekarang topbar putih, jadi butuh tint sendiri supaya
   tetap kelihatan sebagai "chip", bukan sekadar ikon polos). */
.right-icons .icon-circle{
  position:relative; width:34px; height:34px; border-radius:50%; flex-shrink:0;
  background:var(--navy-tint); color:var(--navy);
  display:flex; align-items:center; justify-content:center;
}
.right-icons .icon-circle .count{
  position:absolute; top:-4px; right:-4px;
  background:var(--red); color:#fff; font-size:9px; font-weight:800;
  min-width:16px; height:16px; border-radius:50%; padding:0 3px;
  display:flex; align-items:center; justify-content:center;
  border:2px solid var(--card);
}

/* ---------- generic layout ---------- */
.section{ padding:14px 16px 0; }
.card{
  background:var(--card);
  border-radius:16px;
  padding:16px;
  box-shadow:0 1px 3px rgba(0,0,0,0.06);
  margin-bottom:14px;
}
.section-head{
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:10px;
}
.section-head h2{ font-size:15px; font-weight:700; display:flex; align-items:center; }
.section-head a{ font-size:12.5px; color:var(--navy); font-weight:700; }
/* badge ikon kotak-membulat bergradasi, pengganti emoji mentah di judul section
   (beranda.php) -- lebih konsisten dengan bahasa desain ikon SVG di seluruh situs */
.head-icon{
  width:26px; height:26px; border-radius:9px; flex-shrink:0;
  display:inline-flex; align-items:center; justify-content:center;
  margin-right:7px; color:#fff; box-shadow:0 2px 6px rgba(0,0,0,.12);
}
.head-icon.bg-lelang{ background:linear-gradient(135deg,#dc2626,#f87171); }
.head-icon.bg-flash{ background:linear-gradient(135deg,#f59e0b,#fde047); }
.head-icon.bg-produk{ background:linear-gradient(135deg,var(--navy),var(--accent)); }
.head-icon.bg-po{ background:linear-gradient(135deg,#6d28d9,#a855f7); }

/* Banner intro po.php (2026-07-28, modernisasi, revisi ke-2 sama hari -- versi
   teal/hijau pertama nyeleneh, versi navy kedua terasa terlalu "sama dengan semua
   section lain" jadi tidak menonjol sebagai identitas PO sendiri) -- pengganti
   kartu putih polos + emoji 📦 mentah. Ungu dipilih karena belum dipakai section
   manapun (Lelang=merah, Flash Sale=oranye, beranda-hero/topbar=navy), kesan
   "premium/terjamin" cocok untuk positioning PO (harga tetap, tidak naik-turun). */
.po-hero{
  background:linear-gradient(135deg,#5b21b6 0%,#7c3aed 55%,#6d28d9 100%);
  border-radius:16px; padding:14px 16px 16px; margin:0 0 14px;
  box-shadow:0 4px 14px rgba(109,40,217,.28);
}
.po-hero-top{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:8px; }
.po-hero-title{ display:flex; align-items:center; gap:8px; }
.po-hero-title h2{ font-size:16px; font-weight:800; color:#fff; }
.po-hero-badge{
  background:rgba(255,255,255,.18); color:#fff; font-size:9.5px; font-weight:800;
  letter-spacing:.3px; padding:3px 9px; border-radius:20px; text-transform:uppercase;
}
.po-hero-cta{
  flex-shrink:0; background:#fff; color:#6d28d9; font-size:12px; font-weight:800;
  padding:7px 14px; border-radius:20px; white-space:nowrap;
}
.po-hero-desc{ font-size:11.5px; color:rgba(255,255,255,.85); line-height:1.6; }
.po-hero-desc a{ color:#fff; font-weight:800; text-decoration:underline; text-underline-offset:2px; }

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  background:var(--navy); color:#fff; border:none; border-radius:12px;
  padding:13px 20px; font-size:14px; font-weight:700;
  font-family:'Inter', sans-serif; cursor:pointer; width:100%;
}
.btn:active{ background:var(--navy-dark); }
.btn-outline{
  background:var(--card); color:var(--navy); border:1.5px solid var(--navy);
}
.btn-outline:active{ background:#f5f7ff; }

/* ---------- badges ---------- */
.badge-verif{
  display:inline-flex; align-items:center; gap:3px;
  background:var(--navy-tint); color:var(--navy);
  font-size:10.5px; font-weight:700;
  padding:2px 8px; border-radius:20px;
}
/* "Seller Umum" (2026-07-30) -- amber, sengaja beda dari .badge-verif biru
   (terverifikasi) supaya level kepercayaan yang beda kebaca sekilas. */
.badge-umum-inline{
  display:inline-flex; align-items:center; gap:3px;
  background:rgba(217,119,6,.12); color:#b45309;
  font-size:10.5px; font-weight:700;
  padding:2px 8px; border-radius:20px; margin-left:4px;
}
[data-theme="dark"] .badge-umum-inline{ background:rgba(217,119,6,.22); }

/* ---------- product grid (belanja, beranda) ---------- */
.product-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:12px;
}
/* Tinggi SERAGAM antar kartu (2026-08-13, laporan pemilik: "tinggi card tidak
   seragam antar card (beda-beda tergantung panjang konten)") -- akar masalahnya
   BUKAN grid (CSS Grid sudah otomatis menyamakan tinggi antar kartu SATU BARIS
   lewat align-items:stretch bawaan), tapi antar BARIS grid yang berbeda: kartu
   dengan nama produk 3 baris (dulu tidak dibatasi -webkit-line-clamp) atau tanpa
   data lokasi (dulu .lokasi TIDAK dirender sama sekali kalau kosong, lihat
   catatan di includes/fungsi_tab_produk.php/belanja.php/profil_toko.php) bikin
   TINGGI ASLI kartu itu beda dari kartu lain, jadi baris grid yang berisi kartu
   itu ikut lebih tinggi dari baris grid lain -- terlihat "tidak rapi" susunan
   berjajar ke bawah. Solusinya: setiap elemen di dalam (.name/.meta/.lokasi) di
   bawah dikunci tinggi maksimal+minimalnya (line-clamp/nowrap+min-height), jadi
   tinggi ASLI kartu otomatis konsisten di kartu MANA PUN tanpa perlu grid-auto-
   rows manual (persis prinsip yang sama dipakai spec redesign kartu produk yang
   diberikan pemilik). display:flex TETAP dipertahankan (bukan cuma block) supaya
   .info bisa mengisi sisa ruang kalau suatu saat kartu ini SENDIRI di-stretch
   lebih tinggi dari tinggi aslinya oleh baris grid (mis. bertetangga dengan
   kartu yang benar-benar 2 baris nama), bukan menyisakan celah kosong janggal
   di tengah kartu. */
.product-card{
  background:var(--card); border-radius:10px; overflow:hidden;
  box-shadow:0 1px 2px rgba(15,32,66,.08); cursor:pointer;
  display:flex; flex-direction:column; min-width:0; border:1px solid rgba(15,32,66,.06);
  transition:box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
/* Hover elevation (2026-07-27, modernisasi) -- cuma berlaku kalau perangkat punya
   mouse sungguhan (media hover:hover), supaya tidak ada efek "nyangkut aktif" aneh
   di layar sentuh yang tidak punya konsep hover sungguhan. */
@media (hover:hover){
  .product-card:hover{ box-shadow:0 10px 24px rgba(15,32,66,.16); transform:translateY(-3px); border-color:rgba(15,32,66,.12); }
}
.product-card .thumb-wrap{ position:relative; }
.product-card img{ width:100%; aspect-ratio:1; object-fit:cover; display:block; background:#eee; }
/* Pita diskon merah gaya marketplace besar (2026-07-28, referensi Blibli) --
   sebelumnya cuma kotak kecil melayang di sudut, sekarang pita rata menempel ke
   sudut kartu (flush corner ribbon) dengan gradasi+bayangan supaya lebih menonjol
   dan terasa "festival diskon", bukan label datar polos. */
.product-card .badge-diskon{
  position:absolute; top:0; right:0;
  background:linear-gradient(135deg,#ff3b30,#e53935); color:#fff; font-size:10.5px; font-weight:800;
  padding:3px 8px; border-radius:0 10px 0 10px; letter-spacing:.2px;
  box-shadow:0 2px 5px rgba(229,57,53,.4);
}
.product-card .wishlist{
  position:absolute; bottom:8px; right:8px;
  width:26px; height:26px; border-radius:50%;
  background:rgba(255,255,255,0.9);
  display:flex; align-items:center; justify-content:center;
  color:var(--muted); box-shadow:0 1px 3px rgba(0,0,0,.15);
}
/* Favorit sungguhan (2026-08-05, lihat assets/js/favorit.js) -- merah #ef4444
   sama persis dengan warna yang dipakai tombol wishlist tunggal di
   produk_detail.php supaya konsisten di seluruh situs. */
.product-card .wishlist.aktif{ color:#ef4444; }
.product-card .wishlist.aktif svg{ fill:#ef4444; }
/* Badge "PO" (2026-08-04, produk fisik dengan estimasi_kirim_hari terisi) --
   bottom-left, sengaja sudut BERBEDA dari .badge-corner (top-left, verified/seller
   umum) supaya bisa tampil BERSAMAAN tanpa tabrakan/menimpa -- produk bisa saja
   verified DAN PO sekaligus. */
.product-card .badge-po{
  position:absolute; bottom:8px; left:8px;
  background:#7c3aed; color:#fff; font-size:9px; font-weight:800;
  padding:3px 8px; border-radius:20px; letter-spacing:.3px;
  box-shadow:0 1px 4px rgba(0,0,0,.12);
}
.product-card .badge-corner{
  position:absolute; top:8px; left:8px;
  font-size:10px; font-weight:700; padding:3px 8px; border-radius:20px;
  box-shadow:0 1px 4px rgba(0,0,0,.12);
}
.product-card .badge-sponsor{ background:rgba(255,255,255,.95); color:#546e7a; }
.product-card .badge-verified{ background:rgba(255,255,255,.95); color:var(--navy); display:inline-flex; align-items:center; gap:3px; }
/* "Seller Umum" (2026-07-30) -- amber, konsisten dengan .badge-umum-inline di
   produk_detail.php dan .arrive-box.umum -- satu warna dipakai di semua tempat
   yang menandai produk Seller Umum supaya langsung dikenali di seluruh situs. */
.product-card .badge-umum{ background:rgba(255,255,255,.95); color:#b45309; display:inline-flex; align-items:center; gap:3px; }
.product-card .info{ padding:9px 10px 11px; flex:1; display:flex; flex-direction:column; }
/* -webkit-line-clamp:2 (2026-08-13, BARU -- sebelumnya cuma min-height TANPA
   pembatas maksimal, jadi nama produk panjang bisa tembus 3+ baris dan bikin
   kartu itu lebih tinggi dari tetangganya). min-height sengaja tetap dipasang
   BARENGAN clamp (bukan salah satu saja) -- clamp membatasi ATAS (nama panjang
   tidak pernah lebih dari 2 baris), min-height menjamin BAWAH (nama pendek 1
   baris tetap dapat ruang setinggi 2 baris) -- kombinasi keduanya yang bikin
   tinggi elemen ini SELALU sama persis di kartu apa pun. */
.product-card .name{
  font-size:12.5px; font-weight:600; line-height:1.35; color:var(--text);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  min-height:34px;
}
/* Harga tebal hitam-kebiruan (2026-07-28, referensi Blibli: harga selalu warna
   paling gelap/kontras di kartu, BUKAN warna brand -- warna brand dipakai untuk
   aksen/CTA, bukan angka harga) menggantikan var(--navy) yang sebelumnya membuat
   harga terasa "sama pentingnya" dengan elemen brand lain, kurang menonjol. */
.product-card .price{ font-size:15px; font-weight:800; color:var(--text); margin-top:5px; letter-spacing:-.2px; min-height:19px; }
/* display:block (2026-08-13, BARU -- dulu inline di baris yang sama dengan
   harga) -- harga+harga-coret berdampingan sering tidak muat 1 baris di kartu
   sempit (mis. "Rp2.400.000 Rp2.900.000"), otomatis wrap ke baris ke-2 dan
   bikin .price kartu itu 2x lebih tinggi dari kartu tanpa diskon (1 baris
   saja) -- akar penyebab lain laporan "tidak seragam", ketahuan lewat
   pengukuran getBoundingClientRect langsung antar kartu. Sekarang SELALU baris
   sendiri (display:block, bukan lagi ikut alur baris .price) -- SELALU
   dirender juga (kosong/&nbsp; kalau tidak ada diskon, lihat pemanggilnya)
   supaya tingginya selalu 2 baris yang sama persis, ada diskon atau tidak. */
.product-card .price-old{ display:block; font-size:11px; color:var(--muted); text-decoration:line-through; font-weight:500; margin-top:1px; }
/* .price-old-kosong (2026-08-13) -- placeholder saat produk TIDAK diskon (lihat
   pemanggilnya). visibility:hidden (BUKAN cuma teks kosong) -- &nbsp; polos
   dengan text-decoration:line-through di atas tetap menggambar garis coret
   pendek yang kelihatan seperti "-" nyangkut, walau tidak ada teks sungguhan.
   visibility:hidden menyembunyikan SEMUANYA (termasuk garis coretnya) tapi
   tetap mempertahankan ruang tingginya di layout, itulah tujuannya. */
.product-card .price-old-kosong{ visibility:hidden; }
/* REVISI (2026-08-13, permintaan pemilik lanjutan: "JANGAN dipotong/ellipsis,
   BOLEH wrap ke maksimal 2 baris, tapi WAJIB tetap rapi dengan tinggi seragam
   ... menggunakan min-height tetap") -- versi SEBELUMNYA (nowrap+ellipsis 1
   baris) diganti: teks sekarang boleh wrap NORMAL sampai maksimal 2 baris.
   min-height MENJAMIN bawah (teks 1 baris tetap dapat ruang 2 baris, kartu lain
   di baris yang sama tidak ikut memendek), max-height+overflow:hidden MENJAGA
   atas (kasus super ekstrem yang butuh >2 baris dipotong SENYAP tanpa "...",
   bukan skenario normal -- konten rating/terjual/lokasi pada dasarnya pendek,
   ini cuma jaring pengaman, bukan mekanisme utama). line-height eksplisit
   (bukan ikut bawaan) supaya perhitungan min/max-height 2-baris presisi. */
.product-card .meta{
  font-size:10.5px; line-height:1.4; color:var(--muted); margin-top:5px;
  display:flex; align-items:flex-start; gap:4px;
  min-height:29px; max-height:29px; overflow:hidden;
}
.product-card .meta svg{ color:#fbbf24; flex-shrink:0; margin-top:1px; }
/* SELALU dirender (2026-08-13) -- dulu <div class="lokasi"> hanya muncul kalau
   produk punya data lokasi (lihat includes/fungsi_tab_produk.php/belanja.php),
   jadi kartu TANPA lokasi kehilangan satu baris penuh tingginya dibanding kartu
   yang punya lokasi -- akar penyebab utama laporan "tidak seragam". Sekarang
   baris ini SELALU ada (min-height tetap terpakai walau kosong/&nbsp; -- lihat
   pemanggilnya). Boleh wrap 2 baris (2026-08-13, revisi lanjutan) -- pola sama
   persis seperti .meta di atas, lihat catatan lengkap di sana. */
.product-card .lokasi{
  font-size:9px; line-height:1.4; color:var(--muted); margin-top:2px;
  display:flex; align-items:flex-start; gap:3px;
  min-height:26px; max-height:26px; overflow:hidden;
}

/* ---------- bottom navigation ---------- */
/* Bar rata menempel penuh di tepi bawah layar (2026-07-14, diminta user "jangan
   floating seperti itu") -- kembali ke pola bottom-tab standar seperti referensi
   Figma src/components/BottomNav.tsx: full width, background putih, garis tipis
   di atas, bayangan naik, TANPA border-radius/jarak dari tepi. */
.bottomnav{
  position:fixed; left:50%; bottom:0;
  transform:translateX(-50%);
  /* max-width 430px->480px (2026-08-07, bug ditemukan lewat audit responsif
     menyeluruh) -- TIDAK PERNAH disamakan dengan .phone (480px) sejak awal,
     jadi di lebar viewport 430-480px menu bawah ini kelihatan lebih SEMPIT
     dari konten .phone di atasnya (ada sedikit latar halaman mengintip di
     kiri-kanan menu, tidak rata). left:50%+translateX(-50%) di sini otomatis
     aman di lebar viewport BERAPA PUN (beda dari pola calc(50vw-240px) yang
     dipakai .forum-fab/.cs-fab, TIDAK butuh override manual per breakpoint)
     -- cukup samakan angka max-width-nya sekali di sini. */
  width:100%; max-width:480px;
  background:var(--card); border-top:1px solid var(--border);
  display:flex; z-index:30;
  box-shadow:0 -4px 20px rgba(0,0,0,.08);
  padding-bottom:env(safe-area-inset-bottom);
}
.bottomnav a{
  flex:1; display:flex; flex-direction:column; align-items:center; gap:3px;
  padding:10px 2px; color:var(--muted); font-size:10.5px; font-weight:600; position:relative;
}
.bottomnav a.active{ color:var(--navy); }
.bottomnav a svg{ width:21px; height:21px; }
/* Ikon custom per menu (migrasi_60, 2026-08-13) -- admin_utama mengunggah PNG/JPG
   pengganti <svg> lewat admin/kelola_tampilan.php. Beda dari <svg stroke="currentColor">
   yang otomatis ikut warna aktif/nonaktif, gambar raster tidak bisa direwarnai CSS --
   opacity dipakai sebagai penanda status aktif sebagai gantinya (pudar = nonaktif,
   penuh = aktif), bukan pergantian warna. */
.bottomnav a img.nav-custom-icon{ width:22px; height:22px; object-fit:contain; opacity:.55; }
.bottomnav a.active img.nav-custom-icon{ opacity:1; }
.bottomnav a.nav-jual .jual-circle img.nav-custom-icon{ width:24px; height:24px; opacity:1; }

/* Tombol "Jual" tengah (2026-07-30, fitur Seller Umum) -- bulat, terangkat di atas
   garis bottomnav, ala tombol "create post" Facebook/Instagram, supaya paling
   menonjol dibanding 4 menu teks lain (prioritas pemilik saat ini: perbanyak produk
   & pendaftar). flex:0 0 auto (lebar tetap 60px) BUKAN flex:1 seperti item lain --
   4 item teks lain otomatis berbagi rata sisa lebar yang ada, jadi ini aman di layar
   sesempit apa pun (iPhone SE 320px: (320-60)/4 = 65px per item teks, masih cukup
   untuk 1 kata pendek + ikon 21px). border:4px solid var(--bg) memberi efek "terpotong
   keluar" dari garis bottomnav, bukan var(--card) supaya menyatu ke LATAR halaman,
   bukan ke kartu bottomnav-nya sendiri. */
.bottomnav a.nav-jual{ flex:0 0 auto; width:60px; padding-top:0; }
.bottomnav a.nav-jual .jual-circle{
  position:absolute; top:-16px; left:50%; transform:translateX(-50%);
  width:50px; height:50px; border-radius:50%;
  background:var(--navy); color:#fff;
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 4px 14px rgba(120,20,20,.4);
  border:4px solid var(--bg);
}
.bottomnav a.nav-jual .jual-circle svg{ width:22px; height:22px; }
.bottomnav a.nav-jual .jual-label{
  display:block; margin-top:34px; font-size:10.5px; font-weight:600; color:var(--muted);
}
.bottomnav a.nav-jual.active .jual-circle{ background:var(--navy-dark); }
.bottomnav a.nav-jual.active .jual-label{ color:var(--navy); }
/* Layar sangat sempit (2026-07-30, HP jadul <=340px) -- lingkaran+font sedikit
   diperkecil supaya tidak mepet ke 4 item tetangga. */
@media (max-width:340px){
  .bottomnav a.nav-jual{ width:52px; }
  .bottomnav a.nav-jual .jual-circle{ width:44px; height:44px; top:-14px; }
  .bottomnav a.nav-jual .jual-circle svg{ width:19px; height:19px; }
  .bottomnav a.nav-jual .jual-label{ font-size:9.5px; margin-top:30px; }
}

/* ---------- Widget Customer Service AI (2026-08-05) ---------- */
/* Tombol bulat mengambang, SATU-SATUNYA widget mengambang di situs ini
   (2026-08-14, permintaan pemilik: "floating forum masih ada harusnya di
   hapus cukup cs putri saja") -- .forum-fab yang dulu ditumpuk DI BAWAH
   widget ini SUDAH DIHAPUS total (includes/forum_fab.php dihapus filenya,
   tidak di-include halaman manapun lagi) -- posisi .cs-fab sekarang PERSIS
   di posisi forum-fab yang lama (dekat .bottomnav), bukan lagi ditumpuk di
   atasnya. Warna biru (var(--navy), revisi 2026-08-05 -- sebelumnya hijau)
   dipertahankan, label teks "CS" di bawah lingkaran ikon tetap ada. */
.cs-fab{
  /* font-family eksplisit (2026-08-05, bug ditemukan lewat pengecekan getComputedStyle
     di Chrome) -- .cs-fab elemen <button>, browser default-nya TIDAK mewarisi
     font body (jadi Arial/font sistem) seperti elemen <a> biasa. */
  font-family:'Inter',sans-serif;
  position:fixed;
  /* right:14px SAJA (dari tepi viewport asli) baru benar kalau .phone selebar
     viewport (viewport <=480px). Begitu .phone berhenti melebar dan DITENGAHKAN
     (body{display:flex;justify-content:center}) sementara viewport lebih lebar
     dari itu (HP dimiringkan, tablet, dst), ada margin kosong kiri-kanan --
     right:14px polos bikin FAB "lepas" nempel di tepi viewport asli, jauh dari
     kolom .phone yang terlihat -- inilah bug "tidak responsif kalau HP
     dimiringkan/tablet" yang dilaporkan pemilik (2026-08-05, dilaporkan lagi
     2026-08-07 setelah breakpoint tablet baru ditambahkan tapi HP miring masih
     sengaja dikecualikan darinya, lihat catatan --lebar-phone di :root).
     max(14px, calc((100vw - min(100vw, var(--lebar-phone))) / 2 + 14px)) --
     menghitung jarak sesungguhnya dari tepi viewport ke tepi kanan .phone + 14px,
     BACA LANGSUNG dari --lebar-phone (bukan angka tetap per breakpoint) supaya
     FAB otomatis ikut lebar .phone yang berlaku SAAT INI, breakpoint apapun,
     tanpa perlu override calc() manual lagi tiap kali ada breakpoint .phone
     baru/berubah. Berlaku untuk <900px saja -- 900px+ (desktop sungguhan)
     di-reset balik ke 14px polos di @media di bawah, karena widget mengambang
     menempel ke pojok viewport asli itu wajar/lazim di desktop. */
  right:max(14px, calc((100vw - min(100vw, var(--lebar-phone))) / 2 + 14px));
  /* 58px = tinggi .bottomnav (lihat komentar .pd-above-bottomnav di atas untuk
     rincian perhitungannya), +14px jarak aman di atasnya -- formula persis yang
     dulu dipakai forum-fab (satu-satunya FAB yang menempel dekat bottomnav). */
  bottom:calc(58px + 14px + env(safe-area-inset-bottom));
  display:flex; flex-direction:column; align-items:center; gap:2px;
  z-index:35; /* di atas .bottomnav/.actionbar (30), di bawah toast(9999)/modal overlay(50+) */
  cursor:pointer; padding:0; border:none; background:none;
}
.cs-fab .fab-circle{
  width:44px; height:44px; border-radius:50%;
  background:var(--navy);
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 4px 14px rgba(15,45,90,.35);
  border:2px solid #fff;
}
.cs-fab .fab-circle svg{ width:22px; height:22px; }
/* Ikon custom (migrasi_60, 2026-08-13) -- lihat catatan sama di .bottomnav
   img.nav-custom-icon soal kenapa admin_utama upload gambar, bukan warna SVG.
   Isi PENUH lingkaran (2026-08-13, laporan pemilik: "harusnya otomatis full
   bulet jadi ga kepotong") -- width/height:100%+object-fit:cover+
   border-radius:50%, foto mengisi SELURUH lingkaran ala avatar profil. */
.cs-fab .fab-circle img.fab-custom-icon{ width:100%; height:100%; object-fit:cover; border-radius:50%; }
.cs-fab .fab-label{
  font-size:9.5px; font-weight:700; color:var(--navy); white-space:nowrap;
  background:var(--card); padding:1px 6px; border-radius:8px;
  box-shadow:0 1px 4px rgba(0,0,0,.15);
}
/* produk_detail.php SATU-SATUNYA halaman yang juga punya .actionbar mengambang
   DI ATAS .bottomnav (~66px: padding 10+10 + tombol .btn ~46px) -- FAB perlu
   naik lagi supaya tidak menutupi tombol Keranjang/Beli Sekarang di sana. */
.cs-fab.pd-above-actionbar{
  bottom:calc(58px + 66px + 14px + env(safe-area-inset-bottom));
}
@media (min-width:900px){
  /* .bottomnav (dan .actionbar di produk_detail.php) disembunyikan total di
     breakpoint ini -- FAB tidak perlu clear apa pun lagi, cukup jarak tetap
     dari tepi bawah layar. right DIRESET ke 14px polos -- di desktop
     sungguhan, widget mengambang menempel ke pojok viewport asli itu wajar
     (pola umum semua widget chat web). */
  .cs-fab, .cs-fab.pd-above-actionbar{ bottom:20px; right:14px; }
  .cs-fab .fab-circle{ width:48px; height:48px; }
}

/* Panel chat -- disembunyikan default (display:none), dibuka lewat class
   .cs-panel-open (toggle JS di cs_widget.php).
   PENUH LAYAR di mobile (2026-08-05, permintaan pemilik: "tampilan chat ai di
   hanphone terlalu kecil ... bisa full layar namun floating chat ainya masih
   ada") -- sebelumnya kotak kecil mengambang (340x480px maks) di SEMUA lebar
   layar, termasuk HP, jadi ruang mengetik/baca jadi sempit. FAB (.cs-fab)
   TIDAK dihapus/diganti apa pun -- tetap ada persis di tempatnya, cuma
   tertutup visual oleh panel penuh layar ini (z-index:200, sama konvensi
   .pd-lightbox) selama panel terbuka; begitu ditutup lewat tombol X
   (#csPanelClose, JS tidak berubah sama sekali) panel kembali display:none dan
   FAB langsung terlihat lagi apa adanya -- alur "klik ikon buka, klik X
   tutup balik jadi ikon" TIDAK perlu perubahan JS, murni CSS. inset:0 dipakai
   (bukan lagi right/bottom dihitung dari posisi .cs-fab) karena panel ini
   sekarang menutupi SELURUH viewport, bukan lagi kotak mengambang di dekat
   FAB. .pd-above-actionbar TIDAK relevan lagi di lebar ini (tidak ada
   .actionbar yang perlu dihindari kalau panelnya sendiri sudah menutupi
   semuanya) -- variannya dikembalikan HANYA di breakpoint desktop di bawah,
   tempat kotak mengambang kecil yang lama tetap dipakai (permintaan pemilik
   eksplisit menyebut "di hanphone", desktop tidak diminta berubah). */
.cs-panel{
  display:none; flex-direction:column;
  position:fixed; inset:0;
  width:100%; height:100%;
  background:var(--card); border:none; border-radius:0;
  box-shadow:none; overflow:hidden;
  z-index:200;
}
.cs-panel.cs-panel-open{ display:flex; }
@media (min-width:900px){
  /* Kembali jadi kotak mengambang kecil di dekat FAB (perilaku lama) --
     permintaan pemilik hanya soal tampilan mobile, desktop tidak disentuh. */
  .cs-panel, .cs-panel.pd-above-actionbar{
    inset:auto;
    /* 20px (basis .cs-fab desktop) + 66px (tinggi total FAB: lingkaran 48 +
       gap 2 + label ~16) + 10px (jarak) = 96px -- panel menempel pas di atas
       FAB, formula sama seperti bottom .cs-fab sendiri, cuma ditambah
       tinggi+jarak FAB-nya. */
    bottom:calc(20px + 66px + 10px); right:14px;
    width:min(92vw, 340px); height:min(70vh, 480px);
    border-radius:14px; border:1px solid var(--border);
    box-shadow:0 8px 28px rgba(0,0,0,.25);
    z-index:36;
  }
  .cs-panel-head{ padding:12px 14px; }
  .cs-panel-footer{ padding:10px 12px; }
}
.cs-panel-head{
  background:var(--navy); padding:calc(12px + env(safe-area-inset-top)) 14px 12px;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  flex-shrink:0;
}
.cs-panel-title{ font-size:13px; font-weight:800; color:#fff; }
.cs-panel-sub{ font-size:10.5px; color:rgba(255,255,255,.85); margin-top:1px; }
#csPanelClose{ background:none; border:none; padding:4px; cursor:pointer; display:flex; flex-shrink:0; }
/* min-height:0 (2026-08-14, bug nyata ditemukan lewat audit -- laporan pemilik
   "kolom input teks chat itu harusnya ngikutin scrollan di menu pesan",
   dibandingkan dengan forum/pesan_chat.php yang SUDAH benar) -- flex item
   defaultnya min-height:auto (=tinggi konten sendiri, bukan 0), jadi begitu
   riwayat chat cukup panjang, .cs-panel-msgs bisa tumbuh melebihi jatah
   flex:1-nya dan mendorong .cs-panel-footer (kolom ketik) ke luar batas
   .cs-panel -- persis kelas bug yang sama yang sudah ditemukan+diperbaiki di
   forum/assets/style.css .chat-list (2026-07-30), belum ikut diterapkan di
   sini. min-height:0 memaksa elemen ini patuh ke flex:1 (tinggi jatahnya),
   overflow-y:auto lalu benar-benar scroll di DALAM elemen ini, kolom ketik
   tetap menempel di bawah panel. */
.cs-panel-msgs{
  flex:1; min-height:0; overflow-y:auto; padding:12px 14px;
  display:flex; flex-direction:column; gap:8px;
  background:var(--bg);
}
.cs-bubble{
  max-width:80%; padding:8px 12px; border-radius:12px;
  font-size:12.5px; line-height:1.5; white-space:pre-wrap; word-break:break-word;
}
.cs-bubble-user{
  align-self:flex-end; background:var(--navy); color:#fff;
  border-bottom-right-radius:3px;
}
.cs-bubble-assistant{
  align-self:flex-start; background:var(--card); color:var(--text);
  border:1px solid var(--border); border-bottom-left-radius:3px;
}
.cs-bubble-typing{
  align-self:flex-start; background:var(--card); color:var(--muted);
  font-style:italic; border:1px solid var(--border);
}
.cs-bubble-error{
  align-self:flex-start; background:rgba(220,38,38,.12); color:var(--red);
  border:1px solid var(--red);
}
/* Kartu produk yang bisa diklik di dalam chat (2026-08-05) -- muncul di bawah
   balasan Putri kalau pencarian produk relevan (cariProdukRelevan()) menemukan
   hasil, klik langsung ke produk_detail.php. Dibungkus .cs-produk-list (bukan
   card individual) supaya align-self:flex-start diterapkan sekali di wrapper,
   konsisten dengan .cs-bubble-assistant di atasnya. */
.cs-produk-list{
  display:flex; flex-direction:column; gap:6px;
  align-self:flex-start; max-width:80%;
}
.cs-produk-card{
  display:flex; align-items:center; gap:8px; padding:6px;
  border-radius:10px; background:var(--card); border:1px solid var(--border);
  text-decoration:none;
}
.cs-produk-card img{
  width:36px; height:36px; border-radius:6px; object-fit:cover;
  flex-shrink:0; background:var(--bg);
}
.cs-produk-info{ min-width:0; }
.cs-produk-nama{
  font-size:11.5px; font-weight:700; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.cs-produk-harga{ font-size:11.5px; font-weight:800; color:var(--navy); }
.cs-panel-footer{
  border-top:1px solid var(--border); padding:10px 12px calc(10px + env(safe-area-inset-bottom));
  display:flex; flex-direction:column; gap:8px; background:var(--card); flex-shrink:0;
}
.cs-panel-wa{
  font-size:11px; color:var(--navy); text-align:center; font-weight:700;
  text-decoration:none;
}
.cs-panel-form{ display:flex; gap:8px; }
.cs-panel-form input{
  flex:1; border:1px solid var(--border); border-radius:20px; padding:8px 14px;
  font-size:12.5px; background:var(--bg); color:var(--text); font-family:'Inter',sans-serif;
}
.cs-panel-form button{
  width:36px; height:36px; border-radius:50%; background:var(--navy); border:none;
  display:flex; align-items:center; justify-content:center; flex-shrink:0; cursor:pointer; padding:0;
}

/* ---------- fixed bottom action bar (product detail, checkout) ---------- */
.actionbar{
  position:fixed; bottom:0; left:0; right:0; margin:0 auto;
  /* 430px->480px (2026-08-07, bug sekelas .bottomnav ditemukan lewat audit
     responsif -- lihat catatan lengkap di .bottomnav) -- disamakan dengan
     .phone. */
  width:100%; max-width:480px;
  background:var(--card); border-top:1px solid var(--border);
  box-shadow:0 -2px 10px rgba(0,0,0,0.06);
  padding:10px 16px calc(10px + env(safe-area-inset-bottom));
  display:flex; align-items:center; gap:10px; z-index:30;
}
/* .pd-above-bottomnav (2026-08-04) -- produk_detail.php sekarang JUGA punya
   .bottomnav (5 menu utama, sebelumnya tidak ada di halaman ini sama sekali), yang
   sama-sama fixed+bottom:0 dengan .actionbar -- tanpa modifier ini keduanya akan
   tumpang tindih persis di posisi yang sama. Digeser ke atas setinggi .bottomnav
   (~58px: padding 10+10 + ikon 21px + gap 3px + label ~13px + border 1px) supaya
   keduanya bertumpuk rapi, bukan bertabrakan. TIDAK diterapkan ke .actionbar biasa
   (lelang_detail.php juga memakainya tapi TANPA .bottomnav) supaya halaman itu tidak
   ikut berubah/malah jadi menggantung dengan celah kosong di bawahnya. */
.actionbar.pd-above-bottomnav{ bottom:calc(58px + env(safe-area-inset-bottom)); }
/* .msg (tombol "Pesan" via WhatsApp di produk_detail.php) DIHAPUS (2026-08-13,
   permintaan pemilik: "di produk detil button pesan dihapus saja") -- tidak ada
   markup manapun lagi yang memakai class ini, .btn-kontak-seller sudah cukup. */

/* ---------- helpers ---------- */
.hscroll{ display:flex; gap:10px; overflow-x:auto; padding-bottom:2px; scrollbar-width:none; }
.hscroll::-webkit-scrollbar{ display:none; }
.pill{
  padding:8px 16px; border-radius:20px; font-size:12.5px; font-weight:700;
  background:var(--card); color:var(--muted); border:1px solid var(--border);
  white-space:nowrap; flex-shrink:0; cursor:pointer;
}
.pill.active{ background:var(--navy); color:#fff; border-color:var(--navy); }

.filter-row{ display:flex; gap:8px; overflow-x:auto; padding:10px 0 12px; scrollbar-width:none; }
.filter-row::-webkit-scrollbar{ display:none; }
.verif-toggle{
  display:inline-flex; align-items:center; gap:6px;
  padding:8px 14px; border-radius:20px; font-size:12.5px; font-weight:700;
  background:var(--card); color:var(--text); border:1px solid var(--border);
  white-space:nowrap; flex-shrink:0; cursor:pointer;
}
.verif-toggle.active{ background:var(--navy-tint); color:var(--navy); border-color:var(--navy); }
.load-more{ margin:16px 0 4px; }

.empty-state{ text-align:center; padding:40px 24px; color:var(--muted); }
.empty-state svg{ color:var(--border); margin-bottom:12px; }
.empty-state p{ font-size:13px; }

/* ==========================================================
   Komponen tambahan khusus beranda.php versi lengkap
   (rujukan visual: zip Figma "Beranda", src/app/App.tsx)
   ========================================================== */

/* Header melengkung + transisi scroll (2026-08-13, spec redesign "setara
   Blibli.com", HANYA beranda.php -- .topbar dasar yang dipakai halaman lain
   TIDAK disentuh sama sekali). .bh-curve = SVG wave sungguhan (bukan
   border-radius) sebagai latar, .topbar bawaan dibuat transparan di dalamnya
   (pola sama seperti .kat-hero di kategori.php). State scroll (kelas
   .bh-scrolled, toggle lewat JS inline di beranda.php berdasarkan
   window.scrollY > 80) melebur ke bentuk pipih+pendek, transisi via CSS
   transition murni supaya halus, bukan snap. */
/* box-shadow sebagai pembatas elegan (2026-08-14, permintaan pemilik, 3
   revisi berturut-turut hari yang sama sampai ketemu maksud pastinya):
   1) "shadow gradasi putih sebagai pembatas" -- dicoba pseudo-element
      gradasi 36px, TERNYATA menutupi bagian atas banner (banner cuma
      berjarak ~14px lewat padding .section, jauh lebih pendek dari 36px).
   2) "shadow sedikit ga sampe nutupin banner ... kek 3D" -- diganti
      box-shadow biasa. TERNYATA celah putih .section (padding-top 14px) di
      ANTARA header dan banner (dua permukaan merah senada dipisah garis
      putih tipis) kelihatan seperti "lipatan/patahan" -- celah itu dihapus
      total di beranda.php (.section pembungkus banner: padding:0, lihat
      catatan di sana), banner sekarang MENEMPEL LANGSUNG ke tepi bawah
      header, tanpa celah apa pun.
   3) "background header lebih tinggi sedikit ... shadow item tapi kalo
      discroll kebawah ilang" -- padding-bottom dinaikkan (header sedikit
      lebih tinggi/lega), box-shadow HANYA tampil di state AWAL/belum
      discroll -- begitu .bh-scrolled aktif (JS toggle berdasarkan
      window.scrollY>80 di beranda.php), box-shadow dihapus total (bukan
      cuma diperkecil seperti percobaan sebelumnya). */
.bh-header{
  position:sticky; top:0; z-index:25;
  background:linear-gradient(135deg,var(--navy) 0%,var(--navy-dark) 100%);
  transition:box-shadow .3s ease;
  padding-bottom:22px;
  box-shadow:0 6px 16px rgba(0,0,0,.18);
}
/* padding-bottom SENGAJA tidak lagi ikut animasi/berubah di sini (2026-08-14,
   bug baru ditemukan: "di background header ada lipatan pas discroll") --
   sebelumnya .bh-scrolled juga menyusutkan padding-bottom 22px->0px, yang
   berarti TINGGI KOTAK .bh-header ikut animasi. Karena foto header custom
   (background-size:cover, style inline dari tampilanHeaderBackgroundCss())
   menempel di kotak ini sendiri, tiap frame animasi tinggi itu memaksa
   browser meng-crop ulang foto supaya tetap "cover" -- kelihatan seperti
   foto meremas/melipat diri sendiri selama 0.3 detik discroll. Efek ini nyaris
   tidak kelihatan waktu background masih gradient polos (makanya lolos saat
   fitur box-shadow-hilang-pas-scroll ini pertama dibuat hari yang sama),
   tapi jadi sangat kentara begitu admin upload foto asli. Permintaan asli
   pemilik ("shadow ada tapi kalau discroll ilang") sebenarnya cuma soal
   shadow, bukan soal tinggi header -- jadi cukup box-shadow saja yang
   ditoggle, tinggi kotak (dan foto di dalamnya) dibiarkan tetap konstan. */
.bh-header.bh-scrolled{ box-shadow:none; }
/* Vignette gradasi di tepi bawah (2026-08-14, permintaan pemilik: "gimana
   biar dua ini bagus dan ada gradasinya" -- setelah bug lipatan/misalign
   selesai, ternyata batas header-banner MASIH terlihat kasar begitu admin
   upload foto header custom: dua FOTO BERBEDA (ilustrasi proklamasi di
   header, batik+bendera di banner) bertemu di garis LURUS TEGAS tanpa
   transisi apa pun -- terverifikasi lewat screenshot zoom, potongan foto
   headernya bahkan jatuh pas di tengah wajah ilustrasi orang, terlihat
   "terpotong tidak sengaja"). Vignette ini memudarkan ~70px terakhir foto
   header ke var(--navy-dark) SEBELUM sampai ke garis potong -- foto apa pun
   yang diupload admin (beda tone/warna sekalipun) akan selalu "mendarat"
   di warna brand yang sama pas di tepi bawah, bukan terpotong mentah-mentah.
   Berlaku juga saat TIDAK ada foto custom (gradient bawaan) -- pemanis
   halus, kedalaman visual tambahan, tidak mengubah warnanya (sudah
   var(--navy-dark) di ujung gradient dasarnya). z-index:0 -- eksplisit di
   BAWAH .bh-content (z-index:1) supaya tidak pernah menutupi logo/search/
   ikon. pointer-events:none -- murni dekoratif, tidak pernah menghalangi
   klik. */
.bh-header::before{
  content:""; position:absolute; left:0; right:0; bottom:0; height:70px;
  background:linear-gradient(to bottom, transparent, rgba(35,8,14,.65));
  pointer-events:none; z-index:0;
}
.bh-content{ position:relative; z-index:1; }
/* !important (2026-08-14, bug nyata ditemukan+diperbaiki: "di background
   heading ada lipatan") -- akar masalah: .topbar DAN .bh-header (pembungkus
   luarnya, lebih TINGGI karena ada padding-bottom ekstra) SAMA-SAMA menerima
   inline style background-image:...;background-size:cover dari
   tampilanHeaderBackgroundCss() (dipanggil terpisah di beranda.php UNTUK
   .bh-header, dan di includes/topbar.php UNTUK .topbar) -- begitu admin
   upload foto header custom, KEDUA elemen me-render SALINAN foto yang sama
   secara independen, "cover" menghitung crop/scale BEDA di masing-masing
   (kotak .topbar lebih pendek dari kotak .bh-header) -- hasilnya foto di
   .topbar dan foto di .bh-header (yang mengintip di celah padding-bottom di
   bawah .topbar) TIDAK PERNAH presisi menyambung, kelihatan seperti garis
   patahan/lipatan tepat di batas bawah .topbar. Base rule
   ".bh-header .topbar{background:none}" ini SEBENARNYA sudah bermaksud
   membuat .topbar transparan (biar .bh-header yang render SATU-SATUNYA
   salinan foto, tanpa duplikat) -- tapi kalah spesifisitas lawan inline
   style begitu topbar-branded aktif (inline style SELALU menang lawan
   class selector apa pun, kecuali !important). !important di sini
   memenangkan balik aturan transparan ini, jadi .bh-header SATU-SATUNYA
   yang pernah render foto -- tidak ada lagi dua salinan yang bisa tidak
   presisi. */
.bh-header .topbar{ background:none !important; border-bottom:none; color:#fff; padding-bottom:6px; }
.bh-header .topbar .icon-btn{ color:#fff; }
.bh-header .wordmark .w1{ color:#fff; }
.bh-header .wordmark .w2{ color:var(--accent); }
.bh-header .wordmark .dom{ color:rgba(255,255,255,.6); }
.bh-header .right-icons .icon-circle{ background:rgba(255,255,255,.18); color:#fff; }
.bh-header .right-icons .icon-circle .count{ border-color:var(--navy-dark); }
.bh-header .topbar .search-wrap{ background:#fff; }
.bh-header .search-submit{ background:var(--navy); color:#fff; }
.bh-header .search-submit svg{ color:#fff; }
.bh-header .btn-masuk{ background:#fff; color:var(--navy); }
.bh-header .location-strip{ background:none; padding:2px 16px 0; }
.bh-header .location-strip span{ color:rgba(255,255,255,.8); }
.bh-header .location-strip b{ color:#fff; }

/* .topbar-branded (migrasi_60, 2026-08-13) -- generalisasi dari 13 aturan
   ".bh-header ..." di atas supaya bisa dipakai di MANA PUN .topbar tampil,
   bukan cuma dalam .bh-header (beranda). includes/topbar.php menambahkan
   kelas ini + inline style background HANYA kalau admin_utama sudah mengganti
   header lewat admin/kelola_tampilan.php (migrasi_60) -- kalau belum, kelas
   ini tidak pernah muncul dan belanja.php/lelang.php/po.php tetap tampil
   persis seperti sebelumnya (.topbar putih polos). Inline style="background:..."
   PASTI menang lawan ".bh-header .topbar{background:none}" di atas (spesifisitas
   inline attribute > kombinasi class apa pun) -- jadi di beranda.php pun aturan
   ini tetap efektif begitu admin menetapkan header custom, tidak perlu
   pengecualian terpisah untuk kasus "di dalam .bh-header". */
/* box-shadow sebagai pembatas elegan (2026-08-14, permintaan pemilik --
   REVISI, lihat catatan lengkap di .bh-header: versi gradasi pertama
   menutupi konten di bawahnya, diganti box-shadow biasa yang cepat memudar
   tanpa elemen tambahan). */
.topbar.topbar-branded{ color:#fff; border-bottom:none; box-shadow:0 6px 16px rgba(0,0,0,.18); }
.topbar.topbar-branded .icon-btn{ color:#fff; }
.topbar.topbar-branded .wordmark .w1{ color:#fff; }
.topbar.topbar-branded .wordmark .w2{ color:var(--accent); }
.topbar.topbar-branded .wordmark .dom{ color:rgba(255,255,255,.6); }
.topbar.topbar-branded .right-icons .icon-circle{ background:rgba(255,255,255,.18); color:#fff; }
.topbar.topbar-branded .right-icons .icon-circle .count{ border-color:var(--navy-dark); }
.topbar.topbar-branded .search-wrap{ background:#fff; }
.topbar.topbar-branded .search-submit{ background:var(--navy); color:#fff; }
.topbar.topbar-branded .search-submit svg{ color:#fff; }
.topbar.topbar-branded .btn-masuk{ background:#fff; color:var(--navy); }
.topbar.topbar-branded .location-strip{ background:none; padding:2px 16px 0; }
.topbar.topbar-branded .location-strip span{ color:rgba(255,255,255,.8); }
.topbar.topbar-branded .location-strip b{ color:#fff; }
/* Refresh visual beranda (2026-07-12) -- "jangan terlalu polos, kontainer rapi
   seperti Blibli". Semua kelas di bawah ADITIF dan dipakai HANYA di beranda.php;
   .cat-row/.trust-row/.section polos punya markup yang sama persis di
   belanja.php/lelang.php/po.php/produk_detail.php (lihat catatan proyek), jadi
   sengaja tidak menyentuh definisi kelas dasarnya supaya halaman lain tidak ikut
   bergeser tampilannya. */

/* Kartu Koin Saya / Multi Game (2026-08-06, migrasi_57) -- REVISI TOTAL
   2026-08-13 (permintaan pemilik: ubah dari 2 kartu jadi 4 -- Koin Saya,
   Multi Game, Forum, Berbagi -- selang-seling putih-merah). Menggantikan
   .hero-quick-row/.hero-quick-card/.quick-koin/.quick-game/.hero-quick-ic/
   .hero-quick-text/.hero-quick-label/.hero-quick-value lama (dihapus, tidak
   dipakai elemen lain manapun di situs -- dicek dulu sebelum dihapus).

   REVISI SKALA (2026-08-13, laporan pemilik: "di pc laptop dan desktop 4
   card ini terlalu besar di hp juga dan di tablet ipad juga harusnya
   container icon dan cardnya sama seperti trust row") -- versi SEBELUMNYA
   pakai aspect-ratio:1/1 (kartu jadi PERSEGI, ikut selebar 1/4 kontainer --
   di desktop 1280px itu berarti kartu ~300x300px, jauh lebih besar dari
   maksud aslinya) + ukuran ikon/font pakai clamp(...,Nvw,...) yang MEMBESAR
   mengikuti lebar layar -- akar penyebab "terlalu besar di desktop", dan
   tetap terasa besar di HP/tablet karena aspect-ratio:1/1 tetap memaksa
   tinggi kartu = lebar kolomnya. Sekarang strukturnya DISAMAKAN PERSIS
   dengan .trust-row/.trust-item/.ic-wrap di bawah (baris "100% Verifikasi"
   dkk) -- container flex row (bukan grid persegi), ukuran ikon+font TETAP
   (bukan vw-scaled), tinggi kartu mengikuti konten alami (bukan dipaksa
   persegi) -- satu-satunya beda dari trust-row murni: tiap item di sini
   punya latar warna sendiri (putih/merah selang-seling, tetap dipertahankan
   sesuai permintaan sebelumnya) karena trust-item aslinya transparan tanpa
   latar per-item. */
.quick-tile-wrap{
  background:var(--card); border-radius:18px; padding:16px 8px;
  box-shadow:0 4px 18px rgba(15,32,66,.08);
}
[data-theme="dark"] .quick-tile-wrap{ border:1px solid var(--border); }
.quick-tile-grid{
  display:flex; justify-content:space-between; gap:6px;
}
.quick-tile{
  flex:1; min-width:0; /* min-width:0 -- flex item juga defaultnya min-width:auto
    (lebar min-content), tanpa ini kartu ke-4 tetap bisa terdorong keluar di
    layar sangat sempit, sama akar masalah seperti versi grid sebelumnya. */
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:4px; text-align:center; text-decoration:none;
  padding:10px 4px; border-radius:14px;
  box-shadow:0 1px 4px rgba(15,32,66,.08);
  transition:transform .18s ease;
}
.quick-tile:active{ transform:scale(1.03); }
@media (hover:hover){
  .quick-tile:hover{ transform:scale(1.02); }
}
.quick-tile.tile-putih{ background:var(--card); border:1px solid rgba(15,32,66,.06); }
.quick-tile.tile-merah{ background:var(--navy); }
[data-theme="dark"] .quick-tile.tile-putih{ border:1px solid var(--border); }
/* 20px (2026-08-13) -- SAMA PERSIS dengan ukuran ikon .trust-item (lihat
   beranda.php baris .ic-wrap img: width:20px;height:20px), TETAP di semua
   lebar layar (bukan lagi clamp(...,vw,...) yang membesar di desktop). */
.quick-tile-ic{
  width:20px; height:20px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
}
.quick-tile-ic svg{ width:100%; height:100%; }
.quick-tile.tile-putih .quick-tile-ic{ color:var(--navy); }
.quick-tile.tile-merah .quick-tile-ic{ color:#fff; }
/* Ikon custom Koin/Game/Forum/Berbagi -- upload admin, object-fit contain
   supaya tetap proporsional mengikuti kontainernya, SATU ukuran dasar sama
   untuk keempatnya (mengisi .quick-tile-ic yang sama persis). */
.quick-tile-ic img.quick-tile-custom-icon{ width:100%; height:100%; object-fit:contain; }
/* 10px/9px (2026-08-13) -- skala sama dengan label .trust-item (font-size:10px),
   TETAP (bukan clamp vw) di semua lebar layar, sama alasan seperti ikon di atas. */
.quick-tile-judul{ font-size:10px; font-weight:800; line-height:1.3; }
.quick-tile-sub{ font-size:9px; font-weight:600; line-height:1.25; margin-top:1px; }
.quick-tile.tile-putih .quick-tile-judul, .quick-tile.tile-putih .quick-tile-sub{ color:var(--navy); }
.quick-tile.tile-merah .quick-tile-judul, .quick-tile.tile-merah .quick-tile-sub{ color:#fff; }
.quick-tile.tile-putih .quick-tile-sub{ opacity:.75; }
.quick-tile.tile-merah .quick-tile-sub{ opacity:.88; }

/* Hero promo Merah Putih (2026-08-13, REVISI setelah pemilik menilai versi
   pertama "terlalu ngejreng, warna section lain ga sepadan") -- dulu
   .beranda-hero membungkus TOPBAR+banner+cat-row jadi satu tembok merah
   full-bleed tanpa jeda. Sekarang jadi .hero-promo-card: satu kartu MEMBULAT
   TERBUNGKUS (bukan full-bleed) di dalam .section biasa, sama seperti .card
   lain di halaman -- topbar & cat-row TIDAK lagi ikut merah, cuma kartu ini.
   Ini satu-satunya tempat merah boleh dominan penuh (banner kampanye) sesuai
   aturan "merah sebagai aksen" -- lihat memori project. Balon dekoratif LAMA
   dihapus (kesan playful, bukan "elegan" seperti diminta pemilik).

   REVISI KEDUA (2026-08-13, hari yang sama) -- versi pertama di atas SENGAJA
   "teks saja, tanpa gambar" (lihat riwayat), tapi pemilik lapor gambar yang
   diupload admin/kelola_banner.php tidak pernah tampil sama sekali ("kok ga
   bisa saya tampilkan"). Sekarang gambar ($heroPromo['gambar']) dipasang
   sebagai lapisan foto SUNGGUHAN di belakang teks, pakai teknik "blur extend"
   yang SAMA PERSIS dengan .banner-slide (lihat catatan lengkap di sana) --
   object-fit:contain (foto TIDAK PERNAH terpotong, permintaan eksplisit
   "terlihat full di layar pelanggan") + backdrop blur dari foto yang sama
   mengisi ruang kosong kiri-kanan, TANPA gradasi gelap di atas foto (permintaan
   lama pemilik di .banner-slide: "banner ga da shadow atau menggelap",
   dipakai konsisten di sini) -- keterbacaan teks dijaga lewat text-shadow.
   Kalau admin belum pernah upload gambar sama sekali, gradient merah anggur
   bawaan di bawah ini tetap tampil apa adanya (fallback, tidak ada regresi
   untuk banner yang cuma teks).

   Rasio per breakpoint (2026-08-13, permintaan eksplisit pemilik, tabel
   device->rasio->tinggi) -- BEDA dari .banner-slider yang satu rasio (16:7)
   di semua lebar -- kartu ini sengaja makin PIPIH (rasio makin lebar) di
   layar makin besar, supaya tetap proporsional sebagai "kartu kampanye"
   ukuran sedang, bukan banner raksasa penuh layar di desktop.

   REVISI KETIGA (2026-08-13, hari yang sama) -- .hero-promo-card SEBELUMNYA
   cuma tampil SATU banner (banners[0]), padahal pemilik sudah simpan beberapa
   banner aktif untuk Beranda lewat admin/kelola_banner.php dan mengira semua
   akan tampil. Dipecah jadi wrapper .hero-promo-slider (aspect-ratio/rounded/
   shadow/fallback gradient pindah ke sini, TIDAK berubah nilainya) + banyak
   .hero-promo-card di dalamnya sebagai slide yang saling tumpuk+fade gantian
   (position:absolute+opacity, pola identik .banner-slide) -- kalau cuma ada 1
   banner aktif, perilakunya PERSIS seperti sebelumnya (satu kartu diam, tidak
   ada dot/autoplay karena JS di beranda.php sengaja skip kalau slide<2). */
/* min-height:140px (2026-08-13, ditemukan lewat audit responsif menyeluruh) --
   aspect-ratio:2.35/1 SAJA di layar SANGAT sempit (<=320px, HP jadul/kecil,
   di bawah rentang 360-480px yang jadi acuan tabel rasio pemilik) menghasilkan
   kartu cuma ~116px tinggi -- badge+judul 3 baris+subjudul+tombol butuh ~127px,
   TERPOTONG overflow:hidden (tombol "Belanja Sekarang" ikut hilang, bukan cuma
   subjudul). min-height jadi PAGAR BAWAH tambahan (menang lawan aspect-ratio
   kalau aspect-ratio hasilnya lebih pendek) -- di 360-480px+ tidak berpengaruh
   sama sekali (aspect-ratio disitu sudah menghasilkan >=140px, sesuai tabel
   pemilik 144-160px), CUMA menyelamatkan kasus ekstrem HP <360px yang memang
   di luar rentang tabel itu. */
.hero-promo-slider{
  position:relative; overflow:hidden;
  width:100%; /* (2026-08-13, bug nyata diperbaiki: "banner lelang condong ke
    kanan") -- tanpa width eksplisit, saat min-height:168px MENANG lawan
    aspect-ratio (layar sempit ~<395px, tinggi dari rasio 2.35:1 cuma ~152px),
    browser recompute LEBAR dari rasio x 168px = ~395px -- lebih lebar dari
    ruang .section yang tersedia (~358px), jadi kartu melebar ke KANAN
    (sisi kiri tetap nempel 16px padding, sisi kanan tembus nyaris ke tepi
    layar). width:100% mengunci lebar selalu mengisi container, aspect-ratio
    tetap menentukan tinggi seperti biasa, min-height tetap jadi pagar bawah
    tinggi tanpa lagi mengganggu lebar. */
  aspect-ratio:2.35/1; min-height:168px;
  background:linear-gradient(150deg,var(--navy) 0%,var(--navy-dark) 100%);
  border-radius:20px; margin-bottom:14px;
  box-shadow:0 10px 28px rgba(0,0,0,.14);
}
/* .beranda-full (2026-08-14, permintaan pemilik: "banner lebarnya full dan ga
   ada potonya sudut ... khusus di banner beranda saja") -- modifier TAMBAHAN
   di atas .hero-promo-slider dasar, HANYA dipasang di beranda.php (lihat
   markupnya) -- lelang.php TETAP pakai .hero-promo-slider polos (kartu
   membulat biasa di dalam .section), tidak ikut berubah sama sekali.

   Trik "full-bleed" width:100vw + margin-left:calc(50% - 50vw) -- 50% di sini
   dihitung dari lebar CONTAINING BLOCK elemen ini (.section, anak .phone),
   TIDAK terpengaruh .phone{position:relative} (margin persentase pada elemen
   normal-flow selalu dihitung dari lebar parent langsungnya, bukan dari
   posisi/positioning ancestor manapun) -- selama .phone sendiri berada di
   TENGAH viewport (body{display:flex;justify-content:center}, sudah berlaku
   di seluruh situs), formula ini melepaskan elemen dari batas max-width+
   padding .phone/.section, benar-benar menyentuh kedua tepi viewport
   sungguhan di lebar layar berapa pun -- TERMASUK saat .phone sendiri dibatasi
   (desktop, breakpoint manapun). Aman dari sliver horizontal-scroll (isu
   klasik 100vw yang ikut lebar scrollbar) karena html,body sudah
   overflow-x:clip (lihat :root) -- pola sama yang sudah dipakai/dibuktikan
   aman di breakpoint HP-miring/tablet .phone sendiri (lihat catatan
   --lebar-phone:100vw di bawah). border-radius:0 + box-shadow:none -- elemen
   edge-to-edge, sudut membulat/bayangan kartu akan terlihat aneh menempel
   pas di tepi layar sungguhan. */
.hero-promo-slider.beranda-full{
  width:100vw;
  margin-left:calc(50% - 50vw);
  border-radius:0;
  box-shadow:none;
}
.hero-promo-card{
  position:absolute; inset:0; overflow:hidden;
  opacity:0; transform:translateX(20px); pointer-events:none;
  transition:opacity .5s ease, transform .5s ease;
}
.hero-promo-card.active{ opacity:1; transform:translateX(0); pointer-events:auto; }
/* Backdrop blur (identik .banner-slide::before) -- --hero-bg diisi inline per
   banner (lihat beranda.php), fallback none kalau banner tidak punya gambar. */
.hero-promo-card::before{
  content:""; position:absolute; inset:-20px; z-index:0;
  background-image:var(--hero-bg, none);
  background-size:cover; background-position:center;
  filter:blur(28px) brightness(.65) saturate(1.15);
  transform:scale(1.1);
}
.hero-promo-card .hero-promo-img{
  position:absolute; inset:0; width:100%; height:100%; z-index:1;
  object-fit:contain;
}
.hero-promo-dots{ position:absolute; bottom:10px; left:50%; transform:translateX(-50%); z-index:5; display:flex; gap:5px; }
.hero-promo-dots span{ width:6px; height:6px; border-radius:50%; background:rgba(255,255,255,.4); transition:all .25s; cursor:pointer; }
.hero-promo-dots span.active{ width:18px; border-radius:4px; background:#fff; }
.hero-promo-txt{
  position:relative; z-index:2; height:100%;
  display:flex; flex-direction:column; justify-content:center;
  max-width:75%; padding:0 20px;
}
.hero-promo-badge{
  display:inline-flex; align-items:center; gap:5px; background:var(--accent); color:#3d2e05;
  font-size:10.5px; font-weight:800; letter-spacing:.3px; padding:4px 11px; border-radius:20px;
  margin-bottom:8px; width:fit-content; text-shadow:none;
}
.hero-promo-title{
  color:#fff; font-size:17px; font-weight:800; line-height:1.22;
  margin-bottom:5px; text-wrap:balance; text-shadow:0 1px 6px rgba(0,0,0,.5);
}
.hero-promo-sub{
  color:rgba(255,255,255,.9); font-size:11.5px; line-height:1.45; margin-bottom:10px;
  text-shadow:0 1px 5px rgba(0,0,0,.5);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.hero-promo-cta{
  display:inline-flex; align-items:center; gap:6px; background:#fff; color:var(--navy);
  font-size:12px; font-weight:800; padding:8px 15px; border-radius:12px; text-decoration:none;
  width:fit-content;
}
/* "Tablet" 768-1024px (permintaan pemilik) -- rasio 3:1, teks kembali sedikit
   lebih lega karena kartu jadi lebih tinggi absolut walau rasio lebih pipih. */
@media (min-width:768px){
  .hero-promo-slider{ aspect-ratio:3/1; }
  .hero-promo-title{ font-size:22px; margin-bottom:7px; }
  .hero-promo-sub{ font-size:12.5px; margin-bottom:14px; }
  .hero-promo-badge{ font-size:11px; padding:5px 12px; margin-bottom:10px; }
  /* .beranda-full (2026-08-14) -- width:100vw lolos dari batas max-width
     .phone, jadi di layar TABLET/DESKTOP LEBAR (>.phone yang biasanya
     membatasi lebar efektif kartu ini) aspect-ratio bisa menghasilkan tinggi
     lebih besar dari yang dimaksud pemilik -- max-height jadi pagar atas,
     aspect-ratio tetap menentukan tinggi normal selama belum melewati ini. */
  .hero-promo-slider.beranda-full{ max-height:340px; }
}
/* "Desktop" 1280px+ (permintaan pemilik) -- rasio 3.75:1 (tengah rentang
   3.5-4:1 yang diminta). */
@media (min-width:1280px){
  .hero-promo-slider{ aspect-ratio:3.75/1; }
  .hero-promo-txt{ padding:0 34px; }
  .hero-promo-title{ font-size:28px; }
  .hero-promo-sub{ font-size:13.5px; }
  /* Sama seperti tablet di atas -- makin lebar layar (monitor ultra-lebar
     dst), makin penting pagar ini supaya banner tidak jadi raksasa tidak
     proporsional. */
  .hero-promo-slider.beranda-full{ max-height:460px; }
}

.promo-member-strip{ background:var(--navy-tint); border-bottom:1px solid var(--border); padding:12px 0 14px; }
.promo-member-head{ display:flex; align-items:center; justify-content:space-between; padding:0 16px 10px; gap:10px; }
.promo-member-eyebrow{ font-size:10.5px; color:var(--muted); line-height:1.2; }
.promo-member-title{ font-size:13.5px; font-weight:800; color:var(--navy); line-height:1.3; }
.promo-member-more{ display:flex; align-items:center; gap:2px; font-size:11.5px; font-weight:700; color:var(--navy); white-space:nowrap; }
.promo-member-row{ padding:0 16px; }
.promo-member-card{
  min-width:96px; max-width:96px; background:var(--card); border-radius:12px; overflow:hidden; flex-shrink:0;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); display:block;
}
.promo-member-card img{ width:100%; height:80px; object-fit:cover; display:block; background:#eee; }
.promo-member-card .body{ padding:7px; }
.promo-member-card .name{ font-size:10px; font-weight:600; color:var(--text); line-height:1.3; margin-bottom:3px; display:-webkit-box; -webkit-line-clamp:1; -webkit-box-orient:vertical; overflow:hidden; }
.promo-member-card .price{ font-size:11px; font-weight:800; color:var(--navy); }
.promo-member-card .price-old{ font-size:9px; color:var(--muted); text-decoration:line-through; }

/* Kontainer kartu untuk section yang sebelumnya cuma <div class="section"> polos
   tanpa latar/bayangan sendiri (Lelang, Flash Sale, Produk Unggulan) -- beda dengan
   .trust-row yang sudah jadi kartu putih sendiri sejak awal, jadi TIDAK dipakai di situ
   supaya tidak jadi kartu-di-dalam-kartu. */
.section-card{
  background:var(--card); border-radius:20px; padding:16px; margin:0 16px 14px;
  box-shadow:0 2px 10px rgba(23,31,97,.07); border:1px solid rgba(23,31,97,.04);
}
.section-card .section-head{ margin-bottom:12px; }
/* semburat warna tipis khusus section yang sifatnya "mendesak/waktu terbatas",
   Produk Unggulan sengaja dibiarkan putih polos (bukan promo, jadi tidak perlu
   kesan urgent) */
.section-card.tint-lelang{ background:linear-gradient(180deg,#fff5f5 0%,#ffffff 60%); }
.section-card.tint-flash{ background:linear-gradient(180deg,#fffbeb 0%,#ffffff 60%); }

/* Tab kategori produk beranda (2026-07-19) -- gaya teks+underline biru, SENGAJA
   beda dari .pill/.dash-tab yang sudah ada (pill terisi navy penuh) -- permintaan
   eksplisit pemilik "warna BIRU teks dan/atau underline", bukan pill terisi. */
.produk-tab-row{ display:flex; gap:18px; overflow-x:auto; scrollbar-width:none; padding:0 0 2px; }
.produk-tab-row::-webkit-scrollbar{ display:none; }
.produk-tab{
  background:none; border:none; padding:0 0 8px; margin:0;
  font-size:13px; font-weight:700; color:var(--muted); white-space:nowrap; flex-shrink:0;
  cursor:pointer; border-bottom:2px solid transparent;
}
.produk-tab.active{ color:var(--navy); border-bottom-color:var(--navy); }

/* kategori dengan lingkaran warna per kategori -- grid 6 kolom (2026-08-13,
   spec redesign "a b": "6-col category grid" ala Shopee, gantikan strip
   scroll-horizontal lama). auto-fill (BUKAN grid-template-columns:repeat(6,1fr)
   tetap) -- .phone melebar jauh lebih lebar dari 480px di breakpoint desktop
   (lihat --lebar-phone di :root, sampai 1720px di layar sangat lebar), kalau
   dipaksa 6 kolom tetap ikon akan meregang jadi lingkaran raksasa dengan celah
   kosong aneh. minmax(58px,1fr) pas menghasilkan PERSIS 6 kolom di lebar HP
   (~360-430px isi setelah padding), lalu otomatis nambah kolom (bukan
   melebarkan ikon) begitu kontainer melebar di tablet/desktop -- ikon selalu
   tampil ukuran wajar di breakpoint mana pun. Item yang tersisa di baris
   terakhir (mis. 11 item -> baris kedua cuma 5) dibiarkan rata kiri apa
   adanya, pola umum grid kategori e-commerce, tidak perlu dipaksa center. */
/* Kontainer kartu (2026-08-13, permintaan pemilik: "katagori ada kontainer bisa
   ga yang bagus modern pas elegan keren") -- disamakan bahasa visualnya dengan
   .trust-row/.hero-quick-row (kartu putih membulat+bayangan lembut yang sama
   persis), supaya 3 section berurutan ini (Koin/Game, Kategori, Trust) terasa
   satu keluarga desain, bukan tiga gaya berbeda-beda.

   Ukuran presisi mobile/tablet (2026-08-13, permintaan eksplisit pemilik: ikon
   42x42px, gap antar kolom 4-6px) TETAP dipertahankan -- margin:0 (bukan lagi
   -10px) karena sekarang .cat-row py sendiri padding+kartu, tidak perlu lagi
   "mencuri" padding .section seperti versi tanpa-kontainer sebelumnya. padding
   10px kiri-kanan dipilih supaya 6 kolom tetap muat nyaman (~308px area grid
   di layar 360px setelah padding .section 16px + padding kartu 10px, mirip
   perhitungan sebelumnya, cuma sekarang sebagian "jatah lebar" itu terpakai
   jadi padding kartu yang terlihat, bukan celah kosong). repeat(6,1fr) (BUKAN
   auto-fill) supaya SELALU tepat 6 kolom sampai breakpoint desktop 900px
   (lihat override di sana). */
.cat-row{
  display:grid; grid-template-columns:repeat(6,1fr); gap:12px 5px;
  background:var(--card); border-radius:18px; box-shadow:0 4px 18px rgba(15,32,66,.08);
  margin:0; padding:14px 10px 16px;
}
.cat-item{ display:flex; flex-direction:column; align-items:center; gap:4px; }
.cat-item .ic{
  width:42px; height:42px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 3px 8px rgba(0,0,0,.10);
  transition:transform .15s ease;
  overflow:hidden;
  margin:0 auto;
}
.cat-item .ic img{ width:100%; height:100%; object-fit:cover; }
.cat-item:active .ic{ transform:scale(.92); }
.cat-item span{ font-size:9.5px; color:var(--text); font-weight:700; text-align:center; line-height:1.2; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }

/* "Semua Kategori" (kategori.php, migrasi_59, 2026-08-13, desain dirombak
   2026-08-13 kedua -- permintaan pemilik: "harusnya lebih bagus responsif dan
   modern dan keren"). Kartu pakai warna_bg/warna_text ASLI per kategori (bukan
   navy generik) supaya variatif, animasi expand/collapse murni CSS lewat
   grid-template-rows 0fr->1fr (jauh lebih halus dari <details> native yang snap
   mendadak tanpa transisi), 1 kartu terbuka per waktu lewat assets/js/
   kategori_akordeon.js. Kelas baru semua, TIDAK menyentuh .cat-row/.cat-item
   di atas (dipakai berbeda-beda di banyak halaman lain, lihat catatan di atasnya). */
.kat-hero{
  background:linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  padding-bottom:18px;
}
.kat-hero-sub{ margin:0; padding:0 16px; font-size:12.5px; color:rgba(255,255,255,.8); line-height:1.5; }

.kat-tree{ display:flex; flex-direction:column; gap:12px; }
.kat-card{
  background:var(--card); border:1px solid var(--border); border-radius:16px; overflow:hidden;
  transition:box-shadow .2s ease, border-color .2s ease;
  /* 76px = tinggi .bottomnav (~58px) + jarak aman, angka acuan yang sama dipakai
     base .phone padding-bottom (2026-08-13) -- tanpa ini scrollIntoView() di
     kategori_akordeon.js berhenti tepat di tepi viewport asli, padahal bagian
     itu ketutupan .bottomnav yang fixed+z-index:30 di atasnya. scroll-margin
     dihormati otomatis oleh scrollIntoView() native, tidak perlu ubah JS. */
  scroll-margin-bottom:76px;
}
.kat-card.is-open{ box-shadow:0 8px 24px rgba(0,0,0,.08); border-color:transparent; }
.kat-card-head{
  width:100%; display:flex; align-items:center; gap:12px; padding:14px 16px;
  background:none; border:none; cursor:pointer; text-align:left; font:inherit; color:inherit;
}
@media (hover:hover){
  .kat-card-head:hover .kat-card-ic{ transform:scale(1.06); }
}
.kat-card-ic{
  width:52px; height:52px; border-radius:16px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  font-weight:800; font-size:19px; overflow:hidden;
  box-shadow:0 4px 10px rgba(0,0,0,.10);
  transition:transform .2s ease;
}
.kat-card-ic img{ width:100%; height:100%; object-fit:cover; }
.kat-card-info{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.kat-card-nama{ font-weight:800; font-size:14.5px; color:var(--text); }
.kat-card-count{ font-size:11px; color:var(--muted); font-weight:600; }
.kat-chevron{ color:var(--muted); transition:transform .25s ease; flex-shrink:0; }
.kat-card.is-open .kat-chevron{ transform:rotate(180deg); color:var(--navy); }

/* Animasi tinggi halus tanpa JS ukur pixel -- grid 0fr (tertutup) ke 1fr (terbuka)
   otomatis mengikuti tinggi konten asli, transisi mulus di kedua arah. Konten
   dalamnya WAJIB dibungkus 1 elemen (.kat-card-body-inner) dengan overflow:hidden
   supaya tidak "bocor" kelihatan sebelum grid selesai melebar. */
.kat-card-body-wrap{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .3s ease; }
.kat-card.is-open .kat-card-body-wrap{ grid-template-rows:1fr; }
.kat-card-body-inner{ overflow:hidden; }
.kat-card-body-inner > *{ padding-left:16px; padding-right:16px; }
.kat-card-body-inner > *:first-child{ margin-top:2px; }
.kat-card-body-inner > *:last-child{ margin-bottom:16px; }

.kat-lihat-semua{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:11px 14px; border-radius:12px; font-weight:800; font-size:12.5px;
  text-decoration:none; margin-bottom:14px;
}
.kat-sub-grid{ display:flex; flex-direction:column; gap:10px; }
.kat-sub-card{
  background:var(--bg); border-radius:12px; padding:10px 12px; display:flex; flex-direction:column; gap:10px;
}
.kat-sub-head{ display:flex; align-items:center; gap:10px; text-decoration:none; }
.kat-sub-ic{
  width:30px; height:30px; border-radius:9px; flex-shrink:0; overflow:hidden;
  display:flex; align-items:center; justify-content:center; font-weight:800; font-size:12.5px;
}
.kat-sub-ic img{ width:100%; height:100%; object-fit:cover; }
.kat-sub-nama{ font-weight:700; font-size:13px; color:var(--text); }
.kat-l3-row{ display:flex; flex-wrap:wrap; gap:7px; padding-left:40px; }
.kat-l3-chip{
  padding:5px 12px; border-radius:20px; background:var(--card); border:1px solid var(--border);
  color:var(--muted); font-size:11px; font-weight:700; text-decoration:none; white-space:nowrap;
  transition:border-color .15s ease, color .15s ease;
}
@media (hover:hover){
  .kat-l3-chip:hover{ border-color:var(--navy); color:var(--navy); }
}
.kat-kosong{ font-size:12px; color:var(--muted); }

/* Desktop (900px+) -- kartu kategori jadi grid 2 kolom biar tidak jomplang panjang
   ke bawah di layar lebar, sub kategori di dalam kartu terbuka ikut jadi 2 kolom. */
@media (min-width:900px){
  .kat-tree{ display:grid; grid-template-columns:repeat(2, 1fr); align-items:start; gap:14px; }
  .kat-card.is-open{ grid-column:1 / -1; }
  .kat-sub-grid{ display:grid; grid-template-columns:repeat(2, 1fr); gap:10px; }
}
@media (min-width:1280px){
  .kat-tree{ grid-template-columns:repeat(3, 1fr); }
  .kat-sub-grid{ grid-template-columns:repeat(3, 1fr); }
}

/* .banner-slider/.banner-slide/.banner-dots DIHAPUS (2026-08-13) -- lelang.php
   sudah dipindah ke .hero-promo-slider/.hero-promo-card yang sama persis dengan
   beranda.php (permintaan pemilik: "banner lelang di buat sama mirip gayanya
   seperti banner di beranda"), tidak ada markup manapun lagi yang memakai kelas
   .banner-slider/.banner-slide/.banner-dots -- lihat .hero-promo-* di atas untuk
   aturan yang sekarang dipakai KEDUA halaman. */

/* baris trust badge (2026-07-28, modernisasi ikon+kartu -- permintaan pemilik
   "bisa ga lebih modern termasuk iconnya") -- kotak lebih besar & rounded, gradasi
   lembut dua-nada pengganti tint datar 15% opacity yang terasa flat, plus
   bayangan+cincin tipis di baliknya supaya terasa "melayang", dan hover lift halus
   di desktop (mouse sungguhan saja, sama pola dengan .product-card:hover). */
.trust-row{
  /* margin horizontal DIHAPUS (2026-08-13, laporan pemilik "kontainernya kurang
     lebar sedikit, samakan lebarnya dengan flashsale jsm") -- .trust-row selalu
     dipasang DI DALAM <div class="section"> (beranda.php/lelang.php/po.php) yang
     sudah punya padding 16px kiri-kanan sendiri, jadi margin 16px tambahan di
     sini bikin insetnya DOBEL (32px total) dibanding .promo-section (Flash Sale/
     Lelang/Tukar Koin) yang cuma dapat 16px karena BUKAN anak .section -- itulah
     kenapa trust-row terlihat lebih sempit. margin:0 (biarkan .section yang atur
     inset kiri-kanan) menyamakan lebarnya persis dengan .promo-section. */
  display:flex; justify-content:space-between; gap:4px; background:var(--card); border-radius:18px;
  padding:16px 8px; margin:0 0 14px; box-shadow:0 4px 18px rgba(15,32,66,.08);
}
.trust-item{ display:flex; flex-direction:column; align-items:center; gap:8px; flex:1; }
.trust-item svg{ color:var(--navy); }
.trust-item span{ font-size:10px; color:var(--text); text-align:center; font-weight:700; line-height:1.3; }
/* Ikon berwarna dalam kotak membulat pastel (dipakai beranda.php) -- .ic-wrap murni
   aditif, trust-item TANPA .ic-wrap (statistik lelang.php/po.php yang isinya angka
   bukan ikon) tidak terpengaruh sama sekali. Warna 2026-07-13 disamakan persis
   dengan referensi Figma (teal/blue/purple/orange) -- nama kelas ikut diganti dari
   c-green/c-amber jadi c-teal/c-orange dkk supaya nama kelas tetap cocok dengan
   warna sesungguhnya (lihat pemakaiannya di beranda.php).*/
.trust-item .ic-wrap{
  width:48px; height:48px; border-radius:16px;
  display:flex; align-items:center; justify-content:center;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6), 0 3px 8px rgba(15,32,66,.08);
  transition:transform .18s ease, box-shadow .18s ease;
}
.trust-item .ic-wrap svg{ color:inherit; }
@media (hover:hover){
  .trust-item:hover .ic-wrap{ transform:translateY(-3px) scale(1.05); box-shadow:0 8px 16px rgba(15,32,66,.16); }
}
.trust-item.c-teal .ic-wrap{ background:linear-gradient(150deg,#e3f6f2,#c3ece3); color:#00897B; }
.trust-item.c-blue .ic-wrap{ background:linear-gradient(150deg,#e6f2fe,#cbe6fc); color:#1E88E5; }
.trust-item.c-purple .ic-wrap{ background:linear-gradient(150deg,#f3e8fc,#e6cdf8); color:#7B1FA2; }
.trust-item.c-orange .ic-wrap{ background:linear-gradient(150deg,#fff1de,#ffdfb0); color:#F57C00; }
/* Item ke-5 "Garansi Uang Kembali" (2026-07-28, permintaan pemilik) -- hijau
   dipilih karena asosiasi umum "uang kembali/refund" di UI e-commerce, dan belum
   dipakai warna lain di baris ini (teal/blue/purple/orange). */
.trust-item.c-green .ic-wrap{ background:linear-gradient(150deg,#e3f7e9,#c2edd0); color:#1f9d55; }

/* Section promo (Lelang/Flash Sale/Tukar Koin) -- kelas baru semua (promo-*),
   SENGAJA tidak dicampur dengan .section-head/.head-icon/.live-badge yang dipakai
   halaman lain (produk_detail, po, lelang, artikel_detail, akun) supaya tidak
   menabrak apa pun di luar beranda.php. Dua bagian: .promo-band (kepala bertema
   tint) + .promo-body (badan var(--card)).
   RESTYLE 2026-08-13 (task lanjutan rebrand Merah Putih, dulu terlewat) -- versi
   SEBELUMNYA band-red/orange/gold berupa gradasi warna JENUH PENUH (#C62828,
   #FF6B00, #8D6E00 dst, teks putih di atasnya) -- melanggar prinsip "merah jadi
   aksen, bukan cat tembok" yang sudah dipakai komponen lain (topbar, cat-row,
   dst, lihat catatan :root di atas), dan hardcode hex literal jadi TIDAK ikut
   dark mode sama sekali (section ini akan tetap menyala terang walau tema gelap
   diaktifkan). Sekarang pakai --navy-tint/--amber-tint (pudar, dark-mode aware)
   sebagai latar kepala + teks berwarna sebagai aksen, konsisten dengan
   .promo-member-strip yang sudah lebih dulu direstyle. */
.promo-section{ background:var(--card); margin:0 16px 14px; border-radius:16px; overflow:hidden; box-shadow:0 2px 10px rgba(0,0,0,.08); }
/* Bug ditemukan 2026-07-30 (audit responsif HP jadul layar kecil, ~320px) --
   .promo-title ("Flash Sale JSM"/"Lelang") dan .promo-countdown (3 kotak angka)
   sebelumnya cuma flex row polos tanpa flex-wrap, jadi di layar sesempit ini
   judulnya kepepet sampai kepotong tengah kata ("Flash Sale" lalu "JSM" turun
   sendirian) alih-alih rapi. flex-wrap:wrap membiarkan countdown pindah ke baris
   sendiri di bawah judul kalau memang tidak muat sejajar -- tidak berpengaruh
   sama sekali di lebar HP normal (375px+) yang memang sudah cukup lega. */
.promo-band{ padding:14px 16px 12px; display:flex; flex-wrap:wrap; row-gap:6px; align-items:center; justify-content:space-between; border-bottom:1px solid var(--border); }
.promo-band.band-red{ background:var(--navy-tint); }
.promo-band.band-orange{ background:var(--amber-tint); }
/* Tukar Koin (2026-08-06, migrasi_57) -- tint SAMA dengan band-orange (satu
   keluarga warna amber/emas) -- pembeda antara Flash Sale/Tukar Koin sekarang
   emoji+judul di .promo-title, bukan lagi warna latar berbeda (band-orange vs
   band-gold dulu 2 gradasi jenuh berbeda; keduanya sudah dipudarkan jadi tint
   yang sama supaya tidak ada 2 warna jenuh bertabrakan sekaligus di halaman). */
.promo-band.band-gold{ background:var(--amber-tint); }
.promo-title{ display:flex; align-items:center; gap:8px; }
.promo-title span{ color:var(--navy); font-weight:800; font-size:14.5px; }
.promo-band.band-orange .promo-title span,
.promo-band.band-gold .promo-title span{ color:var(--amber); }
.promo-live{ display:flex; align-items:center; gap:5px; background:var(--navy); border-radius:999px; padding:4px 10px; }
.promo-live .dot{ width:5px; height:5px; border-radius:50%; background:#fff; animation:blink 1.2s infinite; }
.promo-live span{ color:#fff; font-size:9.5px; font-weight:800; letter-spacing:.5px; }
.promo-countdown{ display:flex; align-items:center; gap:4px; }
.promo-countdown .lbl{ color:var(--muted); font-size:10px; margin-right:2px; }
.promo-countdown .d{
  display:inline-flex; align-items:center; justify-content:center; width:27px; height:27px;
  border-radius:7px; background:var(--bg); color:var(--navy); font-weight:800; font-size:12px;
  font-variant-numeric:tabular-nums; border:1px solid var(--border);
}
.promo-band.band-orange .promo-countdown .d,
.promo-band.band-gold .promo-countdown .d{ color:var(--amber); }
.promo-countdown .sep{ color:var(--muted); font-weight:800; font-size:11px; }
.promo-body{ background:var(--card); padding:12px; }
.promo-cta{
  display:flex; align-items:center; justify-content:center; gap:6px; width:100%; margin-top:10px;
  border-radius:11px; padding:10px; font-weight:700; font-size:12.5px; cursor:pointer;
  border:2px solid var(--navy); color:var(--navy); background:var(--card);
}
.promo-cta.cta-orange, .promo-cta.cta-gold{ border-color:var(--amber); color:var(--amber); }
.promo-empty-jsm{ font-size:11.5px; color:var(--muted); text-align:center; padding:18px 12px; line-height:1.5; }

/* Kartu Tukar Koin di beranda (2026-08-06) -- ukuran+radius sama persis
   .flash-card/.auction-card supaya tinggi baris hscroll seragam saat ketiga
   section ini ditumpuk, kontennya cuma disesuaikan (tidak ada progress bar
   kuota/countdown, cukup biaya koin + nilai/jenis). */
.koin-promo-card{
  min-width:150px; max-width:150px; background:var(--card); border-radius:14px; overflow:hidden; flex-shrink:0;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); text-decoration:none; display:block;
}
.koin-promo-card .thumb img{ width:100%; height:110px; object-fit:cover; display:block; background:#eee; }
.koin-promo-card .body{ padding:10px; }
.koin-promo-card .name{ font-size:11.5px; font-weight:700; min-height:32px; line-height:1.3; margin-bottom:6px; color:var(--text); }
.koin-promo-card .koin-biaya{ font-size:13px; font-weight:800; color:#B8860B; }
.koin-promo-card .koin-nilai{ font-size:10.5px; color:var(--muted); margin-top:2px; }

/* Ticker pengumuman pemenang lelang (2026-07-14) -- baris tipis full-bleed dari
   ujung kiri ke ujung kanan layar, isi contoh/placeholder dulu (bagian 1 dokumen
   tidak merinci fitur ini). Border di KEEMPAT sisi (bukan cuma atas-bawah seperti
   percobaan pertama) supaya kelihatan jelas sebagai kontainer persegi panjang,
   walau tetap menempel rata ke kedua sisi layar (tidak ada margin kiri-kanan) --
   beda dari .promo-section yang dibungkus radius+shadow+margin.
   Teks berjalan (marquee) beneran, bukan cuma dipotong "...": isi teks digandakan
   dua kali (satu disembunyikan dari screen reader lewat aria-hidden) lalu digeser
   translateX(-50%) tanpa henti -- karena kontennya persis dua salinan berdampingan,
   pas salinan pertama habis di kiri, salinan kedua sudah pas menyambung, jadi
   putarannya kelihatan mulus tanpa jeda/lompatan. */
/* Tema disamakan merah-putih (2026-08-13, permintaan pemilik: "buat tema uinya
   merah putih") -- SEBELUMNYA amber/gold (#fff7e6 dkk), warna keluarga sendiri
   yang tidak nyambung dengan palet rebrand. var(--navy-tint)/var(--navy) dipakai
   persis seperti .promo-member-strip, otomatis ikut dark mode juga (tidak seperti
   hex literal sebelumnya). Kecepatan (2026-08-13, laporan "terlalu cepat buat
   lebih lambat agar terbaca") sekarang baca var(--ticker-durasi) yang diisi
   inline oleh beranda.php dari pengaturan_tampilan.ticker_kecepatan_detik
   (migrasi_61, admin_utama bisa atur lewat admin/kelola_tampilan.php) --
   fallback 30s (dulu hardcode 16s) kalau admin belum pernah mengatur. */
.winner-ticker{
  display:flex; align-items:center; gap:8px; background:var(--navy-tint); border:1px solid var(--border);
  padding:8px 16px; color:var(--navy); overflow:hidden;
}
.winner-ticker svg{ flex-shrink:0; color:var(--navy); }
.ticker-viewport{ flex:1; overflow:hidden; }
.ticker-track{ display:flex; width:max-content; animation:winner-ticker-scroll var(--ticker-durasi, 30s) linear infinite; }
.ticker-track span{ font-size:11px; font-weight:600; white-space:nowrap; padding-right:56px; }
@keyframes winner-ticker-scroll{
  from{ transform:translateX(0); }
  to{ transform:translateX(-50%); }
}
@media (prefers-reduced-motion: reduce){
  .ticker-track{ animation:none; }
}

/* baris lelang */
.auction-card{
  min-width:180px; max-width:180px; background:var(--card); border-radius:14px; overflow:hidden; flex-shrink:0;
  box-shadow:0 1px 3px rgba(0,0,0,0.06);
}
.auction-card .thumb{ position:relative; }
.auction-card img{ width:100%; height:110px; object-fit:cover; display:block; background:#eee; }
.auction-card .status-badge{
  position:absolute; top:7px; left:7px; font-size:9px; font-weight:800; color:#fff;
  padding:2px 7px; border-radius:20px; letter-spacing:.3px;
}
.auction-card .kondisi-badge{
  position:absolute; top:7px; right:7px; font-size:9px; font-weight:700; color:#fff;
  background:rgba(0,0,0,.55); padding:2px 6px; border-radius:20px;
}
.auction-card .body{ padding:10px; }
.auction-card .name{ font-size:11.5px; font-weight:700; min-height:32px; line-height:1.3; }
.auction-card .bid-row{ display:flex; align-items:flex-end; justify-content:space-between; margin:6px 0; }
.auction-card .bid-label{ font-size:9px; color:var(--muted); text-transform:uppercase; }
.auction-card .bid{ font-size:14px; font-weight:800; color:var(--navy); }
.auction-card .bid-count{ font-size:10px; color:var(--muted); }
.auction-card .countdown{
  display:flex; align-items:center; gap:4px; background:rgba(26,35,126,.06);
  border-radius:10px; padding:6px 8px; margin-bottom:8px;
}
.auction-card .countdown.urgent{ background:#fef2f2; }
.auction-card .countdown .seg-h, .auction-card .countdown .seg-m, .auction-card .countdown .seg-s{ font-size:11px; font-weight:800; color:var(--navy); font-variant-numeric:tabular-nums; }
.auction-card .countdown.urgent .seg-h, .auction-card .countdown.urgent .seg-m, .auction-card .countdown.urgent .seg-s{ color:var(--red); }
.auction-card .countdown .sep{ font-size:10px; font-weight:700; color:var(--navy); }
.auction-card .countdown.urgent .sep{ color:var(--red); }
.auction-card .btn-tawar{
  width:100%; background:var(--navy); color:#fff; border:none; border-radius:10px;
  padding:8px; font-size:11px; font-weight:800; font-family:'Inter',sans-serif; cursor:pointer;
}
.live-badge{ background:var(--red); color:#fff; font-size:9px; font-weight:800; padding:2px 8px; border-radius:20px; animation:blink 1.4s infinite; }
@keyframes blink{ 50%{ opacity:.45; } }

/* lelang.php: .lelang-card (2026-08-04, permintaan pemilik -- sebelumnya .lelang-row,
   baris horizontal lebar penuh sesuai spec 5.4 asli). Ukuran DISAMAKAN PERSIS
   .product-card (dipakai di dalam .product-grid yang sama, lihat definisinya di atas)
   -- struktur/nilai visual (border-radius, shadow, hover elevation, padding info)
   sengaja disalin identik supaya konsisten sebagai satu grid, tapi tetap class/CSS
   terpisah (bukan reuse .product-card langsung) karena kartu lelang butuh elemen yang
   tidak ada di kartu produk biasa (bid-row, countdown, dst). */
.lelang-card{
  background:var(--card); border-radius:10px; overflow:hidden;
  box-shadow:0 1px 2px rgba(15,32,66,.08);
  display:block; min-width:0; border:1px solid rgba(15,32,66,.06);
  transition:box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
@media (hover:hover){
  .lelang-card:hover{ box-shadow:0 10px 24px rgba(15,32,66,.16); transform:translateY(-3px); border-color:rgba(15,32,66,.12); }
}
.lelang-card .thumb-wrap{ position:relative; display:block; }
.lelang-card .thumb-wrap img{ width:100%; aspect-ratio:1; object-fit:cover; display:block; background:#eee; }
.lelang-card .status-badge{
  position:absolute; top:6px; left:6px; font-size:9px; font-weight:800; color:#fff;
  padding:2px 7px; border-radius:20px; letter-spacing:.3px;
}
.lelang-card .status-badge.ending{ background:var(--red); }
.lelang-card .status-badge.hot{ background:var(--amber); }
.lelang-card .status-badge.new{ background:var(--accent); color:var(--navy); }
.lelang-card .status-badge.verified{ background:var(--green); }
.lelang-card .kondisi-badge{
  position:absolute; bottom:6px; right:6px; font-size:9px; font-weight:700; color:#fff;
  background:rgba(0,0,0,.55); padding:2px 6px; border-radius:20px;
}
.lelang-card .info{ padding:9px 10px 11px; }
.lelang-card .name{ font-size:12.5px; font-weight:600; line-height:1.35; margin:6px 0; color:var(--text); overflow-wrap:break-word; }
.lelang-card .bid-row{ display:flex; align-items:flex-end; justify-content:space-between; margin:0 0 6px; }
.lelang-card .bid-label{ font-size:9px; color:var(--muted); text-transform:uppercase; }
.lelang-card .bid{ font-size:14px; font-weight:800; color:var(--navy); }
.lelang-card .bid-count{ font-size:10px; color:var(--muted); }
/* Banner countdown -- diletakkan DI ATAS nama produk lewat urutan markup (lelang.php),
   bukan lewat CSS order, supaya tetap masuk akal kalau JS/CSS mati. .seg-d (hari)
   disembunyikan default lewat inline style di markup, JS (mulaiCountdown()) yang
   menampilkannya kalau sisa waktu masih >= 1 hari. */
.lelang-card .countdown{
  display:flex; align-items:center; gap:4px; flex-wrap:wrap; background:rgba(26,35,126,.06);
  border-radius:10px; padding:6px 8px;
}
.lelang-card .countdown.urgent{ background:#fef2f2; }
.lelang-card .countdown .seg-d, .lelang-card .countdown .seg-h, .lelang-card .countdown .seg-m, .lelang-card .countdown .seg-s{ font-size:11px; font-weight:800; color:var(--navy); font-variant-numeric:tabular-nums; }
.lelang-card .countdown.urgent .seg-d, .lelang-card .countdown.urgent .seg-h, .lelang-card .countdown.urgent .seg-m, .lelang-card .countdown.urgent .seg-s{ color:var(--red); }
.lelang-card .countdown .sep{ font-size:10px; font-weight:700; color:var(--navy); }
.lelang-card .countdown.urgent .sep{ color:var(--red); }
.lelang-card .lelang-tanggal-berakhir{ font-size:9.5px; color:var(--muted); margin:5px 0 2px; }
.lelang-card .btn-tawar{
  width:100%; background:var(--navy); color:#fff; border:none; border-radius:10px;
  padding:8px; font-size:11px; font-weight:800; font-family:'Inter',sans-serif; cursor:pointer;
  margin-top:6px;
}
.lelang-card .btn-tawar:disabled{ opacity:.6; cursor:not-allowed; }

/* po.php: kartu horizontal PO (bagian 5.5) -- markup sendiri turunan .lelang-row,
   progress bar kuota mengikuti pola .flash-card di beranda.php */
.po-row{
  display:flex; gap:12px; background:var(--card); border-radius:14px; padding:10px;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); margin-bottom:12px;
  transition:box-shadow .18s ease, transform .18s ease;
}
@media (hover:hover){
  .po-row:hover{ box-shadow:0 8px 20px rgba(15,32,66,.12); transform:translateY(-2px); }
}
.po-row .thumb{ position:relative; width:92px; height:92px; flex-shrink:0; border-radius:10px; overflow:hidden; }
.po-row .thumb img{ width:100%; height:100%; object-fit:cover; display:block; background:#eee; }
.po-row .badge-tetap{
  position:absolute; top:6px; left:6px; font-size:9px; font-weight:800; color:#fff;
  background:var(--navy); padding:2px 7px; border-radius:20px; letter-spacing:.3px;
}
.po-row .body{ flex:1; min-width:0; display:flex; flex-direction:column; }
.po-row .name{ font-size:12.5px; font-weight:700; line-height:1.3; margin-bottom:4px; }
.po-row .harga{ font-size:14px; font-weight:800; color:var(--navy); }
.po-row .deposit-label{ font-size:9.5px; color:var(--muted); font-weight:700; margin-bottom:6px; }
.po-row .progress-kuota{ height:6px; background:var(--border); border-radius:10px; overflow:hidden; margin-bottom:4px; }
.po-row .progress-bar{ height:100%; background:var(--navy); border-radius:10px; }
.po-row .progress-label{ font-size:9.5px; color:var(--muted); font-weight:700; margin-bottom:8px; }
.po-row .btn-pesan{
  width:100%; background:var(--navy); color:#fff; border:none; border-radius:10px;
  padding:8px; font-size:11px; font-weight:800; font-family:'Inter',sans-serif; cursor:pointer;
  text-align:center; text-decoration:none; display:block; box-sizing:border-box;
}
.po-row .btn-pesan:disabled{ opacity:.6; cursor:not-allowed; }
.po-alert{
  display:flex; align-items:center; gap:10px; background:#fef9c3; color:#854d0e;
  border-radius:12px; padding:10px 12px; margin-bottom:12px; font-size:11.5px; font-weight:700;
  text-decoration:none;
}
.po-alert svg{ flex-shrink:0; }

/* ==========================================================
   Komponen tambahan khusus produk_detail.php
   (fondasi: produk_detail.html prototipe; tab/video/sosmed/ulasan
   mengikuti zip Figma "Detail Product Menu")
   ========================================================== */

.pd-topbar{
  background:var(--card); display:flex; align-items:center; justify-content:space-between;
  gap:10px; padding:12px 14px; position:sticky; top:0; z-index:20; border-bottom:1px solid var(--border);
}
.icon-circle{
  width:34px; height:34px; border-radius:50%; background:#f0f0f0; border:none;
  display:flex; align-items:center; justify-content:center; color:var(--text); cursor:pointer; flex-shrink:0;
}
.pd-icons{ display:flex; align-items:center; gap:8px; flex-shrink:0; }
/* Badge angka lonceng notifikasi (2026-08-04, bug ditemukan+diperbaiki saat audit) --
   <span class="count"> yang baru ditambahkan ke ikon lonceng produk_detail.php
   (dan .cart-badge .count yang sudah lama ada di halaman ini) TIDAK PUNYA style
   sama sekali dalam konteks .pd-icons -- .topbar .cart-badge .count/.right-icons
   .icon-circle .count (styling gelembung merah pojok kanan-atas yang sebenarnya)
   cuma berlaku di includes/topbar.php, tidak match markup .pd-topbar milik
   produk_detail.php ini. Akibatnya angka tampil sebagai teks polos font-size:16px
   (ukuran default) mengalir SEJAJAR ikon di dalam flex .icon-circle 34px, bukan
   gelembung kecil menumpuk di pojok -- selain terlihat rusak, teks inline ini ikut
   menambah lebar .icon-circle di dalam flex row .pd-icons, jadi turut menyumbang
   overflow horizontal .pd-topbar di layar sempit (lihat catatan @media di bawah).
   Ditambal dengan pola position:absolute yang sama persis dengan
   .right-icons .icon-circle .count supaya konsisten look-nya sekaligus tidak lagi
   ikut dihitung lebarnya oleh flex layout. */
.pd-icons .icon-circle{ position:relative; }
.pd-icons .icon-circle .count{
  position:absolute; top:-4px; right:-4px;
  background:var(--red); color:#fff; font-size:9px; font-weight:800;
  min-width:16px; height:16px; border-radius:50%; padding:0 3px;
  display:flex; align-items:center; justify-content:center;
}
/* Overflow .pd-topbar di layar sempit (2026-08-04, bug ditemukan+diperbaiki saat
   audit) -- penambahan ikon notifikasi+forum ke .pd-icons produk_detail.php
   (sekarang sampai 5 ikon saat login: wishlist/share/notifikasi/forum/keranjang,
   sebelumnya cuma 3: wishlist/share/keranjang) membuat total lebar tombol-kembali +
   wordmark + grup ikon tidak lagi muat di HP <=360px (verified live lewat iframe
   getBoundingClientRect(): ikon keranjang di ujung kanan terdorong SEBAGIAN/SELURUHNYA
   keluar batas layar pada viewport 320-360px, lebar yang masih umum untuk HP Android
   kelas menengah-bawah di Indonesia) -- bahkan SETELAH perbaikan badge count di atas.
   Ikon+jarak dikecilkan bertahap (pola sama dengan .bottomnav a.nav-jual di atas yang
   sudah lebih dulu punya breakpoint 340px untuk masalah serupa) supaya tetap muat
   tanpa menghilangkan ikon apa pun. Diterapkan ke .pd-topbar/.pd-icons secara umum
   (dipakai juga lelang_detail.php yang cuma py 2 ikon dan sebenarnya tidak butuh
   pengecilan ini, tapi aman/tidak mengganggu -- kedua halaman memang sengaja berbagi
   style .pd-topbar untuk konsistensi visual, lihat catatan berkas lelang_detail.php). */
@media (max-width:390px){
  .pd-topbar .icon-circle{ width:30px; height:30px; }
  .pd-icons{ gap:5px; }
}
@media (max-width:340px){
  .pd-topbar{ gap:6px; padding:12px 8px; }
  .pd-topbar .icon-circle{ width:28px; height:28px; }
  .pd-icons{ gap:4px; }
  /* .wordmark ("watchwatch" teks brand) adalah satu-satunya elemen di baris ini yang
     TIDAK bisa mengecil lewat flex-shrink (teks, bukan kotak tetap) -- di antara
     back-button+wordmark+5 ikon, wordmark polos (89px di lebar font default) adalah
     kontributor lebar TERBESAR sesudah grup ikon itu sendiri, jadi ikut dikecilkan
     sedikit di layar tersempit supaya marjin aman lebih besar dari perhitungan
     kasar di atas. */
  .pd-topbar .wordmark{ font-size:13px; }
}

.pd-tabs{ display:flex; border-bottom:1px solid var(--border); }
.pd-tab{
  flex:1; padding:11px; text-align:center; font-size:13px; font-weight:700; color:var(--muted);
  background:none; border:none; border-bottom:2px solid transparent; cursor:pointer; font-family:'Inter',sans-serif;
}
.pd-tab.active{ color:var(--navy); border-bottom-color:var(--navy); }

.pd-pane{ display:none; }
.pd-pane.active{ display:block; }

/* Layout dua kolom produk_detail.php di desktop (2026-07-29) -- lihat override
   di @media min-width:900px untuk versi sungguhan (grid kiri-kanan); di mobile/
   tablet sempit ini cuma div polos (block, urut ke bawah seperti sebelumnya),
   TIDAK mengubah apa pun di layar sempit. */
.pd-layout{ display:block; }
.pd-desktop-actions{ display:none; } /* tombol Pesan/Keranjang/Beli Sekarang inline -- cuma dipakai di desktop, mobile tetap pakai .actionbar mengambang di bawah */
.btn-kontak-seller{
  display:flex; align-items:center; justify-content:center; gap:8px;
  background:#25d366; color:#fff; font-weight:700; font-size:13px;
  border-radius:12px; padding:12px; margin-bottom:14px; text-decoration:none;
}

/* Lightbox foto produk_detail.php (2026-07-29) -- overlay fullscreen, zoom (pinch
   2 jari di HP, scroll-wheel/klik-dobel di desktop) + geser (1 jari/drag mouse)
   ditangani penuh lewat JS (lihat script di bawah produk_detail.php), CSS di sini
   cuma kerangka visual + transisi transform-nya. */
.pd-lightbox{
  display:none; position:fixed; inset:0; z-index:200; background:rgba(0,0,0,.95);
  align-items:center; justify-content:center; touch-action:none; overscroll-behavior:contain;
}
.pd-lightbox.active{ display:flex; }
.pd-lightbox-stage{
  width:100%; height:100%; display:flex; align-items:center; justify-content:center;
  overflow:hidden;
}
.pd-lightbox-stage img{
  max-width:100%; max-height:100%; object-fit:contain; user-select:none;
  transform-origin:center center; will-change:transform;
  /* transisi dimatikan SAAT drag/pinch aktif lewat kelas .no-anim (JS toggle) --
     kalau transisi tetap aktif selama jari bergerak, foto terasa "kelambatan"/
     lag mengikuti jari, transisi cuma dipakai untuk snap-back yang mulus
     setelah jari dilepas (balik ke batas zoom/posisi wajar). */
  transition:transform .25s ease;
}
.pd-lightbox-stage img.no-anim{ transition:none; }
.pd-lightbox-close, .pd-lightbox-nav{
  position:absolute; z-index:201; background:rgba(255,255,255,.12); color:#fff;
  border:none; border-radius:50%; width:42px; height:42px; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
}
.pd-lightbox-close{ top:16px; right:16px; }
.pd-lightbox-nav.prev{ left:16px; top:50%; transform:translateY(-50%); }
.pd-lightbox-nav.next{ right:16px; top:50%; transform:translateY(-50%); }
.pd-lightbox-counter{
  position:absolute; bottom:20px; left:50%; transform:translateX(-50%);
  background:rgba(255,255,255,.15); color:#fff; font-size:12px; font-weight:600;
  padding:4px 12px; border-radius:20px;
}
@media (max-width:599px){
  /* Panah prev/next disembunyikan di HP -- di layar sempit itu cuma menutupi
     foto, swipe jari sudah cukup jadi satu-satunya cara pindah foto. */
  .pd-lightbox-nav{ display:none; }
}

.pd-gallery{ position:relative; background:var(--card); }
.pd-gallery img{ width:100%; aspect-ratio:1; object-fit:cover; display:block; background:#eee; }
.pd-counter{
  position:absolute; bottom:10px; right:10px; background:rgba(0,0,0,.55); color:#fff;
  font-size:11px; font-weight:600; padding:2px 9px; border-radius:20px;
}
.pd-thumbs{ display:flex; gap:8px; padding:10px 16px; overflow-x:auto; scrollbar-width:none; }
.pd-thumbs::-webkit-scrollbar{ display:none; }
.pd-thumb{
  width:52px; height:52px; border-radius:10px; object-fit:cover; flex-shrink:0;
  border:2px solid transparent; cursor:pointer; background:#eee;
}
.pd-thumb.active{ border-color:var(--navy); }
/* Galeri gabungan foto+video (2026-07-12) -- slide video ditandai kotak gelap
   berikon play, main area <img>/<iframe> ditoggle lewat JS, bukan dua tab terpisah. */
.pd-thumb-video{ display:flex; align-items:center; justify-content:center; background:#1c1c1e; }
.pd-gallery #pd-main-video{ width:100%; aspect-ratio:1; background:#000; }
.pd-gallery #pd-main-video iframe{ width:100%; height:100%; border:none; display:block; }

.video-card{
  display:flex; gap:10px; background:var(--card); border-radius:14px; overflow:hidden;
  box-shadow:0 1px 3px rgba(0,0,0,0.06);
}
.video-thumb{ position:relative; width:110px; height:80px; flex-shrink:0; background:linear-gradient(135deg,#1a237e,#283593); }
.play-btn{
  position:absolute; inset:0; margin:auto; width:36px; height:36px; border-radius:50%;
  background:#ff0000; display:flex; align-items:center; justify-content:center;
}
.video-info{ padding:10px 12px 10px 0; display:flex; flex-direction:column; justify-content:center; }
.video-title{ font-size:12px; font-weight:700; line-height:1.35; margin-bottom:4px; }
.video-channel{ font-size:11px; color:#ef4444; font-weight:600; }

/* Kontainer badge kepercayaan + judul + rating + harga (2026-07-13) -- sebelumnya
   .badge-row/.trust-chip TIDAK PERNAH punya CSS sama sekali (bug nyata, sama seperti
   kasus .msg dulu), makanya tampil sebagai teks polos nempel tanpa jarak/warna.
   .pd-info-card menyatukan blok ini jadi satu kartu, mengikuti resep visual yang
   sama persis dengan .spec-table/.desc-box di bawah (radius 14px, padding 14px 16px)
   supaya konsisten dalam satu halaman -- bukan resep .section-card (radius 20px)
   dari beranda.php, itu untuk halaman berbeda. */
.pd-info-card{
  background:var(--card); border-radius:14px; padding:14px 16px;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); margin-bottom:14px;
}
.badge-row{ display:flex; flex-wrap:wrap; gap:6px; }
.trust-chip{
  display:inline-flex; align-items:center; gap:3px;
  font-size:10.5px; font-weight:700; padding:4px 9px; border-radius:20px;
  white-space:nowrap;
}
.trust-chip.blue{ background:#e3f2fd; color:#1565c0; }
.trust-chip.green{ background:#dcfce7; color:#16a34a; }
.trust-chip.orange{ background:#fff3e0; color:#e65100; }
.pd-title{ padding:8px 0 0; font-size:16px; font-weight:700; line-height:1.4; }
.pd-rating{ padding:8px 0; font-size:13px; color:var(--muted); display:flex; align-items:center; gap:6px; }
.pd-rating a{ color:var(--navy); font-weight:700; }
.pd-price-wrap{ padding:6px 0 0; }
.pd-price{ font-size:22px; font-weight:800; color:var(--navy); }
.pd-price-old{ font-size:13px; color:var(--muted); text-decoration:line-through; margin-left:8px; font-weight:400; }

.arrive-box{
  background:#e8f5e9; border-radius:12px; padding:12px 14px; margin-bottom:14px;
  display:flex; gap:10px; align-items:flex-start;
}
.arrive-box svg{ color:#2e7d32; flex-shrink:0; margin-top:1px; }
.arrive-box p{ font-size:12.5px; color:#2e7d32; line-height:1.5; }
/* Varian Seller Umum (2026-07-30) -- amber, bukan hijau (itu janji platform, tidak
   berlaku di sini) atau merah (bukan bahaya, sekadar info penting). */
.arrive-box.umum{ background:#fef3c7; }
.arrive-box.umum svg{ color:#b45309; }
.arrive-box.umum p{ color:#92400e; }
[data-theme="dark"] .arrive-box.umum{ background:rgba(217,119,6,.18); }

.spec-table{ background:var(--card); border-radius:14px; padding:14px 16px; box-shadow:0 1px 3px rgba(0,0,0,0.06); margin-bottom:14px; }
.spec-row{ display:flex; justify-content:space-between; padding:7px 0; font-size:13px; border-bottom:1px solid var(--border); }
.spec-row:last-child{ border-bottom:none; }
.spec-row .l{ color:var(--muted); }
.spec-row .r{ font-weight:600; text-align:right; }

.desc-box{ background:var(--card); border-radius:14px; padding:14px 16px; box-shadow:0 1px 3px rgba(0,0,0,0.06); margin-bottom:14px; }
.desc-box h3{ font-size:14px; font-weight:700; margin-bottom:8px; }
.desc-box p{ font-size:13px; color:var(--muted); line-height:1.6; white-space:pre-line; }
.desc-box p.clamped{ display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; }
.link-btn{ background:none; border:none; color:var(--navy); font-weight:700; font-size:12.5px; padding:6px 0 0; cursor:pointer; font-family:'Inter',sans-serif; }

.seller-box{
  background:var(--card); border-radius:14px; padding:14px 16px; margin-bottom:14px;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); display:flex; align-items:center; justify-content:space-between;
}
.seller-box .left{ display:flex; align-items:center; gap:10px; }
.seller-box .avatar{ width:40px; height:40px; border-radius:50%; background:var(--navy-tint); display:flex; align-items:center; justify-content:center; color:var(--navy); font-weight:800; font-size:15px; flex-shrink:0; }
.seller-box .name{ font-size:13.5px; font-weight:700; }
/* 2026-07-30, bug ditemukan: .lokasi cuma pernah punya aturan font-size di dalam
   .product-card (9px) -- di seller-box (dan .toko-header di bawah) tidak ada
   aturan sama sekali, jadi diam-diam mewarisi ukuran default browser (~16px),
   terlihat jauh lebih besar dari teks lokasi di kartu produk manapun. */
.seller-box .lokasi{ font-size:9px; color:var(--muted); margin-top:2px; display:flex; align-items:center; gap:3px; }

.social-box{ background:var(--card); border-radius:14px; padding:14px 16px; box-shadow:0 1px 3px rgba(0,0,0,0.06); margin-bottom:14px; }
.social-box h3{ font-size:13px; font-weight:700; margin-bottom:12px; }
.social-grid{ display:flex; flex-wrap:wrap; gap:14px; }
.social-item{ display:flex; flex-direction:column; align-items:center; gap:5px; width:52px; }
.social-item span:last-child{ font-size:10px; color:var(--muted); font-weight:600; text-align:center; }
.social-ic{ width:42px; height:42px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-weight:800; font-size:15px; color:#fff; overflow:hidden; }
.social-ic.square{ border-radius:12px; }
.social-ic img{ width:100%; height:100%; object-fit:cover; }

.review-card{ background:var(--card); border-radius:14px; padding:14px 16px; box-shadow:0 1px 3px rgba(0,0,0,0.06); margin-bottom:10px; }
.review-head{ display:flex; align-items:center; gap:8px; margin-bottom:4px; flex-wrap:wrap; }
.review-name{ font-size:13px; font-weight:700; }
.review-stars{ color:#fbbf24; font-size:13px; margin-bottom:6px; }
.review-text{ font-size:12.5px; color:var(--muted); line-height:1.55; }

/* ==========================================================
   Komponen khusus profil_toko.php (bagian 5.11 dokumen)
   ========================================================== */
.toko-header{
  background:linear-gradient(135deg,var(--navy),var(--navy-dark));
  color:#fff; padding:24px 16px 20px; text-align:center;
}
.toko-header .avatar{
  width:72px; height:72px; border-radius:50%; margin:0 auto 10px;
  background:rgba(255,255,255,.15); display:flex; align-items:center; justify-content:center;
  font-size:28px; font-weight:800; overflow:hidden; border:2.5px solid rgba(255,255,255,.4);
}
.toko-header .avatar img{ width:100%; height:100%; object-fit:cover; }
.toko-header .nama{ font-size:17px; font-weight:800; display:flex; align-items:center; justify-content:center; gap:6px; flex-wrap:wrap; }
.toko-header .tagline{ font-size:12px; opacity:.8; margin-top:4px; }
.toko-header .lokasi{ font-size:9px; color:var(--muted); display:flex; align-items:center; gap:3px; }

.toko-stat-row{
  display:flex; background:var(--card); margin:-14px 16px 14px; border-radius:14px;
  box-shadow:0 4px 14px rgba(0,0,0,.08); position:relative; z-index:2; overflow:hidden;
}
.toko-stat-row .item{ flex:1; text-align:center; padding:14px 4px; }
.toko-stat-row .item + .item{ border-left:1px solid var(--border); }
.toko-stat-row .n{ font-size:16px; font-weight:800; color:var(--navy); }
.toko-stat-row .l{ font-size:10px; color:var(--muted); font-weight:700; margin-top:2px; }

.btn-subscribe{
  display:flex; align-items:center; justify-content:center; gap:8px;
  background:#ff0000; color:#fff; font-weight:800; font-size:13px;
  padding:11px; border-radius:12px; margin:0 16px 14px;
}

.toko-tabs{ display:flex; border-bottom:1px solid var(--border); margin:0 16px; }
.toko-tab{
  flex:1; padding:11px; text-align:center; font-size:13px; font-weight:700; color:var(--muted);
  background:none; border:none; border-bottom:2px solid transparent; cursor:pointer; font-family:'Inter',sans-serif;
}
.toko-tab.active{ color:var(--navy); border-bottom-color:var(--navy); }
.toko-pane{ display:none; padding:14px 16px 0; }
.toko-pane.active{ display:block; }

/* ==========================================================
   Komponen tambahan khusus akun.php dan lengkapi_profil.php
   (dashboard: zip Figma "akun saya". Form Masuk/Daftar/Lengkapi Profil
   tidak ada rujukan visual di manapun — dirancang mengikuti sistem
   desain yang sudah dipakai di seluruh situs.)
   ========================================================== */

.form-label{ display:block; font-size:11px; font-weight:700; color:var(--muted); margin:12px 0 4px; }
.form-label:first-child{ margin-top:0; }
.form-input{
  width:100%; padding:11px 14px; border-radius:12px; border:1.5px solid var(--border);
  font-size:13.5px; font-family:'Inter',sans-serif; color:var(--text); outline:none;
}
.form-input:focus{ border-color:var(--navy); }
/* Kotak pemberitahuan error/sukses (2026-07-19, permintaan pemilik: "harus ada
   style CSS ditengah laman, bagus") -- SEBELUMNYA cuma strip warna polos yang ikut
   alur dokumen (bisa muncul di mana saja tergantung scroll, gampang terlewat).
   Sekarang posisi fixed melayang di tengah-atas layar (position:fixed, horizontal
   center) dengan ikon+bayangan+animasi masuk-keluar, DAN otomatis hilang sendiri
   lewat CSS animation (bukan JS) supaya berlaku ke SEMUA halaman yang sudah
   memakai .form-error/.form-success apa adanya (30+ file, satu-satunya tempat
   yang perlu diubah adalah definisi kelas ini). Ikon pakai ::before (bukan markup
   baru) dengan alasan yang sama -- tidak perlu sentuh satu pun file PHP. */
.form-error, .form-success{
  position:fixed; top:16px; left:50%; z-index:9999;
  transform:translateX(-50%);
  display:flex; align-items:center; gap:10px;
  width:calc(100vw - 32px); max-width:400px;
  padding:14px 18px; border-radius:14px;
  font-size:13px; font-weight:700; line-height:1.4;
  box-shadow:0 10px 30px rgba(0,0,0,.18);
  animation:notifMasuk .35s ease, notifKeluar .35s ease 5.2s forwards;
}
.form-error{ background:var(--card); color:#b91c1c; border:1.5px solid #fecaca; }
.form-success{ background:var(--card); color:#166534; border:1.5px solid #bbf7d0; }
.form-error::before{ content:"⚠"; font-size:17px; flex-shrink:0; }
.form-success::before{ content:"✓"; font-size:17px; font-weight:800; flex-shrink:0; }
@keyframes notifMasuk{ from{ opacity:0; transform:translate(-50%,-14px); } to{ opacity:1; transform:translate(-50%,0); } }
@keyframes notifKeluar{ to{ opacity:0; transform:translate(-50%,-14px); visibility:hidden; } }

.auth-tabs{ display:flex; gap:8px; margin-bottom:14px; }
.auth-tab{
  flex:1; padding:11px; border-radius:12px; border:1.5px solid var(--border); background:var(--card);
  color:var(--muted); font-weight:800; font-size:13.5px; cursor:pointer; font-family:'Inter',sans-serif;
}
.auth-tab.active{ background:var(--navy); border-color:var(--navy); color:#fff; }
.auth-pane{ display:none; }
.auth-pane.active{ display:block; }
.auth-divider{ display:flex; align-items:center; gap:10px; margin:16px 0; color:var(--muted); font-size:11.5px; font-weight:700; }
.auth-divider::before, .auth-divider::after{ content:""; flex:1; height:1px; background:var(--border); }
/* Bug ditemukan 2026-07-29 -- tombol ini sengaja tetap putih literal di kedua tema
   (lihat catatan tema gelap di atas file), tapi warna TEKS-nya masih var(--text)
   yang ikut berubah terang di tema gelap -- akibatnya "Masuk dengan Google" nyaris
   tidak terbaca (terang di atas putih). Dipatok #1c1c1e (sama seperti --text tema
   terang) supaya konsisten dengan background-nya yang memang selalu putih. */
.btn-google{
  display:flex; align-items:center; justify-content:center; gap:10px; width:100%;
  background:#fff; border:1.5px solid var(--border); border-radius:12px; padding:12px;
  font-size:13.5px; font-weight:700; color:#1c1c1e;
}
.auth-switch{ text-align:center; font-size:12.5px; color:var(--muted); margin-top:16px; }
.auth-switch .link-btn{ padding:0; }

.password-wrap{ position:relative; }
.password-wrap .form-input{ padding-right:42px; }
.password-toggle{
  position:absolute; right:4px; top:50%; transform:translateY(-50%);
  background:none; border:none; padding:8px; cursor:pointer; color:var(--muted);
  display:flex; align-items:center; justify-content:center;
}

.profile-avatar{
  position:relative; width:56px; height:56px; border-radius:50%; background:var(--navy-tint); flex-shrink:0;
  display:flex; align-items:center; justify-content:center; color:var(--navy); font-weight:800; font-size:20px;
  overflow:hidden;
}
.profile-avatar img{ width:100%; height:100%; object-fit:cover; }
.cam-badge{
  position:absolute; bottom:-1px; right:-1px; width:19px; height:19px; border-radius:50%;
  background:var(--navy); border:2px solid #fff; display:flex; align-items:center; justify-content:center;
}
.btn-chip{
  flex-shrink:0; background:var(--navy-tint); color:var(--navy); border:none; border-radius:10px;
  padding:8px 12px; font-size:11.5px; font-weight:800; font-family:'Inter',sans-serif; cursor:pointer;
}

.menu-row{ display:flex; align-items:center; gap:10px; }

/* repeat(3,1fr) (2026-08-05, sebelumnya 4) -- grid sekarang menampung 6 tile
   (ditambah Dibatalkan+Digital/Jasa), 3 kolom x 2 baris rapi ketimbang 4 kolom
   yang menyisakan baris kedua timpang (cuma 2 dari 4 slot terisi). */
.pesanan-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:6px; }
.pesanan-item{ display:flex; flex-direction:column; align-items:center; gap:6px; }
.pesanan-ic{ position:relative; width:48px; height:48px; border-radius:14px; background:var(--navy-tint); display:flex; align-items:center; justify-content:center; }
.pesanan-badge{
  position:absolute; top:-4px; right:-4px; background:#ef4444; color:#fff; font-size:9px; font-weight:800;
  width:16px; height:16px; border-radius:50%; display:flex; align-items:center; justify-content:center; border:2px solid #fff;
}
.pesanan-item span:last-child{ font-size:9.5px; font-weight:700; color:var(--muted); text-align:center; }

/* Timeline "Lacak Paket" (2026-08-13, permintaan pemilik: "ada garis panjang
   penghubung titik titik udah sampe mana mananya ... ada card setiap progress
   smpe mana yang rapih dan cantik") -- dulu <ul><li> bullet polos. Dirender
   lewat assets/js/resi_timeline.js (satu fungsi dipakai akun_pesanan.php DAN
   mitra/pesanan_masuk.php DAN admin/kelola_pesanan.php, lihat catatan lengkap
   di file JS itu) -- kelas di sini juga dipakai bareng dashboard.css (admin/
   mitra) dengan definisi setara, disesuaikan warna dashboard masing-masing. */
.resi-status-head{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; margin-bottom:10px; }
.resi-status-label{ font-size:12.5px; font-weight:800; color:var(--navy); }
.resi-status-tanggal{ font-size:10.5px; color:var(--muted); }
.resi-timeline{ position:relative; padding-left:16px; }
.resi-timeline-item{ position:relative; padding-bottom:12px; }
.resi-timeline-item:last-child{ padding-bottom:0; }
.resi-timeline-item::before{
  content:''; position:absolute; left:-16px; top:5px; width:8px; height:8px; border-radius:50%;
  background:var(--border); z-index:1;
}
.resi-timeline-item::after{
  content:''; position:absolute; left:-13px; top:13px; bottom:-12px; width:2px; background:var(--border);
}
.resi-timeline-item:last-child::after{ display:none; }
.resi-timeline-item.aktif::before{ background:var(--navy); box-shadow:0 0 0 3px var(--navy-tint); }
.resi-timeline-card{ background:var(--bg); border:1px solid var(--border); border-radius:10px; padding:8px 10px; }
.resi-timeline-date{ font-size:10px; color:var(--muted); font-weight:700; margin-bottom:2px; }
.resi-timeline-desc{ font-size:11.5px; color:var(--text); line-height:1.5; }

/* Footer (includes/footer.php) sengaja disembunyikan di mobile -- konten identitas
   toko/legal/badge pembayaran ini fungsinya untuk kesan "toko resmi" saat versi
   desktop dicek verifikator (Midtrans dkk), bukan kebutuhan navigasi pembeli di HP
   yang sudah cukup terlayani lewat akun.php. Ditampilkan lagi di @media
   (min-width:900px) di bawah. */
.footer-box{ display:none; background:#e4e8ef; border-radius:16px; padding:18px 16px; }
.footer-box.footer-box-selalu{ display:block; }
.footer-nama{ font-size:15px; font-weight:800; color:var(--navy); }
.footer-tagline{ font-size:12px; font-weight:600; color:#6b7a96; margin:2px 0 10px; }
.footer-line{ font-size:11.5px; font-weight:600; color:#8898aa; line-height:1.5; }
.footer-cols{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }
.footer-col-title{ font-size:11px; font-weight:800; color:var(--navy); margin-bottom:6px; }
.footer-cols a{ display:block; font-size:10px; font-weight:600; color:#8898aa; line-height:1.6; }
.footer-pay-label{ font-size:10px; font-weight:800; color:var(--navy); margin:16px 0 8px; text-align:center; }
.footer-pay-row{ display:flex; flex-wrap:wrap; justify-content:center; gap:6px; }
.footer-pay-row .trust-chip{ background:var(--card); color:#6b7a96; }
.footer-copy{ font-size:10px; font-weight:600; color:#8898aa; text-align:center; margin-top:14px; }

.modal-overlay{
  display:none; position:fixed; inset:0; z-index:50; align-items:flex-end; justify-content:center;
  background:rgba(0,0,0,.4);
}
.modal-sheet{
  width:100%; max-width:430px; background:var(--card); border-radius:24px 24px 0 0; padding:20px;
  /* max-height+overflow-y (2026-08-05, permintaan pemilik: dialog konfirmasi
     "Jadi Penawar" butuh teks lebih panjang dari konfirmasi biasa) -- jaring
     pengaman supaya pesan panjang tidak terpotong di layar pendek (HP lama,
     landscape) tanpa cara men-scroll isinya. Tidak mengubah tampilan modal
     pendek yang sudah ada (retur/sengketa/dll) karena kontennya memang belum
     pernah setinggi ini. */
  max-height:85vh; overflow-y:auto;
}

/* ==========================================================
   Komponen tambahan khusus keranjang.php
   (fondasi: keranjang.html prototipe; checkbox/indeterminate
   mengikuti zip Figma "Keranjang")
   ========================================================== */

.edit-link{ font-size:12.5px; font-weight:700; color:#fff; cursor:pointer; flex-shrink:0; }

.seller-group{ background:var(--card); border-radius:14px; margin-bottom:12px; overflow:hidden; box-shadow:0 1px 3px rgba(0,0,0,0.06); }
.seller-group-head{ display:flex; align-items:center; gap:8px; padding:12px 14px; border-bottom:1px solid var(--border); }
.seller-group-head .name{ font-size:13.5px; font-weight:700; flex:1; }

.item-row{ display:flex; align-items:flex-start; gap:10px; padding:12px 14px; border-bottom:1px solid var(--border); }
.item-row:last-child{ border-bottom:none; }
.item-thumb-wrap{ position:relative; width:56px; height:56px; border-radius:10px; overflow:hidden; flex-shrink:0; background:#eee; }
.item-thumb-wrap img{ width:100%; height:100%; object-fit:cover; display:block; }
.item-thumb-badge{
  position:absolute; left:0; right:0; bottom:0; background:rgba(0,0,0,.65); color:#fff;
  font-size:8px; font-weight:700; text-align:center; padding:2px 0; line-height:1.3;
}
.item-row .name{ font-size:12.5px; font-weight:600; line-height:1.35; }
.item-row .cond{ font-size:11px; color:var(--muted); margin:2px 0; }
.item-row .price{ font-size:13px; font-weight:700; color:var(--navy); }
/* .price-old di sini sebelumnya tidak pernah dicoret (2026-07-27 fix) -- text-decoration
   line-through cuma didefinisikan di scope .product-card/.flash-card/.promo-member-card,
   tidak ada aturan untuk .item-row, jadi harga lama tampil polos tanpa coretan sama sekali. */
.item-row .price-old{ font-size:11px; color:var(--muted); text-decoration:line-through; margin-left:6px; font-weight:400; }
.item-row .qty{ font-size:11px; color:var(--muted); margin-top:3px; }

input[type="checkbox"]{ width:18px; height:18px; accent-color:var(--navy); flex-shrink:0; margin-top:2px; cursor:pointer; }

.qty-stepper{ display:flex; align-items:center; gap:8px; margin-top:5px; }
.qty-stepper button{
  width:22px; height:22px; border-radius:7px; border:1px solid var(--border); background:#f8fafc;
  color:var(--navy); font-weight:800; font-size:13px; cursor:pointer; font-family:'Inter',sans-serif;
  display:flex; align-items:center; justify-content:center; padding:0;
}
.qty-stepper button:disabled{ opacity:.4; cursor:not-allowed; }
.qty-stepper span{ font-size:12.5px; font-weight:800; color:var(--navy); min-width:14px; text-align:center; }

.del-btn{
  margin-left:auto; flex-shrink:0; background:none; border:none; color:var(--muted); cursor:pointer;
  padding:2px; display:flex; align-items:center;
}

.kr-bottombar{
  position:fixed; bottom:0; left:0; right:0; margin:0 auto;
  /* 430px->480px (2026-08-07, bug sekelas .bottomnav, lihat catatan di sana). */
  width:100%; max-width:480px; background:var(--card); border-top:1px solid var(--border);
  box-shadow:0 -2px 10px rgba(0,0,0,0.06);
  padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  display:flex; align-items:center; justify-content:space-between; gap:12px; z-index:30;
}
.kr-bottombar label{ display:flex; align-items:center; gap:6px; font-size:12.5px; font-weight:600; flex-shrink:0; }
.kr-bottombar .tot{ flex:1; text-align:right; }
.kr-bottombar .tot .l{ font-size:10.5px; color:var(--muted); }
.kr-bottombar .tot .n{ font-size:16px; font-weight:800; color:var(--navy); }
.kr-bottombar .btn{ width:auto; padding:12px 22px; flex-shrink:0; }
.kr-bottombar .btn:disabled{ opacity:.4; cursor:not-allowed; }

/* Kupon (2026-07-28) -- kartu input kode + saran, dipakai keranjang.php (dan
   checkout.php dengan markup serupa, lihat catatan di sana). Dimodernisasi
   2026-07-28 sore -- versi awal cuma kotak input polos + chip putus-putus datar,
   pemilik minta "lebih modern dan bagus lagi" -- ditambah header ikon+judul,
   tombol pil bergradasi konsisten dengan .kupon-tiket-btn-pakai, dan chip saran
   diberi badge ikon bulat (bukan cuma teks) supaya terasa sama dengan bahasa
   visual "tiket" yang sudah dipakai kupon_saya.php. */
.kupon-card-head{ display:flex; align-items:center; gap:8px; margin-bottom:12px; font-size:13.5px; font-weight:800; color:var(--text); }
.kupon-input-row{ display:flex; gap:8px; }
.kupon-input-row input{
  flex:1; min-width:0; padding:11px 14px; border-radius:12px; border:1.5px solid var(--border);
  font-size:13px; font-family:'Inter',sans-serif; color:var(--text); outline:none; background:var(--bg);
  transition:border-color .15s;
}
.kupon-input-row input:focus{ border-color:var(--navy); background:var(--card); }
.kupon-input-row button{
  flex-shrink:0; background:linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%); color:#fff; border:none;
  border-radius:12px; padding:0 20px; font-size:13px; font-weight:700; font-family:'Inter',sans-serif; cursor:pointer;
}
.kupon-input-row button:hover{ filter:brightness(1.08); }
.kupon-input-row button:disabled{ opacity:.6; cursor:not-allowed; filter:none; }
.kupon-pesan{ font-size:11.5px; color:var(--red); margin-top:8px; line-height:1.5; }
.kupon-diterapkan{
  display:flex; align-items:center; gap:10px; margin-top:10px;
  background:#e8f5e9; color:#2e7d32; border-radius:10px; padding:9px 12px; font-size:12px; font-weight:700;
  border:1px solid #bfe3c2;
}
.kupon-diterapkan button{ background:none; border:none; color:#2e7d32; font-size:16px; line-height:1; cursor:pointer; flex-shrink:0; }
.kupon-saran-row{ margin-top:12px; }
.kupon-saran-chip{
  display:flex; align-items:flex-start; gap:8px;
  min-width:198px; max-width:198px; flex-shrink:0; background:var(--card); border:1.5px solid var(--border);
  border-radius:12px; padding:10px 12px; cursor:pointer; box-shadow:0 1px 3px rgba(0,0,0,0.05);
  transition:border-color .15s, transform .1s;
}
.kupon-saran-chip:hover{ border-color:var(--navy); transform:translateY(-1px); }
.kupon-saran-chip-ic{
  flex-shrink:0; width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  background:var(--navy); color:#fff; margin-top:1px;
}
.kupon-saran-chip-ic svg{ width:13px; height:13px; }
.kupon-saran-chip-ongkir .kupon-saran-chip-ic{ background:#16a34a; }
.kupon-saran-chip-body{ min-width:0; flex:1; }
.kupon-saran-chip .kode{ font-size:13px; font-weight:800; color:var(--navy); }
.kupon-saran-chip .ket{ font-size:10.5px; color:var(--text); margin-top:2px; font-weight:600; line-height:1.4; }
.kupon-saran-chip .kurang{ font-size:9.5px; margin-top:4px; font-weight:700; line-height:1.4; }
.kupon-saran-chip-nonaktif{
  background:var(--bg); border-color:var(--border); cursor:not-allowed; opacity:.75; box-shadow:none;
}
.kupon-saran-chip-nonaktif:hover{ border-color:var(--border); transform:none; }
.kupon-saran-chip-nonaktif .kupon-saran-chip-ic{ background:var(--muted); }
.kupon-saran-chip-nonaktif .kode{ color:var(--muted); }
.kupon-saran-chip-nonaktif .kurang{ color:#b45309; }

/* Kartu "tiket" kupon (2026-07-28) -- dipakai kupon_saya.php. Gaya sobekan tiket
   (potongan bergerigi + notch lingkaran kiri-kanan) supaya terasa seperti kupon
   fisik, bukan kartu generik -- pola visual umum di Shopee/Tokopedia/Blibli.
   .kupon-daftar jadi grid 2-3 kolom di desktop/tablet (lihat @media di bawah)
   supaya tiket tidak melar jadi satu baris raksasa kosong di layar lebar --
   pola sama seperti .pd-gallery/.auth-tabs yang juga dikunci lebar wajar di
   breakpoint 900px (lihat catatan di sana), bukan mengikuti lebar penuh .phone. */
.kupon-daftar{ display:flex; flex-direction:column; gap:12px; }
.kupon-tiket{
  display:flex; background:var(--card); border-radius:14px; overflow:hidden;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); position:relative;
}
.kupon-tiket-kiri{
  flex-shrink:0; width:96px; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:6px; padding:14px 8px; text-align:center;
  background:linear-gradient(160deg, var(--navy) 0%, var(--navy-dark) 100%);
}
.kupon-tiket-ongkir .kupon-tiket-kiri{ background:linear-gradient(160deg, #16a34a 0%, #0d6b31 100%); }
.kupon-tiket-nilai{ color:#fff; font-size:13px; font-weight:800; line-height:1.25; }
.kupon-tiket-potong{
  flex-shrink:0; width:0; position:relative; border-left:2px dashed rgba(0,0,0,0.12);
  margin:10px 0;
}
.kupon-tiket-potong::before, .kupon-tiket-potong::after{
  content:""; position:absolute; left:-8px; width:16px; height:16px; border-radius:50%;
  background:var(--bg);
}
.kupon-tiket-potong::before{ top:-18px; }
.kupon-tiket-potong::after{ bottom:-18px; }
.kupon-tiket-kanan{ flex:1; min-width:0; padding:12px 14px; }
.kupon-tiket-baris-atas{ display:flex; align-items:center; justify-content:space-between; gap:8px; }
.kupon-tiket-kode{ font-size:14.5px; font-weight:800; color:var(--navy); letter-spacing:.3px; }
.kupon-tiket-salin{
  flex-shrink:0; background:var(--bg); border:1.5px solid var(--border); color:var(--navy);
  font-size:11px; font-weight:700; font-family:'Inter',sans-serif; border-radius:20px;
  padding:5px 12px; cursor:pointer;
}
.kupon-tiket-salin:hover{ background:var(--navy); color:#fff; border-color:var(--navy); }
.kupon-tiket-desk{ font-size:12px; color:var(--text); margin-top:5px; line-height:1.4; }
.kupon-tiket-syarat{ font-size:10.5px; color:var(--muted); margin-top:6px; line-height:1.5; }
.kupon-tiket-aksi{ margin-top:10px; }
.kupon-tiket-btn-pakai{
  display:inline-block; background:var(--navy); color:#fff; font-size:12px; font-weight:700;
  text-decoration:none; padding:7px 16px; border-radius:20px;
}
.kupon-tiket-kurang{ font-size:10.5px; color:#b45309; font-weight:700; }
.kupon-tiket-belum{ opacity:.72; }
.kupon-tiket-belum .kupon-tiket-kiri{ filter:grayscale(.55); }

/* HP layar sangat sempit (2026-07-28, "hp jadul" cth. iPhone SE/Android lama
   ~320-360px) -- kolom kiri 96px + padding kanan mulai menyempitkan konten
   kanan jadi terlalu padat, dikecilkan sedikit supaya tetap lega. */
@media (max-width:360px){
  .kupon-tiket-kiri{ width:78px; padding:12px 6px; }
  .kupon-tiket-nilai{ font-size:11.5px; }
  .kupon-tiket-kanan{ padding:10px 11px; }
  .kupon-tiket-kode{ font-size:13px; }
}

/* Tablet/desktop/MacBook (2026-07-28) -- grid 2 kolom mulai 900px (breakpoint
   desktop existing situs), 3 kolom di layar sangat lebar (1280px+) supaya tiket
   tidak melar jadi satu baris kosong panjang di monitor besar. */
@media (min-width:900px){
  .kupon-daftar{ display:grid; grid-template-columns:repeat(2, 1fr); gap:16px; }
}
@media (min-width:1280px){
  .kupon-daftar{ grid-template-columns:repeat(3, 1fr); }
}

/* ==========================================================
   Komponen tambahan khusus alamat.php
   (rujukan visual: zip Figma "alamatuser")
   ========================================================== */

.alamat-card{ position:relative; }
.alamat-card-head{ display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.label-chip{
  background:#eceff1; color:#546e7a; font-size:10.5px; font-weight:800;
  padding:2px 9px; border-radius:20px; text-transform:uppercase;
}
.alamat-nama{ font-size:13px; font-weight:700; margin-bottom:3px; }
.alamat-full{ font-size:12px; color:var(--muted); line-height:1.5; margin-bottom:10px; }
.alamat-actions{ display:flex; gap:16px; }
.alamat-actions a, .alamat-actions button{ font-size:12px; font-weight:700; color:var(--navy); background:none; border:none; padding:0; cursor:pointer; font-family:'Inter',sans-serif; }

.paste-card{ background:var(--navy-tint); border-radius:16px; padding:16px; margin-bottom:14px; }

.wilayah-field{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:11px 14px; border-radius:12px; border:1.5px solid var(--border); background:var(--card);
  font-size:12.5px; font-family:'Inter',sans-serif; color:var(--text); text-align:left; cursor:pointer;
  margin-bottom:2px; line-height:1.5;
}

.toggle-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding-bottom:14px; margin-bottom:14px; border-bottom:1px solid var(--border); }
.switch{ position:relative; width:38px; height:22px; flex-shrink:0; }
.switch input{ opacity:0; width:0; height:0; position:absolute; }
.switch .slider{ position:absolute; cursor:pointer; inset:0; background:#d1d5db; border-radius:22px; transition:.2s; }
.switch .slider:before{ content:""; position:absolute; height:16px; width:16px; left:3px; top:3px; background:#fff; border-radius:50%; transition:.2s; }
.switch input:checked + .slider{ background:var(--navy); }
.switch input:checked + .slider:before{ transform:translateX(16px); }
.switch input:disabled + .slider{ opacity:.5; cursor:not-allowed; }

.tag-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; }
.tag-option{ display:flex; align-items:center; gap:5px; font-size:12px; font-weight:700; color:var(--muted); border:1.5px solid var(--border); border-radius:10px; padding:6px 12px; cursor:pointer; }
.tag-option input{ accent-color:var(--navy); width:14px; height:14px; margin:0; }

/* ---------- jual.php (Seller Umum, 2026-07-30) ---------- */
.jual-photo-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:8px; margin-bottom:4px; }
.jual-photo-slot{
  position:relative; aspect-ratio:1; border:2px dashed var(--border); border-radius:14px;
  display:flex; align-items:center; justify-content:center; background:var(--bg); cursor:pointer;
  overflow:hidden;
}
.jual-photo-slot input{ position:absolute; inset:0; opacity:0; cursor:pointer; }
/* Pratinjau foto (2026-07-30) -- diisi lewat JS saat file dipilih, object-fit:cover
   supaya foto apa pun rasio-nya tetap mengisi slot persegi tanpa distorsi. */
.jual-photo-slot img.jual-preview{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.jual-disclaimer{
  background:#fef3c7; border-radius:12px; padding:12px 14px; margin:14px 0;
  font-size:11.5px; color:#92400e; line-height:1.6;
}
[data-theme="dark"] .jual-disclaimer{ background:rgba(217,119,6,.18); }

.picker-overlay{
  display:none; position:fixed; inset:0; z-index:60; background:var(--card); flex-direction:column;
  /* 430px->480px (2026-08-07, bug sekelas .bottomnav, lihat catatan di sana). */
  max-width:480px; margin:0 auto;
}
.picker-search-bar{ display:flex; align-items:center; gap:10px; padding:12px 16px; border-bottom:1px solid var(--border); flex-shrink:0; }
.picker-search-bar input{
  flex:1; min-width:0; border:none; outline:none; background:#f0f2f5; border-radius:20px;
  padding:9px 14px; font-size:13px; font-family:'Inter',sans-serif;
}
.gps-btn{
  display:flex; align-items:center; justify-content:center; gap:8px; margin:12px 16px 0;
  padding:11px; border:1.5px solid var(--navy); border-radius:14px; background:var(--card); color:var(--navy);
  font-size:13px; font-weight:700; font-family:'Inter',sans-serif; cursor:pointer; flex-shrink:0;
}
/* min-height:0 (2026-08-14, ditemukan lewat audit CSS menyeluruh -- pola bug
   SAMA PERSIS yang ditemukan+diperbaiki di .cs-panel-msgs/forum .chat-list
   hari yang sama) -- .picker-overlay adalah flex-column tinggi tetap
   (position:fixed;inset:0), .picker-list ini flex:1 TANPA min-height:0 bisa
   tumbuh melebihi jatahnya kalau hasil pencarian wilayah panjang (banyak
   kecamatan/kelurahan cocok), mendorong .picker-list keluar batas, halaman
   ikut discroll alih-alih list-nya sendiri. */
.picker-list{ flex:1; min-height:0; overflow-y:auto; padding-bottom:20px; }
.picker-letter{ padding:6px 16px; font-size:10.5px; font-weight:800; color:var(--accent); }
.picker-row{
  display:block; width:100%; text-align:left; padding:12px 16px; border:none; background:none;
  border-bottom:1px solid var(--border); font-size:13px; font-weight:600; color:var(--text);
  font-family:'Inter',sans-serif; cursor:pointer;
}

/* ==========================================================
   Komponen tambahan khusus checkout.php
   (rujukan visual dan kalkulasi: prototipe checkout.html — dijadikan
   acuan persis sesuai bagian 5.7 dokumen)
   ========================================================== */

.addr-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
.addr-head .label{ display:flex; align-items:center; gap:8px; font-weight:700; font-size:14px; }
.addr-head .label svg{ color:var(--navy); flex-shrink:0; }
.addr-head .ganti{ font-size:13px; color:var(--navy); font-weight:700; }
.addr-name{ font-size:14px; font-weight:700; }
.addr-full{ font-size:13px; color:var(--text); line-height:1.5; }

.seller-card{ padding:0; overflow:hidden; }
.seller-head{ display:flex; align-items:center; gap:8px; padding:14px 16px; border-bottom:1px solid var(--border); }
.seller-head .name{ font-weight:700; font-size:14px; }
.product-row{ display:flex; gap:10px; padding:14px 16px; border-bottom:1px solid var(--border); }
.product-row img{ width:56px; height:56px; border-radius:10px; object-fit:cover; flex-shrink:0; background:#eee; }
.product-name{ font-size:13px; font-weight:600; line-height:1.35; }
.product-cond{ font-size:12px; color:var(--muted); margin:2px 0; }
.product-price{ font-size:13px; font-weight:700; color:var(--navy); }
/* Sama pola bug dengan keranjang.php (2026-07-27 fix) -- .price-old flash sale/promo
   di checkout.php sebelumnya tidak pernah tercoret sama sekali karena tidak ada
   aturan CSS yang cocok dengan scope .product-price di sini. */
.product-price .price-old{ font-size:11px; color:var(--muted); text-decoration:line-through; margin-left:6px; font-weight:400; }
.product-qty{ font-size:12px; color:var(--muted); }

/* Watchwatch Instant = COD (2026-07-12): harga produk grup ini dicoret+dipudarkan
   selama Instant Jabodetabek dipilih, menandakan harga itu TIDAK ikut dibayar lewat
   Midtrans sekarang -- lihat checkout.php recalc(). */
.seller-items.cod-mode .product-price{ text-decoration:line-through; color:var(--muted); opacity:.75; }
.cod-note{
  font-size:11px; color:#e65100; background:#fff3e0; margin:0 16px 10px;
  padding:8px 10px; border-radius:8px; line-height:1.4;
}

.ship-title{ font-size:13px; font-weight:700; padding:12px 16px 6px; color:var(--text); }
.ship-option{ display:flex; align-items:center; gap:10px; padding:11px 16px; border-bottom:1px solid var(--border); cursor:pointer; }
.ship-option:last-of-type{ border-bottom:none; }
.ship-option input{ width:18px; height:18px; accent-color:var(--navy); flex-shrink:0; }
.ship-option .info{ flex:1; }
.ship-option .info .t{ font-size:13px; font-weight:700; }
.ship-option .info .s{ font-size:11.5px; color:var(--muted); }
.ship-option .price{ font-size:13px; font-weight:700; }

.addon-wrap{ padding:4px 16px 14px; }
.addon-row{ display:flex; align-items:center; justify-content:space-between; padding:9px 0; }
.addon-row .t{ font-size:13px; }
.addon-row .t .f{ font-size:11.5px; color:var(--muted); display:block; }

.rincian-row{ display:flex; justify-content:space-between; font-size:13px; padding:6px 0; color:var(--text); }
.rincian-row .l{ color:var(--muted); }
.rincian-row.total{ border-top:1.5px solid var(--border); margin-top:6px; padding-top:12px; font-size:15px; font-weight:800; }
.rincian-row.total .l{ color:var(--text); font-weight:800; }
.rincian-row.total .r{ color:var(--navy); }

.bottombar{
  position:fixed; bottom:0; left:0; right:0; margin:0 auto;
  /* 430px->480px (2026-08-07, bug sekelas .bottomnav, lihat catatan di sana). */
  width:100%; max-width:480px; background:var(--card); border-top:1px solid var(--border);
  box-shadow:0 -2px 10px rgba(0,0,0,0.06);
  padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  display:flex; align-items:center; justify-content:space-between; gap:14px; z-index:30;
}
.bottombar .totwrap .l{ font-size:11px; color:var(--muted); }
.bottombar .totwrap .n{ font-size:17px; font-weight:800; color:var(--navy); }
.bottombar button{
  background:var(--navy); color:#fff; border:none; border-radius:12px;
  padding:13px 26px; font-size:14px; font-weight:700; font-family:'Inter', sans-serif;
  cursor:pointer; white-space:nowrap;
}
.bottombar button:active{ background:var(--navy-dark); }
.bottombar button:disabled{ opacity:.6; cursor:not-allowed; }

.note{ font-size:11.5px; color:var(--muted); padding:10px 16px 4px; line-height:1.5; }

/* ==========================================================
   Komponen tambahan khusus menunggu_pembayaran.php
   (rujukan visual: prototipe menunggu_pembayaran.html)
   ========================================================== */

.mp-topbar{
  background:var(--card); display:flex; align-items:center; gap:14px;
  padding:14px 16px; border-bottom:1px solid var(--border); position:sticky; top:0; z-index:20;
}
.mp-topbar svg{ width:20px; height:20px; cursor:pointer; }
.mp-topbar h1{ font-size:16px; font-weight:700; }

.status-card{ text-align:center; }
.clock-circle{
  width:64px; height:64px; border-radius:50%; background:#fff3e0; color:var(--amber);
  display:flex; align-items:center; justify-content:center; margin:6px auto 14px;
}
.status-card h2{ font-size:19px; font-weight:800; margin-bottom:6px; }
.status-card p.desc{ font-size:13px; color:var(--muted); line-height:1.6; margin-bottom:20px; }

.tracker{ display:flex; align-items:flex-start; margin-bottom:22px; }
.tracker .step{ flex:1; text-align:center; position:relative; }
.tracker .step .dot{
  width:26px; height:26px; border-radius:50%; background:#eceff1; color:#90a4ae;
  display:flex; align-items:center; justify-content:center; margin:0 auto 6px; position:relative; z-index:2;
  font-size:11px; font-weight:800;
}
.tracker .step.active .dot{ background:var(--navy); color:#fff; }
.tracker .step span{ font-size:10.5px; color:var(--muted); font-weight:600; }
.tracker .step.active span{ color:var(--navy); font-weight:700; }
.tracker .step:not(:last-child)::after{
  content:""; position:absolute; top:13px; left:50%; width:100%; height:2px; background:#eceff1; z-index:1;
}

.btn-wa{
  background:#25d366; color:#fff; border:none; border-radius:12px; padding:13px 20px;
  font-size:14px; font-weight:700; font-family:'Inter',sans-serif; width:100%;
  display:flex; align-items:center; justify-content:center; gap:8px; cursor:pointer;
}
.helper-text{ font-size:11.5px; color:var(--muted); text-align:center; padding:12px 4px; line-height:1.6; }
.helper-text b{ color:var(--text); }

.order-card .order-no{ text-align:center; font-weight:800; font-size:14px; letter-spacing:0.5px; padding-bottom:10px; border-bottom:1px solid var(--border); margin-bottom:10px; }
.order-line{ display:flex; justify-content:space-between; font-size:13px; padding:6px 0; }
.order-line.muted{ color:var(--muted); }
.order-line.total{ border-top:1px solid var(--border); margin-top:6px; padding-top:10px; font-weight:800; font-size:14.5px; }
.order-line.total span:last-child{ color:var(--navy); }
.order-line.cod span:first-child{ text-decoration:line-through; color:var(--muted); opacity:.75; }
.order-line.cod b{ text-decoration:none; opacity:1; color:#e65100; font-size:10.5px; border:1px solid #e65100; border-radius:4px; padding:1px 4px; margin-left:4px; }

/* ---------- akun_pesanan.php / beri_penilaian.php ---------- */
.rating-picker{ display:flex; gap:8px; padding:6px 0 4px; }
.rating-picker .bintang{ cursor:pointer; }

/* ---------- blog.php / artikel_detail.php ---------- */
.kategori-tag{
  display:inline-block; font-size:10px; font-weight:800; color:var(--navy);
  background:rgba(26,35,126,.08); padding:3px 10px; border-radius:20px; margin-bottom:6px;
}
.article-card{ display:block; padding:0; margin-bottom:14px; overflow:hidden; }
.article-card img{ width:100%; height:160px; object-fit:cover; display:block; background:#eee; }
.article-card .body{ padding:12px 14px; }
.article-card .judul{ font-size:14px; font-weight:700; line-height:1.4; margin-bottom:4px; }
.article-card .meta{ font-size:11px; color:var(--muted); }

.konten-artikel{ font-size:13.5px; line-height:1.8; color:var(--text); }
.konten-artikel h1, .konten-artikel h2{ font-size:16px; font-weight:800; margin:18px 0 8px; color:var(--navy); }
.konten-artikel p{ margin-bottom:12px; }
.konten-artikel ul, .konten-artikel ol{ margin:0 0 12px 20px; }
.konten-artikel img{ width:100%; border-radius:10px; margin:12px 0; }
.konten-artikel a{ color:var(--navy); text-decoration:underline; }

/* ---------- beranda.php: Flash Sale ---------- */
.section-head .countdown{
  display:flex; align-items:center; gap:4px; background:rgba(26,35,126,.06);
  border-radius:10px; padding:6px 10px;
}
.section-head .countdown .seg-h, .section-head .countdown .seg-m, .section-head .countdown .seg-s{
  font-size:12px; font-weight:800; color:var(--navy); font-variant-numeric:tabular-nums;
}
.section-head .countdown .sep{ font-size:11px; font-weight:700; color:var(--navy); }

.flash-card{
  min-width:150px; max-width:150px; background:var(--card); border-radius:14px; overflow:hidden; flex-shrink:0;
  box-shadow:0 1px 3px rgba(0,0,0,0.06); display:block;
}
.flash-card .thumb{ position:relative; }
.flash-card img{ width:100%; height:110px; object-fit:cover; display:block; background:#eee; }
.flash-card .body{ padding:10px; }
.flash-card .name{ font-size:11.5px; font-weight:700; min-height:32px; line-height:1.3; margin-bottom:6px; }
.flash-card .price-row{ display:flex; flex-direction:column; margin-bottom:6px; }
.flash-card .price-diskon{ font-size:13px; font-weight:800; color:var(--red); }
.flash-card .price-old{ font-size:10.5px; color:var(--muted); text-decoration:line-through; }
.flash-card .progress-kuota{ height:6px; background:var(--border); border-radius:10px; overflow:hidden; margin-bottom:4px; }
.flash-card .progress-bar{ height:100%; background:var(--red); border-radius:10px; }
.flash-card .progress-label{ font-size:9.5px; color:var(--muted); font-weight:700; }

/* ==========================================================
   Breakpoint TABLET + HP MIRING (2026-08-07, bug ditemukan lewat laporan
   pemilik: "di tablet ipad dan hp miring jelek ga responsif ... ipad mini
   4") -- SEBELUM ini, breakpoint langsung lompat dari .phone max-width:480px
   (dasar/mobile) ke 900px (desktop) TANPA apa pun di antaranya. iPad Mini 4
   dalam mode POTRET lebar layarnya 768px -- persis jatuh di celah itu, jadi
   seluruh situs tampil selebar 480px "mengambang" kecil di tengah layar
   tablet dengan ruang kosong besar kiri-kanan, bukan memakai lebar layar
   yang tersedia sama sekali.

   REVISI (2026-08-07, laporan pemilik lanjutan: "hp dimiringin dan tablet
   dan ipad masih ga responsif ... masih tidak melebar") -- versi PERTAMA
   breakpoint ini sengaja dibatasi JUGA dengan (min-height:600px) supaya
   TIDAK kena HP landscape (lebar mirip tablet, 480-900px, tapi viewport-nya
   PENDEK, <600px tinggi) -- alasannya waktu itu: formula posisi FAB
   "50vw - 240px" (mengasumsikan .phone tetap 480px) akan salah hitung kalau
   HP landscape ikut melebar juga. Itu keliru diprioritaskan: HP landscape
   jadi TETAP terkunci 480px sempit selamanya cuma supaya rumus FAB tidak
   perlu disesuaikan -- padahal justru itu yang dikeluhkan pemilik ("masih
   tidak melebar"). Diperbaiki dari akarnya (lihat --lebar-phone di :root,
   dipakai .forum-fab/.cs-fab) -- FAB sekarang otomatis membaca lebar .phone
   yang berlaku, JADI syarat (min-height:600px) di sini tidak diperlukan lagi
   sama sekali dan dihapus -- HP landscape sekarang ikut melebar sama seperti
   tablet potret, breakpoint ini murni berdasar LEBAR viewport saja. */
@media (min-width:600px) and (max-width:899px){
  /* max-width:700px TETAP (2026-08-07, laporan lanjutan pemilik: "di hp rotasi
     layar masih kurang sedikit lebar ... di ipad tablet juga kurang lebar
     sedikit ... ipad mini 4 kurang lebar sedikit") -- 700px itu angka TETAP,
     padahal rentang breakpoint ini lebar viewport-nya 600-899px. Di ujung
     BAWAH (600px) 700px sudah lewat batas (tertahan ke lebar asli, wajar), tapi
     di iPad Mini 4 (768px potret) sisa ruang kosong 68px (34px kiri-kanan) --
     "kurang sedikit" itu KELIHATAN, dan makin lebar viewport-nya (mendekati
     899px) sisa kosongnya makin besar karena angkanya TETAP tidak ikut naik.
     Diganti 96vw (relatif viewport, bukan angka tetap) -- 4% margin kiri-kanan
     total (2% tiap sisi) di lebar BERAPA PUN dalam rentang ini.

     REVISI (2026-08-13, laporan pemilik LAGI dengan kalimat yang PERSIS sama:
     "kalo di rotasi hp saya kurang lebar ... semua halaman seluruh web") --
     96vw ternyata MASIH menyisakan margin yang kelihatan "kurang lebar
     sedikit" itu. Dinaikkan ke 100vw (TIDAK ADA margin kiri-kanan sama sekali)
     -- aman dari sliver horizontal-scroll (masalah klasik 100vw yang IKUT
     lebar scrollbar) karena html,body sudah overflow-x:clip (lihat :root),
     bukan lagi trik full-bleed breakout var(--lebar-viewport-asli) yang
     butuh perhitungan JS terpisah (itu cuma untuk elemen yang LEPAS dari
     .phone/alur dokumen, .phone sendiri sudah otomatis di-tengah-kan browser
     tanpa butuh trik itu). */
  :root{ --lebar-phone:100vw; }
  .phone{ max-width:100vw; }
  /* Bar bawah (bottomnav/actionbar/kr-bottombar/bottombar/picker-overlay) --
     SEMUA ikut 100vw juga, sinkron dengan .phone di atas (kalau tidak, bar-bar
     ini kelihatan "menyempit" tidak rata dengan konten di atasnya, sama persis
     kelas bug yang baru ditambal di .bottomnav base). */
  .bottomnav, .actionbar, .kr-bottombar, .bottombar, .picker-overlay{ max-width:100vw; }
  .product-grid{ grid-template-columns:repeat(3, 1fr); }
  /* .forum-fab/.cs-fab TIDAK PERLU override apa pun lagi di sini -- formulanya
     (lihat :root/.forum-fab) sudah otomatis membaca --lebar-phone di atas. */
}

/* ==========================================================
   Breakpoint desktop (2026-07-12) — container yang tadinya fixed 430px
   (dirancang mobile-only) dilebarkan di layar besar, TIDAK redesign total per
   halaman. product-grid dapat kolom tambahan supaya ruang ekstra tidak sia-sia
   kosong di kanan-kiri. Modal/bottom-sheet SENGAJA tidak ikut melebar (popup
   yang terlalu lebar terasa aneh, proporsinya memang seharusnya lebih kecil
   dari container utama).
   ========================================================== */
@media (min-width:900px){
  /* Redesign desktop (2026-07-14) -- sebelumnya .phone cuma melebar sampai 600px lalu
     berhenti, jadi terlihat seperti kotak HP kecil mengambang di tengah layar kosong.
     Sekarang .phone benar-benar memakai ruang layar lebar.
     .bottomnav DISEMBUNYIKAN total di desktop -- gantinya .topbar-desktop-nav yang
     tampil di baris atas (perbaikan 2026-07-14: sebelumnya bottomnav cuma dilebarkan,
     bukan disembunyikan, jadi KEDUA nav tampil sekaligus di desktop -- salah, harus
     saling meniadakan: mobile = bottomnav saja, desktop = topbar-desktop-nav saja).
     Ini aman untuk SEMUA halaman yang include includes/bottom_nav.php (beranda,
     belanja, lelang, po, akun) karena kelima-limanya kini juga punya markup
     .topbar-desktop-nav sendiri -- 4 lewat includes/topbar.php, 1 (akun.php) langsung
     di file itu sendiri (topbar sederhana, bukan topbar-full). Kalau nanti ada
     halaman baru yang include bottom_nav.php tanpa .topbar-desktop-nav, dia akan
     kehilangan nav di desktop -- wajib tambahkan juga di file itu.
     .actionbar/.kr-bottombar/.bottombar/.picker-overlay SENGAJA TETAP 600px -- itu
     bar transaksi (tombol beli/bayar/konfirmasi) yang tidak perlu selebar seluruh
     halaman, melebarkannya cuma bikin kosong di kiri-kanan tombol. */
  :root{ --lebar-phone:1100px; } /* .forum-fab/.cs-fab tetap direset right:14px polos di breakpoint ini (lihat aturan masing-masing) -- variable ini diperbarui murni supaya tetap akurat/tidak basi, bukan karena ada yang membacanya di sini saat ini. */
  .phone{
    max-width:1100px;
    padding-bottom:0; /* bottomnav hilang di desktop, tidak perlu lagi ruang cadangan di bawah */
  }
  .bottomnav{ display:none; }
  /* Modal konfirmasi/notifikasi (2026-07-28) -- .modal-overlay dasar (align-items:
     flex-end + .modal-sheet radius atas saja) sengaja bottom-sheet ala app HP, pas
     untuk mobile. Di desktop itu jadi terlihat "nyangkut" di bawah layar lebar --
     dipusatkan supaya jadi dialog box mengambang di tengah, konsisten dengan pola
     "semua popup keputusan di tengah halaman" yang dipakai di seluruh situs. */
  .modal-overlay{ align-items:center; }
  .modal-sheet{ border-radius:20px; box-shadow:0 20px 60px rgba(0,0,0,.25); }
  /* Form Masuk/Daftar (akun.php, 2026-07-28) -- .auth-tabs/.auth-pane cuma
     mewarisi lebar penuh .phone (1100px+) tanpa batas sendiri, jadi kotak
     email/password jadi selebar hampir seluruh layar -- terlihat rusak/tidak
     digaya untuk form login (ditemukan lewat screenshot Chrome asli). Dikunci
     ke lebar kartu wajar + ditengahkan, konsisten dengan pola .pd-gallery dkk
     di atas yang juga sengaja tidak mengikuti lebar penuh .phone di desktop. */
  .auth-tabs, .auth-pane{ max-width:440px; margin-left:auto; margin-right:auto; }
  /* jual.php (2026-07-30) -- form kartu-kartu ini juga terlihat rusak kalau ikut
     lebar penuh .phone (1100px+), sama alasan/pola persis .auth-tabs di atas. */
  .jual-wrap{ max-width:560px; margin-left:auto; margin-right:auto; }
  .actionbar, .kr-bottombar, .bottombar, .picker-overlay{
    max-width:600px;
  }
  /* Produk_detail.php jadi dua kolom sungguhan di desktop (2026-07-29, permintaan
     pemilik: "kalo di dekstop produk detil itu kebelah dua kiri dan kanan") --
     sebelumnya (2026-07-14) .pd-gallery/.pd-thumbs cuma dikunci lebar wajar +
     ditengahkan sementara SISA konten (nama/harga/deskripsi/profil toko/dst) tetap
     mengalir di bawahnya satu kolom penuh -- itu solusi sementara sebelum layout
     dua kolom ini dibangun. Sekarang .pd-media (foto, lebar tetap, sticky supaya
     tetap kelihatan saat kolom kanan di-scroll kalau deskripsi panjang) ada di
     kiri, .pd-main (nama/harga/deskripsi/profil toko/kontak seller/tombol aksi)
     di kanan mengisi sisa ruang. .actionbar (bottom bar mengambang ala app HP)
     disembunyikan di lebar ini -- gantinya .pd-desktop-actions yang mengalir
     rapi di dalam .pd-main, sejajar dengan sisa konten (bukan mengambang di
     bawah layar seperti mobile, sesuai permintaan "harus sejajar dan rapih"). */
  .pd-layout{
    display:grid; grid-template-columns:480px 1fr; gap:32px; align-items:start;
    max-width:1100px; margin:0 auto;
  }
  .pd-media{ position:sticky; top:20px; }
  .actionbar{ display:none; }
  .pd-desktop-actions{ display:flex; gap:8px; margin-top:2px; margin-bottom:14px; }
  .product-grid{
    grid-template-columns:repeat(5, 1fr);
  }
  /* Skema 6-kolom-fix (repeat(6,1fr), ikon 42px) di atas HANYA untuk
     mobile/tablet (permintaan eksplisit pemilik) -- di desktop grid balik ke
     auto-fill supaya kolom TIDAK meregang jadi lingkaran raksasa di .phone
     yang jauh lebih lebar (lihat catatan --lebar-phone), ikon dibesarkan lagi
     ke 52px karena ruang sudah lega. background/border-radius/box-shadow
     (kartu, disamakan .trust-row) diwarisi apa adanya dari rule dasar, cuma
     padding-nya sedikit dilonggarkan di sini karena kartu lebih lebar. */
  .cat-row{
    display:grid; grid-template-columns:repeat(auto-fill, minmax(58px,1fr));
    gap:26px; padding:16px 20px 20px;
  }
  .cat-item .ic{ width:52px; height:52px; }
  .cat-item span{ font-size:11px; }
  /* topbar-full (beranda/belanja/lelang/po) jadi header desktop sungguhan: brand+menu
     horizontal+ikon di baris atas, kolom pencarian tidak lagi full-bleed edge-to-edge,
     strip "Dikirim dari Tangerang" disembunyikan (detail gaya app mobile). */
  .topbar.topbar-full{ padding:16px 32px 0; }
  .topbar-row1{ padding:0 0 12px; }
  /* Search bar ditengahkan + dilebarkan (2026-07-28, permintaan pemilik: "kalo di
     pc kolom searchnya bisa pas ditengah tengah" lalu "kurang lebar ... harusnya
     agak lebar sesuai lebar katagori produk") -- sebelumnya dibatasi max-width kecil
     (480-660px tergantung breakpoint) jadi keliatan mepet di tengah walau layar
     lebar. Sekarang width:100% mengikuti lebar kontainer topbar-row (yang paddingnya
     sama dengan cat-row/product-grid di bawahnya), dengan satu batas atas generik
     supaya di monitor sangat lebar kolom cari tidak jadi tak berbatas. Breakpoint
     1280/1366/1536/1600/1920px TIDAK perlu lagi override max-width satu-satu --
     width:100% otomatis menyesuaikan di semua ukuran. */
  .topbar-full .search-wrap{ width:100%; margin:0 auto 14px; max-width:1400px; }
  .topbar-full .location-strip{ display:none; }
  .topbar-desktop-nav{ display:flex; gap:26px; }
  .footer-box{ display:block; }
  /* .banner-slider dkk DIHAPUS (2026-08-13) -- lihat catatan penghapusan di
     definisi dasarnya (dekat .hero-promo-*), tidak ada markup yang memakainya
     lagi. .hero-promo-slider TIDAK butuh override khusus breakpoint ini --
     aspect-ratio-nya sudah diatur sendiri lewat @media (min-width:768px)/
     (min-width:1280px) di aturan dasarnya. */
}

/* Breakpoint tambahan (2026-07-14) -- sebelumnya .phone berhenti di max-width:1100px
   mulai 900px dan TIDAK PERNAH melebar lagi walau layar 1440px/1920px/lebih besar,
   jadi masih terlihat sempit dengan ruang kosong besar di kiri-kanan pada monitor
   desktop biasa. Sekarang progresif seperti referensi Figma/versi lama: makin lebar
   layar, makin lebar juga .phone dan makin banyak kolom grid produk -- bukan cuma
   satu lompatan di 900px lalu mentok. */
@media (min-width:1280px){
  :root{ --lebar-phone:1320px; }
  .phone{ max-width:1320px; }
  .product-grid{ grid-template-columns:repeat(6, 1fr); }
  .cat-row{ gap:32px; }
  .topbar.topbar-full{ padding:18px 48px 0; }
  .topbar-row1{ padding:0 0 14px; }
  .topbar-desktop-nav{ gap:32px; }
}

/* Breakpoint tambahan (2026-07-22) -- celah 1280-1600px dulu tidak punya penyesuaian
   sama sekali (.phone mentok di max-width:1320px dari 1280px sampai nyaris 1600px),
   padahal 1366px (resolusi laptop paling umum) dan ~1536px (viewport efektif panel
   1920x1080 dengan Windows display scaling 125%, skala paling umum di laptop baru)
   keduanya jatuh persis di celah ini. Murni tambahan progresif, tidak mengubah
   breakpoint 900/1280/1600px yang sudah ada. */
@media (min-width:1366px){
  :root{ --lebar-phone:1360px; }
  .phone{ max-width:1360px; }
  .cat-row{ gap:34px; }
  .topbar.topbar-full{ padding:19px 54px 0; }
}

@media (min-width:1536px){
  :root{ --lebar-phone:1460px; }
  .phone{ max-width:1460px; }
  .cat-row{ gap:36px; }
  .topbar.topbar-full{ padding:19px 60px 0; }
}

@media (min-width:1600px){
  :root{ --lebar-phone:1560px; }
  .phone{ max-width:1560px; }
  .product-grid{ grid-template-columns:repeat(7, 1fr); }
  .cat-row{ gap:38px; }
  .topbar.topbar-full{ padding:20px 64px 0; }
}

/* Breakpoint tambahan (2026-07-22) -- monitor/panel 1920px ke atas sebelumnya
   disamakan begitu saja dengan aturan 1600px (mentok max-width:1560px tanpa batas
   atas), padahal masih ada ruang cukup untuk kolom grid produk ke-8 dan proporsi
   yang lebih lega. Murni tambahan, tidak mengubah rule 1600px di atas. */
@media (min-width:1920px){
  :root{ --lebar-phone:1720px; }
  .phone{ max-width:1720px; }
  .product-grid{ grid-template-columns:repeat(8, 1fr); }
  .cat-row{ gap:44px; }
  .topbar.topbar-full{ padding:22px 76px 0; }
}

/* Bug HP/tablet (2026-07-29, ditemukan saat audit responsif menyeluruh) -- SEMUA
   kolom input teks di situs ini (search bar, form login/daftar/alamat, kolom kode
   kupon, dll) dipakai dengan font-size 13-13.5px untuk konsistensi desain. Safari
   di iPhone/iPad (dan browser berbasis WebKit lain di iOS) OTOMATIS MEMPERBESAR
   TAMPILAN (zoom) begitu pengguna mengetuk kolom input mana pun yang font-size-nya
   di bawah 16px -- perilaku bawaan WebKit, bukan bug halaman ini, tapi efeknya
   terasa seperti "halaman tiba-tiba zoom sendiri/rusak" tiap kali pengguna
   mengetuk kolom cari/form apa pun di HP/iPad, dan pengguna harus pinch-zoom
   manual untuk kembali normal. Diperbaiki dengan menaikkan font-size jadi 16px
   KHUSUS di lebar mobile/tablet (di bawah breakpoint desktop 900px) -- di
   desktop tetap 13-13.5px seperti semula, tidak ada perubahan visual sama sekali
   di sana karena pointer mouse tidak memicu perilaku zoom ini. Selector generik
   berdasarkan [type=...]/textarea/select dipakai (bukan hanya class tertentu)
   supaya SEMUA kolom input ikut ter-cover, termasuk yang belum/tidak pakai class
   .form-input/.kupon-input-row dll. */
@media (max-width:899px){
  input[type="text"], input[type="email"], input[type="password"], input[type="tel"],
  input[type="number"], input[type="search"], input[type="date"], input[type="datetime-local"],
  select, textarea{
    font-size:16px;
  }
}
