/* Minicart drawer. Hasil ukur coterie.com, dipakai apa adanya.
   Sumber angka: brief ukur cart drawer (1280 dan 375).

   Port dari clvn-desk src/components/site/minicart.css ke situs statis.
   Yang berubah cuma NAMA, bukan angka:
     .mc          jadi .mini-cart
     .mc__scrim   jadi .mini-cart__shield   (lihat catatan di bawah)
     camelCase    jadi kebab, contoh .mc__stepBtn jadi .mini-cart__step-btn
     @keyframes mcSpin jadi mini-cart-spin
   Ditambah satu blok baru di paling bawah untuk atribut hidden. Alasannya
   ada di blok itu sendiri.

   Nama shield, bukan scrim: situs ini sudah punya .side-nav__shield untuk
   lapisan gelap di belakang drawer mobile, dengan perilaku dan transisi
   yang persis sama polanya. Dua nama untuk satu benda di satu situs itu
   utang yang tidak ada untungnya. Angka dan transisinya tetap milik
   minicart, cuma namanya yang ikut tetangga.

   Semua rem memakai root font-size dari tokens.css:
   375 -> 10.00px, 1280 -> 8.88px. Jadi "8rem" berarti 80px @375
   dan 71.07px @1280. Pasangan angka seperti "71 desktop / 80 mobile"
   di hasil ukur hampir selalu satu nilai rem yang sama, bukan dua
   nilai px terpisah. Itu sebabnya nyaris tidak ada media query di
   file ini untuk ukuran, hanya untuk hal yang benar benar berubah. */

/* ============ PANEL ============
   Geser dari KANAN. Polanya kebalikan dari .side-nav: left: 100%
   memarkir panel penuh di luar tepi kanan, lalu
   translate3d(-100%, 0, 0) menariknya masuk. Persen pada transform
   dihitung dari lebar elemen sendiri, jadi di desktop panel bergeser
   50vw dan tepi kanannya pas di tepi layar.

   Animasi SENGAJA TIDAK SIMETRIS, ini hasil ukur, bukan kelalaian:
   buka  1000ms cubic-bezier(0.16, 1.08, 0.38, 0.98), delay 0
   tutup 800ms  cubic-bezier(0.77, 0, 0.175, 1), delay 200ms
   Nilai kontrol 1.08 melewati 1, jadi saat buka ada overshoot halus.
   Visibility saat tutup TIDAK ikut delay 200ms: dia 800ms ease
   delay 0, supaya panel sudah tidak bisa difokus sebelum geraknya
   selesai. */
.mini-cart {
  display: flex;
  position: fixed;
  z-index: 23;
  top: 0;
  bottom: 0;
  left: 100%;
  width: 100%;
  flex-direction: column;
  overflow: hidden;
  background: var(--white);
  color: var(--black);
  /* Terukur radius 0. Ditulis eksplisit supaya tidak kena reset lain. */
  border-radius: 0;
  transform: none;
  visibility: hidden;
  transition:
    transform 0.8s var(--ease-out-quart) 0.2s,
    visibility 0.8s ease 0s;
}
.mini-cart.is-open {
  visibility: visible;
  transform: translate3d(-100%, 0, 0);
  transition:
    transform 1s var(--ease-in-overshoot) 0s,
    visibility 1s var(--ease-in-overshoot) 0s;
}
/* Terukur: lebar 50 persen dan garis kiri hanya di 1024 ke atas.
   Di bawah itu panel penuh layar dan tanpa border. */
@media (min-width: 1024px) {
  .mini-cart {
    width: 50%;
    border-left: 1px solid var(--hairline);
  }
}

/* ============ SHIELD ============
   rgba(20, 20, 20, 0.2), sama dengan token --overlay. TANPA blur.
   Nilai ini beda dari .side-nav__shield yang terukur 0.25, jadi yang
   dipinjam dari sana cuma namanya, bukan warnanya.

   Saat tutup dia digeser translateX(-100%) dengan durasi 0s dan
   delay 0.8s: jadi shield baru benar benar disingkirkan SETELAH
   fade selesai. Kalau transform-nya ikut dianimasikan, shield
   akan terlihat melayang ke kiri saat menutup. */
.mini-cart__shield {
  position: fixed;
  z-index: 22;
  inset: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  cursor: pointer;
  background-color: var(--overlay);
  transform: translateX(-100%);
  transition:
    opacity 0.8s var(--ease-out-quart),
    visibility 0.8s var(--ease-out-quart),
    transform 0s linear 0.8s;
}
.mini-cart__shield.is-visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition:
    opacity 1s var(--ease-in-overshoot),
    visibility 1s var(--ease-in-overshoot),
    transform 0s linear;
}

/* ============ HEADER ============
   Terukur tinggi 60px, yaitu 6rem @375. Padding 1.6rem 16px di
   mobile (16px ditulis literal di sumbernya; di 375 nilainya sama
   dengan var(--margin)) dan 2.5rem var(--margin) di desktop.
   min-height dipakai, bukan height: di desktop padding 2.5rem
   (44.4px total) plus baris judul sudah melewati 60px, jadi angka
   60 itu hasil ukur mobile dan desktop mengikuti padding. */
.mini-cart__head {
  display: flex;
  position: sticky;
  z-index: 2;
  top: 0;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem;
  min-height: 6rem;
  padding: 1.6rem 16px;
  background: var(--white);
  border-bottom: 1px solid var(--hairline);
}
@media (min-width: 1024px) {
  .mini-cart__head {
    padding: 2.5rem var(--margin);
  }
}
.mini-cart__title {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0;
}
/* Badge jumlah item. Ukurannya tidak ada di hasil ukur, jadi dia
   memakai skala mono yang sama dengan banner (11px @375 dan @1280). */
.mini-cart__badge {
  font-family: var(--font-mono-ui);
  font-size: clamp(11px, 1rem, 10px);
  letter-spacing: -0.06em;
  color: var(--black7);
}
.mini-cart__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
}
.mini-cart__close svg {
  width: 1.6rem;
  height: 1.6rem;
}

/* ============ DAFTAR ITEM ============
   flex-grow 1, area scroll, scrollbar disembunyikan. */
.mini-cart__lines {
  flex-grow: 1;
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.mini-cart__lines::-webkit-scrollbar {
  display: none;
}
/* Padding baris tidak ada di hasil ukur. Dipakai var(--margin)
   supaya sejajar dengan header dan footer. */
.mini-cart__line {
  padding: 1.6rem var(--margin);
  border-bottom: 1px solid var(--hairline);
}

/* Baris 1: gambar, nama, harga, stepper, tombol hapus. */
.mini-cart__row1 {
  display: flex;
  position: relative;
  gap: 1.2rem;
}
/* Terukur 71x71 desktop dan 80x80 mobile, radius 0.8rem.
   Dua duanya 8rem, satu nilai. */
.mini-cart__thumb {
  flex: 0 0 auto;
  width: 8rem;
  height: 8rem;
  overflow: hidden;
  border-radius: var(--radius-card);
}
.mini-cart__info {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  /* Ruang untuk tombol hapus 24px yang duduk di pojok kanan atas. */
  padding-right: calc(24px + 1.2rem);
}
/* Nama 16.2px desktop dan 18px mobile: itu persis .t-18 di tokens.
   Harga 12.6px desktop dan 14px mobile: itu .t-14. Dua duanya
   dipakai lewat class di markup, bukan diulang di sini. */
.mini-cart__name {
  margin: 0;
}
.mini-cart__price {
  margin: 0;
  color: var(--black7);
}
/* Tombol hapus, ikon tempat sampah 24x24 di pojok KANAN ATAS baris. */
.mini-cart__remove {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--black7);
}
.mini-cart__remove svg {
  width: 16px;
  height: 16px;
}

/* Stepper kuantitas.
   Terukur 88x30 total: minus 28x28, angka 30px, plus 28x28.
   28 + 30 + 28 = 86, ditambah border 1px kiri kanan = 88. Angka
   angka ini px tetap di sumbernya, bukan rem, jadi ditulis px. */
.mini-cart__stepper {
  display: flex;
  align-items: center;
  margin-top: 0.4rem;
  background: var(--white);
  border: 1px solid var(--hairline);
  border-radius: 5px;
}
.mini-cart__step-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  /* Terukur rgb(81, 81, 81), sama dengan token --black7. */
  color: var(--black7);
}
.mini-cart__step-btn:disabled {
  opacity: 0.4;
  cursor: default;
}
.mini-cart__step-btn svg {
  width: 10px;
  height: 10px;
}
/* Terukur lebar 30px dan font 11px di desktop. */
.mini-cart__qty {
  width: 30px;
  text-align: center;
  font-size: 11px;
  line-height: 1;
  color: var(--black);
}

/* Baris 2: pill varian.
   Terukur lebar penuh, tinggi 36px, border 1px hairline, radius
   0.8rem, background putih. Font 12.6 desktop dan 14 mobile (.t-14).
   Padding 0 0.7rem di mobile dan 0 1.2rem di desktop: ini salah satu
   dari sedikit nilai yang memang beda rem antar breakpoint. */
.mini-cart__variant {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  width: 100%;
  height: 36px;
  margin-top: 1.2rem;
  padding: 0 0.7rem;
  background: var(--white);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
}
@media (min-width: 1024px) {
  .mini-cart__variant {
    padding: 0 1.2rem;
  }
}
.mini-cart__variant-meta {
  display: flex;
  min-width: 0;
  align-items: baseline;
  gap: 0.8rem;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.mini-cart__variant-pack {
  color: var(--black7);
}
.mini-cart__edit-size {
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--blue600);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Baris 3: mode kirim.
   Terukur tinggi 35px desktop dan 40px mobile. Dua duanya 4rem. */
.mini-cart__row3 {
  display: flex;
  height: 4rem;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem;
}
.mini-cart__ships {
  color: var(--black7);
}

/* ============ UPSELL ============
   Terukur blok 639x151 desktop dan 375x166 mobile. Lebarnya cuma
   lebar drawer, jadi tidak diset. Tingginya hasil dari isi:
   padding 1.6rem atas bawah, judul, gap 1.2rem, kartu 91 atau 102.
   Padding kanan 0 karena barisnya menggulir horizontal. */
.mini-cart__upsell {
  flex: 0 0 auto;
  padding: 1.6rem 0 1.6rem var(--margin);
  background: var(--stone);
}
/* Judul 15.3px desktop dan 17px mobile. Tidak ada pasangan t-17 di
   tokens (yang ada cuma lg-t-17), jadi sisi mobile ditulis di sini
   dengan rumus yang sama persis: 1.7rem = 17px @375. */
.mini-cart__upsell-title {
  margin: 0 var(--margin) 1.2rem 0;
  font-size: max(1.7rem, 17px);
  line-height: 1.4;
}
@media (min-width: 1024px) {
  .mini-cart__upsell-title {
    font-size: clamp(15.3px, 1.7rem, 17px);
  }
}
.mini-cart__upsell-row {
  display: flex;
  gap: 1.2rem;
  padding-right: var(--margin);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.mini-cart__upsell-row::-webkit-scrollbar {
  display: none;
}
/* Kartu terukur 249x91 desktop dan 280x102 mobile. Lebar 28rem
   memberi 280 @375 dan 248.7 @1280. Tingginya tidak diset: gambar
   8rem + padding 1rem atas bawah + border 1px atas bawah = 102 @375
   dan 90.8 @1280, jadi angka ukurnya keluar sendiri dari isi. */
.mini-cart__upsell-card {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 1rem;
  width: 28rem;
  padding: 1rem;
  background: var(--white);
  border: 1px solid var(--grey-disabled);
  border-radius: var(--radius-card);
}
/* Gambar kartu 71x71 desktop dan 80x80 mobile, sama dengan thumb item. */
.mini-cart__upsell-media {
  flex: 0 0 auto;
  width: 8rem;
  height: 8rem;
  overflow: hidden;
  border-radius: var(--radius-card);
}
.mini-cart__upsell-info {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
}
.mini-cart__upsell-name {
  margin: 0;
}
.mini-cart__upsell-note {
  margin: 0;
  color: var(--black7);
}
/* Tombol "Add Once" terukur 71x26, putih, teks #0000F5, radius pill.
   Font 10.8 desktop dan 13 mobile: itu rumus .u-btn, jadi class
   .u-btn dan .u-btn-secondary dipakai dan hanya kotaknya ditimpa. */
/* Selektor dua class dipakai supaya menang atas .u-btn di tokens.css
   tanpa bergantung pada urutan link stylesheet di head. */
.mini-cart__upsell-card .mini-cart__add-once {
  min-width: 71px;
  height: 26px;
  padding: 0 1.2rem;
  border-color: var(--grey-border);
}

/* ============ FOOTER ============
   Sticky di bawah, border-top hairline. Radius 1.6rem penuh di
   mobile dan hanya dua sudut atas di desktop. Terukur. */
.mini-cart__foot {
  flex: 0 0 auto;
  position: sticky;
  bottom: 0;
  background: var(--white);
  border-top: 1px solid var(--hairline);
  border-radius: var(--radius-sheet);
}
@media (min-width: 1024px) {
  .mini-cart__foot {
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  }
}
/* Keranjang kosong: footer tetap dirender, isinya nol. */
.mini-cart__foot[data-empty='true'] {
  min-height: 0;
}

/* Opsi. Terukur padding 1.6rem var(--margin) 1.2rem. */
.mini-cart__opts {
  padding: 1.6rem var(--margin) 1.2rem;
}
.mini-cart__opt {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem;
  padding: 0.6rem 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
  text-align: left;
}
.mini-cart__opt-icon {
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  color: var(--black7);
}

/* Progress free shipping.
   Teks 12px family mono, letter-spacing -0.72px. Minus 0.72px itu
   -0.06em pada 12px, sama dengan ls mono yang dipakai banner.
   Track tinggi 0.2rem, rgba(39, 39, 39, .35), radius 0.15rem.
   Isinya pseudo ::after dengan transform: scaleX(var(--scale-x)) dan
   origin kiri. JS cuma menulis ulang custom property itu, width tidak
   pernah disentuh.
   CATATAN: CSS Coterie menulis "transition: transfrom .5s", salah eja,
   jadi bar mereka loncat tanpa animasi. Di sini ejaannya dibetulkan. */
.mini-cart__ship {
  padding: 0 var(--margin) 1.6rem;
}
.mini-cart__ship-text {
  display: block;
  margin-bottom: 0.8rem;
  font-family: var(--font-mono-ui);
  font-size: clamp(12px, 1.2rem, 12px);
  line-height: 1.4;
  letter-spacing: -0.06em;
  color: var(--black7);
}
.mini-cart__track {
  position: relative;
  width: 100%;
  height: 0.2rem;
  overflow: hidden;
  background: rgba(39, 39, 39, 0.35);
  border-radius: 0.15rem;
}
.mini-cart__track::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--blue);
  border-radius: inherit;
  transform-origin: left center;
  transform: scaleX(var(--scale-x, 0));
  transition: transform 0.5s var(--ease-media);
}

/* Ringkasan: Shipping dan Subtotal. */
.mini-cart__sum {
  padding: 0 var(--margin) 1.2rem;
}
.mini-cart__sum-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.2rem;
  padding: 0.4rem 0;
}
.mini-cart__sum-label {
  color: var(--black7);
}

/* Tombol checkout.
   Terukur 341x42 @375 dan tinggi 37 @1280. Kotaknya persis .u-btn
   .u-btn-primary dari tokens: radius 6rem, padding 1.4rem 3.2rem,
   font 13 mobile dan 10.8 desktop, weight 600, lh 0.9, bg #0000C9.
   Jadi yang ditulis di sini cuma lebar penuh dan posisinya.
   Lebar ukur desktop 307 TIDAK konsisten dengan 639 dikurangi dua
   var(--margin) (568), jadi lebar dibiarkan penuh sampai ada ukur
   ulang container-nya. */
.mini-cart__checkout-wrap {
  padding: 0 var(--margin) 1.6rem;
}
/* Sama seperti .mini-cart__add-once: .u-btn menetapkan width fit-content,
   jadi selektor ini sengaja dua class supaya lebar penuh tidak
   bergantung pada urutan link stylesheet. */
.mini-cart__checkout-wrap .mini-cart__checkout {
  width: 100%;
  gap: 0.8rem;
}
/* Spinner 22x22 untuk state loading. */
.mini-cart__spinner {
  display: none;
  width: 22px;
  height: 22px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: mini-cart-spin 0.8s linear infinite;
}
.mini-cart__checkout[data-busy='true'] .mini-cart__spinner {
  display: block;
}
.mini-cart__checkout[data-busy='true'] .mini-cart__checkout-label {
  display: none;
}
@keyframes mini-cart-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ============ KERANJANG KOSONG ============
   Pesan 21.6px rata kiri. 21.6 itu lantai .lg-t-24 di tokens
   (clamp(21.6px, 2.4rem, 24px)), dipasangkan dengan .t-22 di mobile.
   Di Coterie tombol cart di header di-disable saat keranjang kosong,
   jadi keadaan ini tidak bisa dibuka lewat UI. Tetap dibangun karena
   drawer bisa dibuka dari state lain. */
.mini-cart__empty {
  flex-grow: 1;
  padding: 2.4rem var(--margin);
  text-align: left;
}
.mini-cart__empty-msg {
  margin: 0 0 2.4rem;
}
/* Blok promo: background abu, gambar, teks, link. */
.mini-cart__promo {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  padding: 1.6rem;
  background: var(--grey-oos);
  border-radius: var(--radius-card);
}
.mini-cart__promo-media {
  flex: 0 0 auto;
  width: 8rem;
  height: 8rem;
  overflow: hidden;
  border-radius: var(--radius-card);
}
.mini-cart__promo-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.8rem;
}
.mini-cart__promo-link {
  color: var(--blue600);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ============ KOSONG VERSUS BERISI ============
   TAMBAHAN, tidak ada di sumbernya. Di React, kosong versus berisi
   diputuskan dengan merender salah satu cabang saja. Di situs statis
   tidak ada yang merender: kedua cabang ada di markup sejak awal dan
   salah satunya harus disembunyikan CSS.

   Sakelarnya adalah kelas .is-empty di akar drawer, BUKAN atribut
   hidden per elemen. Alasannya konkret: js/mini-cart.js memanggil
   akar.classList.toggle('is-empty', kosong) tiap render, tapi dia
   hanya menyentuh atribut hidden pada satu elemen saja, yaitu blok
   kosong. Daftar item, upsell, isi footer, dan badge tidak pernah dia
   sentuh. Kalau keempatnya diberi atribut hidden di markup, tidak ada
   satu pun yang melepasnya lagi dan drawer terlihat kosong selamanya
   walau keranjang berisi. Satu kelas di akar menghindari seluruh
   kelas kesalahan itu.

   Keadaan awal .is-empty ditulis di markup, jadi tanpa JS drawer
   menampilkan keadaan kosong yang jujur, bukan daftar setengah jadi. */
.mini-cart.is-empty .mini-cart__lines,
.mini-cart.is-empty .mini-cart__upsell,
.mini-cart.is-empty .mini-cart__foot-body,
.mini-cart.is-empty .mini-cart__badge {
  display: none;
}
/* Kebalikannya. Blok kosong juga dikendalikan atribut hidden oleh
   modul, dan dua jalur ini sepakat: sama sama menyembunyikan saat
   keranjang berisi. */
.mini-cart:not(.is-empty) .mini-cart__empty {
  display: none;
}
/* Keranjang kosong: footer tetap dirender, isinya nol. Selektor
   [data-empty] warisan port dipertahankan di atas, tapi yang benar
   benar dipakai halaman ini adalah kelas .is-empty, karena tidak ada
   satu pun modul yang memelihara atribut data-empty itu. */
.mini-cart.is-empty .mini-cart__foot {
  min-height: 0;
}

/* Atribut hidden tetap dihormati untuk elemen yang memang dikendalikan
   per elemen. Rule ini wajib ada: hidden bawaan browser cuma
   display: none dari UA stylesheet, dan rule author sekecil apa pun
   yang menyetel display mengalahkannya. .mini-cart__ship-text punya
   display: block, jadi tanpa baris di bawah teks itu TETAP terlihat
   setelah JS menyembunyikannya. */
.mini-cart__empty[hidden],
.mini-cart__ship-text[hidden],
.mini-cart__variant-meta > [hidden] {
  display: none;
}

/* ============ REDUCED MOTION ============
   Panel dan shield tetap muncul dan tetap bisa ditutup, cuma
   geraknya dihapus. Spinner juga berhenti berputar. */
@media (prefers-reduced-motion: reduce) {
  .mini-cart,
  .mini-cart.is-open,
  .mini-cart__shield,
  .mini-cart__shield.is-visible,
  .mini-cart__track::after {
    transition: none;
  }
  .mini-cart__spinner {
    animation: none;
  }
}
