/*
 * style.css — tata letak dan bentuk. TIDAK ADA SATU PUN WARNA MENTAH di sini.
 *
 * Semua warna datang dari /theme.css yang dibuat server dari pengaturan, dan
 * dipasang dengan <link> SESUDAH berkas ini. Sorotan lembut memakai
 * rgba(var(--accent-rgb), .14) supaya tetap bisa disentuh tema.
 *
 * Warna yang hanya ada di dalam aturan CSS biasa tidak akan bisa diubah tema —
 * karena itu berkas ini sengaja tidak punya satu pun nilai hex, rgb(), atau
 * nama warna. Ada uji otomatis yang memeriksanya.
 */

/* ------------------------------------------------------------------ *
 * Dasar
 * ------------------------------------------------------------------ */

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

:root {
  --lebar-isi: 1180px;
  --lebar-sempit: 720px;
  --sudut: 14px;
  --sudut-kecil: 9px;
  --sudut-besar: 22px;
  --jarak: 16px;
  --bayang: 0 1px 2px rgba(var(--text-rgb), 0.06), 0 6px 20px rgba(var(--text-rgb), 0.06);
  --bayang-kuat: 0 2px 6px rgba(var(--text-rgb), 0.1), 0 18px 44px rgba(var(--text-rgb), 0.12);
  --garis: 1px solid var(--border);
  --alur: 180ms cubic-bezier(0.2, 0.7, 0.3, 1);
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-angka: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* Tinggi baris header. Dipakai DUA kali: oleh headernya sendiri, dan oleh
     tempat kosong yang menunggunya. Satu angka supaya keduanya tidak mungkin
     berselisih - kalau berselisih, halaman meloncat persis sebesar selisihnya. */
  --tinggi-kepala: 64px;

  /* Tinggi bilah hak cipta & versi di dasar layar. Dipakai dua kali: oleh
     bilahnya sendiri lewat isinya, dan oleh ruang yang disediakan body. */
  --tinggi-tanda: 30px;
  /* Tinggi bilah kirim di checkout. Dipaku dengan alasan yang sama seperti
     --tinggi-tanda: ruang yang disediakan body harus persis setinggi bilahnya,
     atau selisihnya menutupi isi halaman di ujung bawah. */
  --tinggi-bilah-kirim: 66px;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Ruang bilah gulir SELALU disediakan, walau halamannya sedang pendek.
     Tanpa ini layar terasa bergetar: saat isi sebuah tab diganti, sesaat
     halamannya lebih pendek dari layar, bilah gulirnya hilang, dan seluruh
     halaman melebar 15px — lalu menyempit lagi begitu isinya datang. Diukur
     di panel Admin: 1385px -> 1400px -> 1385px dalam sekejap. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0 0 0.5em;
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(1.7rem, 3.4vw, 2.5rem); }
h2 { font-size: clamp(1.3rem, 2.2vw, 1.7rem); }
h3 { font-size: 1.1rem; }

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a {
  color: var(--accent-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
a:hover { text-decoration-thickness: 2px; }

img { max-width: 100%; height: auto; display: block; }

hr {
  border: 0;
  border-top: var(--garis);
  margin: 24px 0;
}

:focus-visible {
  outline: 3px solid rgba(var(--accent-rgb), 0.55);
  outline-offset: 2px;
  border-radius: 4px;
}

.isi {
  width: 100%;
  max-width: var(--lebar-isi);
  margin: 0 auto;
  padding: 0 20px;
}

.isi-sempit { max-width: var(--lebar-sempit); }

.utama { padding: 28px 0 64px; min-height: 60vh; }

.tumpuk { display: flex; flex-direction: column; gap: var(--jarak); }
.baris { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Kontrol yang berdiri langsung di dalam .baris tidak melebar penuh —
   kalau melebar, baris penyaring akan pecah menjadi beberapa baris. */
.baris > input:not([type="checkbox"]):not([type="radio"]),
.baris > select {
  width: auto;
  min-width: 150px;
  flex: 0 1 auto;
}
.baris-rapat { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Label yang menempel pada kolomnya. Dipakai di baris penyaring supaya kata
   seperti "dari" dan "sampai" ikut berpindah bersama kolom tanggalnya ketika
   barisnya melipat di layar sempit. */
.pasangan { display: inline-flex; align-items: center; gap: 6px; }

/* Atribut `hidden` bawaan HTML kalah oleh aturan display apa pun yang ditulis
   di sini — termasuk .baris-rapat di atas. Akibatnya elemen yang sudah diberi
   hidden lewat JavaScript tetap terlihat, dan itu tidak akan ketahuan dari
   pemeriksaan JavaScript (el.hidden tetap true). Satu aturan ini menutupnya
   untuk seluruh aplikasi. */
[hidden] { display: none !important; }
.dorong { margin-left: auto; }
.tengah { text-align: center; }
.kanan { text-align: right; }
.sembunyi { display: none !important; }

.redup { color: var(--text-muted); }
.kecil { font-size: 0.86rem; }
.tebal { font-weight: 700; }
.angka { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ *
 * Header
 * ------------------------------------------------------------------ */

.kepala {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--header-bg);
  border-bottom: var(--garis);
}

/* Halaman tidak pernah diperlihatkan setengah jadi.
 *
 * Judul, teks, header, dan footer semuanya disusun dari jawaban
 * /api/settings, jadi selama kira-kira 150ms pertama halaman ini baru
 * kerangka kosong. Kalau kerangka itu ikut terlihat, isinya seolah meloncat
 * masuk sekaligus: diukur di beranda, satu geseran tata letak sebesar 0,99 -
 * praktis setinggi satu layar penuh. Itulah sentakan yang terasa setiap kali
 * berpindah lewat menu.
 *
 * Yang ditahan hanya penampakannya, bukan tata letaknya: visibility, bukan
 * display, dan dikenakan pada anak-anak body supaya latar halamannya tetap
 * terlukis - jadi yang terlihat adalah halaman kosong berwarna benar, bukan
 * kilatan putih.
 *
 * Kelasnya dipasang oleh JavaScript, tidak ditulis di HTML. Kalau app.js
 * gagal dimuat sama sekali, tidak ada yang pernah menyembunyikan apa pun dan
 * halaman tetap tampil apa adanya. */
html.menunggu-kerangka body > * { visibility: hidden; }

/* Tempat header, sebelum JavaScript mengisinya.
 *
 * Header disusun dari jawaban /api/settings, jadi selama beberapa ratus
 * milidetik pertama div ini masih kosong dan setinggi nol. Begitu headernya
 * terpasang, SELURUH isi halaman terdorong turun 65px sekaligus - di setiap
 * perpindahan halaman, di setiap lebar layar. Itulah yang terlihat sebagai
 * layar menyentak. Tingginya disediakan lebih dulu, persis sebesar header yang
 * akan menempatinya: 64px baris isinya + 1px garis bawahnya.
 */
[data-kepala] {
  min-height: calc(var(--tinggi-kepala) + 1px);
}

.kepala-isi {
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: var(--tinggi-kepala);
  padding: 8px 20px;
  max-width: var(--lebar-isi);
  margin: 0 auto;
}

.merek {
  display: flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  color: var(--header-text);
  /* BOLEH MENYEMPIT, tapi tidak sampai hilang. Sejak penanda area ikut berdiri
     di luar menu lipat, baris header ponsel tegak memuat merek + penanda +
     keranjang + tombol menu sekaligus. Dengan flex-shrink:0 yang dulu, merek
     menolak menyempit dan yang meluber justru barisnya. min-width:0 itu yang
     mengizinkan tulisannya dipotong, bukan barisnya yang jebol. */
  flex-shrink: 1;
  min-width: 0;
}

.merek-nama,
.merek-sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.merek img {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  object-fit: cover;
  box-shadow: var(--bayang);
}

/* min-width:0 WAJIB, dan tanpa itu ellipsis di bawah tidak pernah bekerja:
   bawaan sebuah item flex adalah min-width:auto, yang menolak menyempit lebih
   kecil daripada isinya. Akibatnya terukur — tulisan mereknya tidak terpotong,
   ia MELUAP ke bawah penanda area dan keduanya saling menimpa. */
.merek-teks { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.merek-nama { font-weight: 800; font-size: 1.06rem; letter-spacing: -0.02em; }
.merek-sub { font-size: 0.74rem; color: var(--header-muted); font-weight: 500; }

.menu { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }

.menu a {
  color: var(--header-text);
  text-decoration: none;
  padding: 8px 13px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.92rem;
  transition: background var(--alur);
}

.menu a:hover { background: rgba(var(--accent-rgb), 0.12); }
.menu a[aria-current="page"] {
  background: rgba(var(--accent-rgb), 0.16);
  color: var(--accent-link);
}

.tombol-menu {
  display: none;
  background: transparent;
  border: var(--garis);
  border-radius: var(--sudut-kecil);
  padding: 8px 11px;
  cursor: pointer;
  color: var(--header-text);
  font-size: 1.1rem;
}

/* Lencana daftar harga khusus ("Harga Agen"), dipakai keranjang & checkout. */
.lencana-harga {
  background: rgba(var(--accent-rgb), 0.14);
  color: var(--accent-link);
  font-weight: 700;
}

/* Kelompok aksi header: penanda area + ikon keranjang. DUA-DUANYA DI LUAR
   menu lipat, jadi tetap terlihat di layar kecil. Dikelompokkan supaya jarak
   dan perataannya diatur di satu tempat, dan supaya keduanya tetap
   berpasangan saat menu-nya terlipat. */
.kepala-aksi {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

/* Ikon keranjang: DI LUAR menu lipat, jadi tetap terlihat di layar kecil.
   Keranjang adalah hal yang paling sering ditengok pembeli; menyembunyikannya
   di balik tombol menu membuatnya hilang justru saat paling dibutuhkan. */
.ikon-keranjang {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 999px;
  border: var(--garis);
  color: var(--header-text);
  text-decoration: none;
  transition: background var(--alur);
}

.ikon-keranjang:hover { background: rgba(var(--accent-rgb), 0.12); }
.ikon-keranjang[aria-current="page"] { background: rgba(var(--accent-rgb), 0.16); }
.ikon-keranjang-gambar { font-size: 1.15rem; line-height: 1; }

.lencana-keranjang {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 0.72rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* Angka menempel di pojok ikon, bukan mendorong lebarnya. */
.ikon-keranjang .lencana-keranjang {
  position: absolute;
  top: -4px;
  right: -4px;
  border: 2px solid var(--surface);
}

@media (max-width: 900px) {
  .tombol-menu { display: block; }
  .menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--surface);
    border-bottom: var(--garis);
    padding: 10px;
    gap: 2px;
    box-shadow: var(--bayang-kuat);
  }
  .menu.buka { display: flex; }
  /* CATATAN: JANGAN kembalikan `.kepala { position: relative }` di sini.
     Dulu barisnya ada, untuk menambatkan menu lipat yang absolut. Tapi
     `position: sticky` SUDAH elemen terposisi, jadi menu absolutnya tetap
     menambat ke header dengan benar tanpa itu — sementara `relative`
     MEMBATALKAN sticky-nya, dan headernya tergulir hilang di setiap halaman
     pada layar sempit. Justru di ponsel header itu paling dibutuhkan: di sana
     ikon keranjang dan tombol menu adalah satu-satunya jalan berpindah. */
  /* Menu lipat menutupi lebar penuh; penanda area dan keranjang tetap di
     barisnya. Yang didorong ke kanan KELOMPOKNYA, bukan keranjangnya sendiri:
     margin-left:auto pada keranjang akan mendorongnya menjauh dari penanda
     area dan memisahkan dua tombol yang justru harus berpasangan. */
  .kepala-aksi { margin-left: auto; }
}

/* ------------------------------------------------------------------ *
 * Hero
 * ------------------------------------------------------------------ */

.hero {
  background: linear-gradient(160deg, var(--hero-from), var(--hero-to));
  border-bottom: var(--garis);
  padding: 52px 0 56px;
  position: relative;
  overflow: hidden;
}

.hero::after {
  content: "";
  position: absolute;
  inset: auto -10% -60% 40%;
  height: 320px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(var(--surface-rgb), 0.75), transparent 70%);
  pointer-events: none;
}

/* Cerita perusahaan yang berputar di hero, dan lencana kepercayaannya. */
.hero-cerita {
  margin-top: 18px;
  max-width: 560px;
}

.hero-cerita-isi {
  background: rgba(var(--surface-rgb), 0.72);
  border: var(--garis);
  border-radius: var(--sudut);
  padding: 14px 16px;
  /* Tingginya dijaga supaya tombol di bawahnya tidak melompat tiap pergantian
     cerita — teks yang panjangnya berbeda akan menggeser tata letaknya. */
  /* Lantai untuk cerita yang sangat pendek. Tinggi sebenarnya ditentukan
     lapisan pengukur di bawah. */
  min-height: 96px;

  /* TINGGINYA TIDAK PERNAH BERUBAH — dan bukan dengan mematoknya.

     Dua lapisan ditumpuk di SATU sel kisi yang sama:

       .hero-cerita-ukuran    semua cerita sekaligus, tidak terlihat
       .hero-cerita-panggung  satu cerita yang sedang dibaca

     Lapisan pengukur memuat SEMUA cerita yang juga saling menumpuk, jadi
     tingginya sama dengan cerita yang PALING PANJANG. Karena ia ikut mengisi
     sel yang sama, kotak ini selalu setinggi itu — cerita mana pun yang
     sedang tampil.

     Yang menghitung peramban, bukan JavaScript. Itu sebabnya ia tetap benar
     waktu jendelanya diubah ukurannya, waktu hurufnya baru selesai dimuat,
     dan waktu pembacanya memperbesar tampilan — tiga keadaan yang semuanya
     mengubah jumlah baris teks, dan yang semuanya akan terlewat kalau
     tingginya diukur sekali lalu disimpan. */
  display: grid;
  align-items: center;
}

.hero-cerita-ukuran,
.hero-cerita-panggung {
  grid-area: 1 / 1;
  min-width: 0;
}

.hero-cerita-ukuran {
  visibility: hidden;
  display: grid;
  align-items: center;
}

.hero-cerita-ukuran > .hero-cerita-kartu { grid-area: 1 / 1; }

/* Tempat gambar di lapisan pengukur — kotak kosong seukuran fotonya, bukan
   fotonya sendiri. Memasang <img> yang sama dua kali berarti mengunduh setiap
   foto cerita dua kali di layar pertama yang dilihat pengunjung, dan ukurannya
   memang sudah dipatok 72px di .hero-cerita-kartu img. */
.hero-cerita-gambar-palsu { width: 72px; height: 72px; flex-shrink: 0; }

/* PERGANTIAN CERITA — dan angka di bawah ini SATU-SATUNYA tempat lamanya
   ditentukan. index.html membacanya kembali lewat getComputedStyle, bukan
   menuliskan angkanya sendiri: dua angka yang harus sama persis tapi tersimpan
   di dua berkas akan berselisih suatu hari, dan selisihnya terlihat sebagai
   kedipan — isinya tertukar waktu kotaknya belum sempat redup.

   Ini juga yang membuat `prefers-reduced-motion` bekerja tanpa satu baris pun
   tambahan: aturan di kaki berkas ini memangkas semua transisi menjadi
   0,001ms, halaman membaca angka itu, dan pergantiannya menjadi seketika. */
.hero-cerita-panggung { transition: opacity var(--alur), transform var(--alur); }

.hero-cerita-panggung.pudar {
  opacity: 0;
  /* Turun sedikit, bukan diam di tempat: gerak kecil ke satu arah membuat
     pergantiannya terbaca sebagai "berganti", bukan sebagai layar yang
     berkedip. Yang bergeser hanya isinya — kotaknya tidak ikut, karena
     tingginya dipegang lapisan pengukur. */
  transform: translateY(6px);
}

.hero-cerita-kartu {
  display: flex;
  gap: 14px;
  align-items: center;
}

/* Gambar yang bisa ditekan untuk diperbesar. Tombolnya polos: yang terlihat
   hanya gambarnya, tapi ia tetap tombol sungguhan supaya bisa dicapai papan
   ketik dan dibacakan pembaca layar. */
.gambar-bisa-besar {
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: var(--sudut-kecil);
  line-height: 0;
  transition: transform var(--alur), box-shadow var(--alur);
}

.gambar-bisa-besar:hover { transform: scale(1.04); }
.gambar-bisa-besar:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.lampu {
  border: 0;
  padding: 0;
  background: none;
  /* Menyusut mengikuti gambarnya. Tanpa ini <dialog> melebar sampai batas
     max-width, dan tombol tutup yang menempel di pojok kanan dialog melayang
     jauh dari gambarnya — terlihat seperti tombol yang bukan miliknya. */
  width: fit-content;
  max-width: 94vw;
  max-height: 94vh;
  margin: auto;
  overflow: visible;
}

.lampu::backdrop { background: rgba(var(--text-rgb), 0.78); }

.lampu img {
  display: block;
  max-width: 94vw;
  /* Sisakan ruang untuk keterangan di bawahnya. */
  max-height: 78vh;
  width: auto;
  height: auto;
  border-radius: var(--sudut);
  box-shadow: var(--bayang-kuat);
  background: var(--surface);
}

.lampu-ket {
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: var(--sudut-kecil);
  background: var(--surface);
  color: var(--text);
  /* Dibatasi supaya keterangan yang panjang MELIPAT, bukan melebarkan
     dialognya melewati gambar. */
  max-width: min(94vw, 620px);
}

.lampu-tutup {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--bayang-kuat);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}

.lampu-tutup:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 620px) {
  .lampu-tutup { top: -10px; right: -6px; }
}

.hero-cerita-kartu img {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: var(--sudut-kecil);
  flex-shrink: 0;
  background: var(--surface-2);
}

.hero-cerita-kartu b { display: block; margin-bottom: 3px; }
.hero-cerita-kartu p { margin: 0; font-size: 0.9rem; color: var(--text-muted); }

.hero-cerita-titik {
  display: flex;
  gap: 7px;
  margin-top: 10px;
}

.hero-cerita-titik button {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--border-strong);
  cursor: pointer;
  transition: background var(--alur), transform var(--alur);
}

.hero-cerita-titik button.aktif {
  background: var(--accent);
  transform: scale(1.35);
}

/* ------------------------------------------------------------------ *
 * Tentang Kami
 *
 * Halaman baca panjang, bukan halaman alat. Jadi yang diatur di sini lebar
 * baris, jarak antarbaris, dan irama antarbagian — tiga hal yang menentukan
 * apakah orang sampai ke kalimat terakhir.
 * ------------------------------------------------------------------ */

.tentang-kepala {
  margin-bottom: 26px;
  padding-bottom: 20px;
  border-bottom: var(--garis);
}

/* Nama perusahaan di atas judul: kecil, berjarak, dan REDUP — ia penanda
   tempat, bukan judulnya. Dibuat sekuat judul, keduanya berebut perhatian. */
.tentang-alis {
  margin: 0 0 6px;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--accent);
}

.tentang-kepala h1 { margin: 0; }

/* Ukuran dan jarak baris DINAIKKAN dari teks biasa aplikasi ini. Yang lain
   halaman alat — dibaca sekilas sambil mengerjakan sesuatu; yang ini dibaca
   bersambung dari atas ke bawah. */
.tentang p {
  margin: 0 0 16px;
  font-size: 1.02rem;
  line-height: 1.75;
}

.tentang-judul {
  margin: 34px 0 14px;
  font-size: 1.24rem;
  line-height: 1.35;
  /* Garis pendek berwarna aksen di atas judul: penanda bagian baru yang
     terlihat sambil menggulir cepat, tanpa menambah satu kata pun. */
  padding-top: 16px;
  border-top: 3px solid var(--accent);
  display: inline-block;
}

/* Kalimat yang sengaja berdiri sendiri. Bukan kutipan dari orang lain — ia
   kalimat penulisnya sendiri yang diberi ruang, jadi tanpa tanda kutip. */
.tentang-sorot {
  margin: 22px 0 24px;
  padding: 16px 0 16px 20px;
  border-left: 3px solid var(--accent);
  background: rgba(var(--accent-rgb), 0.05);
  border-radius: 0 var(--sudut-kecil) var(--sudut-kecil) 0;
}

.tentang-sorot p {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 600;
  line-height: 1.55;
}

.tentang-sorot p + p { margin-top: 4px; }

/* Penutup. Satu-satunya blok berlatar penuh di halaman ini, dan memang harus
   sendirian: kalau ada dua, tidak ada yang menjadi penutup. */
.tentang-slogan {
  margin: 34px 0 0;
  padding: 26px 24px;
  border-radius: var(--sudut);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.14), rgba(var(--accent-rgb), 0.04));
  border: 1px solid rgba(var(--accent-rgb), 0.22);
  text-align: center;
  display: grid;
  gap: 6px;
}

.tentang-slogan-utama {
  font-size: 1.32rem;
  line-height: 1.3;
  color: var(--accent);
}

.tentang-slogan span { color: var(--text-muted); }

/* Baris terakhir biasanya tanda pagar. Dibuat menonjol tanpa membesar: ia
   penanda, bukan kalimat. */
.tentang-slogan span:last-child { font-weight: 600; letter-spacing: 0.01em; }

.tentang-lencana { margin-top: 26px; }

.tentang-ajakan {
  margin-top: 30px;
  padding-top: 24px;
  border-top: var(--garis);
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

@media (max-width: 560px) {
  .tentang-judul { font-size: 1.12rem; margin-top: 28px; }
  .tentang-slogan { padding: 22px 18px; }
  .tentang-slogan-utama { font-size: 1.16rem; }
  /* Tombol selebar layar di ponsel: dua tombol berdampingan pada lebar segitu
     menghasilkan dua tombol yang sama-sama terlalu sempit untuk dibaca. */
  .tentang-ajakan .tbl { width: 100%; }
}

/* ------------------------------------------------------------------ *
 * Tombol "Tentang Kami" di kepala halaman
 * ------------------------------------------------------------------ */

.tombol-tentang {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: var(--garis);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--alur), color var(--alur), border-color var(--alur);
}

.tombol-tentang:hover,
.tombol-tentang.aktif {
  color: var(--accent);
  border-color: rgba(var(--accent-rgb), 0.45);
  background: rgba(var(--accent-rgb), 0.08);
}

.tombol-tentang-ikon { font-size: 1rem; line-height: 1; }

/* Di layar sempit tinggal ikonnya. Kepala halaman di ponsel tegak sudah memuat
   merek, penanda area, keranjang, dan tombol menu; satu kata lagi membuat
   nama merek terpotong. Namanya tidak hilang — ia tetap ada di aria-label dan
   di tautan kaki halaman. */
@media (max-width: 900px) {
  .tombol-tentang-teks { display: none; }
  /* Tanpa min-width, tombol yang tinggal ikonnya menyusut menjadi 25px —
     terukur, dan itu lebih sempit daripada ujung jempol. Tetangganya di kepala
     halaman ini 33px (penanda area) dan 42px (tombol menu); yang ini disamakan
     dengan mereka, bukan dibiarkan menjadi sasaran terkecil di layar. */
  .tombol-tentang {
    padding: 7px;
    min-width: 36px;
    justify-content: center;
  }
}

.hero-lencana {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
}

.hero-lencana li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.87rem;
  font-weight: 650;
  color: var(--text-muted);
}

.hero-lencana-tanda {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--success);
  color: var(--success-contrast);
  font-size: 0.7rem;
  font-weight: 800;
}

@media (max-width: 620px) {
  .hero-cerita-kartu img { width: 56px; height: 56px; }
  .hero-cerita-isi { min-height: 0; }
}

.hero-isi {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 44px;
  align-items: center;
  position: relative;
  z-index: 1;
}

.hero-teks h1 { margin-bottom: 14px; }
.hero-teks p { font-size: 1.08rem; color: var(--text-muted); max-width: 52ch; }

.hero-gambar img {
  width: 100%;
  border-radius: var(--sudut-besar);
  box-shadow: var(--bayang-kuat);
  background: var(--surface);
}

@media (max-width: 860px) {
  .hero { padding: 34px 0 38px; }
  .hero-isi { grid-template-columns: 1fr; gap: 26px; }
  .hero-gambar { order: -1; max-width: 340px; }
}

/* ------------------------------------------------------------------ *
 * Tombol
 * ------------------------------------------------------------------ */

.tbl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-weight: 650;
  font-size: 0.94rem;
  cursor: pointer;
  text-decoration: none;
  transition: transform var(--alur), background var(--alur), box-shadow var(--alur), opacity var(--alur);
  white-space: nowrap;
}

.tbl:hover { transform: translateY(-1px); }
.tbl:active { transform: translateY(0); }

.tbl:disabled,
.tbl[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.tbl-utama {
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: 0 2px 10px rgba(var(--accent-rgb), 0.35);
}
.tbl-utama:hover { background: var(--accent-strong); }

.tbl-garis {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
}
.tbl-garis:hover { background: rgba(var(--accent-rgb), 0.1); }

.tbl-halus {
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent-link);
}
.tbl-halus:hover { background: rgba(var(--accent-rgb), 0.2); }

.tbl-bahaya { background: var(--danger); color: var(--danger-contrast); }
.tbl-sukses { background: var(--success); color: var(--success-contrast); }
.tbl-kedua { background: var(--secondary); color: var(--secondary-contrast); }
.tbl-ingat { background: var(--warning); color: var(--warning-contrast); }

.tbl-kecil { padding: 6px 12px; font-size: 0.84rem; }
.tbl-besar { padding: 13px 26px; font-size: 1.02rem; }
.tbl-penuh { width: 100%; }

.tbl-teks {
  background: transparent;
  padding: 4px 8px;
  color: var(--accent-link);
  border-radius: var(--sudut-kecil);
}
.tbl-teks:hover { background: rgba(var(--accent-rgb), 0.12); transform: none; }

/* Tombol WhatsApp melayang */
.wa-melayang {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 50;
  box-shadow: var(--bayang-kuat);
}

/* ------------------------------------------------------------------ *
 * Kartu & panel
 * ------------------------------------------------------------------ */

.kartu {
  background: var(--surface);
  border: var(--garis);
  border-radius: var(--sudut);
  padding: 20px;
  box-shadow: var(--bayang);
}

.kartu-rapat { padding: 14px; }
.kartu-datar { box-shadow: none; }

.panel {
  background: var(--surface);
  border: var(--garis);
  border-radius: var(--sudut);
  overflow: hidden;
}

.panel-kepala {
  padding: 14px 18px;
  border-bottom: var(--garis);
  background: var(--surface-2);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.panel-kepala h2, .panel-kepala h3 { margin: 0; font-size: 1.02rem; }
.panel-isi { padding: 18px; }

.kisi { display: grid; gap: 18px; }
.kisi-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.kisi-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.kisi-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.kisi-auto { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }

/* KISI PRODUK — sama seperti .kisi-auto, tapi lebar terkecil kartunya datang
   dari pengaturan toko (produk_per_baris), bukan dipatok di sini.

   Yang diatur tetap LEBAR, bukan jumlah kolom, dan itu yang membuatnya aman:
   `auto-fill` menghitung sendiri berapa kartu yang muat, jadi layar sempit
   tetap melipat kartunya seperti biasa. Memaksa jumlah kolom akan membuat
   pilihan "5" tercetak juga di layar ponsel, lima kolom selebar jempol.

   250px -> empat sebaris pada isi selebar 1180px; 200px -> lima. */
.kisi-produk { grid-template-columns: repeat(auto-fill, minmax(var(--kartu-produk, 250px), 1fr)); }
.kisi-sisi { grid-template-columns: minmax(0, 1fr) 340px; align-items: start; }

@media (max-width: 980px) {
  .kisi-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kisi-sisi { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .kisi-2, .kisi-3, .kisi-4 { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------------ *
 * Produk
 * ------------------------------------------------------------------ */

.kategori-judul {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 34px 0 16px;
}

.kategori-ikon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: rgba(var(--accent-rgb), 0.14);
  font-size: 1.25rem;
  flex-shrink: 0;
}

.produk {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: var(--garis);
  border-radius: var(--sudut);
  overflow: hidden;
  transition: transform var(--alur), box-shadow var(--alur), border-color var(--alur);
}

.produk:hover {
  transform: translateY(-3px);
  box-shadow: var(--bayang-kuat);
  border-color: var(--border-strong);
}

.produk-gambar {
  aspect-ratio: 4 / 3;
  background: linear-gradient(160deg, var(--hero-from), var(--hero-to));
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.produk-gambar img { width: 100%; height: 100%; object-fit: cover; }
.produk-gambar .kosong { font-size: 2.4rem; opacity: 0.5; }

.produk-isi { padding: 15px; display: flex; flex-direction: column; gap: 9px; flex: 1; }
.produk-nama { font-weight: 700; font-size: 1rem; line-height: 1.35; }

.produk-meta {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 0.79rem;
  color: var(--text-muted);
}

.produk-harga {
  font-size: 1.24rem;
  font-weight: 800;
  color: var(--accent-link);
  font-variant-numeric: tabular-nums;
}

.produk-satuan { font-size: 0.82rem; font-weight: 600; color: var(--text-muted); }

.tangga {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 9px 11px;
  border-radius: var(--sudut-kecil);
  background: rgba(var(--success-rgb), 0.13);
  font-size: 0.82rem;
}

/* ------------------------------------------------------------------ *
 * Pilihan wadah galon — tukar kosong, atau beli baru + isi
 *
 * Dibuat RINGKAS, bukan sebaris radio biasa: ia duduk di dalam kartu produk
 * yang berbagi satu baris kisi dengan kartu lain, dan tiap piksel tingginya
 * ikut menaikkan seluruh baris itu.
 * ------------------------------------------------------------------ */

.opsi-wadah {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin: 10px 0 12px;
}

.opsi-wadah-pilih {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 7px 9px;
  border: var(--garis);
  border-radius: var(--sudut-kecil);
  cursor: pointer;
  background: var(--surface);
  transition: border-color var(--alur), background var(--alur);
  min-width: 0;
}

/* Radionya disembunyikan dari MATA, bukan dari papan ketik: :focus-visible di
   bawah memakainya untuk menggambar cincin fokus pada kotaknya. Memakai
   display:none akan membuat pilihan ini mustahil dicapai tanpa tetikus. */
.opsi-wadah-radio {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

.opsi-wadah-nama {
  font-size: 0.78rem;
  font-weight: 650;
  line-height: 1.25;
  color: var(--text-muted);
}

.opsi-wadah-tambah { font-size: 0.72rem; color: var(--text-muted); }

.opsi-wadah-pilih:hover { border-color: rgba(var(--accent-rgb), 0.45); }

.opsi-wadah-pilih:has(.opsi-wadah-radio:checked) {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.08);
}

.opsi-wadah-pilih:has(.opsi-wadah-radio:checked) .opsi-wadah-nama { color: var(--accent); }

.opsi-wadah-pilih:has(.opsi-wadah-radio:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 420px) {
  /* Di layar paling sempit dua kolom membuat tulisannya pecah per kata. */
  .opsi-wadah { grid-template-columns: 1fr; }
}

.tangga-baris { display: flex; justify-content: space-between; gap: 10px; }
.tangga-baris b { color: var(--success-link); font-variant-numeric: tabular-nums; }

.produk-aksi { margin-top: auto; display: flex; gap: 8px; align-items: center; }

.spek {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 3px 12px;
  font-size: 0.82rem;
  color: var(--text-muted);
}
.spek dt { font-weight: 600; }
.spek dd { margin: 0; }

/* ------------------------------------------------------------------ *
 * Form
 * ------------------------------------------------------------------ */

.bidang { display: flex; flex-direction: column; gap: 5px; margin-bottom: 15px; }
.bidang:last-child { margin-bottom: 0; }

label { font-weight: 650; font-size: 0.88rem; }
.wajib::after { content: " *"; color: var(--danger-link); }

input[type="text"], input[type="tel"], input[type="email"], input[type="number"],
input[type="password"], input[type="date"], input[type="time"], input[type="search"],
input[type="url"], select, textarea {
  width: 100%;
  padding: 10px 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--sudut-kecil);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
  transition: border-color var(--alur), box-shadow var(--alur);
}

textarea { min-height: 86px; resize: vertical; line-height: 1.55; }
select { cursor: pointer; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.22);
}

input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(var(--danger-rgb), 0.18);
}

input::placeholder, textarea::placeholder { color: var(--text-muted); opacity: 0.75; }

input[type="file"] {
  width: 100%;
  padding: 9px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--sudut-kecil);
  background: var(--surface-2);
  font: inherit;
  font-size: 0.88rem;
}

.pesan-galat { color: var(--danger-link); font-size: 0.83rem; font-weight: 600; }

.teks-bahaya { color: var(--danger-link); }
.petunjuk { color: var(--text-muted); font-size: 0.83rem; }

/* Petunjuk berlangkah yang muncul hanya ketika jalan pintasnya tidak bisa
   dipakai - misalnya tombol lokasi otomatis, yang diblokir browser di
   sambungan http://. Diberi kotak supaya terbaca sebagai satu petunjuk utuh
   dan bukan sebagai kalimat yang tercecer di bawah kolom isian. */
/* Satu temuan pemeriksaan data. Diberi garis pemisah supaya beberapa temuan
   di dalam satu panel tidak terbaca sebagai satu paragraf panjang. */
.periksa-temuan {
  margin-top: 10px;
  padding-top: 10px;
  border-top: var(--garis);
}

.petunjuk-langkah {
  margin-top: 8px;
  padding: 10px 12px;
  border: var(--garis);
  border-radius: var(--sudut-kecil);
  background: var(--bg-soft);
}

.petunjuk-langkah p { margin: 0 0 6px; }
.petunjuk-langkah p:last-child { margin-bottom: 0; }
.petunjuk-langkah ol { margin: 0 0 6px; padding-left: 1.4em; }
.petunjuk-langkah li { margin-bottom: 3px; }

.pilihan {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.pilihan label {
  flex: 1;
  min-width: 170px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--sudut-kecil);
  background: var(--surface);
  cursor: pointer;
  font-weight: 600;
  transition: border-color var(--alur), background var(--alur);
}

.pilihan label:hover { border-color: var(--accent); }
.pilihan input:checked + span { color: var(--accent-link); }
.pilihan label:has(input:checked) {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.1);
}

/* Cara terima yang tidak berlaku di depot terpilih. Tetap TERLIHAT — pembeli
   harus tahu pilihan itu ada dan kenapa ia tidak bisa dipakai di cabang ini.
   Alasannya ditulis di #catatan-antar, tepat di bawah barisan pilihan. */
.pilihan label:has(input:disabled) {
  opacity: 0.5;
  cursor: not-allowed;
}

.pilihan label:has(input:disabled):hover { border-color: var(--border-strong); }

.pilihan input { margin-top: 3px; accent-color: var(--accent); flex-shrink: 0; }
.pilihan span { display: flex; flex-direction: column; gap: 2px; }
.pilihan small { font-weight: 500; color: var(--text-muted); }

.centang { display: flex; align-items: center; gap: 9px; font-weight: 600; cursor: pointer; }
.centang input { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }

.jumlah {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface);
}

.jumlah button {
  width: 34px;
  height: 34px;
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: 1.15rem;
  font-weight: 700;
  cursor: pointer;
  line-height: 1;
}

.jumlah button:hover { background: rgba(var(--accent-rgb), 0.14); }

.jumlah input {
  width: 52px;
  border: 0;
  text-align: center;
  padding: 6px 0;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: transparent;
}

.jumlah input:focus { box-shadow: none; outline: none; }

/* ------------------------------------------------------------------ *
 * Tabel
 * ------------------------------------------------------------------ */

.tabel-bungkus { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Kode pesanan, SKU, dan nama pengguna: huruf lebar-tetap, dan tidak pernah
   dipenggal. Di ponsel kolom KODE hanya kebagian 83px dan kode sepanjang
   QB-260906-CBT8 pecah menjadi tiga baris - satu baris tabel jadi setinggi
   111px, sementara kodenya sendiri jadi sulit dibaca sekali lihat. Tabelnya
   toh sudah bisa digeser ke samping, jadi biarkan lebar yang mengalah. */
.kode {
  font-family: var(--font-angka);
  white-space: nowrap;
}

/* Nilai pendek yang utuh sebagai satu kesatuan - tanggal, misalnya. Di ponsel
   "6 September 2026" pecah menjadi tiga baris dan sendirian membuat satu baris
   tabel setinggi 111px. */
.tanpa-penggal { white-space: nowrap; }

/* Keterangan bahwa tabelnya masih bisa digeser. Hanya muncul kalau memang
   tidak muat - dinyalakan dari JavaScript, bukan dari lebar layar, supaya
   tidak pernah menjanjikan kolom yang sebenarnya sudah kelihatan semua. */
.tabel-petunjuk {
  padding: 7px 12px;
  border-top: var(--garis);
  font-size: 0.78rem;
  color: var(--text-muted);
  background: var(--surface-2);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

th, td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: var(--garis);
  vertical-align: middle;
}

th {
  font-weight: 700;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  background: var(--surface-2);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}

tbody tr:hover { background: rgba(var(--accent-rgb), 0.06); }
tbody tr:last-child td { border-bottom: 0; }

td.angka, th.angka { text-align: right; font-variant-numeric: tabular-nums; }

/* Kolom uang tidak boleh dipatahkan. "Rp 307.000" yang terbelah menjadi "Rp"
   lalu "307.000" di baris berikutnya membuat kolomnya terbaca dua kali lebih
   tinggi dari perlunya, dan angkanya sendiri jadi sulit disejajarkan dengan
   angka di baris atas-bawahnya. */
td.angka, th.angka { white-space: nowrap; }

/* SEPASANG TOMBOL KEPUTUSAN DI DALAM TABEL.

   Dulu keduanya hanya .baris-rapat yang boleh melipat: di kolom sempit "Terima"
   dan "Tolak" bertumpuk tegak, lebarnya mengikuti panjang katanya masing-masing,
   dan tiap baris tabel jadi setinggi dua tombol. Yang terlihat bukan sepasang
   pilihan, melainkan dua tombol yang kebetulan berdekatan.

   Sekarang: satu baris, tidak melipat, lebar sama, dan rata kanan sejajar
   dengan kolom keputusan di baris lain. */
.aksi-tabel {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  white-space: nowrap;
}

.aksi-tabel > .tbl { min-width: 74px; justify-content: center; }

/* Di layar sempit tabelnya digeser mendatar, bukan diperas — jadi pasangan ini
   tetap satu baris di sana. Yang melipat adalah tabelnya, dan itu memang
   perilaku yang sudah ada. */

/* Nama berkas bisa sepanjang "WhatsApp Image 2026-08-24 at 11.00.18 AM.jpeg".
   Dibiarkan utuh, ia memaksa kolom berkas melebar dan memeras kolom keputusan
   sampai tombolnya bertumpuk. Nama lengkapnya tetap terbaca lewat title. */
/* Nama berkas dan tombol Unduh TETAP SATU BARIS.

   Dibiarkan melipat, "Unduh" terlempar ke bawah nama berkas dan barisnya
   menjadi 111px sementara baris bernama pendek hanya 74px — tabel yang
   tingginya naik-turun tanpa sebab yang bisa dilihat pembacanya. Yang mengalah
   adalah nama berkasnya: ia dipotong, dan nama lengkapnya ada di title. */
.sel-berkas {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
}

.nama-berkas {
  max-width: 220px;
  min-width: 0;
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  vertical-align: bottom;
}

/* Tombol Unduh tidak ikut menyusut — ia satu kata pendek, dan yang menyusut
   seharusnya nama berkas yang memang panjang. */
.sel-berkas > a { flex: 0 0 auto; }

/* ------------------------------------------------------------------ *
 * Lencana & status
 * ------------------------------------------------------------------ */

.lencana {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 700;
  white-space: nowrap;
  background: rgba(var(--text-rgb), 0.09);
  color: var(--text);
}

.lencana-accent { background: rgba(var(--accent-rgb), 0.16); color: var(--accent-link); }
.lencana-sukses { background: rgba(var(--success-rgb), 0.18); color: var(--success-link); }
.lencana-ingat { background: rgba(var(--warning-rgb), 0.2); color: var(--warning-link); }
.lencana-bahaya { background: rgba(var(--danger-rgb), 0.16); color: var(--danger-link); }
.lencana-kedua { background: rgba(var(--secondary-rgb), 0.18); color: var(--text); }

.jejak { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }

.jejak li {
  position: relative;
  padding: 0 0 16px 24px;
  border-left: 2px solid var(--border);
}

.jejak li:last-child { border-left-color: transparent; padding-bottom: 0; }

.jejak li::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 5px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.2);
}

.langkah {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

/* Alur "Cara Memesan": kartu bergambar, satu langkah per kartu. */
/*
 * SATU KOLOM LEBAR, BUKAN LIMA KOLOM SEMPIT.
 *
 * Dulu lima langkah berdiri sejajar pada kolom selebar ~190px, yang di layar
 * sedang menyusut jadi sekitar 110px. Kalimat panjang di kolom selebar itu
 * patah menjadi belasan baris berisi 3-4 kata. Justru pembaca yang paling
 * membutuhkan panduan ini — orang yang belum pernah memesan — yang paling
 * dilelahkan bentuk itu.
 *
 * Satu kolom juga berarti bentuk ini tidak perlu ditata ulang untuk ponsel:
 * yang berubah cuma lebarnya.
 */
.langkah-alur {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
  /* Dibatasi supaya barisnya tidak jadi terlalu panjang untuk dibaca. Ukuran
     ini kira-kira 75 huruf per baris pada tulisan seukuran ini — di atas itu
     mata kehilangan awal baris berikutnya. */
  max-width: 760px;
}

.langkah-baris {
  background: var(--surface);
  border: var(--garis);
  border-radius: var(--sudut);
  box-shadow: var(--bayang);
  padding: 16px 18px;
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.langkah-teks h3 {
  margin: 1px 0 3px;
  font-size: 1rem;
}

.langkah-teks p { margin: 0; }

.langkah-nomor {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.95rem;
}

/* ------------------------------------------------------------------ *
 * Cara membayar — nominal dan rekening yang bisa disalin
 *
 * Pelanggan di halaman ini SUDAH memutuskan membeli. Yang ia butuhkan tinggal
 * dua hal, dan keduanya dipakai di aplikasi LAIN (aplikasi banknya): berapa,
 * dan ke mana. Jadi keduanya dibuat besar, terbaca sekilas, dan bisa disalin
 * dengan satu ketukan — yang mengetik ulang dari ingatan akan salah satu digit
 * cepat atau lambat.
 * ------------------------------------------------------------------ */

/* Nominalnya berdiri di atas latar polos, TANPA kotak sendiri: kalau ia ikut
   berkotak, dua kotak bertumpuk di satu panel dan tidak ada lagi yang menonjol.
   Yang perlu menonjol angkanya, dan ukuran hurufnya sudah mengerjakan itu. */
.bayar-nominal {
  margin-bottom: 14px;
}

.bayar-angka {
  font-size: 1.9rem;
  font-weight: 800;
  color: var(--accent-link);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Kartu rekening: BERWARNA dan bergaris putus-putus.
   Warnanya memisahkannya dari isi panel yang lain, dan garis putus-putus
   membacanya sebagai "sesuatu untuk disalin" — bukan sebagai kotak isian yang
   menunggu diketik. Di panel yang isinya hampir semuanya formulir, perbedaan
   itu yang membuat mata menemukannya lebih dulu. */
.bayar-rekening {
  margin-bottom: 10px;
  background: rgba(var(--accent-rgb), 0.06);
  border: 1px dashed rgba(var(--accent-rgb), 0.45);
}

/* Nomor rekening: RENGGANG dan bersatuan lebar.
   Deretan angka panjang tanpa jeda adalah deretan yang salah dibaca; jarak
   antarhuruf memberi mata tempat berpijak, dan angka yang lebarnya sama
   membuat dua rekening berjajar bisa dibandingkan sekilas. */
.bayar-nomor {
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  font-variant-numeric: tabular-nums;
  margin: 2px 0 1px;
}

/* Pemilih berkas: input aslinya disembunyikan DARI MATA, bukan dari papan
   ketik. `display:none` akan membuatnya tidak bisa difokus sama sekali dan
   labelnya tidak lagi bisa dicapai dengan Tab.

   PEMILIHNYA HARUS MENYEBUT input[type="file"], bukan kelasnya saja. Aturan
   umum `input[type="file"]` di berkas ini berkekuatan (0,1,1) — pemilih atribut
   DITAMBAH nama elemen — sedangkan `.berkas-asli` sendirian cuma (0,1,0). Jadi
   `width: 100%` dari aturan umum itu MENANG, dan input yang dikira selebar satu
   piksel sebenarnya selebar panelnya.

   Akibatnya terukur: elemennya menjulur sampai 1193px pada layar 1024px, dan
   halaman pesanan bisa digeser ke kanan sejauh 169px tanpa ada yang terlihat di
   sana. */
input[type="file"].berkas-asli {
  position: absolute;
  width: 1px;
  height: 1px;
  min-width: 0;
  padding: 0;
  margin: 0;
  border: 0;
  overflow: hidden;
  /* Dipotong habis, bukan sekadar dibuat tembus pandang: sebagian browser
     tetap menyediakan tempat untuk isi yang meluap dari kotak sekecil ini. */
  clip-path: inset(50%);
  opacity: 0;
  pointer-events: none;
}

.pilih-berkas {
  display: block;
  text-align: center;
  cursor: pointer;
  border-style: dashed;
}

.berkas-asli:focus-visible + .pilih-berkas {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ *
 * Panduan kerja (SOP) di tab Bantuan
 *
 * Bentuknya sama dengan langkah "Cara Memesan" di beranda, dan itu disengaja:
 * orang yang sudah membaca satu tidak perlu belajar membaca yang lain.
 * ------------------------------------------------------------------ */

.sop-langkah {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
  /* Dibatasi supaya barisnya tidak jadi terlalu panjang untuk dibaca. */
  max-width: 820px;
}

.sop-baris {
  display: flex;
  gap: 13px;
  align-items: flex-start;
  padding: 14px 16px;
  border: var(--garis);
  border-radius: var(--sudut);
  background: var(--surface-2);
}

.sop-nomor {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.88rem;
}

.sop-isi { min-width: 0; }
.sop-isi h4 { margin: 3px 0 6px; font-size: 0.97rem; }
.sop-isi ul { margin: 0; padding-left: 18px; }
.sop-isi li { margin-bottom: 5px; line-height: 1.55; }
.sop-isi li:last-child { margin-bottom: 0; }

/* Kotak isian yang angkanya ditentukan sistem, bukan diketik orang. Dibuat
   TERLIHAT terkunci: kotak yang tampak seperti kotak isian biasa tapi menolak
   diketik terasa seperti halaman yang rusak, bukan seperti aturan. */
/* PEMILIHNYA HARUS MENYEBUT input[type="text"], sama seperti .berkas-asli di
   bawah dan dengan alasan yang sama: aturan umum di baris 818 berkekuatan
   (0,1,1), jadi `.nilai-terkunci` sendirian (0,1,0) kalah dan kotaknya tetap
   tergambar putih seperti kotak isian biasa. Terukur di layar sebelum baris
   ini ditulis. */
input[type="text"].nilai-terkunci {
  background: var(--surface-2);
  color: var(--text-muted);
  cursor: default;
}
input[type="text"].nilai-terkunci:focus {
  outline: none;
  box-shadow: none;
  border-color: var(--border);
}

.sop-catatan { margin-top: 14px; }
.sop-catatan ul { margin: 6px 0 0; padding-left: 18px; }
.sop-catatan li { margin-bottom: 4px; }

/* SATU PANDUAN = SATU BAGIAN YANG BISA DILIPAT.
   Dipasang di atas <details>/<summary> bawaan, jadi yang diatur di sini hanya
   tampilannya: membuka, menutup, papan ketik, dan pembaca layar sudah ditangani
   peramban. */
.sop-kepala {
  cursor: pointer;
  user-select: none;
  /* Segitiga bawaan dibuang di kedua mesin peramban — Firefox lewat
     list-style, Safari/Chrome lewat ::-webkit-details-marker — lalu diganti
     tanda panah sendiri yang ikut berputar. Kalau salah satu baris ini hilang,
     yang muncul DUA tanda, bukan satu. */
  list-style: none;
}
.sop-kepala::-webkit-details-marker { display: none; }
.sop-kepala:hover { background: var(--surface-3, var(--surface-2)); }
.sop-kepala::after {
  content: '';
  flex: none;
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--alur);
}
.sop-panel[open] > .sop-kepala::after { transform: rotate(-135deg) translate(-2px, -2px); }
/* Ringkasan turun ke baris kedua: ia yang memberi tahu isi bagian yang sedang
   tertutup, jadi ia harus terbaca justru saat bagiannya belum dibuka. */
.sop-ringkas {
  flex-basis: 100%;
  /* ::after selalu menjadi anak TERAKHIR, jadi tanpa order ini tanda panahnya
     terdorong ke bawah ringkasan dan menempati baris ketiga sendirian — paling
     kelihatan di layar ponsel, tempat ringkasannya memang selalu pecah. */
  order: 1;
}
.sop-panel > .panel-isi { padding-top: 16px; }

/* ------------------------------------------------------------------ *
 * Pemberitahuan
 * ------------------------------------------------------------------ */

.info {
  padding: 12px 15px;
  border-radius: var(--sudut-kecil);
  border-left: 4px solid var(--accent);
  background: rgba(var(--accent-rgb), 0.1);
  font-size: 0.9rem;
}

.info-sukses { border-left-color: var(--success); background: rgba(var(--success-rgb), 0.12); }
.info-ingat { border-left-color: var(--warning); background: rgba(var(--warning-rgb), 0.14); }
.info-bahaya { border-left-color: var(--danger); background: rgba(var(--danger-rgb), 0.11); }

/* Sisa waktu bayar. Dipisah ke barisnya sendiri dan diberi angka bergaya
   monospasi: angka detik yang berubah tiap detik dengan lebar huruf yang
   berbeda-beda membuat seluruh baris bergoyang ke kiri-kanan. */
.sisa-waktu { margin-top: 6px; }
.hitung-mundur {
  font-family: var(--font-angka);
  /* --danger-link, BUKAN --danger. Yang pertama warna merah yang memang
     ditakar untuk TEKS di berkas ini (dipakai juga oleh .pesan-galat dan
     .lencana-bahaya); yang kedua untuk garis dan bidang, dan terlalu muda
     dibaca sebagai huruf. */
  color: var(--danger-link);
  /* BESAR DAN TEBAL — dan ini bukan selera.

     Angkanya duduk di atas kotak .info-ingat, yaitu warna warning 14% di atas
     surface. Yang dijamin themes.js hanya kontras danger-link terhadap surface
     POLOS, jadi semburat kuning itu memakannya. Diukur di keenam tema:

         kertas 5.80   malam 4.67   brand/tosca/daun 4.53   laut 4.14

     Tema "laut" jatuh di bawah 4.5, ambang AA untuk teks biasa. Di atas
     18.66px DAN tebal, ambangnya 3.0 — dan yang paling tipis pun, 4.14, ada
     jauh di atasnya. Jadi ukuran ini yang membuat merahnya boleh dipakai.

     1.25rem = 20px. Menurunkannya ke bawah 18.66px mengembalikan cacatnya
     tanpa satu pun tanda di layar. */
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
}

.pesan-layar {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(400px, calc(100vw - 32px));
}

.pesan {
  padding: 12px 16px;
  border-radius: var(--sudut-kecil);
  background: var(--surface);
  border: var(--garis);
  border-left: 4px solid var(--accent);
  box-shadow: var(--bayang-kuat);
  font-size: 0.9rem;
  font-weight: 600;
  animation: masuk var(--alur);
}

.pesan-sukses { border-left-color: var(--success); }
.pesan-galat { border-left-color: var(--danger); }

@keyframes masuk {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.kosong {
  text-align: center;
  padding: 44px 20px;
  color: var(--text-muted);
}

.kosong-ikon { font-size: 2.6rem; margin-bottom: 10px; opacity: 0.6; }

.memuat {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid rgba(var(--accent-rgb), 0.3);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: putar 0.7s linear infinite;
}

@keyframes putar { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------------ *
 * Ringkasan biaya
 * ------------------------------------------------------------------ */

.ringkasan { display: flex; flex-direction: column; gap: 9px; }

.ringkasan-baris {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  font-size: 0.93rem;
}

.ringkasan-baris span:last-child { font-variant-numeric: tabular-nums; font-weight: 650; }

.ringkasan-total {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding-top: 11px;
  border-top: 2px solid var(--border-strong);
  font-size: 1.15rem;
  font-weight: 800;
}

.ringkasan-total span:last-child { color: var(--accent-link); font-variant-numeric: tabular-nums; }

.sisi-lengket { position: sticky; top: 84px; }

/* ------------------------------------------------------------------ *
 * Baris keranjang
 * ------------------------------------------------------------------ */

.item {
  display: grid;
  grid-template-columns: 76px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 14px 0;
  border-bottom: var(--garis);
}

.item:last-child { border-bottom: 0; }

.item-gambar {
  width: 76px;
  height: 76px;
  border-radius: var(--sudut-kecil);
  object-fit: cover;
  background: var(--surface-2);
}

/* Baris pada rincian pesanan tidak punya gambar produk — hanya teks. */
.item-tanpa-gambar { grid-template-columns: 1fr auto; }

.item-kanan { text-align: right; display: flex; flex-direction: column; gap: 6px; align-items: flex-end; }

@media (max-width: 620px) {
  .item { grid-template-columns: 56px 1fr; }
  /* Baris tanpa gambar harus ikut dinolkan kolom gambarnya di sini juga.
     Aturan .item di atas datang belakangan dengan kekhususan yang sama, jadi
     tanpa baris ini ia menang dan menyisakan kolom 56px yang kosong — teks
     nama produk lalu diperas ke lebar 56px dan pecah satu kata per baris. */
  .item-tanpa-gambar { grid-template-columns: 1fr; }
  .item-gambar { width: 56px; height: 56px; }
  .item-kanan { grid-column: 1 / -1; flex-direction: row; align-items: center; justify-content: space-between; }
}

/* ------------------------------------------------------------------ *
 * Tab panel Admin
 * ------------------------------------------------------------------ */

.tab-bar {
  display: flex;
  gap: 2px;
  /* MELIPAT, bukan digeser mendatar. Panel ini punya 14 tab; dengan geser
     mendatar hampir 300px di antaranya tersembunyi di balik bilah gulir yang
     mudah tidak terlihat — tab yang tidak kelihatan sama saja dengan tab yang
     tidak ada. Melipat memang bisa memakan satu baris lagi, tapi tidak pernah
     menyembunyikan apa pun. */
  flex-wrap: wrap;
  row-gap: 4px;
  padding: 5px 0;
  border-bottom: var(--garis);
}

/* Layar sempit tetap digeser: melipat 14 tab di ponsel akan memakan hampir
   sepertiga layar sebelum isinya kelihatan. */
@media (max-width: 700px) {
  .tab-bar {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
  }
}

.tab-bar button {
  border: 0;
  background: transparent;
  /* 11px, bukan 12: seluruh 14 tab kelebihan tepat 11px dari lebar isi 1180px,
     dan memangkas 1px per sisi menutupnya tanpa membuat tombolnya terasa
     sempit. Kalau nanti ada tab lagi, .tab-bar akan melipat dengan rapi. */
  padding: 7px 11px;
  border-radius: 999px;
  font: inherit;
  font-weight: 650;
  font-size: 0.86rem;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--alur), color var(--alur);
}

.tab-bar button:hover { background: rgba(var(--accent-rgb), 0.1); color: var(--text); }

.tab-bar button[aria-selected="true"] {
  background: var(--accent);
  color: var(--accent-contrast);
}

/* ------------------------------------------------------------------ *
 * Bilah bagian di dalam sebuah tab (dipakai halaman Laporan)
 *
 * SENGAJA LEBIH TENANG daripada bilah tab utama di atasnya: ia bagian dari
 * satu tab, bukan saudaranya. Dua bilah yang tergambar sama kuat membuat
 * pembacanya harus berpikir dulu mana yang membawanya ke mana.
 * ------------------------------------------------------------------ */

.bilah-bagian {
  border-bottom: 0;
  margin-bottom: 4px;
  gap: 4px;
  /* Menempel saat digulir: tabel laporan bisa sepanjang beberapa layar, dan
     bilah yang hilang di atas membuat orang menggulir balik hanya untuk
     pindah bagian. */
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--bg);
  padding-top: 8px;
}

.bilah-bagian button {
  font-size: 0.82rem;
  padding: 6px 12px;
  background: var(--surface-2);
  border: var(--garis);
}

.bilah-bagian button:hover { background: rgba(var(--accent-rgb), 0.12); }

.bilah-bagian button[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

/* Isi bagian diberi tinggi minimum supaya berpindah bagian tidak membuat
   halaman melompat-lompat saat tingginya berbeda jauh. */
.bagian-isi { min-height: 50vh; }

/* KELOMPOK BIDANG di dalam satu panel pengaturan.

   Dua belas kolom berderet tanpa pemisah memaksa orang membaca semuanya untuk
   menemukan satu. Garis tipis di atas tiap kelompok memberi tahu di sebelah
   mana ia berada tanpa menambah satu panel pun — panel baru berarti satu layar
   gulungan lagi, dan itu justru keluhan yang sedang diperbaiki. */
.kelompok-bidang + .kelompok-bidang {
  margin-top: 22px;
  padding-top: 18px;
  border-top: var(--garis);
}

.kelompok-bidang > h4 { margin: 0 0 2px; font-size: 0.95rem; }
.kelompok-bidang > p { margin: 0 0 12px; }

/* Pemisah untuk satu judul yang berdiri sendiri, bukan sekelompok kolom. */
h4.kelompok-pisah {
  margin: 26px 0 12px;
  padding-top: 18px;
  border-top: var(--garis);
  font-size: 0.95rem;
}

/* Tinggi minimum supaya halaman tidak mengerut saat isi tab sedang dimuat.
   Yang dicegah di sini pergeseran TEGAK-nya; pergeseran mendatarnya dicegah
   scrollbar-gutter di atas. */
.tab-isi {
  padding-top: 18px;
  min-height: 60vh;
}

.statistik {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
}

.statistik-kotak {
  padding: 15px 17px;
  border-radius: var(--sudut);
  border: var(--garis);
  background: var(--surface);
}

.statistik-nilai {
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  color: var(--accent-link);
}

.statistik-label { font-size: 0.8rem; color: var(--text-muted); font-weight: 600; }

/* Di ponsel keenam kotak ini memakan hampir seluruh layar sebelum tab pertama
   bisa disentuh - diukur pada layar 812px: 530px habis sebelum bilah tabnya.
   Angkanya diperkecil secukupnya supaya nilai rupiah terpanjang tetap muat
   dalam satu baris, sehingga tinggi keenam kotaknya sekalian menjadi rata. */
@media (max-width: 560px) {
  .statistik {
    gap: 8px;
    grid-template-columns: repeat(auto-fit, minmax(138px, 1fr));
  }
  .statistik-kotak { padding: 10px 12px; }
  .statistik-nilai { font-size: 1.2rem; }
  .statistik-label { font-size: 0.74rem; }
}

/* ------------------------------------------------------------------ *
 * Dialog
 * ------------------------------------------------------------------ */

dialog {
  border: var(--garis);
  border-radius: var(--sudut);
  padding: 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--bayang-kuat);
  max-width: min(680px, calc(100vw - 32px));
  width: 100%;
  /* Setinggi-tingginya selayar. Peramban memang sudah membatasi tinggi dialog
     sendiri, dan tanpa batas yang kita akui isinya menyembul melewati kotak
     dialognya lalu terpotong. */
  max-height: calc(100vh - 24px);
  max-height: calc(100dvh - 24px);
}

/* Dialog disusun tegak supaya isinya yang mengalah, bukan tombolnya.
 *
 * Sebelum ini kepala, isi, dan kaki hanya ditumpuk begitu saja: pada pesanan
 * dengan enam tombol aksi di layar ponsel, kakinya setinggi 205px dan ujungnya
 * jatuh 19px di luar dialog - tombol terakhir terpotong dan tidak bisa
 * disentuh. Dengan susunan ini kepala dan kaki selalu utuh, dan bagian isinya
 * yang menyusut lalu digulir.
 */
dialog[open] {
  display: flex;
  flex-direction: column;
}

.dialog-kepala,
.dialog-kaki { flex: none; }

dialog::backdrop { background: rgba(var(--text-rgb), 0.45); }

.dialog-kepala {
  padding: 15px 20px;
  border-bottom: var(--garis);
  display: flex;
  align-items: center;
  gap: 10px;
}

.dialog-kepala h3 { margin: 0; }
.dialog-isi {
  padding: 20px;
  max-height: 66vh;
  overflow-y: auto;
  /* Boleh menyusut di bawah tinggi isinya kalau dialognya sudah mentok. */
  flex: 0 1 auto;
  min-height: 0;
}

/* Pratinjau bukti transfer. Foto struk biasanya potret dan tinggi, jadi yang
   dibatasi tingginya — lebarnya mengikuti supaya tidak terpotong. */
.pratinjau-bukti {
  display: block;
  max-width: 100%;
  max-height: 54vh;
  margin: 0 auto;
  object-fit: contain;
  border: var(--garis);
  border-radius: var(--sudut-kecil);
  background: var(--surface-2);
}

/* Foto struk yang lebih kecil dari kotaknya ditampilkan seukuran aslinya —
   dipaksa selebar dialog hanya membuatnya buram. */
img.pratinjau-bukti { width: auto; }
iframe.pratinjau-bukti { width: 100%; height: 54vh; }

.dialog-kaki {
  padding: 14px 20px;
  border-top: var(--garis);
  display: flex;
  gap: 9px 14px;
  /* Dibungkus, bukan meluber: sebuah pesanan bisa punya banyak tombol sekaligus
     (perpindahan status, pembayaran, pesan, cetak).

     DUA KELOMPOK, bukan satu deret. Dulu seluruhnya satu deret dengan
     justify-content: flex-end — tujuh tombol berbaris tanpa urutan yang berarti,
     dan yang terakhir terlempar sendirian ke baris kedua, rata kanan, seolah
     tidak sengaja. Sekarang pembungkusannya jatuh di ANTARA kelompok. */
  flex-wrap: wrap;
  align-items: center;
  background: var(--surface-2);
}

.kaki-alat,
.kaki-aksi {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* Perkakas di kiri, keputusan di kanan. Yang mengubah data tidak boleh
   bertetangga dengan yang cuma membuka nota. */
.kaki-aksi { margin-left: auto; }

@media (max-width: 620px) {
  /* Di ponsel keduanya menjadi dua baris penuh, dan yang MENGUBAH DATA di
     bawah — paling dekat dengan jempol, dan terbaca terakhir. */
  .dialog-kaki { flex-direction: column-reverse; align-items: stretch; }
  .kaki-alat, .kaki-aksi { margin-left: 0; justify-content: flex-start; }
}

/* Di ponsel tombol-tombol ini melipat menjadi empat baris, dan karena rata
   kanan ujung kirinya bertangga - terbaca berantakan, dan tombol sempit di
   tengah tumpukan sulit disentuh dengan tepat. Dibiarkan melar supaya tiap
   baris terisi penuh dan rata. */
@media (max-width: 560px) {
  .dialog-kaki { justify-content: stretch; }
  .dialog-kaki > .tbl { flex: 1 1 auto; }
}

/* ------------------------------------------------------------------ *
 * Footer
 * ------------------------------------------------------------------ */

.kaki {
  border-top: var(--garis);
  background: var(--surface);
  padding: 34px 0 26px;
  margin-top: 44px;
}

.kaki-isi {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 30px;
}

.kaki h4 { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.kaki ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.kaki a { color: var(--text); text-decoration: none; font-size: 0.9rem; }
.kaki a:hover { color: var(--accent-link); text-decoration: underline; }


/* Bilah hak cipta & versi yang menempel di dasar layar, di semua halaman.
 *
 * Setinggi satu baris dan tidak pernah lebih: ia menemani halaman, bukan ikut
 * memperebutkan tempatnya. Tingginya disediakan lewat padding pada body supaya
 * tidak pernah ada isi halaman yang tertutup di ujung bawah — termasuk tombol
 * terakhir sebuah formulir panjang. */
.tanda-tetap {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 45;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* Tingginya DIPAKU ke angka yang sama dengan ruang yang disediakan body.
     Kalau keduanya boleh berbeda, selisihnya menutupi isi halaman di ujung
     bawah — dan selisih dua piksel tidak akan pernah terlihat sampai ada
     tombol yang tidak bisa ditekan. */
  height: var(--tinggi-tanda);
  box-sizing: border-box;
  overflow: hidden;
  white-space: nowrap;
  padding: 0 16px;
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  background: var(--surface);
  border-top: var(--garis);
}

/* Layar sempit hanya muat satu baris pendek. Yang paling tidak dibutuhkan
   pergi duluan, supaya hak cipta dan nomor versi tidak pernah terpotong —
   nomor versi justru yang paling sering perlu disebut saat bertanya. */
@media (max-width: 460px) {
  .tanda-tetap { gap: 10px; }
  .tanda-tetap .tanda-npwp,
  .tanda-tetap .tanda-oleh { display: none; }
}

body { padding-bottom: var(--tinggi-tanda); }

/* ------------------------------------------------------------------ *
 * BILAH KIRIM — aksi utama yang tidak pernah tergulir hilang
 *
 * Formulir checkout panjangnya dua layar penuh, dan tombol "Kirim Pesanan"
 * dulu hanya ada di kartu ringkasan kanan atas. Pembeli mengisi kolom
 * terakhirnya, lalu menatap layar yang tidak punya tombol apa pun — aksi
 * utamanya menghilang tepat pada saat ia dibutuhkan, dan ia harus menggulir
 * NAIK untuk mencarinya.
 *
 * Bilah ini membawa TOTALNYA SEKALIGUS TOMBOLNYA. Tombol saja tidak cukup:
 * orang menekan "kirim" sesudah memastikan angkanya, jadi angka yang dipastikan
 * harus ada di tempat yang sama dengan tombolnya.
 *
 * Di ponsel ini wajib; di layar lebar tetap berguna karena formulirnya memang
 * panjang. Kartu ringkasan di kanan tetap ada — yang pindah hanya tombolnya.
 * ------------------------------------------------------------------ */
.bilah-kirim {
  position: fixed;
  left: 0;
  right: 0;
  /* DI ATAS bilah hak cipta, bukan menimpanya. */
  bottom: var(--tinggi-tanda);
  z-index: 44;
  height: var(--tinggi-bilah-kirim);
  box-sizing: border-box;
  background: var(--surface);
  border-top: var(--garis);
  box-shadow: var(--bayang-kuat);
}

.bilah-kirim-isi {
  max-width: var(--lebar-isi);
  height: 100%;
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  align-items: center;
  gap: 14px;
}

.bilah-kirim-total {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  min-width: 0;
}

.bilah-kirim-angka {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--accent-link);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Tombolnya tidak ikut menyempit: aksi utama yang terpotong separuh lebih
   buruk daripada angka yang terpotong. */
.bilah-kirim .tbl {
  margin-left: auto;
  flex: none;
}

/* Ruang untuk bilahnya, supaya kolom terakhir formulir tidak tertutup — dan
   yang melayang di sudut bawah ikut naik lagi supaya tidak duduk di atasnya. */
body.ada-bilah-kirim { padding-bottom: calc(var(--tinggi-tanda) + var(--tinggi-bilah-kirim)); }
body.ada-bilah-kirim .wa-melayang { bottom: calc(18px + var(--tinggi-tanda) + var(--tinggi-bilah-kirim)); }
body.ada-bilah-kirim .pesan-layar { bottom: calc(16px + var(--tinggi-tanda) + var(--tinggi-bilah-kirim)); }

/* Layar sempit: keterangan "Perkiraan total" boleh pergi, angkanya tidak. */
@media (max-width: 420px) {
  .bilah-kirim-isi { padding: 0 13px; gap: 10px; }
  .bilah-kirim-total .kecil { display: none; }
}


/* Yang melayang di sudut bawah ikut naik, supaya tidak duduk di atas bilahnya. */
.wa-melayang { bottom: calc(18px + var(--tinggi-tanda)); }
.pesan-layar { bottom: calc(16px + var(--tinggi-tanda)); }

/* Dua kelompok: hak cipta di kiri, versi dan pembuat aplikasi di kanan. */

/* Tanda versi di panel Admin, yang footernya tidak dipasang. */

@media (max-width: 760px) {
  .kaki-isi { grid-template-columns: 1fr; gap: 22px; }
}

/* ------------------------------------------------------------------ *
 * Cetak — invoice & surat jalan A4
 * ------------------------------------------------------------------ */

.dokumen {
  max-width: 210mm;
  margin: 20px auto;
  padding: 16mm 15mm;
  background: var(--surface);
  border: var(--garis);
  border-radius: var(--sudut);
  box-shadow: var(--bayang);
}

.dok-kop {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding-bottom: 14px;
  border-bottom: 2px solid var(--border-strong);
  margin-bottom: 18px;
}

.dok-kop img { width: 64px; height: 64px; object-fit: contain; }
.dok-kop-nama { font-size: 1.3rem; font-weight: 800; line-height: 1.2; }
.dok-judul { text-align: right; margin-left: auto; }
.dok-judul h1 { font-size: 1.5rem; margin: 0; }

.dok-blok { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 18px; }
.dok-blok h4 { font-size: 0.75rem; text-transform: uppercase; color: var(--text-muted); margin-bottom: 4px; }

.ttd {
  margin-top: 40px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 40px;
  text-align: center;
  font-size: 0.85rem;
}

.ttd-kotak { padding-top: 62px; border-bottom: 1px solid var(--text); }

/* Kaki dokumen: rekening & catatan di kiri, ringkasan angka di kanan. */
.dok-kaki { display: flex; gap: 24px; margin-top: 18px; align-items: flex-start; }
.dok-kaki > :first-child { flex: 1; }
.dok-kaki .ringkasan { min-width: 250px; }

/* Di layar ponsel, lembar A4 tidak boleh memaksa halaman bergeser mendatar.
   Padding 15mm memakan 114px dari lebar 375px, dan sisanya tidak cukup untuk
   tabel barang. Geometri A4-nya sendiri tidak diubah — itu diatur @media print
   di bawah, jadi hasil cetaknya tetap sama. */
@media (max-width: 620px) {
  .dokumen { margin: 12px auto; padding: 18px 14px; }
  .dok-blok { grid-template-columns: 1fr; gap: 14px; }
  .ttd { grid-template-columns: 1fr; gap: 24px; }
  /* Kop dan kaki dokumen ditumpuk. Dibiarkan berdampingan, kolomnya tinggal
     seratusan piksel dan teksnya pecah satu kata per baris. */
  .dok-kop { flex-wrap: wrap; }
  .dok-judul { margin-left: 0; width: 100%; text-align: left; }
  .dok-kaki { flex-direction: column; }
  .dok-kaki .ringkasan { min-width: 0; width: 100%; }
  /* Tabel barang diberi lebar minimum supaya kolomnya tidak diperas sampai
     nama produk pecah per kata. Yang lebih panjang digeser di dalam
     .tabel-bungkus. Aturan ini tidak berlaku saat mencetak: lebar kertas A4
     jauh di atas 620px, jadi media query ini tidak ikut. */
  .dokumen .tabel-bungkus table { min-width: 520px; }
}

/* ------------------------------------------------------------------ *
 * TANDA "UJI COBA"
 *
 * Tiga sifat di bawah ini yang membuatnya berguna, bukan mengganggu —
 * dan ketiganya sama pentingnya:
 *
 *   pointer-events: none   kliknya TEMBUS. Tanpa ini, elemen ini menjadi
 *                          selembar kaca tak terlihat yang menutupi seluruh
 *                          aplikasi, dan tidak satu tombol pun bisa ditekan.
 *   z-index: 90            di bawah .pesan-layar (100) dan di bawah <dialog>
 *                          yang selalu di lapisan teratas. Jadi notifikasi
 *                          dan kotak konfirmasi tetap bersih.
 *   opacity rendah         terbaca sebagai latar, bukan sebagai isi halaman.
 *
 * `position: fixed` + `inset: 0`: selalu selayar penuh, tidak ikut bergulir,
 * dan tidak menambah tinggi halaman satu piksel pun.
 * ------------------------------------------------------------------ */
.tanda-uji {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  opacity: 0.07;
  background-repeat: repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='330' height='190'%3E%3Ctext x='165' y='100' fill='%23000' font-family='system-ui,-apple-system,Segoe UI,Roboto,sans-serif' font-size='40' font-weight='700' letter-spacing='3' text-anchor='middle' transform='rotate(-24 165 100)'%3EUJI COBA%3C/text%3E%3C/svg%3E");
  /* Latar belakang yang tercetak biasanya dibuang peramban demi tinta. Di sini
     justru itu isinya: nota dari salinan latihan HARUS terlihat berbeda dari
     nota sungguhan, termasuk sesudah dicetak. */
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

@media print {
  .kepala, .kaki, .wa-melayang, .tanpa-cetak, .pesan-layar, .bilah-kirim { display: none !important; }
  /* Tandanya TETAP tercetak — lihat alasannya di atas — tapi lebih tipis,
     supaya angka di bawahnya tidak ikut kabur. */
  .tanda-uji { opacity: 0.09; }
  /* Ruang untuk bilah yang menempel tidak ada gunanya di atas kertas. */
  body { background: none; font-size: 11pt; padding-bottom: 0; }
  /* Disebut TERPISAH, bukan digabung ke pemilih di atas. `body.ada-bilah-kirim`
     lebih kuat daripada `body` saja, jadi tanpa baris ini ruang untuk bilah
     kirim tetap tercetak sebagai sejengkal kosong di kaki kertas — sementara
     menggabungkannya ke atas akan membuat penjaga di uji 11 kehilangan aturan
     `body {}` yang ia cari. */
  body.ada-bilah-kirim { padding-bottom: 0; }
  .dokumen {
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    max-width: none;
  }
  .utama { padding: 0; }
  /* Bungkus geser hanya berguna di layar. Di atas kertas ia harus lenyap,
     supaya tabel yang lebih lebar dari kolomnya tidak terpotong diam-diam. */
  .tabel-bungkus { overflow: visible; }
  /* Panduan yang tertutup tetap tercetak. Di layar melipatnya menolong; di atas
     kertas ia hanya menghilangkan isi yang justru ingin dibawa orang. */
  .sop-panel > .panel-isi { display: block !important; }
  .sop-kepala::after { display: none; }
  a { text-decoration: none; color: inherit; }
  table { font-size: 10pt; }
  th { background: none; border-bottom: 1pt solid var(--text); }
  @page { size: A4; margin: 14mm; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ------------------------------------------------------------------ *
 * Pemilih area
 *
 * Hanya muncul kalau toko melayani lebih dari satu area. Kartunya sengaja
 * besar dan bisa ditekan seluruh badannya: ini pilihan pertama yang diambil
 * pengunjung, sering dengan satu tangan sambil memegang galon kosong.
 * ------------------------------------------------------------------ */

.kisi-area {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--jarak);
}

.kartu-area {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 20px;
  background: var(--surface);
  border: var(--garis);
  border-radius: var(--sudut);
  box-shadow: var(--bayang);
  color: inherit;
  text-decoration: none;
  transition: transform var(--alur), box-shadow var(--alur), border-color var(--alur);
}

.kartu-area:hover,
.kartu-area:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--bayang-kuat);
  border-color: var(--accent);
}

.kartu-area.aktif {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.08);
}

/* Kode area (BPP, SMD) dipakai sebagai lencananya. Ia sudah ada di data dan
   sudah dicetak di kode pesanan, jadi tidak ada gambar baru yang perlu
   disiapkan tiap kali area baru dibuka. */
.kartu-area-tanda {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 42px;
  height: 28px;
  padding: 0 10px;
  margin-bottom: 6px;
  border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.14);
  color: var(--accent);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
}

.kartu-area-nama {
  font-size: 1.15rem;
  font-weight: 700;
}

.kartu-area-alamat {
  font-size: 0.86rem;
  opacity: 0.7;
  line-height: 1.45;
}

.kartu-area-kini {
  margin-top: 8px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
}

/* Penanda di header: keterangan, bukan hiasan. Harga dan ongkir yang dilihat
   pembeli bergantung padanya, jadi ia harus terbaca sekilas di tiap halaman. */
.penanda-area {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-weight: 600;
  font-size: 0.88rem;
  text-decoration: none;
  white-space: nowrap;
}

/* Tidak ikut menyempit: nama area yang terpotong separuh lebih buruk daripada
   merek yang terpotong — merek masih dikenali dari logonya, area tidak. */
.penanda-area { flex: none; }

/* Yang panjang dulu; yang pendek baru muncul di layar sempit. */
.penanda-area-pendek { display: none; }

.penanda-area:hover,
.penanda-area:focus-visible {
  background: rgba(var(--accent-rgb), 0.12);
}

/* Belum memilih: ia harus menarik mata, karena tidak ada harga yang bisa
   ditampilkan sebelum ditekan. */
.penanda-area.perlu {
  background: var(--accent);
  color: var(--accent-contrast);
}

/*
 * PONSEL TEGAK: yang tampil KODE AREANYA, bukan namanya.
 *
 * Di lebar 390px, baris header memuat merek, penanda area, ikon keranjang, dan
 * tombol menu sekaligus. "BALIKPAPAN" menghabiskan ruang yang tersisa dan
 * mendorong mereknya sampai tinggal logo; "BPP" muat dengan longgar.
 *
 * Diganti, bukan dipotong dengan ellipsis: "BALIKP..." dan "BALIKPAPAN TIMUR"
 * terlihat sama di layar, dan pembeli yang salah area tidak punya cara tahu.
 * Kode areanya pendek karena memang dibuat untuk dibaca sekilas.
 */
@media (max-width: 560px) {
  .kepala-isi { gap: 10px; padding: 8px 13px; }
  .kepala-aksi { gap: 7px; }
  .penanda-area-panjang { display: none; }
  .penanda-area-pendek { display: inline; }
  .penanda-area {
    padding: 5px 10px;
    gap: 4px;
    font-size: 0.82rem;
    letter-spacing: 0.01em;
  }
  /* Pin-nya ikut mengecil: di ruang sesempit itu ia keterangan, bukan hiasan. */
  .penanda-area-pin { font-size: 0.78rem; }

  /* JARING PENGAMAN untuk area yang TIDAK diberi kode: yang dipakai namanya,
     dan nama seperti "PENAJAM PASER UTARA" akan menjebol baris header karena
     penandanya sengaja tidak menyempit.
     Dipotong di sini, walau di atas ditulis "diganti, bukan dipotong" — dan
     kedua-duanya benar. Mengganti selalu lebih baik, tapi itu menuntut areanya
     punya kode; kalau tidak ada, pilihannya tinggal terpotong atau header yang
     jebol, dan header jebol membuat tombol menu tak bisa ditekan sama sekali.
     Kodenya sendiri 3-4 huruf, jadi batas ini tidak pernah menyentuhnya. */
  .penanda-area-pendek {
    max-width: 10ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

/*
 * PONSEL PALING SEMPIT (320px, iPhone SE dan sejenisnya).
 *
 * Di lebar itu anggarannya habis: logo 40px, ikon keranjang 42px, tombol menu
 * 39px, dan sisa ruangnya harus dibagi tulisan merek dengan penanda area.
 * Terukur dengan nama area 27 huruf tanpa kode — penandanya memakan 116px dan
 * MEREKNYA TINGGAL SATU HURUF, "Q" saja.
 *
 * Jadi di sini penandanya yang mengalah lebih dulu. Ia tetap terbaca sebagai
 * sebuah nama, sementara merek yang tinggal satu huruf tidak terbaca sebagai
 * apa pun. Kode area 3-4 huruf tetap tidak tersentuh batas ini.
 */
@media (max-width: 400px) {
  .penanda-area-pendek { max-width: 6ch; }
}

.panel-area {
  padding: 26px;
}

/* Bagian pemilih area di halaman pembuka. */
.sambutan-area {
  margin-top: 40px;
  padding: 26px;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--sudut-besar);
  box-shadow: var(--bayang-kuat);
}
