/* ==========================================================================
   Etalase Feremart v2 — sistem desain
   ==========================================================================

   Arah: hangat dan tegas. Mayoritas tenant adalah F&B, jadi yang harus menonjol
   adalah FOTO dan HARGA — bukan kotak dan garis. Tiga keputusan yang membentuk
   seluruh tampilan:

     1. Tidak ada garis pembatas pada kartu. Kedalaman dibentuk bayangan lembut
        yang diberi rona warna merek, bukan border abu-abu.
     2. Harga adalah elemen paling keras di layar — tebal, rapat, angka tabular.
        Nama produk sengaja lebih tenang supaya tidak berebut perhatian.
     3. Latar halaman diberi rona tipis dari warna merek tenant, bukan abu-abu
        netral. Toko biru dan toko merah harus terasa berbeda begitu dibuka.

   Nol byte font diunduh: memakai tumpukan font sistem (Roboto/SF Pro). Di
   jaringan seluler Indonesia, satu berkas font 40 KB lebih terasa daripada
   perbedaan bentuk hurufnya.

   --brand dan --accent diinjeksi per tenant dari storefront_customization
   (base.html), jadi berkas ini tidak boleh mengunci warna merek apa pun.
   ========================================================================== */

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

:root {
  /* --- netral, dirona warna merek supaya tidak terasa abu-abu pabrikan --- */
  --ink:      #12181f;
  --ink-2:    #5a6672;
  /* #8d99a5 semula -- 2,9:1 di atas putih, gagal kontras minimum WCAG AA
     (4,5:1 utk teks kecil) padahal dipakai di 30+ tempat termasuk info
     penting (harga satuan, jumlah terjual, teks bantuan "kenapa field ini
     perlu diisi"). #697680 tetap terasa "paling redup" dari ketiga warna
     tinta (masih lebih terang dari --ink-2) tapi terbaca dgn benar. */
  --ink-3:    #697680;
  --surface:  #ffffff;
  --surface-2: color-mix(in srgb, var(--brand) 4%, #f6f7f9);
  --ground:   color-mix(in srgb, var(--brand) 5%, #fbfbfc);
  --hairline: color-mix(in srgb, var(--brand) 9%, #e6eaee);

  --ok:   #0e7a55;
  --warn: #96590a;
  --risk: #c02a22;
  /* Warna flash sale — SENGAJA TETAP, tidak dirona --brand. Ia harus terbaca
     sebagai "mendesak/terbatas" terlepas dari warna merek tenant apa pun,
     persis kenapa Shopee/Tokopedia memakai jingga-merah yang sama di semua
     toko, bukan warna tiap penjual. */
  --flash:     #ff3b30;
  --flash-ink: #7a0d06;

  /* Bayangan dirona merek — bayangan hitam murni terlihat kotor di layar HP. */
  --sh-1: 0 1px 2px color-mix(in srgb, var(--brand) 12%, transparent),
          0 2px 8px color-mix(in srgb, var(--brand) 7%, transparent);
  --sh-2: 0 2px 6px color-mix(in srgb, var(--brand) 13%, transparent),
          0 8px 24px color-mix(in srgb, var(--brand) 10%, transparent);
  --sh-3: 0 6px 18px color-mix(in srgb, var(--brand) 18%, transparent),
          0 18px 44px color-mix(in srgb, var(--brand) 14%, transparent);

  --r-sm: 12px;
  --r:    18px;
  --r-lg: 24px;

  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  /* Pegas untuk hal yang "muncul"; ease-out tenang untuk sisanya. */
  --spring: cubic-bezier(.34, 1.4, .64, 1);
  --out:    cubic-bezier(.22, 1, .36, 1);

  --pad: 16px;
  --tinggi-bar-cabang: 44px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink:      #e9eef3;
    --ink-2:    #a2b0bd;
    --ink-3:    #71808e;
    --surface:  color-mix(in srgb, var(--brand) 7%, #131a22);
    --surface-2: color-mix(in srgb, var(--brand) 10%, #18212b);
    --ground:   color-mix(in srgb, var(--brand) 5%, #0b1119);
    --hairline: color-mix(in srgb, var(--brand) 16%, #26313d);

    --ok:   #43c795;
    --warn: #e0a44f;
    --risk: #f28b82;
    --flash:     #ff5c48;
    --flash-ink: #ffe4df;

    --sh-1: 0 1px 2px rgba(0,0,0,.4);
    --sh-2: 0 2px 8px rgba(0,0,0,.45), 0 10px 28px rgba(0,0,0,.3);
    --sh-3: 0 8px 22px rgba(0,0,0,.5), 0 20px 48px rgba(0,0,0,.36);
  }
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--ground);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: -0.004em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }

/* Atribut `hidden` HARUS menang atas `display` dari kelas mana pun.
   Aturan bawaan peramban `[hidden]{display:none}` kalah spesifisitas dari
   selektor kelas seperti `.btn-secondary{display:block}` — akibatnya elemen
   yang disembunyikan JavaScript tetap terlihat. Ini pernah menampilkan tombol
   keranjang saat keranjang kosong dan pemilih nomor meja saat tidak dipilih. */
[hidden] { display: none !important; }

h1, h2, h3 { margin: 0; letter-spacing: -0.024em; line-height: 1.15; text-wrap: balance; }

:focus-visible { outline: 2.5px solid var(--accent); outline-offset: 3px; border-radius: 6px; }

/* Angka selalu tabular — harga yang bergeser saat berubah terasa murah. */
.num, .card-price, .co-item-total, .cart-fab-total, .pd-price,
.co-totals dd, .ord-line-total, .stepper span, .cart-sheet-total strong { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Pita penanda fase uji
   ========================================================================== */

/* Warna dipatok, TIDAK ikut token — memakai --ink/--surface membuat pita ini
   terbalik jadi terang di mode gelap, dan bilah terang di puncak layar gelap
   sangat mengagetkan. Ini pita sistem, wajahnya harus tetap sama. */
.phase-flag {
  background: #12181f;
  color: rgba(233, 238, 243, .88);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.4;
  padding: 8px 16px;
  text-align: center;
  letter-spacing: -0.002em;
}
.phase-flag a { color: var(--accent); font-weight: 650; text-decoration: underline; text-underline-offset: 2px; }

/* ==========================================================================
   Kepala toko — sapuan gradien merek, konten mengambang di atasnya
   ========================================================================== */

/* Sapuan warna merek memberi toko "wajah" tanpa memaksa owner mengunggah
   banner. Tingginya MENGIKUTI ISI, bukan angka tetap — versi sebelumnya dipatok
   190px sehingga judul "Semua produk" yang gelap jatuh di atas gradien gelap
   dan nyaris tak terbaca. Sudut bawah dibulatkan supaya batasnya terasa
   disengaja, bukan garis potong. */
.shop-head {
  position: relative;
  padding: 0 var(--pad) 22px;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  background:
    radial-gradient(120% 90% at 12% 0%, color-mix(in srgb, var(--accent) 28%, transparent), transparent 62%),
    linear-gradient(165deg, var(--brand), color-mix(in srgb, var(--brand) 62%, #000));
}

.shop-head-inner {
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 20px 0 18px;
}

.shop-logo {
  width: 58px; height: 58px;
  border-radius: 16px;
  object-fit: cover;
  flex: none;
  background: var(--surface);
  box-shadow: 0 4px 14px rgba(0,0,0,.22);
}

.shop-id { min-width: 0; flex: 1; }
.shop-id h1 {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: #fff;
}

/* Akun pelanggan hidup di feremart.com (marketplace), bukan di sini --
   subdomain toko.feremart.com terpisah dari sesi login itu, jadi tautan ini
   SELALU tampil "Masuk" (tak bisa tahu pembeli sudah login atau belum). */
.shop-login-link {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 13px;
  border-radius: 999px;
  background: rgba(255,255,255,.17);
  color: #fff;
  font-size: 13px;
  font-weight: 650;
  text-decoration: none;
  white-space: nowrap;
}
.shop-login-link svg { width: 15px; height: 15px; flex: none; }
.shop-login-link--in { align-items: flex-start; padding-top: 6px; padding-bottom: 6px; }
.shop-login-text { display: flex; flex-direction: column; line-height: 1.25; }
.shop-login-balance { font-size: 10.5px; font-weight: 600; opacity: .85; }

.shop-status {
  margin: 5px 0 0;
  font-size: 12px;
  font-weight: 650;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px 4px 9px;
  border-radius: 999px;
  background: rgba(255,255,255,.17);
  color: #fff;
  backdrop-filter: blur(6px);
}
.shop-status::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: #56e0a0;
  box-shadow: 0 0 0 3px rgba(86,224,160,.28);
}
.shop-status.is-closed::before { background: #ffb4a8; box-shadow: 0 0 0 3px rgba(255,180,168,.26); }

.hero {
  margin-bottom: 14px;
  padding: 16px 18px;
  border-radius: var(--r);
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(10px);
  color: #fff;
}
.hero h2 { font-size: 18px; font-weight: 750; }
.hero p { margin: 5px 0 0; font-size: 13.5px; opacity: .9; line-height: 1.45; }

/* --- pencarian: kartu mengambang yang menjembatani gradien dan konten --- */

.search {
  display: flex;
  gap: 8px;
  padding: 6px;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--sh-2);
}
.search input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 15px;
  padding: 10px 8px 10px 16px;
  border: 0;
  background: transparent;
  color: var(--ink);
}
.search input::placeholder { color: var(--ink-3); }
.search input:focus { outline: none; }
.search button {
  padding: 10px 20px;
  border: 0;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: transform .18s var(--spring);
}
.search button:active { transform: scale(.94); }

/* --- baris chip --- */

/* Rail digeser penuh ke tepi layar lewat margin negatif, lalu isinya ditarik
   masuk lagi dengan padding — supaya saat digulir, kartu menghilang di tepi
   layar dan bukan di tepi kolom.
   `scroll-padding` WAJIB menyertai: tanpa itu scroll-snap menggulir rail persis
   sebesar padding-left, dan item pertama malah menempel di x=0. */
.cat-bar {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding: 14px 0 2px;
  margin: 0 calc(var(--pad) * -1);
  padding-left: var(--pad);
  padding-right: var(--pad);
  scroll-padding-left: var(--pad);
  scrollbar-width: none;
}
.cat-bar::-webkit-scrollbar { display: none; }

/* Petunjuk "masih ada lagi ke arah ini" (scroll-hint.js menyalakan kelasnya
   HANYA saat memang ada isi tersembunyi — baris yang muat penuh tak kena
   efek ini). Pudar lewat mask, bukan lapisan gradien warna, supaya otomatis
   cocok dengan latar apa pun di baliknya tanpa perlu warna terpisah
   tiap konteks. */
.cat-bar.has-more-end, .strip-rail.has-more-end {
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to right, black calc(100% - 28px), transparent 100%);
}
.cat-bar.has-more-start, .strip-rail.has-more-start {
  -webkit-mask-image: linear-gradient(to left, black calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to left, black calc(100% - 28px), transparent 100%);
}
.cat-bar.has-more-start.has-more-end, .strip-rail.has-more-start.has-more-end {
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 28px, black calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 28px, black calc(100% - 28px), transparent 100%);
}
.cat-bar > * { scroll-snap-align: start; }

/* ---- Daftar cabang di dalam lembar "Pilih cabang" ----------------------
   Baris penuh yang bisa disentuh, bukan pil sempit: di sinilah pembeli
   MEMBANDINGKAN cabang, jadi alamat diberi ruang untuk membungkus dua baris
   alih-alih dipotong. Tinggi minimum 56px memenuhi sasaran sentuh yang nyaman
   di ponsel. */
.cb-list { list-style: none; margin: 0; padding: 0 0 8px; display: grid; gap: 8px; }

.cb-item {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--surface);
  border: 1.5px solid transparent;
  box-shadow: var(--sh-1);
  color: var(--ink);
  transition: transform .16s var(--spring), border-color .15s;
}
.cb-item:active { transform: scale(.985); }
.cb-item.is-active {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 7%, var(--surface));
}

.cb-item-teks { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cb-item-nama { font-size: 15px; font-weight: 700; line-height: 1.25; }
.cb-item.is-active .cb-item-nama { color: var(--brand); }
.cb-item-alamat {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-2);
  /* Dua baris cukup untuk membedakan; lebih dari itu daftarnya jadi dinding
     teks dan justru lebih sulit dipindai. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cb-item-tanda { flex: none; display: flex; color: var(--ink-3, #7b8794); }
.cb-item-tanda svg { width: 20px; height: 20px; }
.cb-item.is-active .cb-item-tanda { color: var(--brand); }

/* ---- Gerbang WAJIB pilih cabang (owner 25 Agu 2026) -------------------
   Saat pembeli datang tanpa menyebut cabang, lembar ini dirender SUDAH
   TERBUKA oleh server, jadi kunci gulirnya pun harus datang dari CSS: kalau
   menunggu JavaScript, ada jendela di mana katalog di balik gerbang masih
   bisa digulir dengan jari. `:has()` belum ada di peramban lama —
   cabang-sheet.js tetap menyetel `overflow` sebagai jaring pengaman. */
body:has(.cb-sheet[data-wajib]) { overflow: hidden; }

/* Saat digerbang, grip dan tombol ✕ tak dirender (keduanya menjanjikan jalan
   keluar yang tak ada). Jarak atas yang tadinya disumbang grip dikembalikan
   di sini supaya judul lembar tak menempel ke tepi. */
.cb-sheet[data-wajib] .sheet-head { padding-top: 18px; }

/* Tinggi lembar cabang dipatok 80% layar (owner 26 Agu 2026), tidak lagi
   menyusut mengikuti isi. Dengan 3 cabang, lembarnya cuma ~44% layar: katalog
   di baliknya masih terbaca dan gerbangnya terasa seperti kartu yang bisa
   disingkirkan -- padahal tak bisa. Dipatok juga menyiapkan tenant beroutlet
   banyak: daftarnya dapat ruang, sisanya digulir DI DALAM `.sheet-body`,
   bukan menumbuhkan lembar sampai menelan seluruh layar.

   Dua kelas (`.cart-sheet.cb-sheet`) dipakai dengan sengaja: itu satu-satunya
   cara menang atas `.cart-sheet { max-height: 76vh }` di media query desktop
   jauh di bawah -- media query tidak menambah kekhususan, jadi aturan yang
   lebih belakang akan menang kalau kekhususannya sama. */
.cart-sheet.cb-sheet { height: 80vh; max-height: 80vh; }

/* Yang menggulir DAFTARNYA, bukan lembarnya. `min-height: 0` wajib: item flex
   menolak menyusut di bawah tinggi isinya, jadi tanpa baris ini daftar panjang
   mendorong kepala lembar keluar layar alih-alih memunculkan gulir. */
.cb-sheet .sheet-body { flex: 1; min-height: 0; }

/* ---- Penanda cabang yang ikut menggulir ----------------------------------
   Dulu baris kategori yang menempel sementara cabang menghilang: kendali yang
   cuma menyaring tampilan diperlakukan lebih penting daripada kendali yang
   menentukan dapur mana yang memasak. Bar ini membalik urutan itu, dan
   kategori digeser turun tepat setinggi bar supaya keduanya tak bertumpuk. */
.bar-cabang {
  position: sticky;
  top: 0;
  z-index: 31;
  display: flex;
  align-items: center;
  gap: 9px;
  height: var(--tinggi-bar-cabang);
  margin: 0 calc(var(--pad) * -1);
  padding: 0 var(--pad);
  background: color-mix(in srgb, var(--ground) 92%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
.bar-cabang-pin { width: 15px; height: 15px; flex: none; color: var(--brand); }
.bar-cabang-teks {
  margin: 0;
  min-width: 0;
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 7px;
  overflow: hidden;
}
.bar-cabang-label {
  flex: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-3, #7b8794);
}
.bar-cabang-nama {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bar-cabang-ganti {
  flex: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--brand);
  padding: 5px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
}
.shop-main.ada-bar-cabang .cat-bar { top: var(--tinggi-bar-cabang); }

/* Kategori pindah ke area terang di bawah kepala dan MENEMPEL saat digulir —
   di katalog panjang, kehilangan filter setelah menggulir dua layar itu
   menyebalkan. */
.cat-bar {
  position: sticky;
  top: 0;
  z-index: 30;
  padding-top: 12px;
  padding-bottom: 12px;
  background: color-mix(in srgb, var(--ground) 88%, transparent);
  backdrop-filter: blur(12px);
}
.cat-chip {
  flex: none;
  font-size: 13px;
  font-weight: 620;
  padding: 11px 16px;
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  white-space: nowrap;
  box-shadow: var(--sh-1);
  transition: transform .18s var(--spring), color .15s;
}
.cat-chip:active { transform: scale(.95); }
.cat-chip.is-active {
  background: var(--ink);
  color: var(--surface);
  font-weight: 720;
}

/* ==========================================================================
   Isi katalog
   ========================================================================== */

.shop-main { padding: 20px var(--pad) 120px; display: grid; gap: 30px; }

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.section-head h2, .strip h2 { font-size: 18px; font-weight: 780; }
.count {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
  background: var(--surface);
  padding: 3px 10px;
  border-radius: 999px;
  box-shadow: var(--sh-1);
  white-space: nowrap;
}

.strip h2 { margin-bottom: 14px; }
.strip-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 47%;
  gap: 12px;
  overflow-x: auto;
  padding: 4px 0 10px;
  margin: 0 calc(var(--pad) * -1);
  padding-left: var(--pad);
  padding-right: var(--pad);
  scroll-padding-left: var(--pad);
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.strip-rail::-webkit-scrollbar { display: none; }
.strip-rail > .card { scroll-snap-align: start; }

.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols-mobile, 2), minmax(0, 1fr));
  gap: 12px;
}

/* ==========================================================================
   Kartu produk
   ========================================================================== */

.card {
  position: relative;
  background: var(--surface);
  border-radius: var(--r);
  overflow: hidden;
  display: flex;
  box-shadow: var(--sh-1);
  transition: transform .2s var(--out), box-shadow .2s var(--out);
  /* Muncul naik saat halaman terbuka — dianimasikan lewat opacity+transform
     saja supaya murah di HP kelas menengah. */
  animation: card-in .42s var(--out) backwards;
}
.card:active { transform: scale(.985); }
@media (hover: hover) {
  .card:hover { transform: translateY(-3px); box-shadow: var(--sh-2); }
}

@keyframes card-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.grid > .card:nth-child(1) { animation-delay: .02s }
.grid > .card:nth-child(2) { animation-delay: .05s }
.grid > .card:nth-child(3) { animation-delay: .08s }
.grid > .card:nth-child(4) { animation-delay: .11s }
.grid > .card:nth-child(5) { animation-delay: .14s }
.grid > .card:nth-child(6) { animation-delay: .17s }
.grid > .card:nth-child(n+7) { animation-delay: .2s }

.card-link { display: flex; flex-direction: column; width: 100%; }

.card-img {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--surface-2);
  overflow: hidden;
}
.card-img img { width: 100%; height: 100%; object-fit: cover; }

/* Selubung gelap tipis di bawah foto supaya badge tetap terbaca di atas
   gambar terang, tanpa menggelapkan seluruh foto. */
.card-img::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 46%;
  background: linear-gradient(to top, rgba(0,0,0,.34), transparent);
  opacity: 0;
  transition: opacity .2s;
}
.card:has(.badge-out) .card-img::after,
.card:has(.badge-po) .card-img::after,
.card:has(.badge-pickup) .card-img::after { opacity: 1; }

.card-img-none {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 40px;
  font-weight: 800;
  color: color-mix(in srgb, var(--brand) 34%, transparent);
  background:
    radial-gradient(80% 80% at 50% 20%, color-mix(in srgb, var(--brand) 12%, transparent), transparent),
    var(--surface-2);
}

/* Foto diabu-abukan HANYA untuk produk yang benar-benar tak bisa dipesan
   (`is-blocked`). Sampai 28 Agu ini berlaku untuk SEMUA produk berstok nol,
   termasuk yang justru sedang menawarkan pre-order — foto pudar itu berbunyi
   "tak tersedia" dan pembeli pergi tanpa mencoba tombolnya. Kebijakannya kini
   per produk; lihat services/ketersediaan.py. */
.card.is-blocked .card-img img { filter: grayscale(.7); opacity: .5; }

.badge-out, .badge-pickup {
  position: absolute;
  z-index: 1;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  padding: 4px 9px;
  border-radius: 8px;
  text-transform: uppercase;
}
.badge-out {
  inset: auto auto 9px 9px;
  background: rgba(255,255,255,.94);
  color: var(--risk);
  backdrop-filter: blur(4px);
}
/* Stok nol TAPI menerima pesanan. Sengaja memakai warna peringatan (bukan
   merah risiko seperti `badge-out`, bukan pula warna merek): pembeli harus bisa
   membedakan sekilas "tak ada" dari "ada, tapi dijadwalkan" — aturan warna yang
   sama sudah dipakai tombol `card-add--po`. Huruf besar dimatikan karena
   labelnya kalimat, bukan satu kata. */
.badge-po {
  position: absolute;
  z-index: 1;
  inset: auto auto 9px 9px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .01em;
  padding: 4px 9px;
  border-radius: 8px;
  background: rgba(255,255,255,.94);
  color: color-mix(in srgb, var(--warn) 78%, var(--ink));
  backdrop-filter: blur(4px);
}
.badge-pickup {
  inset: 9px 9px auto auto;
  background: var(--accent);
  color: #1a1206;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 50%, transparent);
}

.card-body { padding: 11px 12px 13px; display: grid; gap: 5px; }

.card-name {
  font-size: 13.5px;
  font-weight: 580;
  line-height: 1.32;
  color: var(--ink-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Elemen paling keras di kartu. */
.card-price {
  margin: 0;
  font-size: 17px;
  font-weight: 820;
  letter-spacing: -0.032em;
  color: var(--ink);
}
.per-unit { font-size: 11px; font-weight: 550; color: var(--ink-3); letter-spacing: 0; }

.card-meta { display: flex; flex-wrap: nowrap; align-items: center; gap: 4px 10px; font-size: 11.5px; min-width: 0; }
.meta-rating { color: var(--warn); font-weight: 700; display: inline-flex; align-items: center; gap: 3px; }
.meta-rating .muted, .muted { color: var(--ink-3); font-weight: 500; }
.meta-sold { color: var(--ink-3); font-weight: 550; } /* dipakai halaman detail produk (pd-meta) */

/* Baris SENDIRI di kartu katalog, bukan berbagi baris dgn rating (owner
   2026-08-11, tenant Mizuke): kartu 2 kolom di HP (~144px lebar konten)
   tak muat rating + stok + jarak aman tombol "+" (40px, absolute
   pojok-kanan-bawah) di satu baris -- dulu coba dipaksa satu baris
   (margin-left:auto), berakhir ellipsis parah ("Stok 91 pcs" -> "Sto...")
   atau malah numpuk tombol. Baris sendiri, rata kanan, padding-right jaga
   jarak dari tombol. Digerbangi `.card-body` supaya TIDAK menimpa
   `.pd-meta .meta-stock` (halaman detail produk, tak ada tombol melayang
   di sana jadi tak butuh perlakuan ini -- lihat definisi lain di bawah). */
.card-body > .meta-stock {
  margin: 0;
  text-align: right;
  padding-right: 46px;
  font-size: 11.5px;
  font-weight: 650;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.card-body > .meta-stock.is-out { color: var(--risk); font-weight: 700; }

.card-outlet {
  margin: 2px 0 0;
  font-size: 10.5px;
  font-weight: 650;
  color: var(--brand);
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* --- tombol tambah --- */

.card-add {
  /* 40px, bukan 36px -- target sentuh senyaman mungkin di ruang kartu yang
     sempit (pedoman WCAG 2.5.5 / Apple-Google merekomendasikan ~44px;
     40px kompromi supaya kartu produk tak terasa penuh tombol). */
  position: absolute;
  right: 10px;
  bottom: 10px;
  min-width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 13px;
  background: var(--brand);
  color: #fff;
  font-size: 21px;
  font-weight: 500;
  line-height: 40px;
  text-align: center;
  cursor: pointer;
  box-shadow: 0 3px 10px color-mix(in srgb, var(--brand) 45%, transparent);
  transition: transform .2s var(--spring), background .2s;
}
.card-add:active { transform: scale(.86); }
.card-add--options { font-size: 12px; font-weight: 750; padding: 0 13px; letter-spacing: -0.01em; }
.card-add.is-added { background: var(--ok); animation: pop .4s var(--spring); }
@keyframes pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.22); }
  100% { transform: scale(1); }
}

.empty {
  text-align: center;
  padding: 44px 20px;
  color: var(--ink-2);
  font-size: 14.5px;
  background: var(--surface);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
}
.empty a { color: var(--brand); font-weight: 700; }

.footer-note {
  font-size: 12.5px;
  color: var(--ink-3);
  line-height: 1.55;
  margin: 0;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
}

/* ==========================================================================
   Keranjang mengambang + lembar geser
   ========================================================================== */

.cart-fab {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 12px 11px 18px;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--brand), color-mix(in srgb, var(--brand) 74%, #000));
  color: #fff;
  cursor: pointer;
  box-shadow: var(--sh-3);
  animation: fab-in .34s var(--spring);
  max-width: calc(100% - 32px);
}
.cart-fab[hidden] { display: none; }
.cart-fab:active { transform: translateX(-50%) scale(.96); }
@keyframes fab-in {
  from { opacity: 0; transform: translateX(-50%) translateY(20px) scale(.9); }
  to   { opacity: 1; transform: translateX(-50%); }
}
.cart-fab.is-bumped { animation: fab-bump .45s var(--spring); }
@keyframes fab-bump {
  0%   { transform: translateX(-50%) scale(1); }
  40%  { transform: translateX(-50%) scale(1.07); }
  100% { transform: translateX(-50%) scale(1); }
}

.cart-fab-count {
  min-width: 24px; height: 24px;
  border-radius: 999px;
  background: rgba(255,255,255,.24);
  font-size: 12.5px;
  font-weight: 800;
  line-height: 24px;
  text-align: center;
  padding: 0 6px;
}
.cart-fab-label { font-size: 12px; font-weight: 600; opacity: .82; display: block; text-align: left; }
.cart-fab-total { font-size: 16px; font-weight: 800; letter-spacing: -0.028em; display: block; }
.cart-fab-go {
  background: #fff;
  color: var(--brand);
  font-size: 13.5px;
  font-weight: 780;
  padding: 9px 17px;
  border-radius: 999px;
  white-space: nowrap;
}

/* nilai yang sedang dihitung ulang di server */
.is-loading {
  color: transparent !important;
  background: linear-gradient(90deg,
    color-mix(in srgb, currentColor 14%, transparent) 25%,
    color-mix(in srgb, currentColor 26%, transparent) 37%,
    color-mix(in srgb, currentColor 14%, transparent) 63%);
  background-size: 400% 100%;
  border-radius: 6px;
  animation: shimmer 1.3s ease infinite;
}
@keyframes shimmer { from { background-position: 100% 0 } to { background-position: 0 0 } }

/* --- lembar geser --- */

.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(9, 14, 20, .5);
  backdrop-filter: blur(3px);
  animation: fade-in .2s;
}
.sheet-backdrop[hidden] { display: none; }
@keyframes fade-in { from { opacity: 0 } to { opacity: 1 } }

.cart-sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 71;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
  background: var(--ground);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: 0 -12px 40px rgba(0,0,0,.28);
  animation: sheet-up .34s var(--out);
  padding-bottom: env(safe-area-inset-bottom);
}
.cart-sheet[hidden] { display: none; }
@keyframes sheet-up { from { transform: translateY(100%) } to { transform: none } }

.sheet-grip {
  width: 40px; height: 4px;
  border-radius: 99px;
  background: var(--hairline);
  margin: 10px auto 4px;
  flex: none;
}
.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px var(--pad) 12px;
  flex: none;
}
.sheet-head h2 { font-size: 17px; font-weight: 780; }
.sheet-close {
  /* 40px -- standar target sentuh minimum situs ini (lihat .card-add),
     sebelumnya 32px (owner, audit UI 2026-08-12). */
  width: 40px; height: 40px;
  border: 0;
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  font-size: 18px;
  cursor: pointer;
  box-shadow: var(--sh-1);
}
.sheet-body { overflow-y: auto; padding: 0 var(--pad) 12px; -webkit-overflow-scrolling: touch; }
.sheet-foot {
  flex: none;
  padding: 14px var(--pad) 18px;
  background: var(--surface);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: 0 -4px 20px color-mix(in srgb, var(--brand) 8%, transparent);
  display: grid;
  gap: 12px;
}
.cart-sheet-totals { display: grid; gap: 4px; margin: 0; }
.cart-sheet-totals div { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--ink-3); }
.cart-sheet-totals div[hidden] { display: none; }
.cart-sheet-totals dd { margin: 0; }
.cart-sheet-total { display: flex; justify-content: space-between; align-items: baseline; }
.cart-sheet-total span { font-size: 13px; color: var(--ink-2); font-weight: 600; }
.cart-sheet-total strong { font-size: 22px; font-weight: 820; letter-spacing: -0.03em; }

/* ==========================================================================
   Tombol
   ========================================================================== */

.btn-primary, .btn-secondary {
  display: block;
  width: 100%;
  text-align: center;
  font-size: 15px;
  font-weight: 750;
  letter-spacing: -0.012em;
  padding: 15px 22px;
  border: 0;
  border-radius: 15px;
  cursor: pointer;
  transition: transform .18s var(--spring), opacity .15s;
}
.btn-primary {
  background: linear-gradient(135deg, var(--brand), color-mix(in srgb, var(--brand) 76%, #000));
  color: #fff;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--brand) 34%, transparent);
}
.btn-secondary { background: var(--surface); color: var(--ink); box-shadow: var(--sh-1); }
.btn-primary:active, .btn-secondary:active { transform: scale(.975); }
.btn-primary:disabled {
  background: var(--ink-3);
  box-shadow: none;
  cursor: not-allowed;
  opacity: .75;
}

/* ==========================================================================
   Detail produk
   ========================================================================== */

/* Berada DI DALAM .pd-main (yang position:relative) supaya jangkarnya foto
   produk, bukan puncak halaman — versi sebelumnya menimpa pita penanda fase. */
.pd-head {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 5;
  padding: 14px var(--pad);
}
.back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--ink);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(10px);
  padding: 9px 16px 9px 13px;
  border-radius: 999px;
  box-shadow: var(--sh-1);
}

.pd-main { position: relative; display: grid; gap: 0; padding-bottom: 108px; }

/* Persegi, bukan 4:3. Foto produk di etalase ini banyak yang berupa poster
   promo TEGAK (mis. 800x1200) — di kotak 4:3 separuh tingginya terbuang
   sekalipun sudah `contain`. Persegi memberi ruang layak untuk foto tegak
   maupun mendatar, dan sama dengan bentuk yang dipakai marketplace besar. */
.pd-media { position: relative; background: var(--surface-2); aspect-ratio: 1 / 1; overflow: hidden; }
/* `contain`, BUKAN `cover`: foto harus terlihat UTUH — teks promo di tepi
   atas/bawah poster adalah bagian penting isinya, bukan latar yang boleh
   dipotong. Ruang sisanya diisi .pd-media-bg di bawah. */
.pd-media img { width: 100%; height: 100%; object-fit: contain; position: relative; }
/* Selector dinaikkan (.pd-media .pd-media-bg) supaya menang atas `.pd-media img`
   di atas — keduanya sama-sama mengatur object-fit, dan satu-class saja akan
   KALAH spesifisitas lalu ikut `contain` tanpa jejak galat apa pun. */
.pd-media .pd-media-bg {
  position: absolute;
  inset: 0;
  object-fit: cover;
  filter: blur(26px) saturate(1.25);
  /* Diperbesar supaya tepi buramnya tak menampakkan pinggiran kosong. */
  transform: scale(1.18);
  opacity: .5;
}
.pd-img-none { font-size: 84px; }

.pd-info {
  position: relative;
  background: var(--ground);
  padding: 22px var(--pad) 28px;
  display: grid;
  gap: 18px;
  margin-top: -22px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}

.pd-cat {
  margin: 0;
  font-size: 11px;
  font-weight: 750;
  color: var(--brand);
  text-transform: uppercase;
  letter-spacing: .08em;
}
.pd-info h1 { font-size: 25px; font-weight: 800; letter-spacing: -0.032em; }
.pd-price { margin: -8px 0 0; font-size: 30px; font-weight: 850; letter-spacing: -0.038em; color: var(--ink); }

.pd-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: -6px; }
.pd-meta > * {
  font-size: 12.5px;
  font-weight: 650;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--sh-1);
}
.meta-stock { color: var(--ok); }
.meta-stock.is-out { color: var(--risk); }

.pd-desc, .pd-outlet {
  background: var(--surface);
  border-radius: var(--r);
  padding: 15px 16px;
  box-shadow: var(--sh-1);
}
.pd-desc h2, .pd-outlet h2 {
  font-size: 11px;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--ink-3);
  margin-bottom: 7px;
}
.pd-desc p, .pd-outlet p { margin: 0; font-size: 14px; color: var(--ink-2); line-height: 1.55; white-space: pre-line; }
.pd-outlet strong { color: var(--ink); }

.pd-cta { display: grid; gap: 16px; }

.pd-qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--surface);
  border-radius: var(--r);
  padding: 12px 14px;
  box-shadow: var(--sh-1);
  font-size: 14px;
  font-weight: 700;
}

.pd-error {
  margin: 0;
  font-size: 13px;
  font-weight: 650;
  color: var(--risk);
  background: color-mix(in srgb, var(--risk) 10%, var(--surface));
  padding: 11px 14px;
  border-radius: var(--r-sm);
}
.pd-error[hidden] { display: none; }

/* Bilah aksi menempel di bawah — tombol utama harus selalu terjangkau ibu jari. */
.pd-actions {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  display: flex;
  gap: 10px;
  padding: 12px var(--pad) calc(12px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(14px);
  box-shadow: 0 -2px 20px color-mix(in srgb, var(--brand) 10%, transparent);
}
.pd-actions .btn-primary { flex: 2; }
.pd-actions .btn-secondary { flex: 1; }

.pd-related { padding: 26px var(--pad) 40px; }

/* --- varian & add-on --- */

.opt-group { border: 0; padding: 0; margin: 0; }
.opt-group legend {
  font-size: 11px;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--ink-3);
  padding: 0;
  margin-bottom: 9px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
}
.opt-rule { font-size: 10.5px; font-weight: 650; color: var(--brand); text-transform: none; letter-spacing: 0; }
.opt-list { display: grid; gap: 8px; }

.opt {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 15px;
  border-radius: var(--r-sm);
  background: var(--surface);
  box-shadow: var(--sh-1);
  cursor: pointer;
  transition: transform .16s var(--spring), box-shadow .16s;
}
.opt:active { transform: scale(.985); }
.opt:has(input:checked) {
  box-shadow: 0 0 0 2px var(--brand), var(--sh-1);
  background: color-mix(in srgb, var(--brand) 6%, var(--surface));
}
.opt input { accent-color: var(--brand); width: 19px; height: 19px; flex: none; }
.opt-name { flex: 1; font-size: 14px; font-weight: 600; }
.opt-price { font-size: 13px; font-weight: 750; color: var(--brand); }

.opt-tag, .req { font-size: 10px; font-weight: 750; text-transform: uppercase; letter-spacing: .06em; }
.opt-tag { color: var(--ink-3); }
.req { color: var(--risk); }

/* --- stepper --- */

.stepper {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: var(--surface-2);
  padding: 3px;
}
.stepper button {
  /* 36px, bukan 32px -- baris ini menaik/turunkan jumlah berkali-kali
     (bukan sekali tap spt card-add), jadi salah tap lebih menjengkelkan. */
  width: 36px; height: 36px;
  border: 0;
  border-radius: 999px;
  background: var(--surface);
  color: var(--brand);
  font-size: 18px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: var(--sh-1);
  transition: transform .16s var(--spring);
}
.stepper button:active { transform: scale(.86); }
.stepper span { min-width: 34px; text-align: center; font-size: 14.5px; font-weight: 750; }

/* ==========================================================================
   Checkout
   ========================================================================== */

.co-head { padding: 16px var(--pad) 0; }
.co-head h1 { font-size: 25px; font-weight: 820; letter-spacing: -0.034em; margin: 12px 0 16px; }

/* Batang kemajuan nyata, bukan sekadar remah roti — pembeli tahu tinggal berapa. */
.crumbs {
  display: flex;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0 0 18px;
}
.crumbs li {
  flex: 1;
  display: grid;
  gap: 7px;
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: .04em;
  transition: color .2s;
}
.crumbs li::before {
  content: "";
  display: block;
  height: 4px;
  border-radius: 99px;
  background: var(--hairline);
  transition: background .3s var(--out);
}
.crumbs li span { display: none; }
.crumbs li.is-active { color: var(--brand); }
.crumbs li.is-active::before { background: var(--brand); }
.crumbs li.is-done { color: var(--ok); }
.crumbs li.is-done::before { background: var(--ok); }

.co-main { padding: 4px var(--pad) 128px; max-width: 680px; margin: 0 auto; }
.co-step { display: grid; gap: 14px; animation: step-in .3s var(--out); }
.co-step[hidden] { display: none; }
@keyframes step-in { from { opacity: 0; transform: translateX(12px) } to { opacity: 1; transform: none } }
.co-step h2 { font-size: 19px; font-weight: 780; margin-bottom: 2px; }
.co-sub { margin-top: 14px; }

.co-error {
  margin: 0 0 14px;
  padding: 13px 15px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--risk) 11%, var(--surface));
  color: var(--risk);
  font-size: 13.5px;
  font-weight: 650;
  line-height: 1.45;
  animation: shake .32s;
}
.co-error[hidden] { display: none; }
@keyframes shake {
  0%,100% { transform: translateX(0) }
  25%     { transform: translateX(-5px) }
  75%     { transform: translateX(5px) }
}

.co-empty {
  text-align: center;
  padding: 56px 20px;
  color: var(--ink-2);
  background: var(--surface);
  border-radius: var(--r);
  box-shadow: var(--sh-1);
}
.co-empty a { color: var(--brand); font-weight: 750; }

/* pilihan besar */

.pick {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: 16px;
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sh-1);
  cursor: pointer;
  transition: transform .16s var(--spring), box-shadow .18s;
}
.pick:active { transform: scale(.985); }
.pick:has(input:checked) {
  box-shadow: 0 0 0 2px var(--brand), var(--sh-2);
  background: color-mix(in srgb, var(--brand) 5%, var(--surface));
}
.pick input { accent-color: var(--brand); width: 21px; height: 21px; margin-top: 2px; flex: none; }
.pick-body { flex: 1; display: grid; gap: 4px; min-width: 0; }
.pick-name { font-size: 15.5px; font-weight: 720; }
.pick-desc { font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }
.pick-desc a { color: var(--brand); font-weight: 700; text-decoration: underline; }
.pick-fee {
  font-size: 12px;
  font-weight: 750;
  color: var(--ok);
  background: color-mix(in srgb, var(--ok) 12%, transparent);
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
}
/* Produk flash sale membatasi metode pengiriman -- opsi yg tak boleh diredupkan
   & tak bisa diklik (input[disabled] sudah menghalangi klik; opacity di sini
   murni penanda visual). */
.pick:has(input:disabled) { cursor: not-allowed; }
.pick--locked { opacity: .45; }
.pick--locked .pick-fee { visibility: hidden; }
.pick-restrict-note {
  font-size: 12.5px;
  font-weight: 650;
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, var(--surface));
  border-radius: var(--r-sm);
  padding: 10px 13px;
  line-height: 1.45;
}
/* field */

.field { display: grid; gap: 7px; }
.field label {
  font-size: 11px;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-3);
  display: flex;
  gap: 8px;
  align-items: baseline;
}
.field input, .field select, .field textarea {
  font: inherit;
  font-size: 16px; /* 16px mencegah iOS memperbesar layar saat fokus */
  padding: 14px 15px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  width: 100%;
  box-shadow: var(--sh-1);
  transition: box-shadow .18s;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--brand), var(--sh-1);
}
.field textarea { resize: vertical; line-height: 1.5; }
.hint { margin: 0; font-size: 12px; color: var(--ink-3); line-height: 1.45; }

/* Umpan balik nomor HP saat pembeli mengetik. Tiga derajat SENGAJA dibedakan:
   netral (sedang mengetik) tak boleh terlihat seperti galat, peringatan
   (panjang tak lazim utk awalannya) tak boleh terlihat seperti larangan --
   nomornya tetap boleh dikirim -- dan hanya galat yang berwarna merah. */
.tel-cek { margin: 2px 0 0; font-size: 12px; line-height: 1.45; display: flex; gap: 5px; align-items: flex-start; }
.tel-cek::before { flex: none; font-weight: 700; }
.tel-cek.is-ok { color: #047857; }
.tel-cek.is-ok::before { content: "\2713"; }
.tel-cek.is-ragu { color: #b45309; }
.tel-cek.is-ragu::before { content: "\26A0"; }
.tel-cek.is-salah { color: #b91c1c; }
.tel-cek.is-salah::before { content: "\2715"; }
.tel-cek.is-mengetik { color: var(--ink-3); }
.field input.tel-salah { box-shadow: 0 0 0 2px #fca5a5, var(--sh-1); }

.co-nav { display: flex; gap: 10px; margin-top: 6px; }

/* metode bayar */

.pay-list { display: grid; gap: 9px; }
.pay-option {
  display: flex;
  gap: 13px;
  align-items: flex-start;
  padding: 15px;
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sh-1);
  cursor: pointer;
  transition: transform .16s var(--spring), box-shadow .18s;
}
.pay-option:active { transform: scale(.985); }
.pay-option.is-active, .pay-option:has(input:checked) {
  box-shadow: 0 0 0 2px var(--brand), var(--sh-2);
  background: color-mix(in srgb, var(--brand) 5%, var(--surface));
}
.pay-option input { accent-color: var(--brand); width: 21px; height: 21px; margin-top: 2px; flex: none; }
.pay-body { display: grid; gap: 4px; min-width: 0; }
.pay-name { font-size: 15px; font-weight: 720; }
/* Akhiran "- Auto Confirm" utk metode DOKU (owner 2026-08-12, ganti awalan
   "PM" yg dibuang di storefront_doku.py) -- dipakai jg di order.html
   (.ord-pay-static, .ord-instr h3), bukan cuma di sini. */
.pay-auto-confirm { font-style: italic; font-weight: 550; color: var(--ink-3); }
.pay-acc {
  font-size: 14px;
  font-weight: 780;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
.pay-instruction { font-size: 12.5px; color: var(--ink-2); line-height: 1.45; }

/* rincian */

.co-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.co-item {
  display: flex;
  gap: 12px;
  justify-content: space-between;
  padding: 13px 14px;
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sh-1);
}
.co-item-info { display: grid; gap: 3px; min-width: 0; }
.co-item-name { margin: 0; font-size: 14.5px; font-weight: 680; }
.co-item-opt {
  margin: 0;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--brand);
}
.co-item-unit { margin: 0; font-size: 12.5px; color: var(--ink-3); }
.co-item-right { display: grid; gap: 9px; justify-items: end; }
.co-item-total { margin: 0; font-size: 15px; font-weight: 800; letter-spacing: -0.025em; }

/* Kini terlihat di SEMUA langkah (bukan cuma langkah 3), jadi diberi
   pemisah sendiri dari konten langkah yang sedang aktif di atasnya. */
#coSummaryBlock {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
}

.co-totals {
  margin: 16px 0 0;
  display: grid;
  gap: 9px;
  background: var(--surface);
  border-radius: var(--r);
  padding: 15px 16px;
  box-shadow: var(--sh-1);
}
.co-totals div { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; }
.co-totals div[hidden] { display: none; }
.co-totals dt { color: var(--ink-2); }
.co-totals dd { margin: 0; font-weight: 650; }
.co-totals .grand {
  border-top: 1px dashed var(--hairline);
  padding-top: 12px;
  margin-top: 3px;
}
.co-totals .grand dt { color: var(--ink); font-weight: 750; font-size: 15px; }
.co-totals .grand dd { font-weight: 850; font-size: 19px; letter-spacing: -0.03em; color: var(--brand); }

/* bilah kirim */

.co-sticky {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px var(--pad) calc(12px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  backdrop-filter: blur(14px);
  box-shadow: 0 -2px 20px color-mix(in srgb, var(--brand) 10%, transparent);
}
.co-sticky-total { flex: none; display: grid; }
.co-sticky-total span { font-size: 11px; font-weight: 650; color: var(--ink-3); text-transform: uppercase; letter-spacing: .05em; }
.co-sticky-total strong { font-size: 20px; font-weight: 840; letter-spacing: -0.032em; color: var(--ink); }
.co-sticky .btn-primary { flex: 1; }

/* ==========================================================================
   Halaman pesanan
   ========================================================================== */

.ord-main { max-width: 620px; margin: 0 auto; padding: 22px var(--pad) 48px; display: grid; gap: 13px; }

.ord-hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  padding: 30px 20px 26px;
  text-align: center;
  color: #fff;
  background: linear-gradient(160deg, var(--brand), color-mix(in srgb, var(--brand) 66%, #000));
  box-shadow: var(--sh-2);
}
.ord-hero::before {
  content: "";
  position: absolute;
  inset: -40% -20% auto;
  height: 150%;
  background: radial-gradient(60% 50% at 50% 0%, color-mix(in srgb, var(--accent) 34%, transparent), transparent 70%);
}
.ord-hero > * { position: relative; }

.ord-check {
  width: 52px; height: 52px;
  margin: 0 auto 14px;
  border-radius: 999px;
  background: rgba(255,255,255,.2);
  display: grid;
  place-items: center;
  font-size: 26px;
  animation: pop .5s var(--spring) .1s backwards;
}
.ord-ok { margin: 0 0 8px; font-size: 11.5px; font-weight: 750; text-transform: uppercase; letter-spacing: .1em; opacity: .85; }
.ord-hero h1 { font-size: 27px; font-weight: 840; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.ord-sub { margin: 8px 0 14px; font-size: 13.5px; opacity: .82; }
.ord-status {
  display: inline-block;
  margin: 0;
  font-size: 12.5px;
  font-weight: 750;
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(255,255,255,.2);
  backdrop-filter: blur(6px);
}
.tone-done { background: rgba(86,224,160,.28); }
.tone-stop { background: rgba(255,150,140,.28); }

.ord-card {
  background: var(--surface);
  border-radius: var(--r);
  padding: 16px 17px 18px;
  box-shadow: var(--sh-1);
}
.ord-card h2 {
  font-size: 11px;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--ink-3);
  margin-bottom: 9px;
}
.ord-card p { margin: 0 0 4px; font-size: 14.5px; }
.ord-card .muted { color: var(--ink-2); font-size: 13px; line-height: 1.5; }
.ord-card .co-totals { box-shadow: none; background: transparent; padding: 14px 0 0; margin-top: 12px; border-top: 1px dashed var(--hairline); }

.ord-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 13px; }
.ord-lines li { display: flex; justify-content: space-between; gap: 12px; }
.ord-line-name { margin: 0; font-size: 14.5px; font-weight: 680; }
.ord-line-opt { margin: 0; font-size: 11.5px; font-weight: 600; color: var(--brand); }
.ord-line-unit { margin: 0; font-size: 12.5px; color: var(--ink-3); }
.ord-line-total { font-size: 14.5px; font-weight: 800; white-space: nowrap; }

.ord-next { display: grid; gap: 10px; }

.ord-reviews { display: grid; gap: 16px; }
.ord-review-form { display: grid; gap: 8px; padding-top: 12px; border-top: 1px dashed var(--hairline); }
.ord-review-form:first-of-type { border-top: none; padding-top: 0; }
.ord-review-name { margin: 0; font-size: 14.5px; font-weight: 680; }
.ord-rating { display: flex; flex-direction: row-reverse; justify-content: flex-end; gap: 2px; border: none; margin: 0; padding: 0; }
.ord-rating input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ord-rating label {
  font-size: 26px; line-height: 1; cursor: pointer; color: var(--hairline);
  transition: color .12s ease;
}
.ord-rating input:checked ~ label,
.ord-rating label:hover,
.ord-rating label:hover ~ label { color: var(--warn); }
.ord-review-form textarea {
  width: 100%; min-height: 64px; resize: vertical; font: inherit; color: var(--ink);
  background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-sm);
  padding: 9px 11px; box-sizing: border-box;
}
.ord-review-form button {
  justify-self: start; padding: 9px 18px; border: none; border-radius: 999px;
  background: var(--brand); color: #fff; font-weight: 700; font-size: 13.5px; cursor: pointer;
}

/* ==========================================================================
   Daftar toko & error
   ========================================================================== */

.index-main, .error-main { max-width: 620px; margin: 0 auto; padding: 40px var(--pad) 56px; }
.index-main h1 { font-size: 30px; font-weight: 840; letter-spacing: -0.035em; }
.index-lede { color: var(--ink-2); font-size: 14.5px; line-height: 1.55; margin: 10px 0 26px; }
.index-lede a { color: var(--brand); font-weight: 700; }

.store-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.store-list a {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--surface);
  border-radius: var(--r);
  padding: 14px 16px;
  box-shadow: var(--sh-1);
  transition: transform .18s var(--spring);
}
.store-list a:active { transform: scale(.985); }
.store-list img, .store-initial { width: 46px; height: 46px; border-radius: 13px; object-fit: cover; flex: none; }
.store-initial {
  display: grid; place-items: center;
  background: var(--surface-2);
  font-weight: 800;
  font-size: 19px;
  color: color-mix(in srgb, var(--brand) 55%, var(--ink-3));
}
.store-name { flex: 1; font-weight: 720; font-size: 15.5px; }
.store-state { font-size: 11px; font-weight: 750; padding: 5px 11px; border-radius: 999px; text-transform: uppercase; letter-spacing: .05em; }
.store-state.is-open { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok); }
.store-state.is-closed { background: color-mix(in srgb, var(--risk) 12%, transparent); color: var(--risk); }

.error-main { text-align: center; }
.error-code { font-size: 68px; font-weight: 850; color: color-mix(in srgb, var(--brand) 26%, transparent); margin: 0; line-height: 1; letter-spacing: -0.05em; }
.error-main h1 { font-size: 23px; margin: 12px 0 10px; }
.error-detail { color: var(--ink-2); font-size: 14.5px; line-height: 1.55; margin: 0 auto 24px; max-width: 40ch; }
.error-main .btn-primary { display: inline-block; width: auto; }

/* ==========================================================================
   Layar lebar
   ========================================================================== */

@media (min-width: 720px) {
  :root { --pad: 24px; }

  .shop-head, .shop-main, .pd-related { max-width: 1120px; margin-inline: auto; }
  .grid { grid-template-columns: repeat(var(--cols-desktop, 3), minmax(0, 1fr)); gap: 18px; }
  .strip-rail { grid-auto-columns: 250px; gap: 16px; }
  .card-name { font-size: 14.5px; }
  .card-price { font-size: 18px; }

  .cart-sheet { left: 50%; right: auto; transform: translateX(-50%); width: 480px; border-radius: var(--r-lg); bottom: 20px; max-height: 76vh; }
  @keyframes sheet-up { from { transform: translateX(-50%) translateY(30px); opacity: 0 } to { transform: translateX(-50%); opacity: 1 } }

  .pd-main {
    max-width: 1120px;
    margin-inline: auto;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 32px;
    padding: 26px var(--pad) 120px;
    align-items: start;
  }
  /* `.pd-main` di sini adalah grid 2 kolom (foto | info). Tanpa grid-column
     penuh, .pd-head (anak pertama, statis lagi di lebar ini) ikut mengalir
     jadi sel pertama grid itu sendiri -- mendorong foto ke kolom kanan &
     info ke BARIS BERIKUTNYA (kosong raksasa di bawah breadcrumb). Rentangkan
     penuh supaya jadi baris breadcrumb tersendiri, foto & info baru mulai
     sejajar di baris kedua. */
  /* max-width/margin-inline:auto (peninggalan versi position:absolute lebar-
     viewport) DIBUANG di sini -- pada grid item, margin auto membuat kotak
     menciut ke lebar konten & memusat (bukan melebar rata kiri seperti
     breadcrumb semestinya) begitu grid-column penuh diterapkan. */
  .pd-head { position: static; grid-column: 1 / -1; padding: 20px var(--pad) 0; }
  .pd-media { border-radius: var(--r-lg); box-shadow: var(--sh-2); aspect-ratio: 1 / 1; }
  .pd-info { margin-top: 0; padding: 0; background: transparent; border-radius: 0; }
  .pd-actions { position: static; background: none; backdrop-filter: none; box-shadow: none; padding: 4px 0 0; }

  .co-sticky { justify-content: center; }
  .co-sticky-total { margin-right: 8px; }
  .co-sticky .btn-primary { flex: 0 0 260px; }
}

/* ==========================================================================
   Aksesibilitas gerak
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Ongkir & pemilih lokasi (Fase 2b)
   ========================================================================== */

.ship-block { display: grid; gap: 12px; margin-top: 2px; }

/* Tombol pemilih lokasi sengaja besar dan berbentuk kartu: ini aksi paling
   menentukan di langkah ini, dan di HP harus mudah dikenai ibu jari. */
.loc-btn {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  text-align: left;
  padding: 14px 16px;
  border: 0;
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sh-1);
  cursor: pointer;
  transition: transform .16s var(--spring), box-shadow .18s;
}
.loc-btn:active { transform: scale(.985); }
.loc-btn-icon {
  width: 38px; height: 38px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
  font-size: 19px;
}
.loc-btn-body { flex: 1; display: grid; gap: 2px; min-width: 0; }
.loc-btn-title {
  font-size: 14.5px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.loc-btn-sub { font-size: 12px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.loc-btn-go { color: var(--ink-3); font-size: 22px; flex: none; }

.ship-label {
  margin: 4px 0 0;
  font-size: 11px;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-3);
}

.courier-list { display: grid; gap: 9px; margin-top: 8px; }

.courier {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 15px;
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sh-1);
  cursor: pointer;
  transition: transform .16s var(--spring), box-shadow .18s;
}
.courier:active { transform: scale(.985); }
.courier:has(input:checked) {
  box-shadow: 0 0 0 2px var(--brand), var(--sh-2);
  background: color-mix(in srgb, var(--brand) 5%, var(--surface));
}
.courier input { accent-color: var(--brand); width: 20px; height: 20px; flex: none; }
.courier-body { flex: 1; display: grid; gap: 2px; min-width: 0; }
.courier-name { font-size: 14.5px; font-weight: 700; }
.courier-dur { font-size: 12px; color: var(--ink-3); }
.courier-fee { font-size: 15px; font-weight: 800; letter-spacing: -0.026em; font-variant-numeric: tabular-nums; }

/* Termurah ditandai — daftar kurir diurut dari yang paling murah. */
.courier.is-cheapest::after {
  content: "Termurah";
  position: absolute;
  top: -7px; left: 14px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--ok);
  color: #fff;
}

.ship-loading { margin: 0; font-size: 13.5px; color: var(--ink-3); padding: 14px 2px; }
.ship-note {
  margin: 8px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, var(--surface));
  padding: 10px 13px;
  border-radius: var(--r-sm);
}
.ship-note[hidden] { display: none; }

/* --- lembar peta --- */

.map-sheet { max-height: 90vh; }

/* Dua baris: kolom cari penuh di atas, tombol lokasi perangkat penuh di
   bawahnya. Sebelumnya keduanya berbagi satu baris — tombolnya jadi pil
   sempit berlabel "GPS", dan placeholder kolom carinya terpotong di HP. */
.map-tools {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 var(--pad) 10px;
}
.map-tools input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 16px;
  padding: 12px 15px;
  border: 0;
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--sh-1);
}
.map-tools input:focus { outline: none; box-shadow: 0 0 0 2px var(--brand), var(--sh-1); }
/* Sengaja BUKAN tombol utama penuh-warna: "Pakai lokasi ini" di kaki lembar
   adalah aksi akhirnya, dan dua tombol solid yang sama menonjol membuat
   pembeli menebak mana yang menyelesaikan. Ini pintasan yang jelas terlihat
   namun tetap sekunder — latar merek yang dilembutkan, teks merek penuh. */
.map-gps {
  flex: none;
  width: 100%;
  min-height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 18px;
  border: 1px solid color-mix(in srgb, var(--brand) 35%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 10%, var(--surface));
  color: var(--brand);
  font-size: 14.5px;
  font-weight: 750;
  cursor: pointer;
}
.map-gps:active { transform: scale(.94); }
/* Mati sementara selagi lokasi dicari — lihat map-picker.js. Tanpa penanda
   visual, tombol yang tak merespons terbaca seperti aplikasi macet. */
.map-gps:disabled { opacity: .55; cursor: default; transform: none; }

.map-results {
  flex: none;
  margin: 0 var(--pad) 10px;
  display: grid;
  gap: 1px;
  background: var(--hairline);
  border-radius: var(--r-sm);
  overflow: hidden;
  max-height: 190px;
  overflow-y: auto;
}
.map-results[hidden] { display: none; }
.map-result {
  border: 0;
  background: var(--surface);
  text-align: left;
  padding: 12px 14px;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  cursor: pointer;
}
.map-result:hover, .map-result:focus-visible { background: var(--surface-2); }

.map-canvas {
  flex: 1;
  min-height: 260px;
  margin: 0 var(--pad);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface-2);
  z-index: 0; /* jaga panel Leaflet tetap di bawah kaki lembar */
}

.map-hint { margin: 0; font-size: 12.5px; color: var(--ink-3); line-height: 1.45; }
.map-hint.is-ok { color: var(--ok); font-weight: 650; }
.map-hint.is-warn { color: var(--warn); font-weight: 650; }

@media (min-width: 720px) {
  .map-sheet { width: 560px; max-height: 82vh; }
  .map-canvas { min-height: 340px; }
}

/* ==========================================================================
   Kupon & promo gratis ongkir (Fase 2c)
   ========================================================================== */

.coupon {
  display: grid;
  gap: 8px;
  margin: 14px 0 4px;
  padding: 15px 16px;
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sh-1);
}
.coupon > label {
  font-size: 11px;
  font-weight: 750;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-3);
}
.coupon-row { display: flex; gap: 8px; }
.coupon-row input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 12px 14px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--ink);
}
.coupon-row input::placeholder { font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--ink-3); }
.coupon-row input:focus { outline: none; box-shadow: 0 0 0 2px var(--brand); }
.coupon-apply {
  flex: none;
  padding: 0 20px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--ink);
  color: var(--surface);
  font-size: 14px;
  font-weight: 750;
  cursor: pointer;
  transition: transform .16s var(--spring);
}
.coupon-apply:active { transform: scale(.95); }
.coupon-apply.is-on { background: var(--risk); }

.coupon-msg { margin: 0; font-size: 12.5px; line-height: 1.45; font-weight: 600; }
.coupon-msg[hidden] { display: none; }
.coupon-msg.is-active { color: var(--ok); }
.coupon-msg.is-pending { color: var(--warn); }
.coupon-msg.is-invalid { color: var(--risk); }

.co-totals .disc dd, #coDisc { color: var(--ok); }

/* --- bilah promo --- */

.promo-bar {
  display: grid;
  gap: 8px;
  padding: 13px 15px;
  border-radius: var(--r);
  background: color-mix(in srgb, var(--ok) 9%, var(--surface));
  box-shadow: var(--sh-1);
}
.promo-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.promo-title { font-size: 13.5px; font-weight: 750; color: var(--ok); }
.promo-state { font-size: 12px; font-weight: 650; color: var(--ink-2); text-align: right; }
.promo-track {
  height: 6px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--ok) 18%, transparent);
  overflow: hidden;
}
.promo-fill {
  height: 100%;
  width: 0;
  border-radius: 99px;
  background: var(--ok);
  transition: width .45s var(--out);
}
.promo-bar.is-done .promo-state { color: var(--ok); font-weight: 750; }

/* ==========================================================================
   Produk timbang (Fase 2d)
   ========================================================================== */

.pd-qty--weight {
  width: 100%;
  border: 0;
  text-align: left;
  cursor: pointer;
  transition: transform .16s var(--spring);
}
.pd-qty--weight:active { transform: scale(.985); }
.pd-weight-value { font-weight: 750; color: var(--brand); font-variant-numeric: tabular-nums; }

.weight-sheet { max-height: 88vh; }
.weight-price {
  margin: 0 0 14px;
  font-size: 15px;
  font-weight: 750;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}
.weight-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.weight-grid input { font-variant-numeric: tabular-nums; font-weight: 700; }

.weight-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.weight-chip {
  border: 0;
  border-radius: 999px;
  padding: 9px 15px;
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
  box-shadow: var(--sh-1);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: transform .16s var(--spring);
}
.weight-chip:active { transform: scale(.94); }

.cart-sheet-total span#weightSummary {
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* baris keranjang untuk produk timbang */
.weight-edit { display: flex; align-items: center; gap: 6px; }
.weight-edit-btn {
  border: 0;
  border-radius: 999px;
  padding: 8px 15px;
  background: color-mix(in srgb, var(--brand) 10%, var(--surface));
  color: var(--brand);
  font-size: 13px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  box-shadow: var(--sh-1);
}
.weight-edit-btn:active { transform: scale(.95); }
.weight-edit-del {
  /* 40px -- standar target sentuh minimum situs ini (lihat .card-add),
     sebelumnya 30px (owner, audit UI 2026-08-12). */
  width: 40px; height: 40px;
  border: 0;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-3);
  font-size: 13px;
  cursor: pointer;
}

/* ==========================================================================
   Penanda "langkah berikutnya di sini"
   ========================================================================== */

/* Bagian yang baru saja dibuka digulir ke atas layar. scroll-margin memberi
   napas di atasnya, dan padding-bawah pada kontainer checkout memastikan
   bagian terakhir masih bisa naik ke puncak walau isinya pendek. */
#coCourierWrap, #coAddressWrap { scroll-margin-top: 14px; }

/* Kedipan singkat — cukup untuk menarik mata, tidak sampai mengganggu.
   Memakai box-shadow, bukan background, supaya isi kartunya tidak berkedip. */
.is-highlight { animation: reveal-pulse 1.5s var(--out); border-radius: var(--r); }

@keyframes reveal-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 42%, transparent); }
  35%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--brand) 16%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 0%, transparent); }
}

/* Judul "Pilih kurir" dinaikkan derajatnya: ini instruksi, bukan label. */
.ship-label {
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .02em;
  text-transform: none;
  color: var(--brand);
  display: flex;
  align-items: center;
  gap: 7px;
}
.ship-label::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--brand);
  flex: none;
}

/* Ruang gulir tambahan KHUSUS langkah 1. Tanpa ini halaman terlalu pendek
   untuk menggulir daftar kurir sampai ke atas, sehingga pilihan terakhir
   tertutup bilah total. Hanya di langkah ini — langkah lain tidak perlu. */
.co-step[data-step="1"] { padding-bottom: 96px; }

/* ==========================================================================
   Lapisan tunggu pemilih lokasi
   ========================================================================== */

.map-stage { position: relative; flex: 1; min-height: 260px; display: flex; }
.map-stage .map-canvas { flex: 1; margin: 0 var(--pad); }

.map-loading {
  position: absolute;
  inset: 0 var(--pad);
  z-index: 400;              /* di atas panel Leaflet (z-index 200-an) */
  border-radius: var(--r);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 20px;
  text-align: center;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(6px);
  animation: fade-in .18s;
}
.map-loading[hidden] { display: none; }

.map-spinner {
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--brand) 20%, transparent);
  border-top-color: var(--brand);
  animation: map-spin .8s linear infinite;
}
@keyframes map-spin { to { transform: rotate(360deg); } }

/* Tanpa animasi: titik berdenyut halus, bukan roda berputar. */
@media (prefers-reduced-motion: reduce) {
  .map-spinner {
    animation: none;
    border-top-color: color-mix(in srgb, var(--brand) 20%, transparent);
    background: var(--brand);
    width: 14px; height: 14px;
  }
}

.map-loading-title { margin: 0; font-size: 15px; font-weight: 750; color: var(--ink); }
.map-loading-sub { margin: 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; max-width: 30ch; }
.map-loading-sub:empty { display: none; }

/* status pencarian alamat, tampil di tempat daftar hasil */
.map-searching {
  margin: 0;
  padding: 13px 14px;
  background: var(--surface);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  display: flex;
  align-items: center;
  gap: 9px;
}
.map-searching::before {
  content: "";
  width: 13px; height: 13px;
  flex: none;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--brand) 22%, transparent);
  border-top-color: var(--brand);
  animation: map-spin .8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .map-searching::before { animation: none; background: var(--brand); border-color: var(--brand); }
}

/* ==========================================================================
   Lembar pilihan produk (dibuka dari kartu katalog)
   ========================================================================== */

.opt-sheet { max-height: 86vh; }
.opt-head-body { display: grid; gap: 3px; min-width: 0; }
.opt-head-body h2 { font-size: 17px; font-weight: 780; }
.opt-head-price {
  margin: 0;
  font-size: 14px;
  font-weight: 750;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

#optGroups { display: grid; gap: 18px; }
#optGroups:empty { display: none; }

.opt-qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 14px;
  font-weight: 700;
  padding-bottom: 2px;
}
.opt-weight { display: grid; gap: 10px; }
.opt-sheet .cart-sheet-total span { font-size: 13.5px; font-weight: 650; color: var(--ink-2); }

/* Tombol "Pilih" kini membuka lembar, jadi wujudnya tombol — bukan tautan. */
button.card-add--options { cursor: pointer; }

/* ==========================================================================
   Halaman pesanan — blok pembayaran
   ==========================================================================
   Bagian ini memikul pekerjaan yang dulu ditanggung nota v1: memberi tahu
   berapa yang masih harus dibayar, ke mana, dan bagaimana mengabarkan toko.
   Karena itu ia diletakkan paling atas dan diberi bobot visual paling besar
   di halaman — bukan kartu netral seperti blok lain.
   ========================================================================== */

.ord-when { font-size: 12.5px; opacity: .75; margin-top: 2px; }

.ord-flash {
  margin: 0 var(--pad) 12px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  font-size: 13.5px;
  font-weight: 550;
  line-height: 1.45;
}
.ord-flash.ok  { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }
.ord-flash.err { background: color-mix(in srgb, var(--risk) 12%, transparent); color: var(--risk); }

/* Sisa tagihan dibuat menonjol: itu satu-satunya angka yang menentukan apakah
   pembeli masih perlu melakukan sesuatu. */
.ord-pay.is-due  { border-color: color-mix(in srgb, #f59e0b 45%, transparent); }
.ord-pay.is-paid { border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.ord-due { font-size: 15px; margin: 2px 0 4px; }
.ord-due strong { font-size: 22px; font-weight: 800; letter-spacing: -.02em; }

.ord-pay-badge {
  display: inline-block;
  padding: 3px 12px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: .01em;
}
.ord-pay-badge.ok { background: color-mix(in srgb, var(--ok) 15%, transparent); color: var(--ok); }

.ord-pay-label {
  margin: 16px 0 8px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  opacity: .68;
}
.ord-pay-static { font-weight: 650; margin: 0; }

/* Pemilih metode: dropdown, bukan petak tombol. Toko bisa punya banyak
   rekening (Demo sudah 7) dan petaknya menghabiskan satu layar penuh sebelum
   pembeli sampai ke petunjuk pembayaran — padahal itulah yang ia cari. */
.ord-pay-picker { display: flex; gap: 8px; align-items: stretch; }

/* Pembungkus supaya panah bisa digambar CSS (mengikuti token warna, jadi ikut
   mode gelap dengan sendirinya) alih-alih SVG data-URI berwarna tetap. */
.ord-pay-field { position: relative; flex: 1; min-width: 0; display: flex; }

.ord-pay-field::after {
  content: "";
  position: absolute;
  right: 15px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2.2px solid var(--ink-2);
  border-bottom: 2.2px solid var(--ink-2);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

/* Kotaknya harus terbaca sebagai KONTROL, bukan sebaris teks. Latar kartu
   putih dan latar select juga putih, jadi tanpa batas yang tegas ia lenyap.
   Diperparah token `--line` yang tak pernah didefinisikan: peramban membuang
   SELURUH deklarasi border tanpa sepatah galat pun. Lihat
   tools/cek-token-css.py — penjaga supaya itu tak terulang. */
.ord-pay-select {
  flex: 1;
  min-width: 0;
  padding: 13px 40px 13px 14px;
  border: 2px solid color-mix(in srgb, var(--brand) 30%, var(--hairline));
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--brand) 4%, var(--surface));
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  font-weight: 650;
  line-height: 1.3;
  cursor: pointer;
  appearance: none;
  transition: border-color .15s, background .15s;
}
.ord-pay-select:hover { border-color: color-mix(in srgb, var(--brand) 50%, var(--hairline)); }
.ord-pay-select:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}

/* Tombol cadangan untuk peramban tanpa JavaScript. order.js menyembunyikannya
   dan mengirim form begitu pilihan berubah — tapi ia HARUS ada di HTML, bukan
   ditambahkan JS, supaya tanpa JS pun metode tetap bisa diganti. */
.ord-pay-apply {
  flex: 0 0 auto;
  padding: 0 18px;
  border: 2px solid var(--brand);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--brand);
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.js-auto .ord-pay-apply { display: none; }


/* --- panel petunjuk --- */
.ord-instr {
  margin-top: 16px;
  padding: 14px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  border: 1px solid var(--hairline);
}
.ord-instr h3 { margin: 0 0 10px; font-size: 14px; font-weight: 750; }
/* Tombol "Bayar sekarang" Payment Gateway: satu-satunya TINDAKAN di kartu
   petunjuk (sisanya keterangan), jadi dibuat penuh-lebar dan diberi jarak
   sendiri supaya tak terbaca sebagai bagian dari teks di bawahnya. */
.ord-pay-now { margin: 0 0 14px; }
.ord-pay-now .btn-primary { width: 100%; }
.ord-pay-now .muted { margin: 7px 0 0; font-size: 12px; line-height: 1.45; }
.ord-instr-body p { margin: 0 0 6px; font-size: 13.5px; line-height: 1.5; }
.ord-instr-body p:last-child { margin-bottom: 0; }
.ord-instr-img { width: 100%; max-width: 320px; border-radius: var(--r-sm); margin-bottom: 10px; }

.ord-qris { display: grid; justify-items: center; gap: 10px; margin-bottom: 12px; }
.ord-qris img {
  width: 100%; max-width: 260px;
  border-radius: var(--r-sm);
  background: #fff;
  padding: 10px;
}

/* Gagal muat gambar yang SENDIRI dibutuhkan utk bayar (QRIS/petunjuk) --
   beda dari foto produk/logo (dekorasi, boleh diam-diam jatuh ke huruf
   awal): di sini pembeli WAJIB tahu jelas + diberi jalan keluar. */
.ord-img-gagal {
  display: grid;
  gap: 8px;
  justify-items: center;
  text-align: center;
  padding: 14px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--warn) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warn) 30%, transparent);
  color: var(--warn);
  font-size: 13.5px;
  width: 100%;
}
.ord-img-gagal .btn-secondary { font-size: 13px; padding: 8px 16px; }
p.ord-img-gagal { display: block; }

/* Nomor rekening: angka besar, monospace, dan tombol salin sebesar jempol —
   salah ketik satu digit berarti uang nyasar. */
.ord-acc {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--hairline);
  margin-bottom: 10px;
}
.ord-acc-label { margin: 0 0 2px; font-size: 11.5px; opacity: .7; }
.ord-acc-no {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: .03em;
}
.ord-copy {
  flex: 0 0 auto;
  padding: 9px 16px;
  border-radius: 10px;
  border: 1.5px solid var(--accent);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.ord-copy.is-done { background: var(--accent); color: #fff; }

/* --- bukti transfer --- */
.ord-proof-form { margin-top: 16px; display: grid; gap: 8px; }
.ord-hint { margin: 0; font-size: 11.5px; opacity: .65; text-align: center; }

.ord-proof { margin-top: 16px; display: grid; gap: 10px; }
.ord-proof-ok { margin: 0; font-weight: 700; font-size: 13.5px; color: var(--ok); }
.ord-proof-thumbs { display: flex; gap: 8px; flex-wrap: wrap; }
.ord-proof-thumb, .ord-proof-thumbs img {
  width: 84px; height: 84px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--hairline);
}
.ord-proof-thumb { display: block; }
.ord-proof-thumb-gagal {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%; height: 100%;
  padding: 6px;
  text-align: center;
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--ink-3);
  background: var(--surface-2);
}

/* Warna WhatsApp dipakai apa adanya: pembeli mengenalinya sebelum membaca
   labelnya, dan tombol ini adalah langkah terakhir yang kita ingin ditekan. */
.btn-wa {
  display: block;
  width: 100%;
  padding: 14px 20px;
  border: none;
  border-radius: 14px;
  background: #25d366;
  color: #06281a;
  font: inherit;
  font-size: 15px;
  font-weight: 750;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.btn-wa:disabled { opacity: .6; cursor: default; }
.btn-wa.is-err { background: color-mix(in srgb, var(--risk) 15%, transparent); color: var(--risk); }

/* --- data pemesan --- */
.ord-kv { margin: 0; display: grid; gap: 8px; }
.ord-kv > div { display: flex; justify-content: space-between; gap: 16px; align-items: baseline; }
.ord-kv dt { font-size: 12.5px; opacity: .68; flex: 0 0 auto; }
.ord-kv dd { margin: 0; font-size: 13.5px; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.ord-kv dd a { color: var(--accent); }

/* Angka di dalam kalimat instruksi yang layak disalin. Digayakan sebagai teks
   bergaris bawah, bukan tombol penuh: ia berada di TENGAH kalimat, dan tombol
   kotak di sana memecah alur baca. */
.ord-copy-inline {
  border: none;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: inherit;
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 6px;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}
.ord-copy-inline.is-done { background: var(--accent); color: #fff; text-decoration: none; }

/* --- dok aksi ---------------------------------------------------------
   Halaman pesanan panjang: petunjuk bayar, rincian, data pemesan. Pembeli
   yang baru selesai mentransfer tak boleh perlu menggulir mencari tombol
   konfirmasi. Di ponsel dok melekat di dasar layar; di layar lebar (tombolnya
   selalu terlihat tanpa itu) ia kembali mengalir biasa. */
.ord-dock { display: grid; gap: 6px; }

@media (max-width: 719px) {
  .ord-dock {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 50;
    padding: 10px var(--pad) calc(10px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: blur(14px);
    box-shadow: 0 -2px 20px color-mix(in srgb, var(--brand) 12%, transparent);
  }
  .ord-dock .ord-hint { font-size: 10.5px; }

  /* Ruang supaya kartu terakhir tak tertutup dok. Dok keluar dari alur
     (position:fixed), jadi tanpa ini "Belanja lagi" tersembunyi di baliknya. */
  .ord-main { padding-bottom: 108px; }
}

/* Pesanan lunas: dok kembali mengalir walau di ponsel. */
@media (max-width: 719px) {
  .ord-dock-flow { position: static; padding: 0; background: none; backdrop-filter: none; box-shadow: none; }
}

/* ==========================================================================
   Pre-order
   ========================================================================== */

/* Tombol pada kartu produk yang stoknya habis. Warnanya sengaja BUKAN warna
   merek: pembeli harus bisa membedakan sekilas mana yang siap dikirim dan mana
   yang perlu dijadwalkan, tanpa membaca labelnya. */
.card-add--po {
  background: color-mix(in srgb, var(--warn) 16%, var(--surface));
  color: color-mix(in srgb, var(--warn) 72%, var(--ink));
  border: 1.5px solid color-mix(in srgb, var(--warn) 42%, transparent);
  font-size: 12px;
  font-weight: 750;
  letter-spacing: -.01em;
}

/* Kartu produk habis tadinya diredupkan penuh karena memang tak bisa dibeli,
   lalu redupnya dikurangi ketika pre-order dibuka untuk semuanya. Sejak 28 Agu
   pertanyaannya per produk, jadi redup itu tinggal untuk yang memang ditutup —
   di sana ia MEMBAWA ARTI, bukan sekadar sisa gaya lama. Produk yang menerima
   pre-order tampil penuh warna. */
.card.is-blocked { opacity: .82; }
.card.is-blocked .card-add--mati { opacity: 1; }

/* Tombol produk yang ditutup: terlihat, terbaca, dan jelas tak bisa ditekan. */
.card-add--mati {
  background: var(--surface-2);
  color: color-mix(in srgb, var(--ink) 45%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--ink) 12%, transparent);
  font-size: 11.5px;
  font-weight: 700;
  cursor: not-allowed;
}

/* Baris stok pada kartu yang menawarkan pre-order — sewarna badge-nya, supaya
   kartu tidak berbicara dua nada sekaligus. */
.meta-stock.is-po { color: color-mix(in srgb, var(--warn) 74%, var(--ink)); font-weight: 650; }

.pd-po-note {
  margin: 0 0 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  color: color-mix(in srgb, var(--warn) 74%, var(--ink));
  font-size: 13px;
  line-height: 1.45;
  font-weight: 550;
}

/* Varian "ditutup": bukan tawaran, melainkan kabar bahwa produknya belum bisa
   dipesan — warnanya karena itu netral-risiko, bukan warna ajakan. HARUS
   ditulis SESUDAH aturan dasar di atas: specificity keduanya sama, jadi yang
   menang semata-mata yang belakangan. */
/* Batas pemesanan harian: fakta operasional, bukan bagian dari ajakan — jadi
   ia diberi bobot lebih ringan daripada kalimat di atasnya. */
.pd-po-batas { display: inline-block; margin-top: 4px; font-weight: 500; opacity: .82; }

.pd-po-note--tutup {
  background: color-mix(in srgb, var(--risk) 10%, transparent);
  color: color-mix(in srgb, var(--risk) 78%, var(--ink));
}

.po-sheet .sheet-body { padding-top: 4px; }
.po-sub { margin: 3px 0 0; font-size: 12.5px; line-height: 1.45; opacity: .75; }
.po-sheet .sheet-foot { display: grid; gap: 8px; }

/* Syarat & Ketentuan Flash Sale -- satu poin per baris di kolom "terms". */
.ft-sheet .sheet-body { padding-top: 4px; }
.ft-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.ft-list li { display: flex; gap: 8px; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.ft-list li::before { content: "•"; color: var(--brand); font-weight: 700; flex: none; }
.ft-sheet .sheet-foot { display: grid; gap: 8px; }

/* Pertanyaan "Mau dikirim kapan?" di puncak langkah pertama. Memakai ulang
   gaya dropdown halaman pesanan (.ord-pay-field/.ord-pay-select) supaya kedua
   tempat yang meminta pembeli memilih dari daftar terlihat sama. */
.co-po { display: grid; gap: 7px; }
.co-po #coPreOrderSchedule { display: grid; gap: 7px; margin-top: 4px; }

/* ==========================================================================
   Flash Sale
   ========================================================================== */

/* --- banner puncak halaman --- */
.flash-banner {
  margin: 0 calc(var(--pad) * -1) 22px;
  padding: 16px 0 14px;
  background: linear-gradient(135deg, var(--flash), color-mix(in srgb, var(--flash) 60%, #ff9500));
  color: #fff;
}
.flash-banner-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 var(--pad);
  margin-bottom: 12px;
}
.flash-banner-head h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 850;
  letter-spacing: -0.02em;
  display: flex;
  align-items: center;
  gap: 6px;
}
.flash-countdown {
  display: flex;
  align-items: center;
  gap: 3px;
  font-variant-numeric: tabular-nums;
}
.fc-box {
  background: rgba(0,0,0,.22);
  border-radius: 6px;
  padding: 3px 6px;
  font-size: 13px;
  font-weight: 800;
  min-width: 22px;
  text-align: center;
}
.fc-sep { font-weight: 800; opacity: .8; }

/* .strip-rail dasar full-bleed via margin negatif (menembus padding wadah
   biasa spt .shop-main/.pd-related) -- tapi .flash-rail sudah di DALAM
   .flash-banner yang SENDIRI sudah full-bleed (margin negatif juga). Dua
   margin negatif bertumpuk = rail melebihi tepi banner, kartu pertama
   nempel rata tepi layar sementara judul "Flash Sale" di atasnya tetap
   berjarak var(--pad) -- tak sejajar (laporan owner 2026-08-12). Margin
   horizontalnya dibuang di sini supaya padding-left/right var(--pad) dari
   .strip-rail dasar yang berlaku, sejajar dgn .flash-banner-head. */
.flash-rail { margin: 0; }
/* Kartu di dalam rail flash sale memakai latar putih solid (bukan warna
   permukaan biasa) supaya tetap kontras di atas gradien jingga banner. */
.flash-rail > .card { background: var(--surface); }

/* --- banner "segera hadir": belum ada rail produk (harga bisa masih
   diubah admin sebelum mulai), cuma judul + hitung mundur + catatan. Warna
   gradien SAMA dgn flash sale aktif (bukan token baru) -- ikon jam ⏰ +
   teks "Segera Hadir" sudah cukup membedakan dari "beli sekarang" ⚡. --- */
.flash-banner.is-upcoming { padding-bottom: 16px; }
.flash-upcoming-note {
  margin: 0;
  padding: 0 var(--pad);
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, .92);
}

/* --- badge diagonal di foto kartu --- */
.badge-flash {
  position: absolute;
  z-index: 2;
  inset: 9px auto auto 9px;
  background: var(--flash);
  color: #fff;
  font-size: 10px;
  font-weight: 850;
  letter-spacing: .02em;
  padding: 4px 8px;
  border-radius: 8px;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--flash) 50%, transparent);
}
/* Warna beda dari badge diskon aktif (bukan --flash) -- ini BUKAN "beli
   sekarang diskon", cuma penanda "produk ini akan ikut flash sale". */
.badge-flash--soon {
  background: var(--brand);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 50%, transparent);
}

/* --- harga: flash besar, harga asli dicoret kecil di sebelahnya --- */
.card-price.is-flash {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
}
.card-price-flash {
  font-size: 17px;
  font-weight: 850;
  color: var(--flash-ink);
  letter-spacing: -0.03em;
}
.card-price-orig {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-thickness: 1.3px;
}

/* --- pratinjau harga flash akan-datang: teks kecil di bawah harga normal
   (yang masih tetap harga sesungguhnya) --- */
.card-flash-preview {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  color: var(--flash-ink);
}
.card-flash-preview .muted { font-weight: 600; }

/* --- flash sale bersyarat jumlah ("beli 2 Rp100.000") ---
   Badge memakai --flash penuh (flash sale-nya memang SEDANG berjalan, beda
   dari --soon yang belum mulai), tapi harga besar di kartu tetap harga
   NORMAL: yang bersyarat cuma tawarannya, bukan status kampanyenya. */
.badge-flash--min {
  background: var(--flash);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--flash) 50%, transparent);
}
.card-flash-min {
  margin: 2px 0 0;
  font-size: 11px;
  font-weight: 700;
  color: var(--flash-ink);
  line-height: 1.35;
}
.card-flash-min .muted { font-weight: 600; }
.card-flash-min b { font-weight: 850; }

/* Dorongan di keranjang: "kurang 1 lagi untuk harga flash". Ditempel pada
   baris produknya sendiri, bukan bilah total — pembeli perlu tahu baris MANA
   yang kurang, dan tombol +/- yang menutupnya ada tepat di baris itu. */
.cart-flash-nudge {
  margin: 4px 0 0;
  font-size: 11px;
  font-weight: 700;
  color: var(--flash-ink);
  background: color-mix(in srgb, var(--flash) 10%, transparent);
  border-radius: 8px;
  padding: 5px 8px;
  line-height: 1.35;
}

/* --- progress bar terjual/kuota --- */
.card-flash-bar {
  height: 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--flash) 15%, var(--surface-2));
  overflow: hidden;
  margin-top: 2px;
}
.card-flash-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--flash), color-mix(in srgb, var(--flash) 70%, #ff9500));
  border-radius: inherit;
  transition: width .3s var(--out);
}
.card-flash-left {
  margin: 0;
  font-size: 10.5px;
  font-weight: 650;
  color: var(--flash-ink);
}

/* --- halaman detail produk --- */
.pd-flash { display: grid; gap: 6px; margin-bottom: 4px; }
.pd-flash .badge-flash { position: static; display: inline-block; width: max-content; }
.pd-flash .pd-price {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.pd-flash .card-price-flash { font-size: 26px; }
.pd-flash .card-price-orig { font-size: 15px; }
.pd-flash .card-flash-bar { max-width: 220px; height: 6px; }
.pd-flash .card-flash-left { font-size: 12px; }
/* Kotak hitung mundur di banner etalase memakai overlay gelap-transparan
   karena sudah di atas gradien --flash; di halaman detail latarnya putih
   polos, jadi kotaknya sendiri diberi warna --flash supaya tetap kebaca
   sbg "flash sale", bukan kotak abu-abu netral. */
.pd-flash-countdown .fc-box {
  background: var(--flash);
  color: #fff;
}

/* --- blok "flash sale berikutnya" di halaman detail ---
   Diberi kotak sendiri supaya terbaca sebagai SATU pengumuman, bukan
   beberapa baris teks yang kebetulan berdekatan — pembeli harus bisa
   menangkap "ada promo, tapi belum sekarang" dalam sekali lihat. */
.pd-flash--upcoming {
  border: 1px solid color-mix(in srgb, var(--flash) 35%, transparent);
  background: color-mix(in srgb, var(--flash) 7%, transparent);
  border-radius: 14px;
  padding: 12px 14px;
  gap: 7px;
}
.pd-flash--upcoming .pd-price { font-size: 24px; font-weight: 850; }
.pd-flash-sched {
  font-weight: 700;
  color: var(--flash-ink);
}
/* Ajakan pre-order: dibedakan dari keterangan lain di blok yang sama karena
   ini satu-satunya baris yang menawarkan TINDAKAN, bukan informasi. */
.pd-flash-po {
  margin: 4px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: #065f46;
  background: color-mix(in srgb, #10b981 12%, transparent);
  border-radius: 10px;
  padding: 8px 10px;
}
.pd-flash-cd-label {
  margin: 2px 0 -2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* --- mode edit pesanan (F3, 2026-08-14) ------------------------------
   Catatan di kepala halaman edit: pembeda visual paling penting dari
   checkout biasa — pembeli harus sadar sedang MENGGANTI pesanan lama. */
.co-edit-note {
  margin: 6px 0 0;
  padding: 8px 12px;
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--warn);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 12.5px;
  line-height: 1.45;
}

/* --- picker "Tambah produk" di halaman edit pesanan (slice 2, 2026-08-14) --- */
.pk-open {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  margin: 10px 0 2px;
  padding: 11px 12px;
  border: 1.5px dashed var(--hairline);
  border-radius: var(--r);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  transition: border-color .15s var(--out), color .15s var(--out);
}
.pk-open:hover { border-color: var(--brand); color: var(--brand); }

.pk-sheet { display: flex; flex-direction: column; max-height: 82dvh; }
.pk-tools { padding: 4px 16px 10px; }
.pk-tools input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--ink);
  font-size: 14px;
}
.pk-list {
  list-style: none;
  margin: 0;
  padding: 0 8px 14px;
  overflow-y: auto;
  flex: 1;
}
.pk-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 8px;
  border-bottom: 1px solid var(--hairline);
}
.pk-row:last-child { border-bottom: 0; }
.pk-info { flex: 1; min-width: 0; }
.pk-name {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pk-price { margin: 2px 0 0; font-size: 12.5px; color: var(--ink-2); }
.pk-per { color: var(--ink-3); }
.pk-flash {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--flash, var(--warn));
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .3px;
  vertical-align: 1px;
}
.pk-add {
  flex: 0 0 auto;
  min-width: 40px;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--brand);
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  cursor: pointer;
}
.pk-add--options { font-size: 12.5px; font-weight: 700; }
.pk-add.is-added { background: var(--ok); }
.pk-empty { padding: 18px 16px 24px; text-align: center; color: var(--ink-3); font-size: 13px; }

/* =======================================================================
   Flash sale PRE-ORDER (owner 2026-08-20)
   Produk yang harga promonya hanya bisa didapat lewat pesanan pre-order,
   dengan jadwal ambil/kirim yang ditetapkan toko dan ditegakkan server.

   Warnanya sengaja TETAP --flash: kampanyenya memang sedang berjalan (beda
   dari --soon yang belum mulai). Yang membedakannya dari flash sale biasa
   hanya kata "PO" pada badge dan daftar aturan di bawah harga — bukan warna,
   karena bagi pembeli ini tetap promo yang sedang hidup.
   ======================================================================= */
.badge-flash--po {
  background: var(--flash);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--flash) 50%, transparent);
}
.card-flash-po {
  margin: 2px 0 0;
  font-size: 11px;
  font-weight: 700;
  color: var(--flash-ink);
  line-height: 1.35;
}
.card-flash-po .muted { font-weight: 600; }
.card-price--po .card-price-flash { color: var(--flash-ink); }

/* Halaman detail: kotak aturan yang WAJIB terbaca sebelum tombol ditekan.
   Daftar, bukan paragraf — tiap baris satu aturan yang benar-benar ditegakkan
   server, jadi pembeli bisa mencocokkannya satu per satu. */
.pd-po-rules {
  margin: 8px 0 0;
  padding-left: 18px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.pd-po-rules li { margin: 2px 0; }
.pd-po-rules b { color: var(--ink); font-weight: 800; }
.pd-flash--po-alt {
  background: color-mix(in srgb, var(--flash) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--flash) 25%, transparent);
}
/* Tombol pre-order sekunder (dipakai saat beli langsung MASIH boleh). */
.btn-po {
  border-color: color-mix(in srgb, var(--flash) 45%, transparent);
  color: var(--flash-ink);
  font-weight: 800;
}

/* Lembar pre-order, varian jadwal TERKUNCI: bukan kolom isian, karena memang
   tak ada yang bisa dipilih pembeli. */
.po-locked {
  background: color-mix(in srgb, var(--flash) 8%, var(--surface-2));
  border-radius: var(--r-sm);
  padding: 12px 14px;
}
.po-locked-label {
  margin: 0;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: .03em;
}
.po-locked-value {
  margin: 4px 0 0;
  font-size: 16px;
  font-weight: 850;
  color: var(--ink);
  line-height: 1.35;
}
.po-locked-warn {
  margin: 8px 0 0;
  font-size: 12px;
  font-weight: 650;
  color: var(--warn);
  line-height: 1.45;
}

/* ==========================================================================
   Halaman pilihan dine-in (feremart.com/toko/{slug})
   Layar pertama sesudah pembeli memindai QR di meja. Sengaja sunyi: dua sasaran
   sentuh besar dan tak ada lagi. Setiap elemen tambahan di sini cuma menunda
   keputusan yang jawabannya cuma dua.
   ========================================================================== */

.pilih-wrap {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 34px;
  padding: 40px var(--pad) calc(40px + env(safe-area-inset-bottom));
  max-width: 520px;
  margin: 0 auto;
}

.pilih-kepala { text-align: center; display: grid; gap: 10px; justify-items: center; }
.pilih-logo { width: 72px; height: 72px; border-radius: 20px; object-fit: cover; box-shadow: var(--sh-1); }
.pilih-nama { margin: 0; font-size: 24px; font-weight: 800; letter-spacing: -.02em; line-height: 1.2; }

/* Nomor meja dari QR ditampilkan sebagai penegasan, bukan hiasan: kalau QR-nya
   tertukar antar meja, di sinilah pembeli punya kesempatan menyadarinya
   sebelum memesan. */
.pilih-meja {
  margin: 0;
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 6px 14px; border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  color: var(--brand); font-weight: 800; font-size: 17px;
}
.pilih-meja-label { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; font-weight: 700; opacity: .75; }

.pilih-tanya { margin: 6px 0 0; font-size: 15.5px; color: var(--ink-2); }

.pilih-opsi { display: grid; gap: 14px; }

.pilih-kartu {
  display: flex; align-items: center; gap: 14px;
  min-height: 84px; padding: 18px;
  border-radius: 18px;
  background: var(--surface);
  border: 1.5px solid var(--hairline);
  box-shadow: var(--sh-1);
  color: var(--ink);
  transition: transform .16s var(--spring);
}
.pilih-kartu:active { transform: scale(.985); }

/* Makan di tempat ditonjolkan karena ITU alasan QR-nya ada di meja. Yang satu
   lagi tetap setara besarnya — pembeli yang ingin bungkus tak boleh merasa
   sedang memilih jalan yang salah. */
.pilih-kartu--utama { border-color: var(--brand); background: color-mix(in srgb, var(--brand) 6%, var(--surface)); }

.pilih-ikon {
  flex: none; width: 46px; height: 46px; border-radius: 14px;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
}
.pilih-ikon svg { width: 24px; height: 24px; }

.pilih-teks { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.pilih-judul { font-size: 17px; font-weight: 750; line-height: 1.25; }
.pilih-sub { font-size: 13.5px; color: var(--ink-2); line-height: 1.35; }

.pilih-panah { flex: none; color: var(--ink-3, #7b8794); display: flex; }
.pilih-panah svg { width: 20px; height: 20px; }
.pilih-kartu--utama .pilih-panah { color: var(--brand); }

/* Pemilih nomor meja — dipakai saat QR tak menyebut mejanya. <details> supaya
   bekerja tanpa JavaScript; kartunya harus tetap terlihat seperti dua kartu
   pilihan lain, jadi gaya kartunya dipindah ke <summary>. */
.pilih-meja-buka { display: block; padding: 0; }
.pilih-meja-buka > summary {
  display: flex; align-items: center; gap: 14px;
  min-height: 84px; padding: 18px;
  cursor: pointer; list-style: none;
}
.pilih-meja-buka > summary::-webkit-details-marker { display: none; }
.pilih-panah--buka { transition: transform .2s var(--spring); }
.pilih-meja-buka[open] .pilih-panah--buka { transform: rotate(180deg); }

.pilih-meja-isi { padding: 0 18px 18px; }
.pilih-meja-tanya {
  margin: 0 0 12px; font-size: 13px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2);
}
/* auto-fill, bukan jumlah kolom tetap: toko dengan 6 meja dan toko dengan 200
   meja sama-sama harus terlihat wajar tanpa aturan terpisah. */
.pilih-meja-petak {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 9px;
}
.pilih-meja-nomor {
  display: grid; place-items: center;
  min-height: 52px;
  border-radius: 13px;
  background: var(--surface);
  border: 1.5px solid var(--hairline);
  color: var(--ink);
  font-size: 17px; font-weight: 750;
  font-variant-numeric: tabular-nums;
  transition: transform .14s var(--spring), border-color .15s;
}
.pilih-meja-nomor:hover { border-color: var(--brand); color: var(--brand); }
.pilih-meja-nomor:active { transform: scale(.94); }

/* Strip meja di kepala katalog dine-in. Duduk DI DALAM kepala bergradien,
   jadi warnanya putih-transparan seperti chip cabang dulu — bukan kartu terang
   yang akan bertabrakan dengan gradien di belakangnya. */
.dinein-meja {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(6px);
  color: #fff;
}
.dinein-meja-kiri { display: flex; align-items: center; gap: 9px; min-width: 0; }
/* `flex: none` WAJIB: tanpa itu SVG tanpa lebar intrinsik melar memenuhi
   kepala halaman (terjadi 25 Agu 2026, tertangkap dari tangkapan layar). */
.dinein-meja-kiri > svg { flex: none; width: 18px; height: 18px; opacity: .9; }
.dinein-meja-teks { font-size: 14.5px; font-weight: 600; white-space: nowrap; }
.dinein-meja-teks b { font-weight: 800; font-size: 16px; }

.dinein-meja-ganti {
  flex: none;
  font-size: 12.5px;
  font-weight: 700;
  color: #fff;
  padding: 6px 13px;
  border-radius: 999px;
  background: rgba(255,255,255,.22);
}
.dinein-meja-ganti:active { transform: scale(.96); }

/* ---- Checkout dine-in --------------------------------------------------- */
.dinein-co { padding-bottom: 120px; }
.dinein-co h1 { font-size: 26px; margin: 14px 0 16px; }
.dinein-co h2 { font-size: 15px; margin: 0 0 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2); }

.dinein-co-meja {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 15px; border-radius: 14px; margin-bottom: 16px;
  background: color-mix(in srgb, var(--brand) 9%, transparent); color: var(--ink);
  font-size: 14.5px;
}
.dinein-co-meja b { font-weight: 800; }
.dinein-co-meja a { font-weight: 700; color: var(--brand); font-size: 13px; }

.dinein-co-blok {
  background: var(--surface); border-radius: 16px; padding: 18px;
  box-shadow: var(--sh-1); margin-bottom: 14px;
}
.dinein-co-items { display: grid; gap: 10px; }
.dinein-co-item { display: grid; grid-template-columns: 1fr auto auto; gap: 10px; align-items: baseline; font-size: 14.5px; }
.dinein-co-item-qty { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.dinein-co-item-harga { font-weight: 700; font-variant-numeric: tabular-nums; }

.dinein-co-totals { margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--hairline); display: grid; gap: 8px; }
.dinein-co-total-row { display: flex; justify-content: space-between; font-size: 14.5px; color: var(--ink-2); }
.dinein-co-total-row span:last-child { font-variant-numeric: tabular-nums; }
.dinein-co-total-row.is-grand { font-size: 17px; font-weight: 800; color: var(--ink); padding-top: 8px; border-top: 1px solid var(--hairline); }

.dinein-co-qris { display: flex; gap: 12px; align-items: flex-start; }
.dinein-co-qris-tag {
  flex: none; font-size: 12px; font-weight: 800; letter-spacing: .06em;
  padding: 7px 12px; border-radius: 9px;
  background: color-mix(in srgb, var(--brand) 12%, transparent); color: var(--brand);
}
.dinein-co-qris-teks { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; }
.dinein-co-galat { margin: 0; font-size: 14px; color: #a6231b; line-height: 1.5; }
.dinein-co-pesan { margin: 12px 0 0; font-size: 14px; color: #a6231b; }

/* Bilah bayar menetap di bawah: total harus terlihat tanpa menggulir kembali. */
.dinein-co-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; align-items: center; gap: 12px;
  padding: 12px var(--pad) calc(12px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--ground) 94%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--hairline);
}
.dinein-co-bar-total { flex: 1; display: flex; flex-direction: column; gap: 1px; }
.dinein-co-bar-total span { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-2); font-weight: 700; }
.dinein-co-bar-total b { font-size: 19px; font-weight: 800; font-variant-numeric: tabular-nums; }
.dinein-co-bar .btn-primary { flex: none; min-width: 150px; }
.dinein-co-bar .btn-primary:disabled { opacity: .55; }

/* ---- Halaman lacak pesanan dine-in -------------------------------------- */
.lacak-wrap { max-width: 560px; margin: 0 auto; padding: 26px var(--pad) calc(40px + env(safe-area-inset-bottom)); }
.lacak-kepala { text-align: center; margin-bottom: 20px; }
.lacak-nomor { margin: 0 0 6px; font-size: 12.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-2); font-weight: 700; }
.lacak-status { margin: 0; font-size: 24px; font-weight: 800; letter-spacing: -.02em; }
.lacak-meja { margin: 8px 0 0; font-size: 14.5px; color: var(--ink-2); }
.lacak-meja b { color: var(--ink); font-weight: 800; }

.lacak-tenggat {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-radius: 14px; margin-bottom: 14px;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--ink);
}
.lacak-tenggat-teks { font-size: 13.5px; }
.lacak-tenggat-jam { font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; }
.lacak-tenggat.is-habis { background: color-mix(in srgb, #a6231b 12%, transparent); }

.lacak-bayar-form { margin-bottom: 16px; }
.lacak-bayar-form .btn-primary { width: 100%; }

.lacak-blok { background: var(--surface); border-radius: 16px; padding: 18px; box-shadow: var(--sh-1); margin-bottom: 14px; }
.lacak-blok h2 { font-size: 13px; margin: 0 0 14px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }

/* Timeline: garis penghubung digambar dari titik, bukan elemen terpisah —
   supaya jumlah langkah bisa berubah (dibatalkan cuma 2) tanpa aturan khusus. */
.lacak-timeline { list-style: none; margin: 0; padding: 0; }
.lacak-langkah { display: grid; grid-template-columns: 22px 1fr; gap: 12px; position: relative; padding-bottom: 20px; }
.lacak-langkah:last-child { padding-bottom: 0; }
.lacak-langkah::before {
  content: ''; position: absolute; left: 10px; top: 18px; bottom: -2px;
  width: 2px; background: var(--hairline);
}
.lacak-langkah:last-child::before { display: none; }
.lacak-langkah.is-done::before { background: var(--brand); }
.lacak-titik {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--hairline); background: var(--surface);
  position: relative; z-index: 1;
}
.lacak-langkah.is-done .lacak-titik { background: var(--brand); border-color: var(--brand); }
.lacak-langkah.is-now .lacak-titik { box-shadow: 0 0 0 5px color-mix(in srgb, var(--brand) 22%, transparent); }
.lacak-langkah-teks { display: flex; flex-direction: column; gap: 2px; padding-top: 1px; }
.lacak-langkah-label { font-size: 15px; font-weight: 600; color: var(--ink-2); }
.lacak-langkah.is-done .lacak-langkah-label { color: var(--ink); font-weight: 700; }
.lacak-langkah-jam { font-size: 12.5px; color: var(--ink-3, #7b8794); font-variant-numeric: tabular-nums; }

/* ---- Kartu "Progres pesanan" di halaman nota (owner 27 Agu 2026) --------
   Memakai ULANG `.lacak-*` di atas — bentuknya memang sama persis dengan
   timeline dine-in, dan menyalinnya jadi `.ord-*` berarti dua timeline yang
   akan menyimpang diam-diam. Yang di bawah ini cuma yang BELUM ada di sana. */

/* Kalimat "apa yang sedang ditunggu", menempel di langkah yang sedang
   berjalan. Diberi warna merek supaya mata jatuh ke sana lebih dulu: di
   antara 4 langkah, satu-satunya baris yang dicari pembeli adalah ini. */
.lacak-langkah-harap {
  font-size: 13px;
  line-height: 1.45;
  color: var(--brand);
  font-weight: 600;
  margin-top: 3px;
}

/* Langkah yang belum tercapai tetap terbaca, tapi jelas belum terjadi —
   bukan dibuat samar sampai tak terbaca (pembeli perlu tahu masih ada berapa
   tahap lagi, dan itu informasi, bukan dekorasi). */
.ord-progres .lacak-timeline { margin-top: 2px; }

.ord-progres-bayar {
  margin: 0 0 14px;
  font-size: 14px;
  font-weight: 700;
  color: #1a7f4b;
}

.ord-progres-catatan {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.5;
}

.lacak-items { display: grid; gap: 10px; }
.lacak-item { display: grid; grid-template-columns: 1fr auto auto; gap: 10px; font-size: 14.5px; align-items: baseline; }
.lacak-item-qty { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.lacak-item-harga { font-weight: 700; font-variant-numeric: tabular-nums; }
.lacak-total { display: flex; justify-content: space-between; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--hairline); font-size: 17px; }
.lacak-total b { font-weight: 800; font-variant-numeric: tabular-nums; }

.lacak-lagi { display: block; text-align: center; padding: 14px; font-weight: 700; color: var(--brand); }

/* ---- Pilihan "dibungkus" di checkout dine-in ---------------------------- */
.bungkus-opsi { display: grid; gap: 8px; }
.bungkus-pilih {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; border-radius: 13px;
  border: 1.5px solid var(--hairline); background: var(--surface);
  font-size: 15px; cursor: pointer;
}
.bungkus-pilih span { flex: 1; }
.bungkus-pilih b { font-weight: 700; font-variant-numeric: tabular-nums; }
.bungkus-pilih:has(input:checked) {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 7%, var(--surface));
}
.bungkus-pilih input { accent-color: var(--brand); width: 18px; height: 18px; }

.bungkus-kemasan { margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--hairline); display: grid; gap: 8px; }
.bungkus-kemasan-judul { margin: 0 0 2px; font-size: 13px; font-weight: 700; color: var(--ink-2); }
.bungkus-kemasan-judul .wajib {
  margin-left: 6px; font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px;
  background: color-mix(in srgb, #a6231b 12%, transparent); color: #a6231b;
}
/* Galat ditaruh SETELAH pilihannya, bukan di atas: pembeli baru memilih, dan
   penjelasannya harus muncul di tempat matanya sedang berada. */
.bungkus-galat, .bungkus-kosong {
  margin: 12px 0 0; font-size: 13.5px; line-height: 1.5; color: #a6231b;
}

/* Penanda toko tutup di halaman pilihan dine-in. Memakai token `--risk` yang
   sama dengan `.store-state.is-closed` di etalase biasa — satu bahasa warna
   untuk "tutup" di seluruh produk, dan gelap/terang ikut benar sendiri. */
.tutup-tanda {
  display: flex; flex-direction: column; gap: 2px; text-align: center;
  padding: 12px 16px; margin-bottom: 16px; border-radius: var(--r);
  background: color-mix(in srgb, var(--risk) 12%, transparent);
}
.tutup-tanda b { font-size: 15px; font-weight: 800; color: var(--risk); }
.tutup-tanda span { font-size: 13px; color: var(--ink-2); }
/* Kartu yang dimatikan tetap TERBACA, cuma jelas tak bisa diketuk — kartu yang
   hilang membuat pembeli mengira QR-nya rusak. */
.pilih-kartu.is-mati { opacity: .55; cursor: not-allowed; border-style: dashed; }
/* Panah ditanggalkan: ia menjanjikan ketukan yang tak akan menghasilkan apa pun. */
.pilih-kartu.is-mati .pilih-panah { display: none; }

/* ==========================================================================
   Bukti sosial — "Nurul A. membeli Layang Besar 1 kg · 11 menit lalu"
   ==========================================================================

   Dirancang untuk DILIRIK, bukan dibaca: ia muncul di pojok selagi mata
   pembeli sedang di katalog, jadi bebannya harus mendekati nol. Karena itu
   lebarnya dikunci sempit, teksnya dua baris, dan hanya dua hal yang ditebalkan
   — nama orangnya dan nama produknya. Sisanya sengaja diredupkan.

   Kartunya memakai --surface + --sh-2 yang sama dengan kartu produk, bukan
   warna merek pekat: ia harus terbaca sebagai "kabar dari toko ini", bukan
   sebagai iklan yang menempel di atas halaman. Satu-satunya warna kuat adalah
   titik hijau --ok, yang memang menandakan sesuatu yang baru saja terjadi.
   -------------------------------------------------------------------------- */

.sp-wrap {
  position: fixed;
  left: 12px;
  bottom: calc(14px + env(safe-area-inset-bottom));
  /* DI BAWAH pil keranjang (60) dan lembar geser (70/71). Kalau toh sempat
     bertindihan sesaat, yang menang harus selalu yang bisa ditekan pembeli
     untuk membeli — bukan hiasan ini. */
  z-index: 55;
  /* Blok, bukan flex: tombol tutup DIPOSISIKAN di sudut kartu (lihat
     `.sp-close`), bukan diletakkan di sebelahnya. Sebagai saudara sejajar ia
     terbaca sebagai tombol yang mengambang lepas — dan di layar sempit ia
     memakan lebar yang seharusnya jadi jatah nama produk. */
  display: block;
  max-width: min(328px, calc(100vw - 30px));
  /* Tumbuh dari sudut tempatnya tinggal, bukan dari titik tengahnya sendiri —
     kartu yang mengembang dari udara di atas pojok terbaca sebagai "muncul
     begitu saja", yang dari sudutnya terbaca sebagai "naik dari sana". */
  transform-origin: 0 100%;
  /* translate3d + will-change: naikkan ke lapisan komposit sendiri supaya
     animasinya tak pernah ikut mengantre di belakang layout katalog. Ia dipakai
     berulang seumur halaman, jadi lapisannya memang layak dipertahankan. */
  will-change: opacity, transform;
  pointer-events: none;

  /* --- KEADAAN TERSEMBUNYI, sekaligus transisi KELUAR ---------------------
     Kurva masuk dan keluar SENGAJA berbeda, dan ini perbaikan yang paling
     terasa: sebelumnya keduanya memakai `--spring` (cubic-bezier ber-overshoot
     1.4). Pegas itu tepat untuk sesuatu yang datang, tapi pada gerak keluar ia
     membuat kartu terlempar sedikit ke ARAH BERLAWANAN dulu sebelum pergi —
     tersentak, dan tersentaknya justru di detik terakhir yang paling terlihat.
     Keluar kini pendek dan menghilang lurus; yang mau dilupakan tak perlu
     dianimasikan lama. */
  opacity: 0;
  transform: translate3d(0, 8px, 0) scale(.985);
  transition:
    opacity .24s cubic-bezier(.4, 0, 1, 1),
    transform .28s cubic-bezier(.4, 0, 1, 1),
    bottom .34s var(--out);
}
.sp-wrap[hidden] { display: none; }

/* --- transisi MASUK: lambat, melambat panjang, tanpa pantulan ------------
   `--out` (ease-out kuintik) melambat jauh lebih lama daripada ease biasa,
   jadi 30% terakhir gerakannya nyaris berhenti sendiri — itu yang dibaca mata
   sebagai "halus". Transform sengaja lebih panjang dari opacity: kartunya
   sudah terbaca penuh saat gerakannya masih menyelesaikan sisa terakhir,
   bukan berhenti mendadak begitu terlihat. */
.sp-wrap.is-tampil {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  pointer-events: auto;
  transition:
    opacity .42s var(--out),
    transform .58s var(--out),
    bottom .34s var(--out);
}
/* Dinaikkan saat pil Keranjang muncul atau di halaman produk (bilah aksi
   menempel di dasar layar). Di HP keduanya selebar layar — tanpa ini
   notifikasi benar-benar tertimpa, bukan sekadar berdempetan. */
.sp-wrap.is-naik { bottom: calc(80px + env(safe-area-inset-bottom)); }

.sp-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 8px 16px 8px 8px;
  border-radius: 999px 16px 16px 999px;
  background: color-mix(in srgb, var(--surface) 97%, transparent);
  backdrop-filter: blur(12px);
  box-shadow: var(--sh-2);
  text-decoration: none;
  color: inherit;
  transition: transform .18s var(--out);
}
.sp-toast:active { transform: scale(.97); }
/* Bukti tentang produk yang SEDANG dibuka tak punya tujuan untuk dituju, jadi
   anchor-nya dirender tanpa `href` (lihat social-proof.js). Ia harus berhenti
   BERLAGAK bisa ditekan juga: kartu yang menyusut saat disentuh tapi tak
   membawa ke mana-mana terbaca sebagai tombol rusak. */
.sp-toast:not([href]) { cursor: default; }
.sp-toast:not([href]):active { transform: none; }

.sp-thumb {
  position: relative;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-2);
}
.sp-thumb img { width: 100%; height: 100%; object-fit: cover; }
/* Foto adalah satu-satunya bagian yang berganti TOTAL tiap putaran; sedikit
   membesar mengikuti kartunya membuat pergantian itu terbaca sebagai satu
   gerakan, bukan sebagai gambar yang ditukar. Sedikit lebih lambat dari
   kartunya supaya terasa mengikuti, bukan berlomba. */
.sp-thumb { transform: scale(.9); transition: transform .5s var(--out); }
.sp-wrap.is-tampil .sp-thumb { transform: scale(1); }
.sp-thumb-none {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 17px;
  font-weight: 800;
  color: color-mix(in srgb, var(--brand) 70%, var(--ink-3));
}
.sp-thumb-none[hidden] { display: none; }

.sp-body { min-width: 0; display: flex; flex-direction: column; gap: 1px; }

/* Dua baris, lalu potong. Nama produk di etalase ini bisa sepanjang
   "CakeBox Mathca Strawberry Delight 450gr" — dibiarkan mengalir, satu
   notifikasi bisa setinggi setengah layar HP. */
.sp-line {
  font-size: 12.8px;
  line-height: 1.35;
  color: var(--ink-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sp-line b { font-weight: 750; color: var(--ink); }
.sp-qty { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }

.sp-meta {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 650;
  color: var(--ink-3);
  letter-spacing: .01em;
}

/* Titik hidup. Denyutnya pelan dan tipis — ini penanda "baru", bukan alarm. */
.sp-live {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 55%, transparent);
  animation: sp-denyut 2.4s ease-out infinite;
}
@keyframes sp-denyut {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 50%, transparent); }
  70%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--ok) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 0%, transparent); }
}

/* Tombol tutup diberi bidang sentuh 28px penuh walau ikonnya kecil: ia berada
   tepat di sebelah tautan produk, dan meleset satu piksel di sini berarti
   pembeli terlempar ke halaman produk yang tidak ia minta. */
.sp-close {
  position: absolute;
  top: -7px;
  right: -7px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--sh-1), 0 0 0 1px var(--hairline);
  color: var(--ink-3);
  cursor: pointer;
}
.sp-close svg { width: 12px; height: 12px; }
.sp-close:active { transform: scale(.92); }

/* Muncul BELAKANGAN, setelah kartunya selesai duduk. Tombol tutup adalah hal
   terakhir yang perlu dilihat pembeli — memunculkannya berbarengan membuat
   matanya harus memilih antara dua benda yang bergerak bersamaan. */
.sp-close { opacity: 0; transform: scale(.7); transition: opacity .2s ease-in, transform .2s ease-in; }
.sp-wrap.is-tampil .sp-close {
  opacity: 1;
  transform: scale(1);
  transition: opacity .3s var(--out) .26s, transform .42s var(--out) .26s;
}

@media (min-width: 768px) {
  .sp-wrap { left: 20px; bottom: calc(20px + env(safe-area-inset-bottom)); }
  /* Di desktop pil Keranjang tetap di tengah bawah dan tak selebar layar,
     jadi kenaikannya cukup sedikit. */
  .sp-wrap.is-naik { bottom: calc(84px + env(safe-area-inset-bottom)); }
}

@media (prefers-reduced-motion: reduce) {
  /* Semua gerak dicabut, pudarnya dipertahankan: pergantian isi yang MENDADAK
     tanpa transisi apa pun justru lebih mengganggu bagi orang yang sensitif
     gerak daripada pudar pelan. `will-change` ikut dilepas — tak ada gerak
     yang perlu diantisipasi lagi. */
  .sp-wrap {
    will-change: auto;
    transform: none;
    transition: opacity .22s linear, bottom 0s;
  }
  .sp-wrap.is-tampil { transform: none; transition: opacity .28s linear; }
  .sp-thumb, .sp-wrap.is-tampil .sp-thumb { transform: none; transition: none; }
  .sp-close, .sp-wrap.is-tampil .sp-close { transform: none; transition: opacity .2s linear; }
  .sp-live { animation: none; }
}
