/* =========================================================================
   SAMZZSTORE — SISTEM TRANSISI
   Sumber pola: transitions.dev (motion tokens bersama: duration, easing,
   distance, blur, scale). Semua gerak di situs ini memakai satu skala
   token yang sama, jadi tiap komponen bergerak dengan "berat" yang
   konsisten — bukan tiap komponen punya durasi karangan sendiri.

   Isi:
     1. Motion tokens
     2. Prinsip: hanya transform / opacity / filter (dapat dikompositor)
     3. Resep: modal, drawer, menu, toast, kartu, chip, tombol, FAQ,
        badge keranjang, halaman (View Transitions)
     4. prefers-reduced-motion: satu titik matikan untuk semua gerak

   Tidak ada script di sini. State dikendalikan kelas dari JS yang sudah
   ada (.on, [hidden], .in, .is-error) supaya tidak ada dua sumber kebenaran.
   ========================================================================= */

/* ── 1. MOTION TOKENS ──────────────────────────────────────────────────
   Skala dari transitions.dev: durasi bertingkat, easing.named, dan
   jarak samar. Namanya sengaja generik (--t-*) supaya tidak bentrok
   dengan --ease/--dur bawaan gaya.css yang tetap dipakai komponen lama. */
:root {
  /* Durasi — 7 tingkat. Jangan menulis angka ms di luar daftar ini. */
  --t-dur-micro: 80ms;      /* feedback sekecil kilas                    */
  --t-dur-quick: 150ms;     /* hover, warna, fokus                       */
  --t-dur-fast: 250ms;      /* chip, badge, tombol kecil                 */
  --t-dur-medium: 350ms;    /* toast, baris keranjang                    */
  --t-dur-slow: 400ms;      /* menu, popover                             */
  --t-dur-slower: 500ms;    /* drawer, modal besar                       */
  --t-dur-page: 420ms;      /* perpindahan halaman                       */
  --t-stagger: 40ms;        /* jeda antar baris dalam satu kelompok       */

  /* Easing — empat karakter, bukan satu rasa untuk semua gerak.
     - smooth-out : masuk tenang, utama dipakai untuk masuk            */
  --t-ease-smooth: cubic-bezier(0.22, 1, 0.36, 1);
  /* - press      : respons cepat ke bawah, lambat kembali           */
  --t-ease-press: cubic-bezier(0.4, 0, 0.2, 1);
  /* - spring     : sedikit memantul, hanya untuk penekanan tombol   */
  --t-ease-spring: cubic-bezier(0.34, 1.36, 0.64, 1);
  /* - drawer     : meluncur lalu men decelerate panjang              */
  --t-ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  /* Jarak —gression */
  --t-move-micro: 4px;
  --t-move-small: 6px;
  --t-move-base: 8px;
  --t-move-medium: 12px;

  /* Skala */
  --t-scale-press: 0.97;
  --t-scale-modal: 0.96;
  --t-scale-menu: 0.94;
  --t-scale-badge: 0.4;

  /* Blur — hanya untuk keluar/masuk, tidak untuk hover diam */
  --t-blur-small: 2px;
  --t-blur-medium: 4px;
}

/* ── 2. AKSESIBILITAS: satu saklar untuk semua gerak ──────────────────
   Di sinilah seluruh animasi situs mati. Menghormati preferensi sistem
   tanpa perlu mematikan tiap komponen satu per satu. State (menu terbuka,
   panel tampil) tetap terjadi — yang hilang hanya geraknya. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --t-dur-micro: 1ms;  --t-dur-quick: 1ms; --t-dur-fast: 1ms;
    --t-dur-medium: 1ms; --t-dur-slow: 1ms;  --t-dur-slower: 1ms;
    --t-dur-page: 1ms;   --t-stagger: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* =========================================================================
   3. RESEP
   ========================================================================= */

/* ── 3.1 MODAL CHECKOUT ───────────────────────────────────────────────
   Modal muncul dari bawah dengan scale + lift; scrim ikut memudar.
   .modal-transaksi[hidden].display:none ditangani gaya.css — di sini
   kita hanya mengUDA state .on dan .is-closing. */
.modal-transaksi .modal-transaksi-card {
  transform: translateY(var(--t-move-medium)) scale(var(--t-scale-modal));
  opacity: 0;
  transition:
    transform var(--t-dur-slower) var(--t-ease-drawer),
    opacity   var(--t-dur-medium) var(--t-ease-smooth);
  will-change: transform, opacity;
}
.modal-transaksi.on .modal-transaksi-card {
  transform: translateY(0) scale(1);
  opacity: 1;
}
.modal-transaksi.is-closing .modal-transaksi-card {
  transform: translateY(var(--t-move-base)) scale(var(--t-scale-modal));
  opacity: 0;
  transition:
    transform var(--t-dur-medium) var(--t-ease-press),
    opacity   var(--t-dur-medium) var(--t-ease-press);
}

/* ── 3.2 MODAL JALUR CHECKOUT (#sz-jalur-modal) ───────────────────────
   Kelas kartunya .sz-kartu (dari gaya.css), bukan .sz-jalur-kartu. */
#sz-jalur-modal .sz-kartu {
  transform: translateY(var(--t-move-base)) scale(var(--t-scale-modal));
  opacity: 0;
  transition:
    transform var(--t-dur-slower) var(--t-ease-drawer),
    opacity   var(--t-dur-medium) var(--t-ease-smooth);
  will-change: transform, opacity;
}
#sz-jalur-modal.on .sz-kartu {
  transform: translateY(0) scale(1);
  opacity: 1;
}

/* ── 3.3 DRAWER KERANJANG ────────────────────────────────────────────
   Drawer sudah punya reveal radial clip-path (dari gaya.css) yang bagus
   dan khas. Di sini kita perhalus: decelerate panjang + bayangan yang
   muncul belakangan supaya terasa "naik", bukan "nyala". */
.drawer {
  z-index: 1000 !important;
  transition:
    transform var(--t-dur-slow) var(--t-ease-drawer),
    box-shadow  var(--t-dur-slower) var(--t-ease-drawer),
    visibility 0s var(--t-dur-slow);
}
.drawer.on {
  z-index: 1000 !important;
  transition:
    transform var(--t-dur-slow) var(--t-ease-drawer),
    box-shadow  var(--t-dur-slow)   var(--t-ease-smooth),
    visibility 0s;
}

/* Baris di dalam drawer muncul berurutan — satuTs group stagger. */
.drawer.on .line {
  animation: t-naik-baris var(--t-dur-medium) var(--t-ease-smooth) both;
  animation-delay: calc(var(--i, 0) * var(--t-stagger));
}
@keyframes t-naik-baris {
  from { opacity: 0; transform: translateY(var(--t-move-base)); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── 3.4 MENU KANAL RESMI (bulat-pop) ────────────────────────────────
   Menu tumbuh dari titik tombolnya. Titik asal ikut bergerak sedikit
   ke arah tombol supaya terasa tersambung, bukan melayang acak. */
.bulat-pop {
  transform-origin: bottom left;
  transform: translateY(var(--t-move-small)) scale(var(--t-scale-menu));
  opacity: 0;
  transition:
    transform var(--t-dur-medium) var(--t-ease-press),
    opacity   var(--t-dur-quick) var(--t-ease-smooth);
  will-change: transform, opacity;
}
.bulat-pop:not([hidden]) {
  transform: translateY(0) scale(1);
  opacity: 1;
  transition:
    transform var(--t-dur-slow) var(--t-ease-spring),
    opacity   var(--t-dur-medium) var(--t-ease-smooth);
}
/* Isi menu masuk sedikit setelah wadah — hierarki, bukan semua serentak. */
.bulat-pop:not([hidden]) .bulat-item {
  animation: t-masuk-item var(--t-dur-medium) var(--t-ease-smooth) both;
}
.bulat-pop:not([hidden]) .bulat-item:nth-child(1) { animation-delay: 40ms; }
.bulat-pop:not([hidden]) .bulat-item:nth-child(2) { animation-delay: 70ms; }
.bulat-pop:not([hidden]) .bulat-item:nth-child(3) { animation-delay: 100ms; }
.bulat-pop:not([hidden]) .bulat-item:nth-child(4) { animation-delay: 130ms; }
.bulat-pop:not([hidden]) .bulat-item:nth-child(5) { animation-delay: 160ms; }
@keyframes t-masuk-item {
  from { opacity: 0; transform: translateX(calc(var(--t-move-base) * -1)); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Tombol bulat ikut berputar saat menu terbuka — ada affordance bahwa
   tombol ini sakelar, bukan sekadar tombol. */
#bulat svg {
  transition: transform var(--t-dur-slow) var(--t-ease-spring);
}
#bulat[aria-expanded="true"] svg {
  transform: rotate(90deg);
}

/* ── 3.5 TOAST ───────────────────────────────────────────────────────
   Toast lama memakai keyframe sekali-pakai yang tidak bisa "dibalik"
   (hilang = hilang). Di sini toast punya state masuk/keluar yang
   seimbang, dan warnanya ikut menyala singkat supaya yeux menangkapnya. */
.toast {
  animation: none;
  transform: translate(-50%, var(--t-move-base)) scale(var(--t-scale-press));
  opacity: 0;
  filter: blur(var(--t-blur-small));
  transition:
    transform var(--t-dur-medium) var(--t-ease-press),
    opacity   var(--t-dur-medium) var(--t-ease-smooth),
    filter    var(--t-dur-medium) var(--t-ease-smooth);
  will-change: transform, opacity, filter;
}
.toast:not([hidden]) {
  transform: translate(-50%, 0) scale(1);
  opacity: 1;
  filter: blur(0);
  transition:
    transform var(--t-dur-slow) var(--t-ease-spring),
    opacity   var(--t-dur-fast) var(--t-ease-smooth),
    filter    var(--t-dur-fast) var(--t-ease-smooth);
}
.toast.ok   { border-color: color-mix(in srgb, #16A34A 45%, var(--line-strong)); }
.toast.err  { border-color: color-mix(in srgb, #DC2626 45%, var(--line-strong)); }

/* ── 3.6 TOMBOL ──────────────────────────────────────────────────────
   Tekan: turun sedikit + scale kecil dengan easing spring (memberi
   rasa "berbalok" singkat). Lepas: kembali dengan easing halus.
   Warna/background tetap transisi biasa, tidak ikut memantul. */
.btn,
.bulat,
.fab,
.cat-pill,
.icon-btn {
  transition:
    transform var(--t-dur-quick) var(--t-ease-press),
    background-color var(--t-dur-quick) var(--t-ease-smooth),
    border-color var(--t-dur-quick) var(--t-ease-smooth),
    box-shadow var(--t-dur-quick) var(--t-ease-smooth),
    color var(--t-dur-quick) var(--t-ease-smooth);
}
.btn:active,
.bulat:active,
.fab:active,
.cat-pill:active,
.icon-btn:active {
  transform: scale(var(--t-scale-press));
  transition-duration: var(--t-dur-micro); /* hampir tanpa jeda saat ditekan */
}

/* Tombol utama: sedikit membesar saat hover supaya tujuannya jelas. */
.btn-primary:hover {
  transform: translateY(-1px);
}

/* Link dengan garis bawah yang tumbuh dari kiri — penanda interaksi
   tanpa mengubah tata letak. */
a.t-link,
.proses-tautan {
  position: relative;
}
a.t-link::after,
.proses-tautan::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--t-dur-quick) var(--t-ease-smooth);
}
a.t-link:hover::after,
.proses-tautan:hover::after {
  transform: scaleX(1);
  transform-origin: left center;
}

/* ── 3.7 KARTU KATALOG ───────────────────────────────────────────────
   Hover: kartu naik sedikit dan bayangan menguat. Lift-nya kecil
(4px) — lebih dari itu membuat kartu terasa "melayang" dan tidak
  berhenti rapi saat cursor keluar cepat. */
.card {
  transition:
    transform var(--t-dur-fast) var(--t-ease-smooth),
    box-shadow var(--t-dur-fast) var(--t-ease-smooth),
    border-color var(--t-dur-fast) var(--t-ease-smooth);
  will-change: transform;
}
.card:hover {
  transform: translateY(-4px);
}

/* Kartu harga/QRIS yang sudah punya scale hover — samakan dengan
   token supaya tidak ada dua skala berbeda di satu halaman. */
.qris-qr-card,
.cat-pill {
  transition:
    transform var(--t-dur-fast) var(--t-ease-smooth),
    box-shadow var(--t-dur-fast) var(--t-ease-smooth);
}

/* ── 3.8 CHIP KATEGORI ───────────────────────────────────────────────
   Chip aktif "menyala" — scale sedikit naik dan warna solidify. */
.cat-pill.on {
  transform: scale(1.03);
  transition: transform var(--t-dur-fast) var(--t-ease-spring);
}

/* ── 3.9 BADGE KERANJANG ─────────────────────────────────────────────
   Angka di badgekeranjang "pop" setiap kali jumlah berubah — memberi
   umpan balik taktil bahwa ada barang masuk/keluar. */
.cart-count,
.fab-n {
  transition: transform var(--t-dur-fast) var(--t-ease-spring);
}
.cart-count.pop,
.fab-n.pop {
  animation: t-pop-badge var(--t-dur-medium) var(--t-ease-spring);
}
@keyframes t-pop-badge {
  0%   { transform: scale(var(--t-scale-badge)); }
  55%  { transform: scale(1.25); }
  100% { transform: scale(1); }
}

/* ── 3.10 FAQ (accordion <details>) ───────────────────────────────────
   <details> punya open/close biner yang tidak bisa dianimasikan dari
   luar. Dua pendekatan, dipilih otomatis:

     (a) Browser modern (::details-content, 2024+): isi jawaban
         memudar + naik sedikit saat details dibuka. Height tetap
         handled browser — tidak perlu JS, tidak perlu ubah HTML.
     (b) Browser lama: isi tetap tampil/ hilang seperti bawaan, tapi
         caret tetap berputar (transisi di bawah selalu berlaku).

   Tidak ada wrapper tambahan, jadi 20+ blok FAQ tidak perlu diubah. */
@supports selector(::details-content) {
  .faq details::details-content {
    opacity: 0;
    transform: translateY(calc(var(--t-move-micro) * -1));
    transition:
      opacity var(--t-dur-medium) var(--t-ease-smooth),
      transform var(--t-dur-medium) var(--t-ease-smooth),
      content-visibility var(--t-dur-medium) allow-discrete;
  }
  .faq details[open]::details-content {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Ikon caret berputar saat terbuka — penanda state yang halus, berlaku
   di semua browser. */
.faq summary .icon {
  transition: transform var(--t-dur-medium) var(--t-ease-smooth);
}
.faq details[open] summary .icon {
  transform: rotate(180deg);
}

/* ── 3.11 INPUT: FOKUS & ERROR ───────────────────────────────────────
   Fokus: border menyala lembut. Error: getar kecil kiri-kanan sekali
   (bukan berulang —ユーザー tidak boleh displeasure). */
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  border-color: var(--accent);
  transition: border-color var(--t-dur-quick) var(--t-ease-smooth),
              box-shadow var(--t-dur-quick) var(--t-ease-smooth);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.t-galat,
input.is-error,
.sz-input.is-error {
  /* Shake error sengaja memakai durasi pendek (350ms) — bukan
     --t-dur-slower — supaya terasa "kena" sekali, bukan lambat. */
  animation: t-geser-error var(--t-dur-medium) var(--t-ease-press);
}
@keyframes t-geser-error {
  0%, 100% { transform: translateX(0); }
  15%  { transform: translateX(-5px); }
  30%  { transform: translateX(5px); }
  45%  { transform: translateX(-4px); }
  60%  { transform: translateX(4px); }
  75%  { transform: translateX(-2px); }
}

/* ── 3.12 REveal saat scroll ──────────────────────────────────────────
   .rv sudah dipakai app.js (bertambah .in saat masuk layar). Di sini
   hanya Germakan jarak/wording geraknya supaya konsisten. */
.rv {
  opacity: 0;
  transform: translateY(var(--t-move-base));
  transition:
    opacity var(--t-dur-slow) var(--t-ease-smooth),
    transform var(--t-dur-slow) var(--t-ease-smooth);
  will-change: transform, opacity;
}
.rv.in {
  opacity: 1;
  transform: translateY(0);
}

/* ── 3.13 PERPINDAHAN HALAMAN (View Transitions API) ────────────────
   Browser yang mendukung (Chrome/Edge/Safari 18+) diberi transisi
   silang saat pindah halaman: halaman lama menghilang dengan fade +
   slide kecil, halaman baru masuk dari bawah. Browser lama tidak
   pernah melihat ini —@Column fallback wajar. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: t-halaman-keluar var(--t-dur-page) var(--t-ease-press) both;
}
::view-transition-new(root) {
  animation: t-halaman-masuk var(--t-dur-page) var(--t-ease-smooth) both;
}
@keyframes t-halaman-keluar {
  to { opacity: 0; transform: translateY(calc(var(--t-move-micro) * -1)); }
}
@keyframes t-halaman-masuk {
  from { opacity: 0; transform: translateY(var(--t-move-base)); }
}

/* Cegah double-transisi saat reduced motion — VT API tidak membaca
   media query token, jadi matikan eksplisit. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ── 3.14 FOKUS TERLIHAT ────────────────────────────────────────────
   Semua elemen fokus dapat cincin accent yang jelas — bagian dari
   "transisi" dalam arti broadest: perpindahan fokus harus terlihat. */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 8px;
  transition: outline-offset var(--t-dur-quick) var(--t-ease-smooth);
}

/* ── 3.15.5 BADGE TETAP vs TEKS ─────────────────────────────────────
   Tombol "Chat admin" (kiri bawah) dan keranjang (kanan bawah) melayang
   di atas konten. Tanpa ruang cadangan, tombolnya menimpa paragraf hero
   dan baris terakhir tiap section — persis yang terjadi sebelum blok ini
   ada.

   Ruang cadangan di akhir halaman: tanpa ini, footer bisa tertutup
   tombol melayang. Hanya untuk halaman yang memang punya tombol itu,
   supaya akun/dashboard tidak dapat ruang kosong di bawah. */
body:has(.fab-wa) {
  padding-bottom: calc(60px + env(safe-area-inset-bottom));
}

/* Badge "Chat admin" melayang SETIAP saat, bukan cuma di akhir halaman.
   Di viewport pendek (jendela laptop dikecilkan) atau layar sempit,
   posisinya menimpa paragraf hero — karena yang bertabrakan adalah posisi
   di layar, bukan posisi di dokumen. Di dua kondisi itu tombol berubah
   jadi lingkaran ikon saja; label tetap terbaca lewat aria-label. */
@media (max-width: 640px), (max-height: 760px) {
  .fab-wa {
    padding: 0;
    width: 52px;
    height: 52px;
    justify-content: center;
    border-radius: 50%;
  }
  .fab-wa span { display: none; }
  .fab-wa .icon { font-size: 1.3rem; }
}

/* ── 3.16 SKELETON LOADING KATALOG ──────────────────────────────────
Saat katalog memuat, kartu muncul dari blur, bukan mengambil ruang
  mendadak — persepsi "memuat cepat". */
.skeleton-kartu {
  background: linear-gradient(
    100deg,
    var(--surface-2) 30%,
    color-mix(in srgb, var(--surface-2) 60%, var(--line-strong)) 50%,
    var(--surface-2) 70%
  );
  background-size: 200% 100%;
  animation: t-kilau 1.4s linear infinite;
}
@keyframes t-kilau {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* =========================================================================
   4. SISTEM ANIMASI FITUR KHUSUS (FEATURE-SPECIFIC MOTION SYSTEM)
   Standar: Stitch Design System v4 & v5 (OpenDesign Masterclass)
   Pola: Emil Kowalski Spring Physics, Token Berjenjang, GPU-Composited
   Prinsip Kunci: Non-Breaking, Pelindung Multi-Device & Bebas Layout Shift
   ========================================================================= */

/* ── 4.1 HEADER & ISLAND NAVIGATION HARMONY ────────────────────────── */
/* Mencegah blowout navbar pada layar mobile (≤ 768px): sembunyikan tombol status panjang */
@media (max-width: 768px) {
  .badge-op-nav {
    display: none !important;
  }
}

/* Radar ping halus pada status dot jam operasional */
.status-dot {
  position: relative;
}
.status-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  opacity: 0;
  animation: sz-beacon-ping 2.5s cubic-bezier(0, 0, 0.2, 1) infinite;
  pointer-events: none;
}
@keyframes sz-beacon-ping {
  0% { transform: scale(0.6); opacity: 0.8; }
  50% { opacity: 0.35; }
  100% { transform: scale(2.2); opacity: 0; }
}

/* Theme Switcher Spring Press */
#theme:active {
  transform: scale(0.92) rotate(45deg);
}
#theme #theme-ico {
  transition: transform var(--t-dur-fast) var(--t-ease-spring);
}

/* Cart Icon Button Micro-Spring */
.cart-btn:active {
  transform: scale(0.92);
}

/* ── 4.2 HERO SECTION POLISH ─────────────────────────────────────────── */
/* Aksen judul: satu warna pekat. Gradien aurora beranimasi dihapus —
   pada huruf display sebesar ini efeknya terbaca sebagai hiasan dan
   menurunkan ketajaman tepi huruf. */
.hero h1 em,
.hero .hero-h1 em {
  font-style: normal;
  background: none;
  -webkit-text-fill-color: currentColor;
  color: var(--accent);
  text-decoration: none !important;
  vertical-align: baseline;
}
@keyframes sz-aurora-text {
  0% { background-position: 0% center; }
  100% { background-position: 250% center; }
}

/* Hero CTA Button Micro-Lift */
.hero-cta .btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px -6px color-mix(in srgb, var(--accent) 40%, transparent);
}
.hero-cta .btn-primary:active {
  transform: scale(0.96);
}

/* Hero Tile Hover (Stabil, tanpa auto-float yang merusak grid) */
.hero-tile {
  transition: transform var(--t-dur-fast) var(--t-ease-spring), box-shadow var(--t-dur-fast) var(--t-ease-smooth);
}
.hero-tile:hover {
  transform: translateY(-4px) scale(1.05);
  box-shadow: 0 8px 18px -4px rgba(0, 0, 0, 0.25);
  z-index: 5;
}

/* ── 4.3 KATALOG BENTO GRID & DYNAMIC STOCK TAGS ─────────────────────── */
/* Search Input Focus Halo */
#q:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* App Logo Micro-Lift saat kartu hover (halus dan tidak merusak layout) */
.app:hover .logo,
.app:hover .logo-g {
  transform: translateY(-2px) scale(1.04);
}

/* Dynamic Stock Tags */
.tag-stok.ready {
  position: relative;
  box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4);
  animation: sz-stock-ready-pulse 2.8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes sz-stock-ready-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
  50% { box-shadow: 0 0 0 4px rgba(16, 185, 129, 0); }
}

.tag-stok.habis {
  animation: sz-stock-habis-pulse 3.2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes sz-stock-habis-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.72; }
}

/* Cosmic Infinity Shimmer for "Ready: ∞" */
.tag-stok.ready {
  background-image: linear-gradient(110deg, rgba(16,185,129,0.14) 20%, rgba(52,211,153,0.35) 50%, rgba(16,185,129,0.14) 80%);
  background-size: 200% 100%;
  animation: sz-infinity-shimmer 3.5s linear infinite;
}
@keyframes sz-infinity-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── 4.4 VARIANT SHEET MODAL (Pelindung Z-Index & Preservasi Desktop) ── */
/* Sheet harus selalu berada di atas tombol floating (#fab & #bulat) */
.sheet {
  z-index: 999 !important;
}
.scrim {
  z-index: 998 !important;
}
.drawer {
  z-index: 1000 !important;
}

/* Menjaga posisi tengah mutlak modal sheet pada Desktop */
@media (min-width: 760px) {
  .sheet.on {
    transform: translate(-50%, -50%) !important;
    opacity: 1 !important;
  }
}

/* Pastikan footer sheet menutupi konten di bawahnya dengan bersih */
.sheet-foot {
  position: relative;
  z-index: 10;
  background: var(--surface);
}

/* Perbaikan ikon garansi di dalam banner */
.sheet-garansi-banner-head svg {
  display: inline-block;
  vertical-align: middle;
}

/* Variant item baris: micro hover & spring press */
.vars .var {
  transition: transform var(--t-dur-fast) var(--t-ease-smooth), background-color var(--t-dur-quick) var(--t-ease-smooth);
}
.vars .var:hover {
  transform: translateX(3px);
}
.vars .var .addv:active {
  transform: scale(0.9);
}

/* ── 4.5 CHECKOUT & QRIS HOLOGRAPHIC SCANNER ─────────────────────────── */
.qris-qr-card {
  position: relative;
  overflow: hidden;
}
.qris-qr-card::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent 0%, #10b981 30%, #34d399 50%, #10b981 70%, transparent 100%);
  box-shadow: 0 0 12px 2px rgba(16, 185, 129, 0.75), 0 0 20px 4px rgba(52, 211, 153, 0.4);
  opacity: 0.85;
  animation: sz-qris-laser 2.6s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes sz-qris-laser {
  0% { transform: translateY(4px); opacity: 0.3; }
  15% { opacity: 0.95; }
  85% { opacity: 0.95; }
  100% { transform: translateY(390px); opacity: 0.3; }
}

/* Tombol Salin Micro-Spring */
.btn-copy-mini:active,
.btn-salin:active {
  transform: scale(0.92);
}

/* ── 4.6 TESTIMONI & FAQ ACCORDION ───────────────────────────────────── */
.ulas-card:hover .star-gold {
  animation: sz-star-sparkle 0.4s var(--t-ease-spring) both;
}
.ulas-card:hover .star-gold:nth-child(1) { animation-delay: 30ms; }
.ulas-card:hover .star-gold:nth-child(2) { animation-delay: 60ms; }
.ulas-card:hover .star-gold:nth-child(3) { animation-delay: 90ms; }
.ulas-card:hover .star-gold:nth-child(4) { animation-delay: 120ms; }
.ulas-card:hover .star-gold:nth-child(5) { animation-delay: 150ms; }
@keyframes sz-star-sparkle {
  0% { transform: scale(1); }
  50% { transform: scale(1.3) rotate(15deg); color: #fbbf24; }
  100% { transform: scale(1); }
}

/* ── 4.7 FLOATING LAUNCHERS & CONTROLS ───────────────────────────────── */
#bulat:active,
#fab:active {
  transform: scale(0.92);
}

/* ── 4.7b MINI ICONS & BADGE SIZING (ANTI-BLOWOUT) ────────────────────── */
.icon-mini,
svg.icon-mini,
.ulas-verified-badge svg {
  width: 13px !important;
  height: 13px !important;
  max-width: 13px !important;
  max-height: 13px !important;
  min-width: 13px !important;
  min-height: 13px !important;
  stroke-width: 2.5 !important;
  flex-shrink: 0 !important;
  display: inline-block !important;
  vertical-align: middle !important;
}

.ulas-verified-badge {
  display: inline-flex !important;
  align-items: center !important;
  gap: 4px !important;
}

/* ── 4.8 ACCESSIBILITY: MATIKAN SEMUA ANIMASI DI REDUCED-MOTION ───────── */
@media (prefers-reduced-motion: reduce) {
  .status-dot::after,
  .hero h1 em,
  .hero .hero-h1 em,
  .tag-stok.ready,
  .tag-stok.habis,
  .qris-qr-card::after,
  .ulas-card:hover .star-gold {
    animation: none !important;
  }
}
