@charset "utf-8";
/* =============================================================================
   Kopi Tepi Alun, desain contoh (kafe, roastery, dan katering acara yang fiktif)
   Sumber desain: stitch/13-kafe-resto/ (DESIGN.md + PROMPTS-WEB + PROMPTS-STATE)

   MODE WARNA DIKUNCI TERANG. Seluruh rasio di bawah DIHITUNG SENDIRI dengan rumus
   WCAG untuk latar terang saja. Mencabut kuncian di <html data-tema="terang">
   berarti menghitung ulang SETIAP pasangan lebih dulu, bukan menghapus atributnya.

   AKSEN NADA-TENGAH, DAN ARAH LARANGANNYA TERBALIK DARI SITUS 07.
   Cokelat karamel #C8842B hanya 2,88:1 di atas latar #FBF6EF, di bawah lantai
   3:1 untuk teks besar sekalipun. Ia ISIAN dan warna cip, TITIK. Dilarang jadi
   warna teks, garis kendali, ikon fungsional, maupun cincin fokus. Teks DI ATAS
   aksen wajib TINTA #2A1B10 (5,38:1); putih di atasnya cuma 3,09:1 dan gagal.
   Ini kebalikan penuh situs 07, tempat maroon 8,53:1 boleh melakukan hampir
   segalanya dan yang haram justru teks gelap di atasnya. Rantainya sekarang
   02 isian - 03 teks - 04 isian - 05 teks - 06 isian - 07 aksen gelap - 13 isian,
   dan itu tetap bukan pola yang boleh dipakai meramal paket berikutnya.

   Untuk garis, ikon fungsional, garis bawah item aktif, dan cincin fokus dipakai
   AKSEN-GELAP #A66A1E (4,15:1 di atas latar), lulus lantai 3:1 untuk komponen,
   dan TETAP TIDAK BOLEH jadi warna teks isi karena 4,15 < 4,5.

   ⛔ RAMBU ISI (ATURAN-KONTEN + DESIGN.md): TIDAK ADA nomor sertifikat halal,
   nomor PIRT, nomor izin edar, atau nomor registrasi apa pun di layar mana pun, yang ditampilkan hanya jenis, penerbit, dan statusnya. TIDAK ADA emoji di mana
   pun: di vertikal makanan, emoji makanan adalah cara ikon paling sering rusak.
   Menu adalah HALAMAN dengan harga terlihat, bukan ajakan memindai kode.

   DUA KELUARGA HURUF: DM Serif Display 400 untuk judul dan angka, DM Sans
   400/700 untuk isi dan harga (angka tabular). DM Serif Display hanya punya SATU
   bobot (400) dan bukan huruf variabel, menulis 700 untuknya berarti huruf tebal
   palsu yang digambar peramban, jadi tidak ada satu pun di berkas ini.
   ========================================================================== */

@import url("aset/huruf/_font-face.css");

/* -----------------------------------------------------------------------------
   1. TOKEN, tiap warna punya PERAN dan RASIO TERHITUNG di sebelahnya.
   Angka di bawah DIHITUNG SENDIRI dengan rumus WCAG relative luminance, bukan
   disalin dari DESIGN.md. Hasilnya: angka DESIGN.md paket ini TERBUKTI BENAR
   sampai dua desimal (15,47 - 6,34 - 2,88 - 4,15 - 5,38 - 3,09 - 10,46 - 2,43).
   Itu tidak membuat pemeriksaan berikutnya boleh dilewati: paket 02 menulis
   2,03:1 untuk pasangan yang sebenarnya 1,47:1.
   -------------------------------------------------------------------------- */
:root {
  /* Permukaan */
  --latar:        #FBF6EF;   /* alas halaman, kertas krem */
  --kertas:       #FFFFFF;   /* alas kartu di atas --latar */
  --sentuh:       #F3EADF;   /* hover/tekan; tinta 13,97:1 - redup 5,73:1 */

  /* Teks */
  --tinta:        #2A1B10;   /* 15,47:1 di atas --latar, teks utama, ukuran apa pun */
  --redup:        #6B5747;   /* 6,34:1 di atas --latar, teks sekunder, LULUS AA */

  /* Aksen, NADA-TENGAH, dan itu membalik seluruh izin paket 07 */
  --aksen:        #C8842B;   /* 2,88:1 di atas latar dan 3,09:1 di atas kertas →
                                ISIAN SAJA. DILARANG jadi warna teks, garis
                                kendali, ikon fungsional, atau cincin fokus.
                                Teks DI ATAS aksen wajib TINTA (5,38:1);
                                putih di atasnya 3,09:1 dan GAGAL WCAG AA. */
  --aksen-tekan:  #B77826;   /* keadaan ditekan; tinta di atasnya 4,54:1, masih
                                lulus AA, dan itu syaratnya boleh dipakai */
  --aksen-alas:   #F6E9D4;   /* alas lembut; tinta 13,88:1 - redup 5,69:1 -
                                aksen-gelap 3,73:1 (ikon di kotak lembut) */
  --nonaktif:     #E8DFD2;   /* alas kendali mati; redup di atasnya 5,17:1 */

  /* Garis */
  --garis:        #E7DCCB;   /* 1,26:1, DEKORATIF saja (garis rambut pemisah,
                                border kartu, sesuai DESIGN.md). DILARANG untuk
                                border kendali: 1,26 jauh di bawah lantai 3:1. */
  --garis-kendali:#A66A1E;   /* 4,15:1 di atas latar dan 4,47:1 di atas kertas, border input, checkbox, tombol outline, garis
                                bawah item aktif, ikon fungsional, DAN cincin
                                fokus. TETAP BUKAN warna teks isi (4,15 < 4,5). */

  /* Pita katering berlatar tinta, jalur audiens kedua (W10) */
  --band:         #2A1B10;   /* latar pita gelap */
  --band-teks:    #FBF6EF;   /* 15,47:1 di atas --band */
  --band-redup:   #D9CBBA;   /* 10,46:1 di atas --band, dan HANYA ini yang boleh
                                jadi teks sekunder di sana. --redup #6B5747 di
                                atas tinta cuma 2,43:1 dan haram di pita itu. */

  /* Semantik, dihitung terhadap --latar */
  --sukses:       #146B3A;   /* 6,11:1 */
  --galat:        #A32017;   /* 7,03:1, maknanya TIDAK PERNAH bersandar pada
                                warna: tiap pesan galat membawa ikon dan kata. */
  --peringatan:   #7A4B00;   /* 6,89:1 */
  --sukses-alas:  #E7F0E9;   /* tinta di atasnya 14,29:1 */
  --galat-alas:   #FAE7E3;   /* tinta di atasnya 13,94:1 */
  --peringatan-alas:#F6EDD9; /* tinta di atasnya 14,28:1 */

  /* Huruf. DUA keluarga (DESIGN.md): DM Serif Display 400 untuk judul dan angka
     besar, DM Sans 400/700 untuk isi dan kolom harga (angka tabular).
     ⚠️ DM Serif Display HANYA punya bobot 400 dan BUKAN huruf variabel (tidak ada
     tabel fvar), jadi tidak ada satu pun 700 untuknya di berkas ini. DM Sans
     justru variabel (fvar, sumbu wght 100–1000), jadi satu berkas woff2 melayani
     400 dan 700 sekaligus; itu benar, bukan salah salin.
     ⚠️ Diperiksa dengan fontTools pada woff2 di aset/huruf: U+2192 (→) TIDAK ADA
     di KEDUA huruf, padahal rentang latin-nya menyebut U+2191 dan U+2193.
     Kejadian KEEMPAT setelah U+2075 di situs 03 dan U+2192 di situs 06 dan 07.
     Karena itu panah di situs ini SELALU ikon SVG (#i-panah), tidak pernah
     karakter. Rantai cadangan --f-isi tetap diisi huruf sistem yang punya
     glifnya, kalau-kalau ada teks yang lolos. */
  --f-judul: "DM Serif Display", Georgia, "Times New Roman", serif;
  --f-isi:   "DM Sans", ui-sans-serif, "Segoe UI", system-ui, sans-serif;

  /* LANTAI UKURAN TEKS, jangan turun di bawah ini di mana pun. */
  --t-isi:   1rem;      /* 16px, teks isi */
  --t-kecil: 0.875rem;  /* 14px, sekunder */
  --t-label: 0.75rem;   /* 12px, label huruf besar, BATAS BAWAH */

  /* Ritme */
  --r1: .25rem; --r2: .5rem; --r3: .75rem; --r4: 1rem;
  --r5: 1.5rem; --r6: 2rem; --r7: 3rem; --r8: 4rem; --r9: 6rem;

  --radius: 10px;                   /* DESIGN.md: radius 10px, tanpa sudut tajam */
  --lebar-isi: 1240px;
  --tepi: 1.25rem;

  --bar-atas: 0px;
  --bar-bawah: calc(56px + env(safe-area-inset-bottom, 0px));
}

/* -----------------------------------------------------------------------------
   2. DASAR
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* Atribut `hidden` KALAH oleh `display` mana pun yang ditulis di CSS. Gejalanya
   mahal dan hanya terlihat setelah dirender: pesan galat formulir tampil sejak
   halaman dibuka karena .pesan menyetel display:flex. Satu aturan ini menutup
   seluruh kelasnya. */
[hidden] { display: none !important; }

html {
  /* Jangkar berhenti tepat di bawah bar, dan ini juga menyelamatkan elemen yang
     menerima fokus keyboard (teknik W3C C43 untuk WCAG 2.2 SC 2.4.11). */
  scroll-padding-top: calc(var(--bar-atas) + var(--r4));
  scroll-padding-bottom: calc(var(--bar-bawah) + var(--r4));
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--latar);
  color: var(--tinta);
  font-family: var(--f-isi);
  font-size: var(--t-isi);
  line-height: 1.6;
  /* Ruang untuk bar tab bawah di mobile supaya isi terakhir tidak tertutup. */
  padding-bottom: var(--bar-bawah);
}

/* DM Serif Display hanya punya SATU bobot, 400. Menulis 700 di sini membuat
   peramban menggambar tebal SINTETIS, tepinya kotor dan lebarnya melar, dan itu
   satu-satunya cacat huruf yang tidak terlihat di kode sama sekali. */
h1, h2, h3, h4 { font-family: var(--f-judul); font-weight: 400; line-height: 1.2; margin: 0; }
h1 { font-size: clamp(2.125rem, 5vw, 3.375rem); letter-spacing: -0.01em; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2.25rem); letter-spacing: -0.01em; }
h3 { font-size: clamp(1.125rem, 1.9vw, 1.375rem); }
p  { margin: 0; }
img { max-width: 100%; height: auto; display: block; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; }

/* Angka besar yang berdiri sebagai JUDUL (statistik pita katering, kode galat):
   DM Serif Display 400 dengan angka tabular. Angka yang DIBANDINGKAN lawan angka
   lain memakai .angka-harga di bawahnya, DESIGN.md menyebut DM Sans 700 tabular
   untuk harga dan angka, dan kolom rupiah 22 baris hanya sejajar dengan itu. */
.angka { font-family: var(--f-judul); font-weight: 400; font-variant-numeric: tabular-nums; }
/* Harga dan angka yang DIBANDINGKAN lawan angka lain (kolom rupiah menu, harga
   per porsi, tabel jam) memakai DM Sans 700 tabular, DESIGN.md meminta itu
   secara eksplisit supaya kolom rupiahnya sejajar. DM Serif Display dipakai untuk
   angka yang berdiri sendiri sebagai judul (statistik pita, kode galat). */
.angka-harga { font-family: var(--f-isi); font-weight: 700; font-variant-numeric: tabular-nums; }

/* CINCIN FOKUS, 2px #A66A1E dengan offset 2px, dan warnanya BUKAN --aksen.
   Aksen #C8842B cuma 2,88:1 di atas latar, di bawah lantai 3:1 untuk indikator
   fungsional: cincin fokusnya akan terlihat "ada" di mata orang yang melihatnya
   dari dekat dan hilang di layar laptop yang lebih terang. --garis-kendali
   #A66A1E 4,15:1 dan lulus. PROMPTS-STATE S1 dan S8 memang menyebut #A66A1E. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--garis-kendali);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Lewati ke konten, wajib ada, dan wajib terlihat saat difokus. */
.lewati {
  position: absolute; left: var(--tepi); top: -100px; z-index: 100;
  background: var(--tinta); color: var(--band-teks); padding: var(--r3) var(--r4);   /* 15,47:1 */
  border-radius: var(--radius); font-weight: 700; text-decoration: none;
}
.lewati:focus-visible { top: var(--r3); }

/* -----------------------------------------------------------------------------
   3. TATA LETAK
   -------------------------------------------------------------------------- */
.bungkus { width: 100%; max-width: var(--lebar-isi); margin-inline: auto; padding-inline: var(--tepi); }
.bagian { padding-block: var(--r7); }
.bagian + .bagian { border-top: 1px solid var(--garis); }
@media (min-width: 768px) { .bagian { padding-block: var(--r8); } }

.kepala-bagian { margin-bottom: var(--r5); max-width: 62ch; }
.kepala-bagian p { color: var(--redup); margin-top: var(--r2); }

.kisi { display: grid; gap: var(--r4); }
@media (min-width: 640px)  { .kisi-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px)  { .kisi-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
                             .kisi-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 640px) and (max-width: 899px) { .kisi-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Tiap anak kisi WAJIB boleh menyusut, kalau tidak isi yang lebar mendorong
   lebar halaman dan yang dilaporkan meluber justru elemen lain. */
.kisi > * { min-width: 0; }

/* -----------------------------------------------------------------------------
   4. PITA "DESAIN CONTOH", tidak bisa ditutup, wajib di tiap halaman
   -------------------------------------------------------------------------- */
.pita {
  background: var(--tinta); color: var(--band-teks);   /* 15,47:1 */
  font-size: 0.8125rem; text-align: center;
  padding: var(--r2) var(--tepi);
}

/* -----------------------------------------------------------------------------
   5. NAVBAR (desktop), di mobile digantikan bar tab bawah
   -------------------------------------------------------------------------- */
.navbar { border-bottom: 1px solid var(--garis); background: var(--latar); }
.navbar-isi { display: flex; align-items: center; gap: var(--r4); min-height: 64px; }
.wordmark {
  font-family: var(--f-judul); font-weight: 400; letter-spacing: .06em;
  font-size: 0.9375rem; text-decoration: none; white-space: nowrap;
}
.nav-tautan { display: none; gap: var(--r5); margin-inline: auto; }
.nav-tautan a { text-decoration: none; color: var(--redup); font-size: var(--t-kecil); }
.nav-tautan a:hover { color: var(--tinta); }
/* Item aktif TIDAK dibedakan warna saja, ada garis bawah tebal juga. */
.nav-tautan a[aria-current="page"] {
  color: var(--tinta); font-weight: 700;
  /* Garis bawah item aktif memakai #A66A1E (4,15:1), BUKAN --aksen (2,88:1).
     PROMPTS-STATE S8 butir 3 menuliskan alasannya persis begitu. */
  box-shadow: inset 0 -2px 0 0 var(--garis-kendali);
}
@media (min-width: 900px) { .nav-tautan { display: flex; } }
.navbar .tombol { margin-left: auto; }
@media (min-width: 900px) { .navbar .tombol { margin-left: 0; } }

/* -----------------------------------------------------------------------------
   6. TOMBOL, target sentuh minimal 48px, tombol utama 52px di mobile
   -------------------------------------------------------------------------- */
.tombol {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--r2);
  min-height: 48px; padding: var(--r3) var(--r5);
  font-family: var(--f-isi); font-size: var(--t-kecil); font-weight: 700;
  border-radius: var(--radius); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; background: none; color: var(--tinta);
  transition: background-color .15s ease, border-color .15s ease;
}
/* Isian aksen dengan teks TINTA: 5,38:1. Putih di atas aksen ini 3,09:1 dan
   gagal WCAG AA, kebalikan penuh situs 07. Tidak ada satu pun teks putih di
   atas #C8842B di berkas ini. */
.tombol-utama { background: var(--aksen); color: var(--tinta); }
.tombol-utama:hover { background: var(--aksen-tekan); }            /* tinta 4,54:1 */
.tombol-utama:active { background: var(--aksen-tekan); }
.tombol-kedua { border-color: var(--garis-kendali); color: var(--tinta); }  /* border 4,15:1 */
.tombol-kedua:hover { background: var(--sentuh); }
.tombol-blok { width: 100%; }
.tombol[disabled], .tombol[aria-disabled="true"] {
  background: var(--nonaktif); color: var(--redup); border-color: transparent;
  cursor: not-allowed;
}
.tombol-alasan { font-size: var(--t-kecil); color: var(--redup); margin-top: var(--r2); }

/* Keadaan memuat: tombol punya LABELNYA SENDIRI, bukan cuma spinner. */
.tombol[data-memuat="ya"] { pointer-events: none; }
.pemintal {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: putar .7s linear infinite; flex: none;
}
@keyframes putar { to { transform: rotate(360deg); } }

/* -----------------------------------------------------------------------------
   7. IKON, SVG sebaris, BUKAN emoji dan bukan font ikon.
   Brief menyebut Material Symbols; yang dipakai di sini SVG sebaris dengan bentuk
   yang sama maknanya. Alasannya bukan selera: font ikon berbasis ligatur
   menampilkan nama glyph sebagai teks mentah sebelum fontnya termuat, dan itu
   berarti kata "request_quote" sempat terbaca di layar pembeli.
   -------------------------------------------------------------------------- */
.ikon { width: 20px; height: 20px; flex: none; stroke: currentColor;
        fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.ikon-besar { width: 28px; height: 28px; }
.ikon-redup { color: var(--redup); }
/* .ikon-aksen di paket ini memakai --garis-kendali #A66A1E, BUKAN --aksen.
   Inilah tempat menyalin paling berbahaya di seluruh berkas: di situs 07 kelas
   ini berisi maroon 8,53:1 dan itu sah. Aksen #C8842B cuma 2,88:1 di atas latar,
   jadi ikon fungsional beraksen akan jatuh di bawah lantai 3:1 tanpa satu pun
   audit berbunyi. #A66A1E 4,15:1 di atas latar dan 3,73:1 di atas --aksen-alas, keduanya lulus, dan DESIGN.md memang menunjuk warna itu untuk ikon dan garis. */
.ikon-aksen { color: var(--garis-kendali); }

/* -----------------------------------------------------------------------------
   8. KARTU, border 1px, TANPA bayangan (DESIGN.md)
   -------------------------------------------------------------------------- */
.kartu {
  background: var(--kertas); border: 1px solid var(--garis);
  border-radius: var(--radius); padding: var(--r4);
}
.kartu h3 { margin-bottom: var(--r2); }
.kartu p { color: var(--redup); font-size: var(--t-kecil); }

.cip {
  display: inline-block; background: var(--aksen); color: var(--tinta);  /* 5,38:1 */
  font-size: var(--t-label); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; padding: 2px var(--r2); border-radius: 4px;
}
.cip-netral { background: var(--nonaktif); color: var(--tinta); }
/* Cip bergaris = cip area antar dan cip penyaring yang TIDAK terpilih. Bordernya
   --garis-kendali (4,15:1) dan TEKSNYA TINTA (15,47:1), bukan aksen, karena
   aksen sebagai warna teks cuma 2,88:1. Yang terpilih memakai .cip biasa: isian
   aksen dengan teks tinta. */
.cip-garis {
  /* inline-flex, BUKAN inline-block warisan .cip: cip bergaris hampir selalu
     membawa ikon, dan sebagai inline-block ikonnya duduk di garis dasar teks lalu
     terlihat seperti glyph yang rusak. Terlihat jelas di kisi cip layanan. */
  display: inline-flex; align-items: center; gap: var(--r2);
  background: var(--kertas); color: var(--tinta);        /* 16,63:1 */
  border: 1px solid var(--garis-kendali); text-transform: none; letter-spacing: 0;
  font-size: var(--t-kecil); padding: var(--r1) var(--r3);
}

.tautan-panah {
  display: inline-flex; align-items: center; gap: var(--r1);
  font-size: var(--t-kecil); font-weight: 700; text-decoration: none;
  /* TINTA dengan garis bawah, BUKAN aksen. Aksen sebagai warna teks di atas
     latar cuma 2,88:1, gagal bahkan untuk teks besar. Karena warnanya tidak
     lagi membedakan tautan ini dari teks biasa, garis bawahnya PERMANEN, bukan
     hanya saat hover: makna tidak boleh disampaikan lewat warna saja. */
  color: var(--tinta); text-decoration: underline; text-decoration-color: var(--garis-kendali);
  text-decoration-thickness: 2px; text-underline-offset: 3px;
}
.tautan-panah:hover { text-decoration-color: var(--tinta); }

/* -----------------------------------------------------------------------------
   9. HERO
   -------------------------------------------------------------------------- */
.hero { display: grid; gap: var(--r5); align-items: center; }
@media (min-width: 900px) { .hero { grid-template-columns: 1.05fr .95fr; gap: var(--r7); } }
.hero-mata { font-size: var(--t-kecil); font-weight: 700; color: var(--redup); letter-spacing: .06em; text-transform: uppercase; }
.hero h1 { margin-block: var(--r3); }
.hero-sub { color: var(--redup); font-size: 1.0625rem; max-width: 56ch; }
.hero-aksi { display: flex; flex-wrap: wrap; gap: var(--r3); margin-top: var(--r5); }
.hero-aksi .tombol { min-height: 52px; }      /* aksi utama di mobile 52px */
.hero-statistik { display: flex; flex-wrap: wrap; gap: var(--r5); margin-top: var(--r5);
                  padding-top: var(--r4); border-top: 1px solid var(--garis); }
.hero-statistik div { min-width: 0; }
.hero-statistik .angka { font-size: 1.25rem; display: block; }
/* :not(.angka) WAJIB. Tiap stat hero paket ini isinya SATU span berkelas
   .angka, jadi span itu sekaligus span:last-child, dan aturan ini (0,2,1)
   menang atas `.hero-statistik .angka` (0,2,0), sehingga angkanya mengecil ke
   14px dan berganti warna jadi --redup. Sama persis dengan cacat cip di pita
   katering, dan ditemukan dengan cara yang sama: melihat hasil rendernya. */
.hero-statistik span:last-child:not(.angka) { font-size: var(--t-kecil); color: var(--redup); }
.hero-foto { border-radius: var(--radius); border: 1px solid var(--garis); overflow: hidden; }
.hero-foto img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }

/* -----------------------------------------------------------------------------
   10. PITA KATERING BERLATAR TINTA, pemisah dua audiens (W10).
   BUKAN pita beraksen seperti situs 07. Halaman ini menjual pemisahan dua jalur,
   dan pemisah itu justru pita gelapnya: dari sini pembacanya orang lain.

   Terhitung untuk latar --band #2A1B10: teks #FBF6EF 15,47:1 dan teks sekunder
   #D9CBBA 10,46:1, keduanya lulus. --redup #6B5747 di atas tinta cuma 2,43:1 dan
   HARAM di sini, itu satu-satunya warna teks yang benar di section lain dan
   salah total di section ini, jadi ia disebut namanya supaya tidak ikut tersalin.

   EMPAT kolom, bukan enam: W10 mendiktekan empat angka, dan jumlah kolom pita
   ikut diperiksa tiap paket (lihat RESEP §5.4). Di bawah 900px ia turun ke dua.
   -------------------------------------------------------------------------- */
.pita-statistik { background: var(--band); color: var(--band-teks); padding-block: var(--r7); }
.pita-statistik .kisi { gap: var(--r5); grid-template-columns: repeat(2, minmax(0,1fr)); }
@media (min-width: 900px) { .pita-statistik .kisi { grid-template-columns: repeat(4, minmax(0,1fr)); } }
.pita-statistik .angka { font-size: clamp(1.5rem, 3vw, 2rem); display: block; }
/* Label memakai --band-redup SOLID, bukan putih beropasitas. "Sedikit lebih
   redup" adalah cara paling sering sebuah pita jatuh di bawah 4,5:1 tanpa ada
   yang menyadarinya, dan opasitas membuat angkanya tidak bisa dihitung dari
   token, jadi warnanya ditulis utuh dan rasionya ikut ditulis. */
/* DIPERSEMPIT KE .kisi, dan ini ditemukan dengan MELIHAT, bukan dengan membaca
   kode. Sebagai `.pita-statistik span:last-child` (0,2,1) aturan ini menang atas
   `.cip` (0,1,0), dan cip "Layanan katering" di pita ini memang satu-satunya
   span di dalam <p>-nya, jadi teksnya ikut jadi #D9CBBA di atas isian aksen
   #C8842B: 1,74:1. Kelas cacat yang persis sama dengan `.galat-halaman p`
   menang atas `.galat-kode`, dan ketiga audit sama-sama buta terhadapnya. */
.pita-statistik .kisi span:last-child { font-size: var(--t-kecil); color: var(--band-redup); }
.pita-statistik p { color: var(--band-teks); }
.pita-statistik .redup { color: var(--band-redup); }
/* Pita ini GELAP, jadi cincin fokus #A66A1E tidak cukup terlihat di atasnya
   (#A66A1E di atas tinta cuma 3,72:1). Di dalam pita, dan hanya di dalamnya,
   cincin fokus jadi #FBF6EF, 15,47:1. */
.pita-statistik :focus-visible { outline-color: var(--band-teks); }
/* Tombol outline DI ATAS pita gelap: border #D9CBBA (10,46:1) dan teks #FBF6EF.
   Tombol isian aksen di atas pita ini TETAP membawa teks tinta (5,38:1). */
.pita-statistik .tombol-kedua { border-color: var(--band-redup); color: var(--band-teks); }
.pita-statistik .tombol-kedua:hover { background: #3B2717; }

/* Pita kalimat beraksen, isian aksen, teks TINTA (5,38:1). */
.pita-aksen {
  background: var(--aksen); color: var(--tinta); border-radius: var(--radius);
  padding: var(--r5); font-size: 1.0625rem;
}

/* -----------------------------------------------------------------------------
   11. BARIS DAFTAR NATIVE, padanan mobile untuk tabel dan dropdown.
   Tinggi minimal 56px. Dipakai juga di desktop karena polanya memang terbaca.
   -------------------------------------------------------------------------- */
.daftar { border: 1px solid var(--garis); border-radius: var(--radius); background: var(--kertas); }
.baris {
  display: flex; align-items: center; gap: var(--r3);
  min-height: 56px; padding: var(--r3) var(--r4);
  border-bottom: 1px solid var(--garis);
}
.baris:last-child { border-bottom: 0; }
.baris-isi { min-width: 0; flex: 1; }
/* Keduanya WAJIB blok. Sebagai span inline, judul dan keterangannya menyambung
   jadi satu paragraf dan barisnya berhenti terbaca sebagai baris daftar native, terlihat jelas di 390px, tidak terlihat sama sekali dari kode. */
.baris-label { display: block; font-weight: 700; font-size: var(--t-kecil); }
.baris-nilai { display: block; font-size: var(--t-kecil); color: var(--redup); }
/* Baris dua kolom (label kiri, nilai kanan) tetap sebaris: di situ keterangannya
   pendek dan memang berpasangan, bukan judul-dan-penjelasan. */
.baris > .baris-nilai:first-child { display: inline; }
/* TANPA nowrap. Nilai panjang seperti "Monday to Friday 08.00 to 17.00, Saturday
   08.00 to 13.00, GMT+7" tidak bisa membungkus dan mendorong lebar halaman:
   terukur meluber 54px di 320px pada situs 02, dan yang dilaporkan meluber justru
   <main>, bukan span penyebabnya. */
.baris-kanan { margin-left: auto; font-weight: 700; font-size: var(--t-kecil);
               text-align: right; min-width: 0; overflow-wrap: anywhere; }
.baris-kanan.angka { font-weight: 700; }
a.baris { text-decoration: none; }
a.baris:hover { background: var(--sentuh); }

/* -----------------------------------------------------------------------------
   12. TABEL, GARIS MENDATAR SAJA, tinggi baris 48px (DESIGN.md).
   Di bawah 768px tabel lebar tetap bisa digulir mendatar di dalam kotaknya
   sendiri; halamannya TIDAK ikut bergeser.
   -------------------------------------------------------------------------- */
.tabel-bungkus { overflow-x: auto; border: 1px solid var(--garis); border-radius: var(--radius);
                 background: var(--kertas);
                 /* WAJIB. Lihat komentar panjang di atas: tanpa ini .hanya-layar-baca
                    di dalam tabel lolos dari pangkasan overflow dan menarik lebar
                    dokumen sampai 263px melewati layar 390px. */
                 position: relative; }
table { border-collapse: collapse; width: 100%; font-size: var(--t-kecil); }
th, td { text-align: left; padding: var(--r3) var(--r4); border-bottom: 1px solid var(--garis);
         height: 48px; }
th { font-weight: 700; background: var(--sentuh); white-space: nowrap; }  /* tinta 13,97:1 */
/* Angka lajur dua dan seterusnya dibandingkan lawan lajur → tabular. */
td:not(:first-child) { font-variant-numeric: tabular-nums; }
tr:last-child td { border-bottom: 0; }
/* Tabel jam buka tujuh hari (W3): kolom jam ditebalkan dan TABULAR supaya
   "07.00" di tujuh baris benar-benar sejajar. Baris HARI INI diberi alas lembut
   DAN cip berlabel "Hari ini", alasnya saja tidak cukup, karena keadaan tidak
   boleh disampaikan lewat warna saja. */
.tabel-jam td:nth-child(2) { font-weight: 700; font-variant-numeric: tabular-nums; }
.tabel-jam tr[data-hari-ini] { background: var(--aksen-alas); }   /* tinta 13,88:1 */
.tabel-jam tr[data-hari-ini] td:first-child { font-weight: 700; }
.tabel-jam .cip { margin-left: var(--r2); vertical-align: middle; }
caption { caption-side: top; text-align: left; padding: var(--r3) var(--r4);
          font-size: var(--t-kecil); color: var(--redup); }

/* -----------------------------------------------------------------------------
   13. CAROUSEL GESER, kartu berikutnya mengintip, ada titik indikator
   -------------------------------------------------------------------------- */
.carousel {
  display: grid; grid-auto-flow: column; grid-auto-columns: min(78%, 320px);
  gap: var(--r4); overflow-x: auto; scroll-snap-type: x mandatory;
  padding-bottom: var(--r3); scrollbar-width: thin;
  /* Geser mendatar ditangkap carousel, gulir tegak halaman tetap jalan. */
  touch-action: pan-y;
}
.carousel > * { scroll-snap-align: start; }
@media (min-width: 900px) {
  .carousel { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0,1fr));
              overflow: visible; scroll-snap-type: none; }
}
.titik { display: flex; gap: var(--r2); justify-content: center; margin-top: var(--r3); }
.titik span { width: 6px; height: 6px; border-radius: 50%; background: var(--garis-kendali); opacity: .35; }
.titik span[data-aktif="ya"] { opacity: 1; width: 18px; border-radius: 3px; }
@media (min-width: 900px) { .titik { display: none; } }

/* -----------------------------------------------------------------------------
   15. AKORDEON FAQ, <details> asli, jadi tetap bisa dibuka tanpa JavaScript
   -------------------------------------------------------------------------- */
.faq { border: 1px solid var(--garis); border-radius: var(--radius); background: var(--kertas); }
.faq details { border-bottom: 1px solid var(--garis); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  display: flex; align-items: center; gap: var(--r3); cursor: pointer;
  min-height: 56px; padding: var(--r3) var(--r4);
  font-weight: 700; font-size: var(--t-kecil); list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary .ikon { margin-left: auto; transition: transform .2s ease; }
.faq details[open] summary .ikon { transform: rotate(180deg); }
.faq .jawab { padding: 0 var(--r4) var(--r4); color: var(--redup); font-size: var(--t-kecil); }

/* -----------------------------------------------------------------------------
   16. FORMULIR, border kendali WAJIB --garis-kendali (5,92:1), bukan --garis (1,21:1)
   -------------------------------------------------------------------------- */
.bidang { display: block; margin-bottom: var(--r4); }
.bidang > label, .label { display: block; font-size: var(--t-kecil); font-weight: 700; margin-bottom: var(--r2); }
.kolom {
  width: 100%; min-height: 48px; padding: var(--r3);
  /* 16px WAJIB: di bawah itu Safari iOS ikut memperbesar layar saat kolom difokus. */
  font-size: var(--t-isi); font-family: var(--f-isi); color: var(--tinta);
  background: var(--kertas); border: 1px solid var(--garis-kendali);
  border-radius: var(--radius);
}
/* Placeholder #7A6555: 5,50:1 di atas kertas putih. Placeholder tetap teks. */
.kolom::placeholder { color: #7A6555; }
textarea.kolom { min-height: 120px; resize: vertical; }
.bantuan { font-size: var(--t-kecil); color: var(--redup); margin-top: var(--r2); }
.bantuan-galat { color: var(--galat); font-weight: 700; }      /* 6,05:1 */
.bantuan-sukses { color: var(--sukses); font-weight: 700; }    /* 6,06:1 */
.kolom[aria-invalid="true"] { border-color: var(--galat); border-width: 2px; }
.kolom[disabled] { background: var(--nonaktif); color: var(--redup); cursor: not-allowed; }

/* Radio sebaris (W14: tiga pilihan dalam satu baris), target sentuh 48px penuh,
   dan yang terpilih ditandai border DAN alas, bukan warna titik saja. */
.pilihan { display: grid; gap: var(--r2); }
@media (min-width: 640px) { .pilihan { grid-auto-flow: column; grid-auto-columns: 1fr; } }
.pilihan label {
  display: flex; align-items: center; gap: var(--r2); min-height: 48px;
  padding: var(--r2) var(--r3); border: 1px solid var(--garis-kendali);
  border-radius: var(--radius); background: var(--kertas);
  font-size: var(--t-kecil); cursor: pointer;
}
/* accent-color menggambar isian kendali DAN centangnya PUTIH, dan itu justru
   alasan kendalinya TIDAK boleh beraksen di sini: putih di atas #C8842B cuma
   3,09:1, jadi centangnya nyaris hilang di dalam isiannya sendiri. Dipakai
   --garis-kendali #A66A1E, tempat putih mencapai 4,47:1. */
.pilihan input { width: 20px; height: 20px; accent-color: var(--garis-kendali); flex: none; }
/* Yang terpilih ditandai border tebal DAN alas lembut, bukan warna titik saja. */
.pilihan label:has(input:checked) { border-color: var(--garis-kendali); border-width: 2px; background: var(--aksen-alas); }

/* Segmented control, padanan mobile untuk radio 2 sampai 3 opsi */
.segmen { display: flex; border: 1px solid var(--garis-kendali); border-radius: var(--radius); overflow: hidden; }
.segmen button {
  flex: 1; min-height: 48px; border: 0; background: var(--kertas); cursor: pointer;
  font-family: var(--f-isi); font-size: var(--t-kecil); font-weight: 700; color: var(--tinta);
}
.segmen button + button { border-left: 1px solid var(--garis-kendali); }
.segmen button[aria-pressed="true"] { background: var(--aksen); color: var(--tinta); }   /* 5,38:1 */

/* -----------------------------------------------------------------------------
   17. PESAN DALAM HALAMAN, supaya implementasi tidak jatuh ke alert() peramban.
   Tidak pernah membawa makna lewat warna saja: selalu ada ikon dan kata.
   -------------------------------------------------------------------------- */
.pesan {
  display: flex; gap: var(--r3); align-items: flex-start;
  padding: var(--r3) var(--r4); border-radius: var(--radius);
  border-left: 4px solid; font-size: var(--t-kecil);
}
.pesan-galat { background: var(--galat-alas); border-color: var(--galat); color: var(--tinta); }
.pesan-peringatan { background: var(--peringatan-alas); border-color: var(--peringatan); color: var(--tinta); }
.pesan-sukses { background: var(--sukses-alas); border-color: var(--sukses); color: var(--tinta); }
.pesan b { display: block; }

/* -----------------------------------------------------------------------------
   18. BAR TAB BAWAH (mobile), navigasi UTAMA di mobile, bukan hamburger
   -------------------------------------------------------------------------- */
.tab-bar {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 40;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: var(--kertas); border-top: 1px solid var(--garis);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.tab-bar a {
  display: grid; place-items: center; gap: 2px;
  min-height: 56px; padding: var(--r2) var(--r1);
  text-decoration: none; color: var(--redup); font-size: var(--t-label);
}
/* Tab aktif dibedakan warna DAN tebal DAN garis atas, bukan warna saja. Warnanya
   #A66A1E (4,15:1), bukan --aksen (2,88:1), PROMPTS-STATE S8 menuliskannya
   sebagai "tinted in #A66A1E" untuk tiga keadaan tab, dan alasannya kontras. */
.tab-bar a[aria-current="page"] { color: var(--garis-kendali); font-weight: 700; box-shadow: inset 0 3px 0 0 var(--garis-kendali); }
.tab-bar .ikon { width: 22px; height: 22px; }
@media (min-width: 900px) { .tab-bar { display: none; } body { padding-bottom: 0; } }

/* -----------------------------------------------------------------------------
   19. BOTTOM SHEET, padanan mobile untuk dropdown
   -------------------------------------------------------------------------- */
.lapis { position: fixed; inset: 0; z-index: 50; background: rgba(42,27,16,.66); display: grid; align-items: end; }
.lapis[hidden] { display: none; }
.sheet {
  background: var(--kertas); border-radius: 12px 12px 0 0;
  padding-bottom: env(safe-area-inset-bottom, 0px); max-height: 80vh; overflow-y: auto;
}
.sheet-pegangan { width: 36px; height: 4px; background: var(--garis-kendali); opacity: .5;
                  border-radius: 2px; margin: var(--r3) auto; }
.sheet-kepala { display: flex; align-items: center; gap: var(--r3); padding: 0 var(--r4) var(--r3);
                border-bottom: 1px solid var(--garis); }
.sheet-kepala h3 { font-size: 1rem; }
.sheet-tutup { margin-left: auto; min-width: 48px; min-height: 48px; display: grid; place-items: center;
               background: none; border: 0; cursor: pointer; color: var(--tinta); }
@media (min-width: 900px) {
  .lapis { align-items: center; justify-items: center; }
  .sheet { border-radius: var(--radius); max-width: 480px; width: 100%; }
}

/* Lightbox foto */
.lightbox img { width: 100%; max-height: 80vh; object-fit: contain; background: #000; }

/* -----------------------------------------------------------------------------
   20. SKELETON MEMUAT, bukan spinner, supaya bentuk halaman sudah terbaca
   -------------------------------------------------------------------------- */
.tulang { background: var(--nonaktif); border-radius: var(--radius); position: relative; overflow: hidden; }
.tulang::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.65), transparent);
  animation: kilau 1.4s ease-in-out infinite;
}
@keyframes kilau { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
.tulang-baris { height: 14px; margin-bottom: var(--r2); }
.tulang-judul { height: 28px; width: 60%; margin-bottom: var(--r3); }
.tulang-foto { aspect-ratio: 4 / 3; }

/* -----------------------------------------------------------------------------
   21. HALAMAN GALAT
   DITUKAR LAGI, KETUJUH KALINYA. Bentuknya tetap BLOK beraksen, tetapi angkanya
   kembali TINTA: tinta di atas #C8842B 5,38:1, sementara putih di atasnya cuma
   3,09:1 dan gagal AA. Persis kebalikan situs 07.

   :not(.galat-kode) WAJIB, dan angkanya DIHITUNG bukan dibaca. Di situs 02–06
   aturan `.galat-halaman p { color: var(--redup); }` ditulis SESUDAH .galat-kode
   dan spesifisitasnya lebih tinggi (0,1,1 lawan 0,1,0), jadi angka 404/500
   diam-diam mewarisi --redup. Untuk paket ini angkanya: --redup #6B5747 di atas
   isian aksen #C8842B = 2,21:1, di bawah bahkan ambang teks besar 3:1, pada
   elemen setinggi 6rem yang justru paling dilihat orang. Ketiga audit buta
   terhadapnya.
   -------------------------------------------------------------------------- */
.galat-kode { font-family: var(--f-judul); font-weight: 400; font-size: clamp(3rem, 12vw, 6rem);
              line-height: 1.1; display: inline-block; padding-inline: var(--r4);
              border-radius: var(--radius);
              background: var(--aksen); color: var(--tinta); }          /* 5,38:1 */
.galat-halaman p:not(.galat-kode) { color: var(--redup); }   /* :not() WAJIB: tanpa itu
                                                                angka galat jadi 2,21:1 */
.galat-aksi { display: flex; flex-wrap: wrap; gap: var(--r3); justify-content: center; }

/* Anak yang dipusatkan lewat place-items:center TIDAK melar: lebarnya lahir dari
   isinya sendiri, jadi satu paragraf panjang bisa melewati viewport, terukur
   10px di 320px pada situs 02, dan yang dilaporkan meluber cuma "p" tanpa kelas,
   mustahil ditebak dari kode. max-width:100% saja TIDAK menutupnya; grid-nya yang
   dicabut. Halaman galat di sini karena itu blok sejak awal, bukan grid. */
.galat-halaman { display: block; text-align: center; padding-block: var(--r9);
                 max-width: 56ch; margin-inline: auto; }
.galat-halaman > * + * { margin-top: var(--r4); }
.galat-halaman > * { max-width: 100%; }

/* -----------------------------------------------------------------------------
   22. FOOTER
   -------------------------------------------------------------------------- */
.footer { background: var(--band); color: var(--band-teks); padding-block: var(--r7); margin-top: var(--r7); }
.footer a { color: var(--band-redup); text-decoration: none; font-size: var(--t-kecil); }  /* 10,46:1 di atas --band */
.footer a:hover { color: var(--band-teks); text-decoration: underline; }
.footer h4 { font-size: var(--t-label); letter-spacing: .08em; text-transform: uppercase; margin-bottom: var(--r3); }
.footer li { margin-bottom: var(--r2); }
.footer-atas { display: grid; gap: var(--r5); }
@media (min-width: 768px) { .footer-atas { grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--r6); } }
.footer-tentang { color: var(--band-redup); font-size: var(--t-kecil); margin-top: var(--r3); max-width: 40ch; }
.footer-bawah {
  margin-top: var(--r6); padding-top: var(--r4); border-top: 1px solid #4A3626;
  display: flex; flex-wrap: wrap; gap: var(--r3); justify-content: space-between;
  font-size: var(--t-kecil); color: var(--band-redup);
}
/* #A66A1E di atas tinta cuma 3,72:1, di footer gelap cincin fokusnya jadi
   #FBF6EF (15,47:1), seperti di pita katering. */
.footer :focus-visible { outline-color: var(--band-teks); }

/* -----------------------------------------------------------------------------
   23. UTILITAS
   -------------------------------------------------------------------------- */
.hanya-layar-baca {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.tumpuk-2 { display: grid; gap: var(--r2); }
.tumpuk-3 { display: grid; gap: var(--r3); }
.tumpuk-4 { display: grid; gap: var(--r4); }
.redup { color: var(--redup); }
.kecil { font-size: var(--t-kecil); }
@media (min-width: 900px) { .hanya-mobile { display: none !important; } }
@media (max-width: 899px) { .hanya-desktop { display: none !important; } }

/* -----------------------------------------------------------------------------
   24. GERAK DIKURANGI, hormati preferensi sistem
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  .tulang::after { animation: none; }
}

/* -----------------------------------------------------------------------------
   25. FOTO DAN PENGGANTI FOTO
   Run paket ini menghasilkan 14 foto, dan TIGA di antaranya memuat nama usaha
   LAIN yang benar-benar ada, tidak satu pun terbaca dari nama berkasnya:
     - interior kafe: papan "KEDAI KOPI DJOGJA" dua kali → dipotong 150px dari atas
     - antrean pintu masuk: papan gantung dan papan tulis "KOPI LOKAL" → dipotong
     - prasmanan kantor: serbet bertulisan "brand" dan seragam berlogo katering
       lain → dipotong sampai keduanya keluar bingkai
   Yang DIBIARKAN dengan sengaja: merek mesin espreso di meja barista, karena
   kafe memang membeli mesin bermerek, ujinya "apakah usaha kita masuk akal
   MEMILIKI benda itu", dan papan nama kafe lain jelas tidak lolos uji itu.
   Wordmark "KOPI TEPI ALUN" pada kemasan katering justru wordmark fiktif milik
   situs ini sendiri, jadi ia memang boleh tampil.

   Run ini TIDAK menghasilkan satu pun potret kepala-dan-bahu, jadi tidak ada
   satu pun wajah yang dipajang sebagai "orang kami"; sidik jari perseptual atas
   ke-14 foto tidak menemukan satu pasang pun berjarak Hamming di bawah 30, jadi
   tidak ada foto kembar yang dipakai dua kali dengan keterangan berbeda.
   -------------------------------------------------------------------------- */
.gambar-lebar, .foto-kosong {
  aspect-ratio: 4 / 3; width: 100%; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--garis); background: var(--nonaktif);
}
.foto-kosong {
  display: grid; place-content: center; justify-items: center; gap: var(--r2);
  color: var(--redup);                                  /* 5,05:1 di atas --nonaktif */
  background-color: var(--nonaktif);
  background-image: linear-gradient(var(--garis) 1px, transparent 1px),
                    linear-gradient(90deg, var(--garis) 1px, transparent 1px);
  background-size: 16px 16px;
}
.foto-kosong span {
  font-family: var(--f-isi); font-weight: 700; font-size: var(--t-label);
  letter-spacing: .08em; background: var(--kertas); padding: 2px var(--r2);
  border-radius: 4px; border: 1px solid var(--garis); text-align: center;
}

.potret {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--garis); margin-bottom: var(--r3);
}
.potret-inisial {
  /* Inisial bertinta di atas alas cokelat lembut: 13,88:1. Alasnya --aksen-alas,
     BUKAN --aksen, di atas aksen penuh inisialnya masih terbaca (5,38:1) tapi
     kotak oranye penuh mendominasi kisi kartu dan berhenti terbaca sebagai
     pengganti foto. */
  display: grid; place-items: center; background: var(--aksen-alas); color: var(--tinta);
  font-family: var(--f-judul); font-weight: 400; font-size: 1.75rem; letter-spacing: .04em;
  aspect-ratio: 1 / 1; border: 1px solid var(--garis); border-radius: var(--radius);
  margin-bottom: var(--r3);
}

/* Tombol pembungkus foto yang bisa diperbesar, tetap terlihat sebagai gambar */
.foto-tombol { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.foto-tombol img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
                   border-radius: var(--radius); border: 1px solid var(--garis); }

/* Pengganti peta, tidak memuat peta pihak ketiga, jadi tidak ada pelacak. */
.peta {
  display: grid; place-content: center; justify-items: center; gap: var(--r3);
  aspect-ratio: 4 / 3; border-radius: var(--radius); border: 1px solid var(--garis);
  color: var(--redup); text-align: center; padding: var(--r4);
  background-color: var(--nonaktif);
  background-image: linear-gradient(var(--garis) 1px, transparent 1px),
                    linear-gradient(90deg, var(--garis) 1px, transparent 1px);
  background-size: 24px 24px;
}
.peta span { font-size: var(--t-kecil); max-width: 28ch; }

/* Dua kolom di layar lebar, satu kolom di mobile. */
@media (min-width: 900px) {
  [data-dua-kolom] { grid-template-columns: 1fr 1fr; align-items: start; }
  /* Menu: kolom kiri daftar harga, kolom kanan catatan dan kartu ajakan (W4).
     align-items:start WAJIB, tanpa itu kartu catatan yang isinya satu paragraf
     ikut melar setinggi daftar 22 baris harga. */
  .menu-tata { grid-template-columns: 1.6fr 1fr; gap: var(--r6) !important; align-items: start; }
  /* Reservasi: formulir di kiri, kartu keterangan di kanan (W9). */
  .reservasi-tata { grid-template-columns: 1.5fr 1fr; gap: var(--r6) !important; align-items: start; }
  /* Jam buka: tabel tujuh hari di kiri, empat kartu kapasitas di kanan (W3). */
  .jam-tata { grid-template-columns: 1.15fr 1fr; gap: var(--r6) !important; align-items: start; }
}

/* -----------------------------------------------------------------------------
   26. PENCARI, dipakai di halaman menu sebagai penyaring kelompok menu
   -------------------------------------------------------------------------- */
.pencari { display: grid; gap: var(--r3); align-items: end; margin-bottom: var(--r6); }
@media (min-width: 900px) { .pencari { grid-template-columns: repeat(3, minmax(0,1fr)) auto; } }
.pencari .bidang { margin: 0; }
.pencari .tombol { min-height: 48px; }

/* -----------------------------------------------------------------------------
   27. RAPI-RAPI DI BAWAH 900px, semuanya hanya terlihat setelah dirender
   -------------------------------------------------------------------------- */
@media (max-width: 899px) {
  /* Tombol navbar membungkus jadi dua baris dan mendesak wordmark sampai nyaris
     tak terbaca. Di mobile aksi ini juga sudah ada di bar tab bawah, jadi di sini
     ia cukup ringkas: tanpa ikon, tanpa membungkus, padding lebih rapat. */
  .navbar .tombol { padding-inline: var(--r3); white-space: nowrap; font-size: var(--t-label); }
  .navbar .tombol .ikon { display: none; }
  .wordmark { font-size: 0.75rem; letter-spacing: .04em; }

  /* Aksi utama melebar penuh supaya lebarnya seragam dan mudah dijangkau jempol. */
  .hero-aksi { flex-direction: column; align-items: stretch; }
  .hero-aksi .tombol { width: 100%; }
}

/* -----------------------------------------------------------------------------
   28. PONSEL SEMPIT (≤ 380px), iPhone SE dan Android kecil
   Label tab turun ke 11px dan padding dirapatkan. Wordmark paket ini panjang
   ("KOPI TEPI ALUN") dan navbarnya membawa DUA tombol karena situs ini melayani
   dua audiens, jadi ketiganya ikut mengecil.
   -------------------------------------------------------------------------- */
@media (max-width: 380px) {
  :root { --tepi: 1rem; }
  .tab-bar a { font-size: 0.6875rem; padding-inline: 2px; min-width: 0; }
  .tab-bar a > :last-child { max-width: 100%; overflow-wrap: anywhere; text-align: center; line-height: 1.15; }
  .tab-bar .ikon { width: 20px; height: 20px; }
  .wordmark { font-size: 0.625rem; }

  /* TERUKUR, bukan ditaksir: di 320px wordmark panjang plus tombol berlabel panjang
     yang TIDAK boleh membungkus mendorong lebar halaman. Label tombol didiktekan
     brief dan diuji verbatim, jadi yang dicabut nowrap-nya. Diwarisi dari situs 03,
     04, 06, dan 07; wordmark paket ini "KOPI TEPI ALUN" dan navbarnya membawa
     DUA tombol sekaligus, "Reservasi Meja" dan "Pesan Katering". */
  .navbar .tombol { white-space: normal; text-align: center; line-height: 1.2;
                    padding-inline: var(--r2); }
}

/* Tombol sunting di baris ringkasan wizard */
.sunting {
  margin-left: auto; min-width: 44px; min-height: 44px;
  display: grid; place-items: center; background: none;
  border: 1px solid var(--garis); border-radius: var(--radius); cursor: pointer;
}
.sunting:hover { background: var(--sentuh); }

/* -----------------------------------------------------------------------------
   29. TABEL BERKOLOM RUPIAH, kolom rupiah rata KANAN dan tabular
   -------------------------------------------------------------------------- */
.tabel-biaya td:last-child, .tabel-biaya th:last-child { text-align: right; }
.tabel-biaya td:last-child { font-weight: 700; font-variant-numeric: tabular-nums; }

/* -----------------------------------------------------------------------------
   30. KOTAK IKON, bingkai lembut untuk ikon kartu penyortir dan kartu paket.
   Alasnya --aksen-alas dan ikonnya --garis-kendali #A66A1E: 3,73:1, di atas
   lantai 3:1 untuk ikon fungsional. Kalau ikonnya diberi --aksen #C8842B ia
   jatuh ke 1,49:1 di atas alas lembut itu, nyaris tak terlihat, dan tidak ada
   audit yang berbunyi.
   -------------------------------------------------------------------------- */
.ikon-kotak {
  width: 44px; height: 44px; flex: none; display: grid; place-items: center;
  border-radius: var(--radius); background: var(--aksen-alas); color: var(--garis-kendali);
  margin-bottom: var(--r3);
}

/* -----------------------------------------------------------------------------
   31. BARIS INFO BERIKON, dipakai untuk rambu, catatan tarif, dan syarat dokumen.
   Ikonnya --redup (5,92:1): barisnya sering panjang dan ikon di sini berfungsi
   sebagai penanda jenis, bukan sebagai aksi.
   -------------------------------------------------------------------------- */
.info-baris { display: flex; gap: var(--r3); align-items: flex-start;
              font-size: var(--t-kecil); color: var(--redup); }
.info-baris .ikon { margin-top: 2px; }
.info-baris b { color: var(--tinta); }

/* Rambu alergen dan rambu tenggat, muncul di beberapa tempat dan sengaja
   seragam. Garis kirinya PERINGATAN (6,89:1), bukan aksen: ia bukan promosi, ia
   batas. Di vertikal makanan batas itu wajib kelihatan, karena yang disebutkan
   apa adanya adalah wajan yang dipakai bergantian untuk beberapa menu. */
.rambu {
  display: flex; gap: var(--r3); align-items: flex-start;
  background: var(--peringatan-alas); border-left: 4px solid var(--peringatan);
  border-radius: var(--radius); padding: var(--r3) var(--r4);
  font-size: var(--t-kecil); color: var(--tinta);
}

/* Cip berbentuk KALIMAT (pil di hero, cip kategori artikel). Cip biasa memakai
   huruf besar semua dan itu benar untuk satu-dua kata; untuk satu kalimat penuh ia
   berhenti terbaca. Bentuknya sama, hurufnya tidak dipaksa. */
.cip-kalimat {
  display: inline-flex; align-items: center; gap: var(--r2);
  text-transform: none; letter-spacing: 0; font-size: var(--t-kecil);
  padding: var(--r2) var(--r4);
}

/* Lima kolom hanya di layar yang benar-benar cukup lebar. Di bawah itu ia turun ke
   tiga lalu dua, bukan memaksa lima kartu sempit yang judulnya patah tiap kata. */
/* Pil status hero berdiri sendiri di atas eyebrow. p{margin:0} membuat keduanya
   berdempetan sampai terbaca seperti satu blok, terlihat di 390px maupun 1440px,
   dan tidak terlihat sama sekali dari kode. */
.hero .cip { margin-bottom: var(--r3); }

/* Pesan "ini desain contoh" yang muncul sesudah tombol yang memang tidak punya
   tujuan nyata. Tersembunyi sampai ditekan, dan isinya ditulis JS. */
.pesan-contoh { margin-top: var(--r3); }

@media (min-width: 1100px) { .kisi-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 900px) and (max-width: 1099px) { .kisi-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 640px) and (max-width: 899px) { .kisi-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* -----------------------------------------------------------------------------
   33. KARTU BERKOLOM, satu kolom isian dengan tombol di sebelahnya (pencarian
   menu di halaman 404)
   -------------------------------------------------------------------------- */
.lacak-kartu { background: var(--kertas); border: 1px solid var(--garis);
               border-radius: var(--radius); padding: var(--r4); margin-top: var(--r5); }
.lacak-baris { display: grid; gap: var(--r3); }
@media (min-width: 560px) { .lacak-baris { grid-template-columns: 1fr auto; align-items: end; } }
.lacak-baris .bidang { margin: 0; }
.lacak-baris .tombol { min-height: 48px; }

/* -----------------------------------------------------------------------------
   34. UBIN AKSI, dua kartu penyortir audiens (W2) dan kisi cip area antar (W12).
   Lima kolom hanya di layar yang cukup lebar; di bawah itu turun ke tiga lalu
   dua, bukan lima ubin sempit yang labelnya patah tiap kata.
   -------------------------------------------------------------------------- */
@media (min-width: 1100px) { .kisi-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 900px) and (max-width: 1099px) { .kisi-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 560px) and (max-width: 899px) { .kisi-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
a.kartu { text-decoration: none; display: block; }
a.kartu:hover { background: var(--sentuh); }

/* -----------------------------------------------------------------------------
   37. UNGGAH BERKAS, dipakai di komponen.html sebagai contoh kendali unggah.
   Bordernya --garis-kendali (5,78:1), bukan --garis: ia area yang bisa diklik.
   -------------------------------------------------------------------------- */
.unggah {
  display: grid; place-items: center; gap: var(--r2); text-align: center;
  padding: var(--r6) var(--r4); border: 2px dashed var(--garis-kendali);
  border-radius: var(--radius); background: var(--kertas); cursor: pointer;
  font-size: var(--t-kecil); color: var(--redup);
}
.unggah:hover { background: var(--sentuh); }

/* -----------------------------------------------------------------------------
   38. PENANDA BERNOMOR, isian aksen dengan angka PUTIH di atasnya (9,21:1)
   -------------------------------------------------------------------------- */
/* Kolom bersatuan (jam, hari). Satuannya menempel di kolomnya, bukan jadi baris
   bantuan terpisah di bawah, di baris bantuan ia terbaca sebagai keterangan,
   bukan sebagai bagian dari angka yang sedang diketik. */
.kolom-satuan { display: flex; align-items: center; gap: var(--r2); }
.kolom-satuan .kolom { flex: 1; min-width: 0; }
.kolom-satuan span { font-weight: 700; white-space: nowrap; }

.pin { display: inline-grid; place-items: center; width: 28px; height: 28px; flex: none;
       border-radius: 50%; background: var(--aksen); color: var(--tinta);   /* 5,38:1 */
       font-family: var(--f-isi); font-weight: 700; font-size: var(--t-kecil); }

/* -----------------------------------------------------------------------------
   39. BARIS RINCIAN BIAYA, label kiri, angka kanan tabular
   -------------------------------------------------------------------------- */
.rincian { display: grid; gap: var(--r3); }
.rincian > div { display: flex; gap: var(--r3); align-items: baseline; font-size: var(--t-kecil); }
.rincian dt, .rincian .rincian-label { flex: 1; min-width: 0; }
.rincian dd, .rincian .rincian-nilai { margin: 0; font-variant-numeric: tabular-nums;
                                       font-weight: 700; white-space: nowrap; }
.rincian-total { border-top: 2px solid var(--tinta); padding-top: var(--r3); font-size: var(--t-isi) !important; }
/* Angka total memakai DM Sans 700 tabular, BUKAN --f-judul: total dibandingkan
   lawan baris di atasnya, dan DM Serif Display tidak punya angka tabular. */
.rincian-total .rincian-nilai { font-size: 1.25rem; font-family: var(--f-isi); }

/* -----------------------------------------------------------------------------
   42. KOLOM LENGKET, kartu ringkasan di sebelah formulir katering (W13).
   Hanya lengket di layar yang tingginya memang cukup; di mobile ia baris biasa.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .lengket { position: sticky; top: var(--r4); }
}

/* Remah jejak, "Katering / Paket per porsi" */
.jejak { font-size: var(--t-kecil); color: var(--redup); margin-bottom: var(--r2); }
.jejak a { color: var(--redup); }

/* Baris keterangan yang isinya dua tingkat (label + kalimat penuh): minimal 72px. */
.baris-tinggi { min-height: 72px; align-items: flex-start; }
.baris-tinggi .ikon { margin-top: 2px; }

/* -----------------------------------------------------------------------------
   44. KISI ENAM, pita statistik memakai aturannya sendiri; kelas ini untuk kisi
   kartu biasa yang berjumlah enam.
   -------------------------------------------------------------------------- */
@media (min-width: 640px)  { .kisi-6 { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1100px) { .kisi-6 { grid-template-columns: repeat(3, minmax(0,1fr)); } }

/* -----------------------------------------------------------------------------
   45. TOMBOL YANG TAMPIL SEBAGAI TAUTAN
   Aksi yang memang tidak punya tujuan di desain contoh (unduh menu PDF, buka
   peta) ditulis sebagai <button> dengan data-contoh, BUKAN <a href="#">:
   tautan ke "#" melompat ke puncak halaman tanpa penjelasan, dan pengunjung
   membacanya sebagai situs yang rusak.
   -------------------------------------------------------------------------- */
.tautan-tombol { appearance: none; background: none; border: 0; padding: 0; margin: 0;
                 font: inherit; color: inherit; cursor: pointer; text-align: left; }
.tautan-tombol.tautan-panah { color: var(--tinta); }
.footer .tautan-tombol { color: var(--band-redup); font-size: var(--t-kecil); }
.footer .tautan-tombol:hover { color: var(--band-teks); text-decoration: underline; }
/* Baris ketiga bar bawah footer: satu kalimat penuh, rata tengah di bawah dua
   baris pertama (W15). */
.footer-catatan { flex-basis: 100%; text-align: center; margin-top: var(--r3); }

/* Kartu paket adalah <a> atau <article> DI DALAM <li> kisi. Yang diregangkan grid
   cuma <li>-nya, jadi tanpa baris ini enam kotak dalam satu baris berakhir di
   tinggi yang berbeda-beda mengikuti panjang teksnya, terlihat jelas sesudah
   dirender, dan tidak terlihat sama sekali dari kode. */
.kisi > li > a.kartu, .kisi > li > .kartu { height: 100%; }

/* Potret inisial versi ringkas. Tidak dipakai di paket ini: run 13 tidak
   menghasilkan satu pun potret kepala-dan-bahu, jadi tidak ada satu pun wajah
   yang dipajang sebagai "orang kami". Kelasnya tetap ada karena etalase komponen
   memperlihatkannya sebagai pengganti foto orang yang sah. */
.potret-kecil { width: 88px; font-size: 1.375rem; }

/* Harga besar di kartu paket katering: DM Sans 700, angka TABULAR, kolom rupiah
   hanya sejajar kalau angkanya tabular (DESIGN.md). BUKAN --f-judul: DM Serif
   Display tidak punya angka tabular dan hanya punya bobot 400. */
.harga { font-family: var(--f-isi); font-weight: 700; font-size: 1.375rem;
         font-variant-numeric: tabular-nums; margin-block: var(--r3); }

/* -----------------------------------------------------------------------------
   47. BARIS HARGA MENU, nama kiri, titik-titik penuntun, harga kanan (DESIGN.md)
   Penuntunnya BUKAN karakter titik berulang: rentetan "." dibacakan pembaca layar
   satu per satu dan ikut tersalin saat orang menyalin menunya. Ia border-bottom
   bergaya dotted pada elemen lentur di antara nama dan harga, jadi ia murni
   gambar dan tidak pernah jadi teks.

   Harga memakai DM Sans 700 TABULAR (DESIGN.md), bukan huruf judul: hanya angka
   tabular yang membuat kolom rupiah 22 baris benar-benar sejajar.
   -------------------------------------------------------------------------- */
.harga-daftar { display: grid; }
.harga-baris {
  display: grid; grid-template-columns: minmax(0,1fr) auto;
  align-items: baseline; column-gap: var(--r2);
  padding-block: var(--r3); border-bottom: 1px solid var(--garis);
}
.harga-baris:last-child { border-bottom: 0; }
.harga-nama { display: flex; align-items: baseline; gap: var(--r2); min-width: 0; }
.harga-nama b { font-weight: 700; }
/* Penuntun titik. flex:1 dengan min-width:0 supaya ia MENYUSUT lebih dulu dan
   tidak pernah ikut mendorong lebar halaman di 320px. */
.harga-titik { flex: 1 1 0; min-width: 0; border-bottom: 1px dotted var(--garis-kendali);
               transform: translateY(-4px); }
@media (max-width: 480px) { .harga-titik { display: none; } }
.harga-nilai { font-family: var(--f-isi); font-weight: 700; font-variant-numeric: tabular-nums;
               white-space: nowrap; }
.harga-ket { grid-column: 1 / -1; font-size: var(--t-kecil); color: var(--redup);
             margin-top: var(--r1); }
/* Baris bantuan yang berdiri SESUDAH .bidang mewarisi jarak yang salah: .bidang
   sudah membawa margin-bawah 1rem, jadi bantuannya terlempar dan menempel ke
   label kolom BERIKUTNYA, terbaca sebagai keterangan kolom yang salah. Terlihat
   jelas di formulir katering ("paling cepat 3 hari dari hari ini" menempel ke
   "Jam makanan harus sampai"), dan tidak terlihat sama sekali dari kode. */
.bidang + .bantuan { margin-top: calc(-1 * var(--r3)); margin-bottom: var(--r4); }
/* Baris bantuan KOSONG adalah wadah kalimat galat yang baru diisi JavaScript.
   Tanpa aturan ini ia tetap memakan satu baris jarak di tiap kolom, dan
   formulir sepuluh kolom berakhir renggang tak beraturan. */
.bantuan:empty { display: none; }

.menu-kelompok + .menu-kelompok { margin-top: var(--r6); }
.menu-kelompok h3 { display: flex; align-items: center; gap: var(--r2); margin-bottom: var(--r2); }

/* -----------------------------------------------------------------------------
   48. GALERI SUASANA, kisi masonry enam foto dengan bar keterangan (W8)
   Dibuat dengan CSS columns, bukan grid: tinggi fotonya memang berbeda-beda dan
   grid akan memaksa baris seragam lalu memotong sisi gambarnya.
   break-inside WAJIB, kalau tidak satu kartu terbelah antar-kolom.
   -------------------------------------------------------------------------- */
.galeri { columns: 1; column-gap: var(--r4); }
@media (min-width: 640px)  { .galeri { columns: 2; } }
@media (min-width: 1000px) { .galeri { columns: 3; } }
.galeri > li { break-inside: avoid; margin-bottom: var(--r4); }
.galeri figure { margin: 0; }
.galeri .foto-tombol img { aspect-ratio: auto; height: auto; }
.galeri figcaption { font-size: var(--t-kecil); color: var(--redup); padding-top: var(--r2); }

/* -----------------------------------------------------------------------------
   49. KARTU BIJI, sembilan biji single origin, tiga kali tiga (W6)
   Run Stitch paket ini TIDAK menghasilkan satu pun foto biji kopi, jadi kartunya
   memakai pita warna sangrai yang digambar CSS, bukan foto kopi milik orang lain
   dan bukan foto yang sama diulang sembilan kali. Tingkat sangrainya tetap
   dieja sebagai cip berteks, jadi maknanya tidak pernah hanya di warna.
   -------------------------------------------------------------------------- */
.biji-pita { height: 8px; border-radius: 999px; margin-bottom: var(--r3); }
.biji-pita[data-sangrai="terang"] { background: linear-gradient(90deg, #E4C48F, #C99A55); }
.biji-pita[data-sangrai="sedang"] { background: linear-gradient(90deg, #C08A46, #8A5A25); }
.biji-pita[data-sangrai="gelap"]  { background: linear-gradient(90deg, #7A4E22, #3E2814); }
.biji-kartu dl { display: grid; gap: var(--r1); margin: var(--r3) 0 0; font-size: var(--t-kecil); }
.biji-kartu dt { color: var(--redup); }
.biji-kartu dd { margin: 0; }
.biji-kaki { display: flex; align-items: center; justify-content: space-between;
             gap: var(--r3); flex-wrap: wrap; margin-top: var(--r4);
             padding-top: var(--r3); border-top: 1px solid var(--garis); }

/* -----------------------------------------------------------------------------
   50. KARTU PAKET KATERING, foto, nama, harga per porsi, isi paket (W11)
   -------------------------------------------------------------------------- */
.paket-foto { width: 100%; aspect-ratio: 3 / 2; object-fit: cover;
              border-radius: var(--radius) var(--radius) 0 0; display: block; }
.paket-kartu { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.paket-isi { padding: var(--r4); display: flex; flex-direction: column; flex: 1; }
.paket-minimum { font-size: var(--t-kecil); color: var(--redup); }
.paket-daftar { display: grid; gap: var(--r2); margin-top: var(--r4); font-size: var(--t-kecil); }
.paket-daftar li { display: flex; gap: var(--r2); align-items: flex-start; }
.paket-daftar .ikon { margin-top: 2px; }
.paket-kartu .tautan-panah { margin-top: var(--r4); align-self: flex-start; }

/* -----------------------------------------------------------------------------
   51. KARTU KETENTUAN, label kecil, nilai besar, satu kalimat penjelas (W12)
   -------------------------------------------------------------------------- */
.ketentuan-label { font-size: var(--t-label); letter-spacing: .08em; text-transform: uppercase;
                   color: var(--redup); }
.ketentuan-nilai { font-family: var(--f-isi); font-weight: 700; font-size: 1.375rem;
                   font-variant-numeric: tabular-nums; margin-block: var(--r2); }

/* -----------------------------------------------------------------------------
   52. KISI CIP AREA ANTAR, lima wilayah pengantaran (W12)
   -------------------------------------------------------------------------- */
.cip-baris { display: flex; flex-wrap: wrap; gap: var(--r2); margin-block: var(--r3); }

/* -----------------------------------------------------------------------------
   53. DUA JALUR, kartu penyortir audiens (W2). Dua kartu selebar sama, dengan
   tombolnya menempel di DASAR kartu berapa pun panjang butirnya, supaya kedua
   tombol sejajar dan tidak ada satu jalur yang terlihat lebih penting.
   -------------------------------------------------------------------------- */
.jalur-kartu { display: flex; flex-direction: column; }
.jalur-kartu ul { display: grid; gap: var(--r3); margin-block: var(--r4); flex: 1; }
.jalur-kartu li { display: flex; gap: var(--r3); align-items: flex-start; font-size: var(--t-kecil); }
.jalur-kartu li .ikon { margin-top: 2px; }
.jalur-kartu .tombol { width: 100%; }

/* -----------------------------------------------------------------------------
   54. KARTU KAPASITAS DAN BARIS FAKTA, dipakai di jam buka, roastery, reservasi
   -------------------------------------------------------------------------- */
.fakta { display: grid; gap: var(--r4); margin-top: var(--r5); }
.fakta > li { display: flex; gap: var(--r3); align-items: flex-start; }
.fakta .ikon { margin-top: 2px; }
.fakta-label { display: block; font-size: var(--t-kecil); color: var(--redup); }
.fakta-nilai { display: block; font-weight: 700; }

/* Ringkasan kanan formulir katering: kartu lengket berisi lima baris label-nilai. */
.ringkas-baris { display: flex; gap: var(--r3); justify-content: space-between;
                 align-items: baseline; padding-block: var(--r3);
                 border-bottom: 1px solid var(--garis); font-size: var(--t-kecil); }
.ringkas-baris:last-of-type { border-bottom: 0; }
.ringkas-baris b { text-align: right; overflow-wrap: anywhere; }
