/* ============================================================
   ANAYA — KOMPONEN
   15 komponen berulang dari docs/01-design-system.md §5.
   Dibuat sekali di sini, dipakai di 7 halaman.
   ============================================================ */

/* ------------------------------------------------------------
   1. TOMBOL
   ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  /* Tinggi hasil = 16+16+16+2 = 50px. Dump Home menyebut 54px; token spacing
     terdekat dipilih daripada menyuntik angka lepas ke luar sistem. */
  padding: var(--sp-4) var(--sp-8);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: var(--fs-body-sm);
  /* Weight 400, bukan 500. Dicek ke SELURUH dump (9 halaman, 38 kemunculan
     tombol: Submit, Lihat Detail, Lihat Produk, Dapatkan Penawaran Gratis,
     Download Spesifikasi, Lihat Lebih, Tampilkan Lebih) — semuanya w400,
     tanpa kecuali. --fw-medium adalah karangan Fase 1. */
  font-weight: var(--fw-regular);
  line-height: 1;
  white-space: nowrap;
  transition: background-color var(--t-fast), color var(--t-fast),
              border-color var(--t-fast), transform var(--t-fast);
}

/* Dump lintas halaman konsisten: tombol utama TINGGI 54px dan tidak pernah
   menyusut mengikuti panjang teks — "Submit" (teks cuma 53px) tetap dibuat
   170px (Produk, Blog Detail) sampai 208px (Kontak), sama seperti tombol
   berteks panjang. Sebelumnya tinggi hasil padding cuma 50px dan lebarnya
   ikut teks (Submit jadi 124px, ~40% lebih sempit dari desain).
   .btn--ghost dikecualikan: dump-nya memang kecil (129x33). */
.btn:not(.btn--ghost) {
  min-width: 170px;
  min-height: 54px;
  justify-content: center;
}

.btn:active { transform: translateY(1px); }

.btn .icon {
  width: 18px;
  height: 18px;
  flex: none;
  transition: transform var(--t-fast);
}

.btn:hover .icon { transform: translateX(3px); }

/* Primer — pill biru, teks putih */
.btn--primary {
  background: var(--c-primary);
  color: var(--c-white);
}
.btn--primary:hover { background: var(--c-primary-dark); }

/* Ghost — outline biru, dipakai di kartu blog */
.btn--ghost {
  background: transparent;
  color: var(--c-primary);
  border-color: var(--c-primary);
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-meta);
}
.btn--ghost:hover {
  background: var(--c-primary);
  color: var(--c-white);
}

/* Kaca — tombol di atas foto hero. Biru 50% + blur, sesuai dump Home
   (rgba(28,117,188,.5), radius 30px). Border tipis menjaga tepinya terbaca
   di atas foto terang maupun gelap. */
.btn--glass {
  background: rgba(28, 117, 188, 0.5);
  color: var(--c-white);
  border: 1px solid rgba(255, 255, 255, 0.35);
  -webkit-backdrop-filter: blur(2px);
          backdrop-filter: blur(2px);
}

.btn--glass:hover { background: var(--c-primary); }

/* Putih — di atas latar biru (form Blog Detail) */
.btn--white {
  background: var(--c-white);
  color: var(--c-primary);
}
.btn--white:hover { background: var(--c-surface); }

.btn--block { width: 100%; justify-content: center; }

/* Chip FLEXITANK di navbar. Ukuran dari dump: kotak 118x34, teks 86x20 —
   padding 16px kiri/kanan. Nilai fs-meta (13px) + letter-spacing 0.04em di
   sini sebelumnya karangan Fase 1, meleset dari desain; dump 4 halaman
   (Home, Tentang, Blog, Kontak) sepakat 16px, tanpa tracking.

   TINGGI DIPATOK 34px. Sebelumnya cuma padding 8px yang ditulis, sementara
   line-height-nya terwarisi dari body (~1,7) — hasilnya 45px, 11px lebih
   tinggi dari SETIAP dump. Tidak pernah terlihat karena tinggi header
   ditentukan logo (55px), jadi pill yang kelewat tinggi tidak menggeser apa
   pun. `line-height: 20px` mengunci kotak teksnya ke angka dump.

   Kulitnya lewat custom property supaya varian di atas foto hero cukup
   mengganti NILAINYA, bukan menulis ulang deklarasi border/background/
   shadow-nya — tiga deklarasi yang cepat atau lambat lepas sinkron. */
.chip {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 var(--sp-4);
  border: 1px solid var(--chip-garis, transparent);
  border-radius: var(--r-pill);
  background: var(--chip-bg);
  box-shadow: var(--chip-shadow);
  color: var(--c-primary);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  line-height: 20px;
  transition: background-color 220ms var(--ease), border-color 220ms var(--ease),
              box-shadow 220ms var(--ease), color var(--t-fast);
}

/* Hover ditulis sebagai properti LANGSUNG, bukan lewat --chip-bg: varian
   hero di bawah punya spesifisitas jauh lebih tinggi (5 kelas), jadi kalau
   hover cuma mengganti variabelnya ia kalah dan pill di atas hero tidak
   pernah berubah saat disorot. */
.chip:hover {
  background: var(--c-primary);
  box-shadow: none;
  color: var(--c-white);
}

/* Tombol Bagikan */
.btn-share {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--c-primary);
  border-radius: var(--r-pill);
  color: var(--c-primary);
  font-size: var(--fs-meta);
  background: var(--c-white);
  transition: background-color var(--t-fast), color var(--t-fast);
}
.btn-share:hover { background: var(--c-primary); color: var(--c-white); }
.btn-share .icon { width: 14px; height: 14px; }

/* Menu pilihan kanal — cadangan untuk peramban tanpa Web Share API.
   Di HP hampir selalu tidak pernah terlihat: `navigator.share` menang dan
   memunculkan lembar bagikan bawaan sistem (lihat assets/js/share.js). */
.share { position: relative; display: inline-block; }

.share__menu {
  position: absolute;
  top: calc(100% + var(--sp-2));
  right: 0;
  z-index: var(--z-dropdown);
  min-width: 168px;
  padding: var(--sp-2);
  background: var(--c-white);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
}

/* Rata KIRI, bukan mengikuti perataan induknya. Tombol Bagikan di halaman
   produk duduk di dalam blok yang rata kanan; tanpa aturan ini isi menunya
   ikut rata kanan dan terbaca seperti daftar yang rusak. */
.share__item {
  display: block;
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--c-ink);
  font: inherit;
  font-size: var(--fs-body-sm);
  text-align: left;
  cursor: pointer;
}

.share__item:hover,
.share__item:focus-visible { background: var(--c-surface); color: var(--c-primary); }

/* Tanpa JavaScript tombolnya tidak melakukan apa pun — lebih baik
   disembunyikan daripada tampil sebagai kontrol mati. */
.anaya-no-js .share { display: none; }

/* ------------------------------------------------------------
   2. KARTU BLOG
   ------------------------------------------------------------ */

.card-blog {
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  /* Dump Home (Rectangle 58-60): 388x438, radius 15px, TANPA box-shadow.
     Kartu arsip Blog (Rectangle 88) yang radius 20px + berbayang — itu
     varian --framed di bawah, bukan kartu dasar ini. */
  border-radius: var(--r-sm);
  overflow: hidden;
  box-shadow: none;
  transition: transform var(--t-fast), box-shadow var(--t-fast);
}

.card-blog:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover);
}

/* Gambar rata tepi kartu, bukan di dalam padding. Rasio 388x189 diambil
   langsung dari dump Home — lebih lebar dari 16/10 yang dipakai sebelumnya. */
.card-blog__media {
  aspect-ratio: 388 / 189;
  /* .card-blog itu flex column, dan flex item punya min-height: auto bawaan
     (bukan 0) — tinggi minimumnya ikut isi. <img> di dalamnya punya atribut
     684x492, jadi tingginya dipaksa 276px dan aspect-ratio di atas diabaikan
     (desain 189px). Sekelas dengan aturan #14 catatan proyek, tapi di flex, bukan
     grid. */
  min-height: 0;
}

.card-blog__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-blog__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--sp-3);
  padding: var(--sp-6);
}

.card-blog__title {
  font-size: var(--fs-card-title);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
}

.card-blog__excerpt {
  font-size: var(--fs-body-sm);
  color: var(--c-ink);
  /* Jaga tinggi kartu tetap seragam dalam satu baris grid. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Di lajur sempit (<=900px) kotak ringkasan menyusut ke 260-277px sementara
   hurufnya cuma turun 16->15px, sehingga teks yang muat 3 baris di 1440px
   butuh 4 baris di sini. Klem 3 baris akan memotongnya dan MENAMBAHKAN
   elipsisnya sendiri — elipsis yang tidak ada di desain dan tidak bisa
   dimatikan dari CSS.

   Ditambah satu baris, bukan teksnya yang dipendekkan: memendekkan teks
   demi lebar tersempit akan menyeret kartu DESKTOP ikut pendek, padahal di
   situlah desain menentukan panjangnya (19 kata / 123 karakter, dump Blog).
   Lebar 1024px sengaja TIDAK ikut: di sana grid turun ke 2 kolom sehingga
   kotaknya justru melebar ke 372px dan 3 baris sudah cukup. */
@media (max-width: 900px) {
  .card-blog__excerpt { -webkit-line-clamp: 4; }
}

.card-blog__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: auto;
  padding-top: var(--sp-2);
}

/* Varian berbingkai — dipakai di arsip Blog & "Artikel Lain" di Blog Detail.
   Di sini gambar TIDAK rata tepi kartu: dump memberi kartu 388x520 dengan
   gambar 342x246 di dalamnya (inset 23px, radius sendiri). Beda dari kartu
   ringkas Home/Tentang yang gambarnya rata tepi. */
.card-blog--framed .card-blog__media {
  aspect-ratio: 342 / 246;
  margin: var(--sp-6) var(--sp-6) 0;
  /* `width` WAJIB eksplisit, jangan diserahkan ke peregangan flex.
     Kotak ini anak dari `.card-blog` yang `flex-direction: column`, jadi
     lebarnya HASIL peregangan sumbu silang. Chromium meregangkannya dulu
     (384 - 24 - 24 = 336) baru menghitung tinggi dari aspect-ratio; WebKit
     menghitung tinggi dari lebar SEBELUM margin kiri-kanan dikurangi (384),
     sehingga kartunya 276px — 34px lebih tinggi dari desain, di SETIAP
     kartu arsip Blog & "Artikel Lain".
     Dibuktikan 2026-09-09: dengan margin kiri-kanan dinolkan, KEDUA mesin
     sama-sama memberi 384x276 — jadi 276 memang tinggi yang benar untuk
     lebar 384, dan yang berbeda cuma lebar mana yang dipakai. Dengan lebar
     ditulis eksplisit, dasarnya tidak lagi ambigu dan keduanya memberi
     336x242. Chromium tidak berubah sama sekali oleh baris ini. */
  width: calc(100% - var(--sp-6) * 2);
  border-radius: var(--r-md);
  overflow: hidden;
}

/* Dump (Rectangle 88/89/92/95/96/97, arsip Blog): shadow-nya sendiri,
   5px 2px 13px rgba(0,0,0,0.1) — beda dari --shadow-card generik
   (0 4px 20px rgba(0,0,0,0.08)) yang dipakai kartu ringkas Home. Aturan
   #18 catatan proyek sudah memperingatkan token shadow generik tidak selalu
   sama kuat per komponen — kartu arsip Blog ini belum pernah dikoreksi. */
.card-blog--framed {
  /* Dump Rectangle 88: radius 20px — beda dari kartu dasar (15px). */
  border-radius: var(--r-md);
  box-shadow: 5px 2px 13px rgba(0, 0, 0, 0.1);
}

/* ------------------------------------------------------------
   2b. ARTIKEL UNGGULAN (arsip Blog)
   Panel teks kaca buram menumpang tepi kanan foto — dump: foto
   723px, panel 537px, tumpang tindih ~46px (Rectangle 84 rgba putih
   0.49 di atas Rectangle 83). Didekati dengan backdrop-filter blur.
   ------------------------------------------------------------ */

.blog-featured {
  position: relative;
  /* Dump: 1200x464 di lebar penuh (1440) — tapi TIDAK dipasang sebagai
     aspect-ratio kaku. aspect-ratio menurunkan tinggi kotak mengikuti
     LEBAR container, sedangkan judul+paragraf+CTA di panel kanan
     tingginya tetap (font-size tidak ikut menyusut) — begitu lebar
     browser kurang dari ~1440 (laptop biasa, bukan cuma HP), tinggi
     hasil aspect-ratio jadi lebih pendek dari konten, dan overflow:hidden
     di bawah ini memotong judul & baris CTA (judul sampai numpang naik
     ke foto hero di atasnya). min-height cuma jaminan MINIMUM di lebar
     penuh; kalau konten butuh lebih tinggi, kotak ikut melar — tidak
     pernah kepotong. */
  min-height: 464px;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  display: flex;
  /* Dump: hero (Rectangle 1) tinggi 329px mulai dari top:152 -> bawah di
     481px. Kartu unggulan ini (Rectangle 83) mulai di top:382 — 99px
     SEBELUM hero berakhir, jadi menumpang naik ke atas foto hero, bukan
     berjarak normal di bawahnya. Section pembungkusnya dikasih
     padding-top:0 (lihat blog.html) supaya margin negatif ini genuinely
     jadi overlap, bukan cuma mengurangi jarak kosong. */
  margin-top: -99px;
}

.blog-featured__media { position: absolute; inset: 0; }

.blog-featured__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.blog-featured__body {
  position: relative;
  margin-left: auto;
  /* Dump (Rectangle 84): 537px, alpha 0.49 — bukan 0.75. Panel sempat
     ditulis terlalu opak, jadi tekstur foto di baliknya nyaris tidak
     kelihatan tembus padahal di desain jelas transparan (kabur, tapi
     corak fotonya masih terlihat). */
  width: min(44.75%, 537px);
  background: rgba(255, 255, 255, 0.49);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: var(--sp-10);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-4);
}

/* 30px/800 — sama dengan skala hero, konsisten di seluruh situs. */
.blog-featured__title {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
  line-height: var(--lh-snug);
}

.blog-featured__excerpt {
  font-size: var(--fs-body);
  color: var(--c-ink);
}

/* Di ≤768px susunan kaca-menyamping dilepas jadi wajar: foto di atas
   (rasio sendiri), teks di bawah dengan latar putih solid — bukan kaca
   lagi, karena tanpa foto di baliknya efek blur tidak ada gunanya.
   min-height:auto supaya tinggi kotak murni ikut konten yang sudah
   ditumpuk vertikal (foto + teks), tidak ketarik naik oleh min-height
   464px yang cuma relevan untuk susunan berdampingan di layar lebar. */
@media (max-width: 768px) {
  .blog-featured {
    min-height: auto;
    flex-direction: column;
  }

  .blog-featured__media {
    position: static;
    aspect-ratio: 723 / 464;
  }

  .blog-featured__body {
    width: 100%;
    background: var(--c-white);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* ------------------------------------------------------------
   2b. PAGINASI ARSIP BLOG
   Figma tidak menggambar komponen ini — desainnya berhenti di tombol
   "Tampilkan Lebih". Jadi bentuknya sengaja dipinjam dari komponen bulat
   yang SUDAH ada (.searchbar__btn: lingkaran, isi biru saat hover, mengecil
   saat ditekan) supaya tidak memperkenalkan bahasa visual baru.
   9 kartu per halaman — lihat docs/03-arsitektur-wordpress.md §3b.
   ------------------------------------------------------------ */

.pagination {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-10);
}

.pagination__item {
  display: grid;
  place-items: center;
  /* 44px, sama dengan .nav-toggle: ambang area sentuh yang nyaman di HP.
     Angka nomor halaman kecil-kecil justru paling rawan salah tekan. */
  width: 44px;
  height: 44px;
  border: 1px solid var(--c-border);
  border-radius: 50%;
  color: var(--c-ink);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-medium);
  line-height: 1;
  transition: background-color var(--t-fast), color var(--t-fast),
              border-color var(--t-fast);
}

.pagination__item:hover,
.pagination__item:focus-visible {
  border-color: var(--c-primary);
  color: var(--c-primary);
}

.pagination__item:active { scale: 0.9; }

.pagination__item.is-active {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--c-white);
  /* Halaman yang sedang dibuka bukan tautan — tidak perlu berubah saat
     disentuh, supaya tidak terkesan bisa diklik. */
  pointer-events: none;
}

/* Tombol maju/mundur di ujung. Di halaman pertama & terakhir salah satunya
   mati — ditulis sebagai <span>, bukan <a> nonaktif, supaya tidak bisa
   difokus keyboard sama sekali. */
.pagination__item--nav .icon { width: 18px; height: 18px; }

.pagination__item.is-disabled {
  border-color: var(--c-border);
  color: var(--c-border);
  pointer-events: none;
}

/* Pemisah "…" saat halaman terlalu banyak untuk ditulis semua. */
.pagination__gap {
  padding-inline: var(--sp-1);
  color: var(--c-ink-soft);
  user-select: none;
}

/* Di HP deretan lengkap (6 lingkaran 44px + gap 8px + "…") butuh 338px,
   sementara lebar kolom di 393px cuma 325px — tombol "berikutnya" jatuh
   sendirian ke baris kedua. Diperkecil ke 40px dengan gap 4px (total 286px)
   supaya tetap satu baris. 40px memang di bawah anjuran 44px, tapi itu lebih
   baik daripada alternatifnya: menyembunyikan "…" dan nomor halaman terakhir,
   yang membuat pengunjung HP tidak bisa melompat ke halaman terakhir. */
@media (max-width: 560px) {
  .pagination { gap: var(--sp-1); }
  .pagination__item { width: 40px; height: 40px; }
}

/* ------------------------------------------------------------
   3. KARTU KATEGORI PRODUK
   Hover & aktif sama-sama biru. Ikon ikut berubah warna lewat
   currentColor — inilah sebabnya ikon wajib SVG inline.
   ------------------------------------------------------------ */

.card-cat {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  min-height: 125px;
  /* Padding kiri besar (ikon menjorok ke dalam seperti desain), kanan kecil —
     dengan padding simetris label "Grade Industri / Teknis" pecah dua baris. */
  padding: var(--sp-5) var(--sp-6) var(--sp-5) var(--sp-16);
  /* 90% opacity (dump), bukan putih solid — beda tipis, tapi ikut nilai asli. */
  background: rgba(255, 255, 255, 0.9);
  border-radius: var(--r-md);
  /* Dump (Rectangle 49-53, Home & Produk sama-sama): 2px 5px 20.1px, opacity
     0.25 — jauh lebih kuat dari --shadow-card generik (0.08) yang sebelumnya
     dipakai di sini. Itu sebabnya kartu terlihat "flat"/tanpa highlight
     dibanding Figma, terutama saat menumpang foto hero yang ramai. */
  box-shadow: 2px 5px 20px rgba(0, 0, 0, 0.25);
  color: var(--c-ink);
  /* Dump Home: 18px/25. Sebelumnya --fs-body-sm (16px). Varian kotak di
     halaman Produk (.card-cat--stacked) memang menimpanya lagi ke 18px,
     jadi nilainya sekarang sama — override-nya dipertahankan supaya niatnya
     tetap terbaca kalau salah satu berubah nanti. */
  font-size: var(--fs-body);
  transition: background-color var(--t-fast), color var(--t-fast);
}

.card-cat .icon {
  width: 54px;
  height: 54px;
  flex: none;
  color: currentColor;
}

.card-cat:hover,
.card-cat.is-active {
  /* Dump Home Rectangle 49: 90% opacity, BUKAN biru solid — persis sepasang
     dengan kartu tidak aktif yang juga 90% (rgba(255,255,255,0.9) di atas).
     Sebelumnya var(--c-primary) solid, dengan komentar yang keliru menyebut
     dump-nya "biru solid". */
  background: var(--overlay-card-cat);
  color: var(--c-white);
  /* box-shadow-nya SAMA persis dengan kartu tidak aktif — dump tidak punya
     shadow terpisah yang lebih kuat untuk state hover/aktif. */
}

/* Pembungkus ikon kartu kategori. `display: contents` = tidak ada bagi tata
   letak, jadi kartu desktop & grid Home tidak berubah sedikit pun; ia baru
   menjadi kotak sungguhan di mobile halaman Produk (blok di akhir berkas).
   Aman untuk aksesibilitas: span hias tanpa makna, isinya aria-hidden. */
.card-cat__kotak { display: contents; }

/* Varian kotak (halaman Produk): ikon di tengah-atas, label di tengah-bawah,
   kartu persegi. Dump: 177x177, radius 20, gap antar-kartu ~26px, font 18px. */
.card-cat--stacked {
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: var(--sp-3);
  aspect-ratio: 1;
  min-height: 0;
  padding: var(--sp-5);
  text-align: center;
  font-size: var(--fs-body);
}

/* Baris kartu kategori kotak — satu baris, tidak melebar penuh container
   (dump: 989px dari 1200px container, disisakan margin di kedua sisi). */
.cat-row {
  display: flex;
  gap: var(--sp-6);
  max-width: 990px;
  margin-inline: auto;
}

.cat-row > * { flex: 1 1 0; }

/* Bungkus jadi 3 per baris mulai 1024px (bukan 900px): dengan 5 kartu
   sejajar, di 912px tiap kartu cuma ~133px dan label panjang seperti
   "Grade Industri / Teknis" meluber 12px keluar kartu. */
@media (max-width: 1024px) {
  /* flex-grow dimatikan (dari `flex: 1 1 0` bawaan): tanpa itu kartu yang
     sendirian di baris terakhir — 5 kategori di 2 kolom — melar jadi selebar
     baris dan bentuknya tidak lagi seragam dengan kartu lain. justify-content
     center supaya sisa baris terakhir jatuh di tengah, seperti .cat-grid. */
  .cat-row { flex-wrap: wrap; justify-content: center; }
  /* 3 kolom = 2 gap, bukan 1. Rumus lama (satu gap) kelebihan 24px; dulu
     tidak kelihatan karena flex-grow menutupinya, begitu grow dimatikan
     barisnya jadi cuma muat 2 kartu. */
  .cat-row > * { flex: 0 1 calc((100% - var(--sp-6) * 2) / 3); }
}

@media (max-width: 560px) {
  .cat-row > * { flex: 0 1 calc((100% - var(--sp-6)) / 2); }
  /* Di 2 kolom kartu tinggal ~138px. `aspect-ratio: 1` mengunci tingginya,
     sementara ikon 54px + label 3 baris butuh lebih — labelnya meluber
     keluar kartu. Lepas rasionya, sisakan min-height supaya kartu berlabel
     pendek tetap terlihat persegi. */
  .card-cat--stacked {
    aspect-ratio: auto;
    min-height: 138px;
    font-size: var(--fs-body-sm);
  }
}

/* Grid kartu kategori: 3 per baris, sisanya di baris terakhir ikut ke tengah.
   Dipakai flex-wrap, bukan grid, justru karena jumlah kategori datang dari
   taksonomi dan bisa berubah — 5 kategori jadi 3+2 tengah tanpa aturan khusus. */
.cat-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--grid-gap);
}

.cat-grid > * {
  flex: 0 1 calc((100% - var(--grid-gap) * 2) / 3);
}

@media (max-width: 1024px) {
  .cat-grid > * { flex-basis: calc((100% - var(--grid-gap)) / 2); }
}

/*
 * MOBILE (dump Home 412px, 2026-09-17).
 *
 * Sebelumnya kartu kategori dibuat SELEBAR PENUH dan menumpuk lima baris —
 * terukur 344x125 x5 = 721px. Dump mobile menaruhnya sebagai kotak kecil:
 * 102x102, TIGA kolom (x 35 / 155 / 275), baris kedua berisi dua kartu yang
 * TERPUSAT, gap 18px. 3 x 102 + 2 x 18 = 342 = persis lebar isi di 412px.
 * Selisihnya ~500px tinggi halaman.
 *
 * Bentuk kartunya juga berubah: di dump ikon 45px duduk DI ATAS labelnya
 * (ikon y 2067, label y 2126 di dalam kartu 2055..2157), bukan bersebelahan
 * seperti di desktop. Itu persis varian `.card-cat--stacked` yang sudah
 * dipakai halaman Produk, jadi gayanya dipinjam dari sana alih-alih ditulis
 * ulang.
 */
@media (max-width: 640px) {
  /* 18px dari dump, bukan --grid-gap (24px) — dengan 24px kartunya menyusut
     ke 98px dan tidak lagi 102 seperti desain. */
  .cat-grid { gap: 18px; }
  .cat-grid > * { flex-basis: calc((100% - 18px * 2) / 3); }

  .cat-grid .card-cat {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--sp-2);
    aspect-ratio: 1;
    min-height: 0;
    /* ⚠️ 5px, bukan --sp-3 (12px). Dump menyisakan ~95px untuk labelnya
       (label "Minyak & Gas" 95px di dalam kartu 102px), sementara padding
       12px cuma menyisakan 79px — dan di situ Poppins memecah "Minyak &
       Gas" serta "Pakan Ternak" jadi dua baris, padahal desain satu baris.
       Padding desktop (kiri --sp-16 = 64px) jauh lebih tidak mungkin lagi:
       ia menyisakan 38px untuk ikon yang 45px. */
    padding: 5px;
    text-align: center;
    /* Dump: 12px/18. --fs-body (18px) membuat label terpanjang
       ("Pakan Ternak") pecah dan meluber keluar kartu 102px. */
    font-size: 12px;
    line-height: 18px;
  }

  /* Dump: 45x45 (Layer_1 di 184,2067), bukan 54px seperti desktop. */
  .cat-grid .card-cat .icon { width: 45px; height: 45px; }

}

/* ------------------------------------------------------------
   4. ICON RAIL
   Deretan lingkaran biru dihubungkan garis horizontal.
   Garis digambar dengan ::before di kontainer, bukan per item.
   ------------------------------------------------------------ */

.icon-rail {
  --rail-size: 97px;
  --rail-gap: var(--sp-4);
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--rail-gap);
}

/* Garis penghubung horizontal, berhenti di tengah lingkaran pertama & terakhir.
   Rumus lamanya (100% / jumlah / 2) mengabaikan GAP grid: dengan 5 kolom di
   lebar 1200px + gap 16px, lebar kolom sebenarnya 227px (bukan 240px), jadi
   titik tengah lingkaran terluar ada di 113,5px — sementara garisnya mulai di
   120px. Selisih ~6px itu membuat garis horizontal tidak menyentuh garis
   turun paling kiri & paling kanan, terlihat seperti garis putus. */
.icon-rail::before {
  content: '';
  position: absolute;
  top: 0;
  left: calc((100% - (var(--rail-count, 5) - 1) * var(--rail-gap)) / var(--rail-count, 5) / 2);
  right: calc((100% - (var(--rail-count, 5) - 1) * var(--rail-gap)) / var(--rail-count, 5) / 2);
  height: 1px;
  background: var(--c-border);
}

.icon-rail__item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  padding-top: var(--rail-drop, 34px);
  text-align: center;
}

/* Setiap item punya turunan vertikal sendiri dari garis ke lingkaran —
   di desain ada 5 tangkai, bukan hanya siku di kedua ujung. */
.icon-rail__item::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: var(--rail-drop, 34px);
  background: var(--c-border);
}

.icon-rail__badge {
  display: grid;
  place-items: center;
  width: var(--rail-size);
  height: var(--rail-size);
  border-radius: 50%;
  background: var(--c-primary);
  color: var(--c-white);
}

.icon-rail__badge .icon { width: 46px; height: 46px; }

.icon-rail__label {
  /* Dump Home: 18px/25. Sebelumnya --fs-body-sm (16px). */
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
  /* Dump: frame tiap label 128-175px, kolom rail ~233px. Ditulis 190px,
     bukan 175px seperti dump, karena "Logistik antar-jemput" TIDAK MUAT di
     175px dengan Poppins (lebih lebar dari Google Sans Flex, lihat
     01-design-system.md §2) — di 175px ia pecah jadi 4 baris dengan
     potongan tengah kata "antar-/jemput", desain 3 baris. Harganya:
     "Manajemen Gudang" jadi 1 baris (desain 2). Itu kompromi yang lebih
     kecil daripada pemenggalan kata, dan 190px masih jauh di dalam kolom.
     Jangan ditulis dalam `ch` — satuannya ikut font-size, jadi diam-diam
     berubah setiap skala tipografi disetel. */
  max-width: 190px;
}

/* --- Animasi: badge muncul satu per satu dari kiri, seperti titik di
   diagram Flexitank. GARIS penghubung sengaja TIDAK dianimasikan — ikut
   fade container .reveal saja — supaya kerangkanya sudah utuh sejak awal
   dan mata cuma mengikuti badge yang menyala berurutan.
   Urutan diambil dari :nth-child, jadi markup tidak perlu diubah dan
   halaman lain yang memakai .icon-rail ikut dapat perilaku sama. */
.icon-rail { --rail-jeda: 260ms; }

.icon-rail__item:nth-child(1) { --i: 0; }
.icon-rail__item:nth-child(2) { --i: 1; }
.icon-rail__item:nth-child(3) { --i: 2; }
.icon-rail__item:nth-child(4) { --i: 3; }
.icon-rail__item:nth-child(5) { --i: 4; }
.icon-rail__item:nth-child(6) { --i: 5; }

.icon-rail.reveal .icon-rail__badge { transform: scale(0); }
.icon-rail.reveal .icon-rail__label { opacity: 0; transform: translateY(8px); }

.icon-rail.reveal.is-visible .icon-rail__badge {
  transform: scale(1);
  /* easing sama dengan titik diagram: sedikit memantul saat mendarat */
  transition: transform 380ms cubic-bezier(0.34, 1.4, 0.64, 1);
  transition-delay: calc(var(--i, 0) * var(--rail-jeda) + 200ms);
}

.icon-rail.reveal.is-visible .icon-rail__label {
  opacity: 1;
  transform: none;
  transition: opacity 320ms ease-out, transform 320ms ease-out;
  transition-delay: calc(var(--i, 0) * var(--rail-jeda) + 340ms);
}

@media (prefers-reduced-motion: reduce) {
  .icon-rail.reveal .icon-rail__badge { transform: none; }
  .icon-rail.reveal .icon-rail__label { opacity: 1; transform: none; }
  .icon-rail.reveal.is-visible :is(.icon-rail__badge, .icon-rail__label) { transition: none; }
}


@media (max-width: 768px) {
  .icon-rail {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, 1fr);
  }
  /* Garis & tangkai tidak masuk akal saat item membungkus jadi 2 kolom. */
  .icon-rail::before,
  .icon-rail__item::before { display: none; }
  .icon-rail__item { padding-top: 0; }

  /* Jumlah item ganjil (5 di Home & Flexitank) menyisakan satu item sendirian
     di kolom kiri baris terakhir, terlihat miring. Dibentangkan 2 kolom
     supaya isinya (yang memang rata tengah) jatuh di tengah.
     Hanya berlaku di media query ini — di layar lebar grid-nya kolom
     otomatis, lihat catatan proyek aturan #16. */
  .icon-rail__item:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------
   5. MARQUEE LOGO KLIEN
   Dua baris berlawanan arah. CSS murni, tanpa library.
   Daftar logo diduplikasi 2x di HTML agar loop mulus.
   ------------------------------------------------------------ */

.marquee {
  position: relative;
  overflow: hidden;
  /* Tepi kiri & kanan memudar supaya logo tidak terpotong mendadak. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.marquee + .marquee { margin-top: var(--sp-16); }   /* jarak antar baris di desain ~65px */

.marquee__track {
  display: flex;
  align-items: center;
  /* Dump: jarak antar logo tidak seragam (Figma menaruhnya manual) — baris 1
     rata-rata ~47px, baris 2 ~33px. Dipilih 32px, bukan rata-rata keduanya,
     karena dengan 48px baris 2 (844px logo + 5 jarak) melebihi lebar
     barisnya (1011px) dan logo Dexa terpotong mask di tepi kanan. */
  gap: var(--sp-8);
  width: max-content;
  animation: marquee-left var(--marquee-duration) linear infinite;
}

.marquee--reverse .marquee__track { animation-name: marquee-right; }

/* Jeda saat hover supaya pengunjung bisa membaca nama klien. */
.marquee:hover .marquee__track { animation-play-state: paused; }

/* Ukuran slot dibuat eksplisit. Logo klien punya rasio yang sangat
   beragam (Unilever tinggi, Halliburton sangat lebar), jadi ukurannya
   dikunci di slot dan gambar menyesuaikan lewat object-fit: contain. */
/* Tanpa kotak berukuran tetap. Aset logo diekspor @3x, jadi atribut
   width/height di markup (sepertiga ukuran file) sudah = ukuran persis di
   desain: Pertamina 184x43, Bayer 70x71, Gajah Tunggal 222x44, dst.
   Kotak seragam 150x56 yang dipakai sebelumnya justru mengecilkan logo lebar
   (Gajah Tunggal jadi 150x30, desain 222x44) dan membuat bobot visual tiap
   logo tidak lagi seperti desain. */
.marquee__item { flex: none; }

/* Logo tampil berwarna penuh. Dokumen Fase 1 sempat menyebut grayscale,
   tapi preview Figma menunjukkan warna asli (Pertamina #0049A7,
   Kimia Farma #F39200) — jadi tanpa filter. */
.marquee__item img {
  display: block;
  /* SENGAJA tanpa width/height di sini: ukurannya datang dari atribut
     width/height di markup. `width: auto` justru MEMBATALKAN atribut itu
     (atribut cuma "presentational hint" yang kalah dari aturan author),
     sehingga logo tampil sebesar file aslinya — @3x, tiga kali terlalu besar. */
}

/* Track berisi 2 salinan daftar; geser -50% = tepat satu salinan. */
@keyframes marquee-left {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@keyframes marquee-right {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

/* Fallback: tanpa animasi, tampilkan sebagai grid statis. */
@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee__track {
    animation: none;
    flex-wrap: wrap;
    justify-content: center;
    width: 100%;
    gap: var(--sp-8);
  }
  .marquee__track [aria-hidden='true'] { display: none; }
}

/* ------------------------------------------------------------
   6. FORM
   Input pill dengan ikon di dalam, sesuai desain.
   ------------------------------------------------------------ */

.field {
  position: relative;
  display: block;
}

/* Dump (Produk & Flexitank: field di y 3600/3673/3746/3819 -> jarak 23px;
   Kontak 28px): --sp-6 (24px) paling dekat. Sebelumnya --sp-4 (16px),
   bikin kartu form lebih pendek dari desain (419px vs 434px). */
.field + .field { margin-top: var(--sp-6); }

.field__icon {
  position: absolute;
  top: 50%;
  left: var(--sp-5);
  translate: 0 -50%;
  width: 20px;
  height: 20px;
  /* Sampel piksel Preview.png (Produk & Kontak): keempat ikon field —
     termasuk yang bentuknya logo WhatsApp — abu-abu terang (#c9c9c9,
     persis --c-border), BUKAN biru/hijau. Sempat dikira ikon WhatsApp
     harus hijau seperti brand-nya; ternyata di desain semua ikon field
     seragam abu-abu, cuma inputnya yang bergaris biru. */
  color: var(--c-border);
  pointer-events: none;
}

.field__input {
  width: 100%;
  padding: var(--sp-3) var(--sp-5) var(--sp-3) calc(var(--sp-5) * 2 + 20px);
  border: 1px solid var(--c-primary);
  border-radius: var(--r-pill);
  background: var(--c-white);
  font-size: var(--fs-body-sm);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.field__input::placeholder { color: var(--c-border); }

.field__input:focus {
  outline: none;
  border-color: var(--c-accent);
  box-shadow: 0 0 0 3px rgba(39, 170, 225, 0.2);
}

/* Textarea tidak pakai ikon, sudutnya kotak-membulat bukan pill. */
.field__input--area {
  padding-left: var(--sp-5);
  border-radius: var(--r-md);
  min-height: 200px;
  resize: vertical;
}

/* Dulu dipaksa hijau brand WhatsApp — lihat catatan di .field__icon,
   desainnya seragam abu-abu. Kelas dibiarkan ada (dipakai di beberapa
   halaman) tapi tidak lagi override warna. */
.field__icon--whatsapp {}

/* Kartu form melayang di atas foto (halaman Produk & Flexitank) */
.form-card {
  /* 90% opacity (dump Rectangle 75), bukan putih solid — kartu menumpang
     tepi foto (lihat produk-cta__photo), jadi sedikit tembus di area yang
     overlap. Sama pola dengan .card-cat, lihat catatan proyek aturan #18. */
  background: rgba(255, 255, 255, 0.9);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-float);
  /* Dump (Produk & Flexitank sama): kartu 814px berisi field 765px, jadi
     padding kiri/kanan 24,5px — bukan 40px. Dengan 40px, field-nya cuma
     734px (31px lebih sempit dari desain). Vertikal tetap 40px (dump:
     33px atas / 46px bawah, rata-rata mendekati 40). */
  padding: var(--sp-10) var(--sp-6);
}

/* Varian biru (sidebar Blog Detail) */
.form-card--primary {
  background: var(--c-primary);
  color: var(--c-white);
  /* Dump (Rectangle 122): TANPA box-shadow — kartu ini duduk rata di
     alur konten biasa, beda dari .form-card dasar yang shadow-nya
     (--shadow-float) memang untuk konteks kartu MELAYANG di atas foto
     (Produk/Flexitank). Sampel piksel Blog Detail.png juga tidak
     menunjukkan bayangan apa pun di tepi kartu ini. */
  box-shadow: none;
  /* Diukur langsung dari Blog Detail.png (scan piksel isi-kartu vs sudut
     radius, bukan cuma baca angka dump): jarak konten ke tepi kartu di
     KEEMPAT sisi ~29-31px, seragam — var(--sp-8) (32px), bukan
     var(--sp-10) (40px) bawaan .form-card yang kepakai sebelumnya (sempat
     juga salah dikira 16px saat dikejar-kejar biar judulnya 2 baris —
     lihat .form-card__title, itu masalah terpisah, jangan dikorbankan
     lewat padding kartu). */
  --form-pad: var(--sp-8);
  padding: var(--form-pad);
}

.form-card--primary .field__input {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.6);
  color: var(--c-white);
}

.form-card--primary .field__input::placeholder { color: rgba(255, 255, 255, 0.7); }

/* Dump: ikon di kartu ini BUKAN putih solid — sampel piksel langsung dari
   Blog Detail.png (di luar area anti-aliasing border pill) konsisten
   memberi puncak kecerahan rgb(96,158,208) di atas latar #1C75BC, yang
   cuma bisa dicapai oleh putih ~30% opacity (alpha 0.3 di ketiga kanal
   R/G/B, dihitung mundur dari komposit warnanya — bukan tebakan). Beda
   dari border pill (rgba(...,0.6)) & placeholder (rgba(...,0.7)) yang
   sudah benar duluan; ikonnya sendiri sengaja jauh lebih pudar dari itu. */
.form-card--primary .field__icon { color: rgba(255, 255, 255, 0.3); }

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
  /* ⚠️ `start`, bukan `stretch` bawaan. Field yang teregang mengikuti
     tinggi tetangganya membawa IKONNYA ikut turun: `.field__icon`
     dipusatkan terhadap `.field` (top:50%), bukan terhadap inputnya,
     jadi kotak 53px yang jadi 101px menaruh ikonnya 23px di bawah input.
     Terjadi persis begitu saat notifikasi "pesan terkirim" muncul.
     Dua field bersebelahan memang sudah sama tinggi, jadi `start` tidak
     mengubah apa pun di keadaan normal — ia cuma menutup kasus ini. */
  align-items: start;
}

/* Notifikasi SELALU selebar penuh. Tanpa ini ia menempati satu sel grid,
   sehingga (a) ia berbagi baris dengan field pertama dan meregangkannya,
   dan (b) seluruh field bergeser satu kolom — "Nama Anda" pindah ke kanan.
   Keduanya terlihat setelah form dikirim, bukan sebelumnya. */
.form-grid > .form-notice {
  grid-column: 1 / -1;
}

.form-grid .field + .field { margin-top: 0; }
.form-grid__full { grid-column: 1 / -1; }

@media (max-width: 768px) {
  .form-grid { grid-template-columns: 1fr; }
  /* --form-pad ikut turun supaya judul kartu biru (yang sengaja melar
     sebesar padding ke kanan) tidak lewat dari tepi kartu. */
  .form-card { --form-pad: var(--sp-6); padding: var(--form-pad); }
}

.form-card__title {
  font-size: var(--fs-subsection);
  font-weight: var(--fw-bold);
  /* Dump: 23px/25px -> rasio 1,09, JAUH lebih rapat dari --lh-snug (1,4)
     yang kepakai sebelumnya (32px, +29% dari desain). Diukur dari PNG
     desain juga: jarak baris-1 ke baris-2 judul ini 24px, punya kita 31px. */
  line-height: 1.1;
  margin-bottom: var(--sp-3);
}

/* Dump (Blog Detail): kotak judul 972..1327 di dalam kartu 942..1327 —
   artinya padding KIRI-nya normal (30px, sejajar dengan sub-judul & field)
   tapi padding KANAN-nya 0: kotaknya melebar hanya ke kanan sampai mentok
   tepi kartu. Itu yang bikin "Apakah Anda membutuhkan / KCL dalam jumlah
   besar?" muat 2 baris (butuh ~351px; ruang normal kartu cuma 321px).
   Sempat dilebarkan simetris pakai margin-inline negatif — hasilnya tepi
   kiri judul ikut mundur 16px dan jadi TIDAK sejajar dengan sub-judul di
   bawahnya. Jadi melarnya harus ke kanan saja. */
.form-card--primary .form-card__title {
  /* Melar sebesar padding kartu yang SEDANG berlaku, bukan angka tetap:
     di <=768px padding kartu turun ke --sp-6 (24px) sementara nilai tetap
     --sp-8 (32px) bikin judul lewat 8px keluar kartu. */
  width: calc(100% + var(--form-pad, var(--sp-8)));
  margin-right: calc(var(--form-pad, var(--sp-8)) * -1);
}

.form-card__subtitle {
  font-size: var(--fs-body);
  /* Dump: 18px/25px -> rasio 1,39, pas dengan --lh-snug (1,4). Sebelumnya
     pakai --lh-body (1,7 = 30,6px) yang memang untuk paragraf artikel
     panjang, kelewat renggang untuk teks pendek di kartu ini. */
  line-height: var(--lh-snug);
  margin-bottom: var(--sp-6);
}

/* ------------------------------------------------------------
   6b. DETAIL ARTIKEL BLOG (single.php)
   Sidebar form 385px tetap (dump), sisanya kolom artikel. Sidebar
   sticky — form penawaran tetap terlihat saat pembaca scroll panjang.
   ------------------------------------------------------------ */

/* Judul + tanggal duduk di baris sendiri, lalu baris kedua berisi artikel +
   sidebar. Dengan begitu tepi atas kartu form sejajar dengan tepi atas foto
   artikel — persis dump (Rectangle 122 & Rectangle 83 sama-sama top: 640px),
   bukan sejajar dengan judul.
   row-gap var(--sp-6): dulu 0, jarak ke baris kedua cuma didapat dari
   margin-top .post-photo — aside (kartu biru) tidak punya margin serupa,
   jadi start-nya lebih tinggi 24px dari foto (ketahuan lewat
   getBoundingClientRect, bukan kelihatan di 1440px karena bedanya subtle). */
.post-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 385px;
  /* column-gap dump ~28px (942-914), bukan var(--sp-10) (40px) yang
     kepakai sebelumnya. Bukan cuma soal akurasi — 12px ekstra ini juga
     yang bikin "Apa saja macam - macam grade Potassium Chloride?" (h2
     pertama artikel, dump-nya 1 baris) numpang wrap ke 2 baris sebelum
     saatnya, terutama di jendela browser yang di-zoom/tidak selebar
     1440px penuh. var(--sp-6) (24px) paling dekat ke 28px. */
  gap: var(--sp-6);
  align-items: start;
}

/* Tetap di kolom artikel saja (BUKAN 1/-1 penuh) — dump: "Bagikan" berhenti
   di ~x=914, pas di tepi kanan foto/kolom artikel, masih ada jarak ~28px
   sebelum sidebar mulai (x=942). Sempat dilebarkan ke seluruh container
   supaya judulnya muat 1 baris, tapi itu ikut menarik "Bagikan" ke ujung
   kanan container (nempel di atas sidebar) — salah posisi, beda dari dump.
   Lebar ekstra buat judul sekarang ditangani khusus di .post-title saja
   (lihat aturannya), tidak lagi dengan melebarkan seluruh post-header. */
.post-header          { grid-column: 1; grid-row: 1; }
.post-layout > article { grid-column: 1; grid-row: 2; }
.post-layout > aside   { grid-column: 2; grid-row: 2; }

.post-layout aside { position: sticky; top: var(--sp-10); }

/* Judul besar 30px/800 hitam — "Artikel Lain" (Blog Detail, rata kiri) dan
   "Punya Pertanyaan?" (Kontak, rata tengah pakai .center). Beda dari
   .section-title yang 23px/700 biru & selalu rata tengah. */
.title-lg {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
}

.title-lg + .grid-3 { margin-top: var(--sp-8); }

/* Dump: judul 677px di dalam kolom artikel 801px — jadi HANYA ~85% lebar
   kolomnya, tidak pernah melewati tepi kanan foto. Sempat dikasih lebar
   ekstra (calc(100% + 385px + gap)) supaya tidak wrap di laptop 1280px;
   itu memang bikin 1 baris, tapi judulnya jadi menjorok melewati foto —
   proporsinya meleset dari desain. Akar masalahnya bukan di sini melainkan
   di --gutter yang dulu terlalu besar di rentang 1000-1360px (lihat
   tokens.css); setelah gutter dibetulkan, judul 30px muat wajar di dalam
   kolomnya sendiri tanpa hack apa pun. */
.post-title {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
}

.post-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-top: var(--sp-3);
}

.post-photo {
  /* Jarak ke post-header sekarang dari row-gap .post-layout, bukan margin
     di sini — margin-top di elemen ini doang bikin foto turun 24px lebih
     jauh dari kartu sidebar (yang tidak punya margin serupa), padahal
     dump: keduanya top:640, harus sejajar persis. */
  border-radius: var(--r-md);
  overflow: hidden;
}

.post-photo img {
  width: 100%;
  height: auto;
  aspect-ratio: 801 / 464;
  object-fit: cover;
}

/* Isi artikel dari editor WP standar — heading, paragraf, list. */
.post-body { margin-top: var(--sp-8); }

.post-body h2,
.post-body h3 {
  font-size: var(--fs-subsection);
  font-weight: var(--fw-bold);
  margin-top: var(--sp-10);
}

.post-body p {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--c-ink);
  margin-top: var(--sp-4);
}

.post-body ul,
.post-body ol {
  margin-top: var(--sp-4);
  padding-left: 1.4em;
}

.post-body li {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--c-ink);
}

.post-body li + li { margin-top: var(--sp-2); }

/* Tautan di tengah paragraf wajib bergaris bawah: warna saja tidak cukup
   membedakannya dari teks sekitar (WCAG 1.4.1). */
.post-body a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Penempatan grid eksplisit di atas WAJIB direset di sini. Tanpa reset,
   `grid-column: 2` tetap berlaku walau gridnya tinggal 1 kolom — Chrome
   membuat kolom implisit dan halaman meluber ke samping (ketahuan lewat
   tools/ukur-margin.ps1: margin kiri/kanan jadi tidak simetris di 768px).

   Breakpoint 1024px (bukan 900px): sidebar form dipatok 385px, jadi kolom
   artikelnya yang menyusut — di 1024px tinggal 455px dan di 901px cuma
   342px, terlalu sempit untuk paragraf. Di bawah 1024px lebih baik
   bertumpuk supaya artikel dapat lebar penuh. */
@media (max-width: 1024px) {
  .post-layout { grid-template-columns: 1fr; }

  .post-header,
  .post-layout > article,
  .post-layout > aside {
    grid-column: 1;
    grid-row: auto;
  }

  .post-layout > aside {
    position: static;
    margin-top: var(--sp-10);
  }
}

/* Form Kontak: tanpa kartu (latarnya sudah putih), kolom lebih lebar dan
   lebih renggang dari form penawaran — dump: 2 kolom 441px, jarak 30px,
   total 911px, textarea 260px. */
.form-kontak {
  max-width: 911px;
  margin-inline: auto;
  gap: var(--sp-8);
}

.form-kontak .field__input--area { min-height: 260px; }

/* ------------------------------------------------------------
   6c. INFO KONTAK (halaman Kontak)
   Ikon bulat biru 58px di atas judul, teks rata tengah.
   ------------------------------------------------------------ */

/* .section + .section menolkan padding-top (base.css) — di sini justru
   perlu jarak: dump memberi garis pemisah di y=1227 dan lingkaran ikon
   pertama mulai y=1290, jadi 63px (--sp-16 = 64px). Ditulis .section
   .kontak-info supaya spesifisitasnya menyamai aturan sibling itu dan
   menang karena file ini dimuat belakangan. */
.section.kontak-info {
  border-top: 1px solid var(--c-primary);
  padding-top: var(--sp-16);
}

.contact-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-10);
}

.contact-item { text-align: center; }

.contact-item__icon {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  margin: 0 auto var(--sp-5);
  border-radius: 50%;
  background: var(--c-primary);
  color: var(--c-white);
}

.contact-item__icon .icon { width: 26px; height: 26px; }

.contact-item__title {
  font-size: var(--fs-subsection);
  font-weight: var(--fw-bold);
}

.contact-item__text {
  margin-top: var(--sp-2);
  font-size: var(--fs-body-lg);
  /* Dump: 20px/25px bobot 300 (light) — bukan 400. Bobot 300 baru bisa
     dipakai setelah dimuat di <link> Google Fonts (dulu cuma 400-700). */
  font-weight: var(--fw-light);
  line-height: var(--lh-snug);
}

/* Dump Kontak (Rectangle 7): tombol Submit di sini 208px, lebih lebar dari
   170px baseline tombol utama di halaman lain. */
.form-kontak button[type='submit'] { min-width: 208px; }

/* Telepon & email tetap bisa diklik, tapi di desain warnanya hitam —
   bukan biru seperti tautan lain. Garis bawah muncul saat hover saja. */
.contact-item__text a { color: inherit; }
.contact-item__text a:hover { text-decoration: underline; }

/* Dua alamat gudang dipisah garis vertikal (dump: Line 72, 1px hitam). */
/* Dump: dua kolom masing-masing 408px di x=282 & x=741 (total rentang
   867px, jarak antar-kolom 51px), garis pemisah (Line 72) TEPAT di tengah
   jarak itu (x=720). Sebelumnya dipakai 911px/gap 40px, dan garis pemisah
   ditempel sebagai border-left + padding-left 40px di kolom kedua — padding
   itu memakan lebar teks kolom kanan (436 -> 396px), padahal barisnya
   butuh 398px: "Pergudangan Sentra Prima Techno Park," jadi pecah 2 baris
   padahal di desain 1 baris. Kolomnya juga jadi tidak sama lebar. */
.warehouse-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-12);
  max-width: 867px;
  margin: var(--sp-8) auto 0;
}

/* Border ditarik ke tengah gap lewat margin negatif + padding senilai,
   jadi lebar teks kolom kedua tetap penuh (tidak terpotong padding). */
.warehouse-grid > * + * {
  border-left: 1px solid var(--c-ink);
  margin-left: calc(var(--sp-12) / -2);
  padding-left: calc(var(--sp-12) / 2);
}

@media (max-width: 768px) {
  .contact-grid { grid-template-columns: 1fr; }
  .warehouse-grid { grid-template-columns: 1fr; }
  /* margin-left negatif WAJIB ikut direset — tanpa ini blok gudang kedua
     tertarik 24px ke kiri dan tidak sejajar dengan blok pertama saat
     kolomnya menumpuk (lihat catatan proyek aturan #16). */
  .warehouse-grid > * + * { border-left: 0; margin-left: 0; padding-left: 0; }
}

/* ------------------------------------------------------------
   7. SEARCH BAR (halaman Produk)
   ------------------------------------------------------------ */

.searchbar {
  position: relative;
  max-width: 900px;
  margin-inline: auto;
  /* Dump: search box berakhir di y=574, baris kategori mulai y=633 — jarak
     59px. Section pembungkusnya sengaja padding-bottom:0 (mengikuti pola
     section+section di base.css), jadi tanpa margin di sini jaraknya 0
     sama sekali — itu sebab "mepet" antara search dan kartu kategori. */
  margin-bottom: var(--sp-16);
}

.searchbar__input {
  width: 100%;
  padding: var(--sp-4) calc(var(--sp-5) * 2 + 20px) var(--sp-4) var(--sp-6);
  border: 1px solid var(--c-primary);
  border-radius: var(--r-pill);
  font-size: var(--fs-body);
}

.searchbar__input:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(39, 170, 225, 0.2);
}

.searchbar__btn {
  position: absolute;
  top: 50%;
  right: var(--sp-4);
  translate: 0 -50%;
  display: grid;
  place-items: center;
  /* 36px: ikon (24px, lihat .searchbar__btn .icon) + ruang lingkaran hover
     di sekelilingnya. Sebelumnya 24px pas-pasan dengan ikon — tombol
     <button> juga punya padding bawaan browser (1px 6px) yang tidak pernah
     direset, jadi kotak konten yang tersisa untuk ikon cuma 12px lebar
     (24 - 6 - 6), ikon jadi gepeng/kecil (12x20, ketahuan lewat
     getBoundingClientRect(), bukan cuma "kelihatan agak kecil" di mata). */
  width: 36px;
  height: 36px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 50%;
  color: var(--c-ink);
  transition: background-color var(--t-fast), color var(--t-fast);
}

/* Dump (Vector di dalam Rectangle 54): ikon kaca pembesar ~23x23px, lebih
   besar dari .icon default (20px) — beda cukup terlihat di pill setinggi
   50px ini. */
.searchbar__btn .icon { width: 24px; height: 24px; }

/* Belum ada di dump statis (Figma tidak bisa merekam state hover/klik) —
   pola diambil dari komponen ikon-bulat lain yang sudah ada (.chip:hover,
   .btn-share:hover): isi lingkaran biru + ikon putih. Ikon di-mask (bukan
   <img> polos) supaya bisa ikut var(--c-white) lewat currentColor. */
.searchbar__btn:hover,
.searchbar__btn:focus-visible {
  background: var(--c-primary);
  color: var(--c-white);
}

.searchbar__btn:active { scale: 0.9; }

/* ------------------------------------------------------------
   8. SIDEBAR DAFTAR PRODUK
   ±20 item per kategori — wajib scroll internal.
   ------------------------------------------------------------ */

.product-nav {
  max-height: 620px;
  overflow-y: auto;
  /* Sampel piksel Preview.png (bukan dump — lihat catatan token
     --c-border-strong): garis vertikal & horizontal di sidebar ini lebih
     gelap dari --c-border biasa. */
  border-right: 1px solid var(--c-border-strong);
  padding-right: var(--sp-4);
  scrollbar-width: thin;
}

.product-nav__item {
  display: block;
  /* Inset kiri ~33px di dump (teks "Barite" mulai x=146, sidebar x=113) —
     jauh lebih lebar dari sp-4(16) yang dipakai sebelumnya. */
  padding: var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-8);
  border-bottom: 1px solid var(--c-border-strong);
  color: var(--c-ink);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-snug);
  /* Dump (Rectangle 64, kotak highlight item aktif): TANPA border-radius —
     baris sidebar ini persegi tajam, bukan pil membulat seperti kartu.
     Radius sebelumnya bikin border-bottom terlihat terpotong/melengkung
     di ujung, beda dari garis lurus penuh di desain. */
  transition: background-color var(--t-fast), color var(--t-fast);
}

.product-nav__item:hover { background: var(--c-surface); }

.product-nav__item.is-active {
  background: var(--c-primary);
  color: var(--c-white);
  font-weight: var(--fw-extrabold);
  border-color: transparent;
}

/* ------------------------------------------------------------
   9. TABEL ANALISIS KIMIA
   ------------------------------------------------------------ */

/* Radius di 4 sudut sebenarnya datang dari DUA layer terpisah di dump:
   Rectangle 67 (header biru) radius atas "20px 20px 0 0", Rectangle 68
   (bingkai badan tabel) radius bawah "0 0 20px 20px" — gabungan keduanya
   baru membentuk kotak bulat penuh. Sempat cuma radius atas yang diterapkan
   (Rectangle 68 tidak kelihatan sebagai "border-radius" saat digrep dari
   dump statis, ketahuan cuma setelah user cek langsung ke file Figma-nya
   — lihat catatan proyek aturan #10, dump tidak selalu menangkap semua layer).
   Radius + border digabung di wrapper (bukan per-sel) supaya sudut bawah
   ikut membulat tanpa perlu utak-atik border-collapse per sel. overflow-x
   tetap auto untuk geser horizontal di mobile (aturan #14) — overflow-y
   otomatis ikut "auto" (bukan visible) begitu overflow-x bukan visible,
   jadi radius tetap ke-clip di kedua sumbu. */
.spec-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-md);
  /* .product-block (wrapper-nya) sekarang flex (lihat bagian 14, dibuat
     supaya "PACKAGING:"/"SERTIFIKASI:" sejajar dengan kontennya) — item
     flex defaultnya shrink-to-fit, BUKAN melebar mengisi induk. Tanpa ini
     tabel (satu-satunya child di .product-block-nya) balik ke lebar
     konten aslinya (tabel 2 kolom jadi cuma ~420px, padahal harusnya
     mentok selebar foto produk di atasnya, sama di 2 kolom maupun 4
     kolom). min-width:0 supaya boleh menyempit di bawah lebar konten
     tabel saat overflow-x:auto perlu geser di mobile (aturan #14). */
  flex: 1 1 100%;
  min-width: 0;
}

.spec-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body-sm);
  min-width: 420px;
}

/* Header tabel warna accent (#27AAE1), BUKAN primary — terverifikasi dari
   dump (Rectangle 67), beda dengan warna header lain di situs yang primary. */
.spec-table th {
  background: var(--c-accent);
  color: var(--c-white);
  font-weight: var(--fw-semibold);
  text-align: center;
  padding: var(--sp-3) var(--sp-4);
}

/* Dump (Line 35/Line 58 di semua varian tabel — Standard/Industrial/Pharma
   Grade sama-sama punya ini): garis pemisah PUTIH setinggi header di antar
   kolom judul, kontras di atas latar biru. Beda dari garis body (Line
   33/36/dst, hitam di atas latar putih) — sempat tidak ada sama sekali di
   header, cuma badan tabel yang punya garis lewat border td. */
.spec-table th:not(:last-child) { border-right: 1px solid var(--c-white); }

/* Radius sudut dipasang LANGSUNG di sel pojok (bukan cuma mengandalkan
   overflow-clip di .spec-table-wrap) — kombinasi overflow:auto + radius di
   parent kadang tidak konsisten men-clip pojok tabel <table> di semua
   kondisi render (kelihatan di Chrome biasa: latar biru pojok kanan-atas
   nyisa siku putih tipis, padahal aman di screenshot headless). Membulatkan
   background sel itu sendiri lebih robust, wrapper tetap dipertahankan
   untuk bingkai luarnya. */
.spec-table th:first-child { border-top-left-radius: var(--r-md); }
.spec-table th:last-child { border-top-right-radius: var(--r-md); }
.spec-table tbody tr:last-child td:first-child { border-bottom-left-radius: var(--r-md); }
.spec-table tbody tr:last-child td:last-child { border-bottom-right-radius: var(--r-md); }

.spec-table td {
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--c-border);
}

.spec-table tr td:last-child { width: 35%; }

/* ------------------------------------------------------------
   10. BARIS SERTIFIKASI
   ------------------------------------------------------------ */

.cert-row {
  /* Pengali ukuran logo per lebar layar (lihat media query di bawah). */
  --cert-skala: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;   /* semua logo di garis tengah yang sama */
  gap: var(--sp-6) var(--sp-8);   /* dump: 34px antar logo sebaris */
}

/* UKURAN DIMILIKI LOGONYA, BUKAN URUTANNYA (2026-10-09).
   Dulu tinggi dipatok lewat :nth-child (86/82/40/79px untuk urutan desain
   ISO-ISO14001-FSSC-Halal), sehingga produk dengan sertifikat atau urutan
   lain tampil kacau: FSSC 86px tinggi, ISO 14001 40px, dan logo ke-5 dst.
   tanpa batas sama sekali (seukuran berkasnya).
   Sekarang lebarnya dihitung PHP per logo supaya muat di kotak 220x84
   (anaya_logo_sertifikat_img, inc/helpers.php) dan dikirim sebagai --w.
   height:auto + atribut width/height asli = rasio terjaga, tidak pernah
   gepeng; max-width:100% = tidak pernah meluber di layar sempit. */
.cert-row img {
  width: calc(var(--w, 84px) * var(--cert-skala));
  height: auto;
  max-width: 100%;
}

@media (max-width: 640px) {
  /* HP: logo persegi 84 -> 60px, FSSC 220 -> 158px. Muat 3-4 logo
     sebaris di kolom 300-340px tanpa ada yang menyusut sendirian. */
  .cert-row {
    --cert-skala: 0.72;
    gap: var(--sp-5) var(--sp-6);
  }
}

/* Carousel sertifikasi (halaman Tentang) — tampil 4, panah bila lebih. */
.cert-carousel {
  /* Mode dibaca JS lewat getComputedStyle (assets/js/cert-carousel.js).
     Ditaruh di CSS supaya BREAKPOINT-nya cuma ada di satu tempat — prinsip
     yang sama dengan jumlah kolom, yang juga dibaca dari CSS dan tidak
     pernah diduplikasi di JS. */
  --cert-mode: halaman;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-5);   /* desain ~19px */
}

.cert-carousel__item {
  aspect-ratio: 289 / 402;   /* dari dump Tentang */
  background: var(--c-placeholder);
  border-radius: var(--r-md);
  overflow: hidden;
}

.cert-carousel__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Tetap 2 kolom sampai layar terkecil. Sempat turun ke 1 kolom di <=640px,
   tapi item ini rasio potret 289:402 — di 390px satu kartu jadi 452px tinggi
   dan section Sertifikasi membengkak ke 2007px (4 kartu beruntun). Sebagai
   thumbnail bukti sertifikat, 2 kolom sudah cukup terbaca dan section-nya
   tinggal ~600px. */
/* Panah geser carousel sertifikat — di sisi kiri & kanan kartu.
   Tidak ada di dump (desain cuma menampilkan 4 kotak tanpa navigasi), tapi
   katalog sertifikat klien akan lebih dari 4, jadi navigasinya wajib nyata.
   Dirender hanya kalau jumlahnya melebihi yang muat; dengan tepat 4 kartu
   halaman Tentang tetap sama persis dengan desain. */
.cert-carousel-wrap { position: relative; }

.cert-nav {
  position: absolute;
  top: 50%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--c-border);
  border-radius: 50%;
  background: var(--c-white);
  box-shadow: var(--shadow-card);
  color: var(--c-primary);
  cursor: pointer;
  transition: background-color var(--t-fast), color var(--t-fast);
}

.cert-nav .icon { width: 18px; height: 18px; }

.cert-nav:hover:not(:disabled) {
  background: var(--c-primary);
  color: var(--c-white);
}

.cert-nav:disabled,
.cert-nav.is-disabled {
  opacity: 0.35;
  cursor: default;
  box-shadow: none;
}

/* Setengah menumpang KELUAR dari tepi kartu, memanfaatkan gutter container.
   Batas amannya dihitung, bukan dikira-kira: `--gutter` itu
   clamp(20px, 8.3vw, 80px), jadi ruang tersempit ada di layar paling kecil
   — 360px memberi 29,9px dan 390px memberi 32,4px. Geseran di sini
   setengah lebar tombol: 22px (desktop) dan 18px (<=768px, tombol 36px),
   dua-duanya masih di dalam ruang itu sehingga TIDAK menimbulkan overflow
   horizontal di lebar mana pun. Kalau tombolnya diperbesar, hitung ulang. */
.cert-nav--prev { left: 0; translate: -50% -50%; }
.cert-nav--next { right: 0; translate: 50% -50%; }

@media (max-width: 768px) {
  .cert-nav { width: 36px; height: 36px; }
  .cert-nav .icon { width: 15px; height: 15px; }
}

@media (max-width: 1024px) {
  .cert-carousel { grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); }
}

/* <=768px: SLIDER GESER-SAMPING, digulir dengan jari.
   Di layar sempit panah bukan alat yang tepat — ia menumpang di atas kartu
   dan menuntut ketepatan tekan, sementara gulir mendatar sudah jadi gerak
   bawaan di HP. Jadi panahnya disembunyikan dan gulirnya diserahkan ke
   peramban: tidak ada transform, tidak ada penghitungan posisi, dan
   inersia/momentum ikut dapat gratis.

   Lebar kartu `clamp(200px, 60vw, 260px)` — BUKAN persentase container.
   Persentase tunggal tidak bisa melayani dua ukuran layar sekaligus: 78%
   memberi 254px yang pas di HP 390px, tapi di tablet 768px melar jadi
   500x695 — satu kartu setinggi hampir seluruh layar. Dengan clamp, HP
   dapat ~234px (kartu berikutnya mengintip, dan intipan itulah satu-satunya
   isyarat bahwa daftarnya berlanjut) sementara tablet berhenti di 260px
   sehingga muat dua kartu lebih sedikit intipan.
   Batas atas 260px sengaja di bawah lebar kartu desktop (285px): ini tetap
   thumbnail bukti, bukan pembaca dokumen.

   ⚠️ `grid-template-columns: none` WAJIB. Tanpa itu aturan 2 kolom di atas
   masih berlaku, item mengisi kedua kolom eksplisit lebih dulu, dan yang
   ikut `grid-auto-columns` cuma sisanya — lebarnya jadi campur aduk. */
@media (max-width: 768px) {
  .cert-carousel {
    --cert-mode: geser;
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: clamp(200px, 60vw, 260px);
    overflow-x: auto;
    overscroll-behavior-x: contain;   /* jangan memicu gestur "kembali" peramban */
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;            /* Firefox */
  }

  /* Chromium & WebKit — keduanya perlu, dan keduanya sudah diverifikasi di
     tools/uji-lintas-peramban.py. */
  .cert-carousel::-webkit-scrollbar { display: none; }

  .cert-carousel__item { scroll-snap-align: start; }

  .cert-nav { display: none; }
}

/* ------------------------------------------------------------
   11. HERO
   ------------------------------------------------------------ */

.hero {
  position: relative;
  display: grid;
  place-items: center;
  /* 329px, bukan 320px: dicek ke 5 dump (Tentang, Blog, Blog Detail, Kontak,
     Produk) — Rectangle 1 selalu 1440x329 mulai y=152, tanpa kecuali. */
  min-height: 329px;
  padding-block: var(--sp-20);
  color: var(--c-white);
  text-align: center;
  background-size: cover;
  background-position: center;
  isolation: isolate;
}

/* Overlay menjaga teks putih tetap lolos kontras AA di atas foto apa pun. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--overlay-hero);
  z-index: -1;
}

/* Foto yang sudah gelap sendiri (bubuk di latar hitam, cairan) —
   overlay default akan membuatnya terlalu gelap. */
.hero--soft::after { background: var(--overlay-hero-soft); }

.hero--tall { min-height: 560px; }

/* Hero Home: 640px sesuai artboard. Padding atas-bawah sengaja tidak simetris —
   di desain blok teks duduk ~53px di bawah titik tengah hero, bukan pas tengah. */
.hero--home {
  min-height: 640px;
  padding-block: var(--sp-30) var(--sp-6);
}

/* Dump mobile (412px): hero 520px, bukan 640px seperti artboard desktop.
   Paddingnya ikut dikecilkan — dengan --sp-30 di atas, blok teks terdorong
   melewati tinggi barunya. Dump: judul mulai y 209 dari hero yang mulai 0. */
@media (max-width: 640px) {
  .hero--home {
    min-height: 520px;
    padding-block: var(--sp-20) var(--sp-6);
  }
}

/* ------------------------------------------------------------
   HERO CAROUSEL (Home)
   Slide bertumpuk, yang berpindah cuma opasitasnya. Dipilih crossfade
   bukan geser mendatar karena dump menaruh judul & tombol di posisi yang
   SAMA di setiap slide -- geser mendatar akan menggerakkan teks yang
   seharusnya diam.
   ------------------------------------------------------------ */

/* Foto latar pindah ke tiap slide, jadi sectionnya sendiri tidak punya. */
.hero-slider { background-image: none; }

/* ⚠️ LAPISAN DITULIS POSITIF SEMUA — jangan pernah memakai z-index negatif
   di sini.

   Versi pertama menaruh track di `z-index: -1`, lalu `-2` untuk mengembalikan
   gradien putih di tepi atas. Yang kedua memperbaiki tampilannya tapi
   MEMATIKAN SELURUH ISI SLIDE: anak ber-z-index negatif dilukis di BELAKANG
   kotak induknya, sehingga `.hero` sendiri yang menerima setiap klik.
   Terukur `document.elementFromPoint()` di tengah tombol "Dapatkan Penawaran
   Gratis" mengembalikan `section.hero`, bukan tombolnya — tombol hero jadi
   tidak bisa diklik sama sekali, tanpa satu pun galat.

   Urutannya sekarang, semuanya di dalam `.hero` yang ber-`isolation: isolate`:
     1 track   -> foto + teks + tombol
     2 gradien -> putih di tepi atas, DI ATAS foto
     3 kontrol -> panah & titik

   Gradien boleh di atas teks karena tingginya cuma 260px (--fade-white-h)
   sementara judul hero mulai di ~400px; dan ia diberi `pointer-events: none`
   supaya tidak ikut menelan klik di wilayah itu. */
.hero-slider__track {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hero-slider.hero--fade-top::before {
  z-index: 2;
  pointer-events: none;
}

/* ⚠️ Slide TIDAK di-`display:none`. Tingginya ikut menentukan tinggi hero,
   dan kalau yang non-aktif dicabut dari alur, hero menyusut lalu melonjak
   tiap kali slide dengan panjang judul berbeda masuk -- CLS yang terlihat
   jelas. Dengan opacity, ketiganya selalu menempati kotak yang sama. */
.hero-slider__slide {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding-block: var(--sp-30) var(--sp-6);
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity var(--t-hero-fade, 500ms) var(--ease);
}

.hero-slider__slide.is-active { opacity: 1; }

/* Tanpa JS slide tidak pernah berganti, jadi yang bertumpuk di baliknya
   harus disembunyikan -- kalau tidak ketiga judul saling menimpa. */
.anaya-no-js .hero-slider__slide:not(.is-active) { visibility: hidden; }

/* Panah kiri-kanan.
   Gaya & posisinya mengikuti rujukan situs yang dikirim klien
   (2026-09-16), diukur langsung dari situsnya di viewport 1440:
   48x48, radius 50%, latar warna merek 62%, garis putih 82%, ikon 27px,
   dan duduk 24px dari tepi layar — jauh lebih ke tepi daripada --gutter.

   ⚠️ TIDAK lagi meminjam `.cert-nav`. Begitu gayanya menyimpang sejauh ini,
   memakai kelas yang sama berarti setiap perubahan pada carousel sertifikat
   diam-diam mengubah panah hero juga — dan sebaliknya. */
.hero-slider__nav {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 3;

  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.82);
  border-radius: 50%;
  background: rgba(28, 117, 188, 0.62);
  color: var(--c-white);
  box-shadow: 0 8px 20px rgba(2, 23, 48, 0.24);
  cursor: pointer;
  transition: background-color 180ms var(--ease), border-color 180ms var(--ease),
              color 180ms var(--ease), scale 180ms var(--ease);
}

.hero-slider__nav .icon { width: 27px; height: 27px; }

/* Hover: isian TERANG penuh + ikon gelap, meniru perubahan keadaan di
   rujukan (di sana kuning merek). Anaya tidak punya warna hangat, jadi yang
   dipakai putih penuh dengan ikon biru merek — pola yang sudah ada di tema
   sebagai `.btn--white`, sekaligus satu-satunya pasangan yang lolos kontras:
   biru merek di atas putih 4,86:1, sementara putih di atas biru muda merek
   (#27AAE1) cuma 2,4:1. */
.hero-slider__nav:hover,
.hero-slider__nav:focus-visible {
  background: var(--c-white);
  border-color: var(--c-white);
  color: var(--c-primary);
  scale: 1.06;
}

.hero-slider__nav--prev { left: 24px; }
.hero-slider__nav--next { right: 24px; }

@media (max-width: 1100px) {
  /* Di bawah ini panah 24px dari tepi mulai menindih teks hero yang
     melebar. Dikembalikan ke dalam gutter. */
  .hero-slider__nav--prev { left: var(--sp-4); }
  .hero-slider__nav--next { right: var(--sp-4); }
}

/* Titik navigasi. Dump: aktif 21px terisi putih 80%, nonaktif 13px bergaris
   putih -- jadi yang berubah UKURAN dan ISIAN-nya, bukan cuma opasitas.
   Kotak tombolnya tetap 21px di kedua keadaan supaya barisnya tidak
   bergeser saat slide berganti. */
.hero-slider__dots {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  /* Dump: Group 16 di y 523 dari hero 640px -> 117px dari dasar. */
  bottom: 96px;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  z-index: 3;
}

.hero-slider__dot {
  display: grid;
  place-items: center;
  width: 21px;
  height: 21px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}

.hero-slider__dot::before {
  content: '';
  width: 13px;
  height: 13px;
  border: 1px solid var(--c-white);
  border-radius: 50%;
  transition: width var(--t-base), height var(--t-base), background-color var(--t-base);
}

.hero-slider__dot.is-active::before {
  width: 21px;
  height: 21px;
  background: rgba(255, 255, 255, 0.8);
  border-color: transparent;
}

/* Tanpa JS kontrolnya tidak melakukan apa pun -- lebih baik tidak ada
   daripada ada tapi mati (pola yang sama dengan tombol Bagikan). */
.anaya-no-js .hero-slider__kontrol,
.anaya-no-js .hero-slider__dots { display: none; }

@media (max-width: 900px) {
  /* Di layar sempit panah menutupi teks hero; titiknya sudah cukup, dan
     geser-sentuh tetap berfungsi. */
  .hero-slider__kontrol { display: none; }
  .hero-slider__dots { bottom: var(--sp-8); }
}

/* Gradien putih di tepi atas foto. Inilah yang membuat menu berteks gelap
   terbaca di atas hero; tanpa ini header harus dibalik jadi teks putih. */
.hero--fade-top::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: var(--fade-white-h);
  background: var(--fade-white);
  z-index: -1;
}

/* Home tidak memakai overlay gelap: foto pelabuhannya terang dan teks putih
   sudah kontras. Bayangan halus dipakai sebagai gantinya. */
.hero--plain::after { background: none; }

.hero--plain .hero__title,
.hero--plain .hero__subtitle {
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35);
}

.hero__title {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
  /* line-height & margin ditulis eksplisit, bukan diwarisi dari <h1>: di
     halaman artikel tunggal elemen ini <p>, karena H1 halaman itu adalah
     JUDUL ARTIKELNYA. Tanpa kedua baris ini tampilannya bergantung pada
     nama tag, dan mengganti tag diam-diam menggeser tata letak. */
  line-height: var(--lh-tight);
  margin: 0;
  text-wrap: balance; /* sama dengan h1, supaya <p> memecah baris persis sama */
}

.hero__subtitle {
  font-size: var(--fs-hero-sub);
  font-weight: var(--fw-regular);
  /* Dump Home & Tentang: 25px/31px = rasio 1,24. --lh-body (1,7) yang
     terwarisi dari body menghasilkan 43px — subjudul hero jadi renggang
     seperti paragraf, padahal ini teks display pendek. */
  line-height: var(--lh-tight);
  margin-top: var(--sp-2);
  /* Dibatasi supaya pecah barisnya mengikuti desain (subjudul Tentang
     lebarnya 808px, bukan selebar container). */
  max-width: 810px;
  margin-inline: auto;
}

.hero__actions { margin-top: var(--sp-6); }

/*
 * ⚠️ Tombol tidak boleh melebihi container. `.btn` itu `inline-flex`, jadi
 * lebarnya murni isi + padding dan ia TIDAK menyusut — di 360px tombol hero
 * "Dapatkan Penawaran Gratis" terukur 308px sementara containernya 300px,
 * dan halamannya meluber 8px. Cacat lama, baru tersingkap saat versi mobile
 * disapu 2026-09-17.
 *
 * `max-width` adalah jaring pengamannya (teks membungkus, tidak meluber);
 * padding yang dirampingkan yang menjaga teksnya tetap satu baris.
 */
.btn { max-width: 100%; }

@media (max-width: 400px) {
  .hero__actions .btn { padding-inline: var(--sp-6); }
}

/* ------------------------------------------------------------
   12. BAND CTA FOTO
   ------------------------------------------------------------ */

.cta-band {
  position: relative;
  display: grid;
  place-items: center;
  /* Dump (Oil 1 / Rectangle 9): band ini 1440x284. Sebelumnya tingginya
     ikut konten (233px) dan meleset dari desain. */
  min-height: 284px;
  /* Dump Tentang: teks mulai 56px dari tepi atas band, tombol berakhir 49px
     sebelum tepi bawah. --sp-16 (64px) membuat total isi 336px sehingga
     min-height 284px di atas tidak pernah terpakai. Dengan 48px total isi
     272px -> min-height yang menentukan, dan place-items:center menaruhnya
     persis di tengah 284px seperti desain. */
  padding-block: var(--sp-12);
  text-align: center;
  color: var(--c-white);
  background-size: cover;
  background-position: center;
  isolation: isolate;
}

.cta-band::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--overlay-band);
  z-index: -1;
}

/* Dump Tentang: jarak teks ke tombol 35px, bukan 64px. */
.cta-band__actions { margin-top: var(--sp-8); }

.cta-band__text {
  /* Dump Tentang: 881px. */
  max-width: 890px;
  /* WAJIB, jangan dihapus. `place-items: center` di .cta-band memusatkan
     ANAKNYA — dan anaknya cuma satu: .container (1200px). Paragraf ini ada
     satu tingkat lebih dalam, jadi ia blok biasa yang menempel di tepi kiri
     container. `text-align: center` menipu di sini: ia memusatkan BARIS
     TEKS di dalam kotak 890px, sementara kotaknya sendiri tetap di kiri —
     sehingga terbaca rata tengah tapi seluruh bloknya bergeser 155px ke
     kiri di setiap lebar layar (diukur 2026-09-09 di 1440px & 1920px).
     Tombolnya tidak kena karena .cta-band__actions selebar penuh container.
     Bug ini ada sejak Fase 2 dan luput dari perbandingan ke prototipe —
     prototipenya pun salah dengan cara yang sama (aturan #38). */
  margin-inline: auto;
  /* Dump Tentang menyebut 24px — sama dengan token --fs-product. Dipakai
     ulang daripada menambah token baru dengan nilai yang sama. */
  font-size: var(--fs-product);
  /* Dump: 24px/30px = rasio 1,25. Dengan --lh-body (1,7) barisnya 41px dan
     band-nya membengkak dari 284px ke 368px. */
  line-height: var(--lh-tight);
}

/* ------------------------------------------------------------
   13. BRAND / LOGO
   ------------------------------------------------------------
   Logo Anaya dipakai di header (versi berwarna) dan footer
   (versi putih). Ukuran di Figma: 134 x 55 px; file PNG diexport
   @3x (402 x 165) supaya tetap tajam di layar retina.
   Tinggi jadi patokan, lebar mengikuti rasio -> aman kalau nanti
   logo diganti file lain dengan proporsi sedikit berbeda.
   ------------------------------------------------------------ */

.brand {
  display: inline-flex;
  align-items: center;
  flex: none;
}

.brand__img {
  display: block;
  width: auto;
  height: var(--brand-h, 55px);
  /* Logo bisa diganti dari Pengaturan Situs (2026-10-14): logo unggahan yang
     jauh lebih lebar dari aslinya (134px) dibatasi tanpa digepengkan, supaya
     navbar tidak terdorong. Logo tema & Flexipack (223px) tidak terdampak. */
  max-width: 300px;
  object-fit: contain;
}

/* Versi putih untuk latar gelap/biru (footer, header transparan). */
.brand--light .brand__img { --brand-h: 55px; }

@media (max-width: 900px) {
  .brand__img { --brand-h: 42px; }
}

/* ------------------------------------------------------------
   14. HEADER / NAVBAR
   ------------------------------------------------------------ */

/* Navbar MENGIKUT saat digulir (permintaan klien, rapat 2026-09-15).
   `sticky`, bukan `fixed`: header tetap berada di dalam alur dokumen,
   sehingga tinggi halaman tidak berubah sedikit pun dan tidak perlu
   padding-top penyeimbang di <body> — ketujuh halaman tetap 0px terhadap
   prototipe. Halaman Home memakai jalur berbeda (lihat .header--overlay). */
.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--c-white);
}

/* Varian Home: header melayang di atas foto hero, tanpa latar sendiri.

   `fixed` SEJAK AWAL, bukan `absolute` yang nanti berganti. Di posisi diam
   hasilnya identik — .hero-stack mulai di y=0, jadi `absolute` di dalamnya dan
   `fixed` terhadap viewport menggambar di tempat yang sama persis, dan keduanya
   sama-sama di luar alur sehingga tinggi halaman tidak berubah. Bedanya: dengan
   `fixed`, navbar TIDAK PERNAH hilang, jadi tidak ada yang perlu "dimunculkan
   kembali" — dan tidak ada momen munculnya yang bisa terlihat patah.

   Versi sebelumnya menunggu hero terlewat baru muncul. Terukur: navbar hilang
   dari scrollY 152 sampai 640, yaitu 488px gulir TANPA navbar sama sekali,
   lalu muncul mendadak; dan saat digulir naik ia lenyap dalam SATU frame
   (masuk dianimasikan 400ms, keluar 0ms). Asimetri itu yang paling terbaca
   sebagai "patah", dan memperhalus animasinya tidak akan menyentuh void
   488px-nya sama sekali. */
.header--overlay {
  position: fixed;
  inset: 0 0 auto;
  background: transparent;
  transition: background-color 220ms var(--ease);
}

/* ⚠️ Latar WAJIB memutih begitu gulir dimulai — ini bukan pilihan gaya.
   Teks navbar hitam, dan foto hero makin gelap ke bawah: rasio kontras teks
   hitam terhadap pita 152px terukur 15,78 di scrollY 0, 4,83 di 200, lalu
   JATUH ke 4,29 di 300 dan 2,78 di 488 (foto pelabuhannya gelap & ramai).
   Jadi kalau navbar menempel tapi dibiarkan transparan, ia berhenti terbaca
   persis di paruh bawah hero. Ambang 40px membuat pemutihannya selesai jauh
   sebelum titik gagal itu. */
.header--overlay.is-solid { background: var(--c-white); }

/* Border chip di atas foto hero: putih ~90% opacity, bukan biru.
   Diverifikasi lewat sampel piksel render Figma langsung (bukan dump CSS,
   yang gagal menangkap stroke ini): tepi pill terbaca ~R250 G253 B254 di atas
   langit ~R211 G230 B241 — border biru akan terlihat gelap/kontras di sana,
   sementara di desain tepinya nyaris menyatu dengan foto terang.

   Sengaja disaring `.header__inner > .header__aside`: di <=900px main.js
   MEMINDAHKAN aside ke dalam drawer putih, dan di sana pill bergaris putih
   tidak terlihat sama sekali. Dengan saringan ini varian hero berhenti
   berlaku begitu aside pindah, jadi tidak perlu aturan kedua yang
   membatalkannya — dulu ada, dan dua aturan yang saling meniadakan seperti
   itu selalu berakhir lepas sinkron.

   Begitu latar header memutih (.is-solid) pill kembali ke kulit bawaannya,
   dan pergantiannya ikut memudar bersama latar headernya.

   ⚠️ Yang berganti cuma WARNA garisnya, bukan ADA/TIDAKNYA garis. Chip selalu
   ber-border 1px; di keadaan padat warnanya `transparent`. Kalau border-nya
   benar-benar dilepas, lebar pill menyusut 2px (lebarnya auto, mengikuti teks)
   sehingga ia tersentak setiap kali berganti keadaan — dan `border-width` juga
   tidak bisa dipudarkan, cuma `border-color` yang bisa. */
.header--overlay:not(.is-solid) .header__inner > .header__aside .chip {
  --chip-garis: rgba(255, 255, 255, 0.9);
  --chip-bg: transparent;
  --chip-shadow: none;
}


/* Grid 1fr auto 1fr, bukan flex space-between: dengan space-between posisi nav
   ikut lebar logo & sisi kanan yang tidak sama, sehingga meleset ~30px dari
   tengah. Kolom sisi yang sama lebar membuat nav persis di tengah seperti desain. */
.header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sp-8);
  /* Asimetris, dari sampel piksel Tentang (Preview).png: pita header putih
     setinggi 152px, logo 134x55 menempati y 37..92 — jadi 37px di atas dan
     60px di bawah, bukan 40/40. Dengan 40/40 header cuma 135px dan SELURUH
     isi halaman naik 17px dari desain. */
  padding-block: 37px 60px;
}

.header__inner > .brand { justify-self: start; }
.header__inner > .header__aside { justify-self: end; }

/* ⚠️ Menu, chip FLEXITANK & pilihan bahasa terpusat pada PITA HEADER (152px),
   BUKAN pada baris logo (55px) — dan itu dua garis tengah yang berbeda: baris
   logo berpusat di y 64,5 sementara pita berpusat di y 76.

   Dengan `align-items: center` saja ketiganya ikut baris logo, jadi SELURUHNYA
   10px terlalu tinggi dari desain. Terukur dari Header.png vs render: logo
   37..91 di keduanya (cocok persis), tapi "Home" 69..80 di desain vs 59..69 di
   render, "Kontak" 69..80 vs 58..69, "ID|EN" 68..83 vs 59..69, dan pill
   FLEXITANK 58..91 vs 48..81. Penyimpangannya seragam 10px di keempatnya —
   tanda satu sebab, bukan empat.

   Dibaca balik dari dump, ketiganya memang kotak yang terpusat pada 152px:
   chip 34px -> (152-34)/2 = 59 (dump 58), teks menu & bahasa 20px -> 66
   (dump 65). Logonya yang justru TIDAK terpusat (37..92), dan itu sudah
   tercatat sejak Fase 2 dari sampel piksel.

   Hanya >=901px. Di bawah itu tinggi baris ditentukan tombol menu 44px dan
   asidenya sudah pindah ke drawer, jadi memusatkan pada pita akan menggeser
   tombol hamburger 11px tanpa ada yang meminta.

   ⚠️ 900.02px, BUKAN 901px (berlaku untuk SEMUA pasangan min/max di berkas
   ini: 900.02 vs 900, 1024.02 vs 1024). Peramban yang di-zoom atau emulator
   perangkat bisa memberi lebar viewport PECAHAN — mis. 1024,5px. Di situ
   `max-width: 1024px` tidak cocok dan `min-width: 1025px` juga tidak, jadi
   KEDUA blok lolos dan halaman jatuh ke aturan dasar. Itu yang dilihat klien
   di iPad 2026-10-07: hero Flexipack memakai geometri Flexitank (gambar 155%
   kolom) dan menutupi kartunya. */
@media (min-width: 900.02px) {
  .header__inner {
    min-height: var(--header-h);
    padding-block: 0;
  }

  .header__inner > .brand {
    align-self: start;
    margin-top: 37px;
  }
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--sp-12);   /* jarak antar menu di desain ~54px */
}

.nav__link {
  /* ANA-019 — target sentuh minimal 24x24 (WCAG 2.2 SC 2.5.8).
     Terukur sebelumnya 23px: kurang SATU piksel.

     ⚠️ Kotaknya tumbuh SIMETRIS di sekitar garis tengah yang sudah
     dikalibrasi ke Header.png (aturan #61) — `inline-flex` + `align-items:
     center` menjaga tinta teksnya tetap di pusat pita 152px, jadi
     perataan navbar yang susah payah disamakan itu tidak bergeser.

     ⚠️ Catatan: navbar ini sebenarnya SUDAH lolos lewat pengecualian jarak
     pada SC 2.5.8 — jarak antar-target terukur 48px, jauh di atas syarat.
     Perbaikan ini menutup temuannya secara harfiah supaya tidak perlu
     dijelaskan ulang setiap kali diaudit. */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--c-ink);
  font-size: var(--fs-body-sm);
  transition: color var(--t-fast);
}

.nav__link:hover { color: var(--c-primary); }

/* Dump Home, Tentang & Produk sepakat: menu nonaktif weight 300 (Light),
   yang aktif 700 — bukan 400/600 yang dipakai sebelumnya. Selisihnya terlihat:
   dengan 400/600 seluruh baris menu terkesan rata tebal dan halaman yang
   sedang dibuka kurang menonjol. */
.nav__link { font-weight: var(--fw-light); }
.nav__link.is-active { font-weight: var(--fw-bold); }

.nav__item { position: relative; }

.nav__item--has-menu > .nav__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

.nav__link .icon { width: 14px; height: 14px; }

/* Dropdown Produk */
.nav__menu {
  position: absolute;
  top: calc(100% + var(--sp-3));
  left: 50%;
  translate: -50% 0;
  min-width: 220px;
  margin: 0;
  padding: var(--sp-4);
  list-style: none;
  background: var(--overlay-nav-dropdown);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-dropdown);
  z-index: var(--z-dropdown);

  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--t-base), transform var(--t-base), visibility var(--t-base);
}

.nav__item--has-menu:hover .nav__menu,
.nav__item--has-menu:focus-within .nav__menu {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.nav__menu a {
  display: block;
  padding: var(--sp-3) 0;
  color: var(--c-white);
  font-size: var(--fs-body-sm);
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
}

.nav__menu li:last-child a { border-bottom: 0; }
.nav__menu a:hover { opacity: 0.8; }

/* Toggle bahasa */
.lang {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-body-sm);
}

.lang a { color: var(--c-ink); }
.lang .is-active { font-weight: var(--fw-bold); }
.lang__sep { color: var(--c-border); }

.nav-toggle { display: none; }

@media (max-width: 900px) {
  /* .nav jadi drawer LAYAR-PENUH sehingga keluar dari alur grid; yang tersisa
     di baris header cuma logo + tombol menu. Chip FLEXITANK & pilihan bahasa
     dipindahkan ke dalam drawer oleh main.js (initHeaderAside) — aturan
     display:none di bawah cuma jaring pengaman kalau JS belum sempat jalan,
     supaya kolom grid tidak terlanjur salah hitung. */
  .header__inner { grid-template-columns: 1fr auto; }
  .header__inner > .header__aside { display: none; }

  /* Logo ikut diangkat di atas drawer bersama tombolnya, supaya baris
     header (logo + tombol tutup) tetap utuh saat menu terbuka — tanpa ini
     drawer putih menutup seluruh branding. */
  .header__inner > .brand { position: relative; z-index: calc(var(--z-drawer) + 1); }

  .nav-toggle {
    display: grid;
    place-items: center;
    /* 44px = ambang minimum area sentuh yang nyaman di HP; ikonnya sendiri
       dinaikkan dari 20px (ukuran .icon umum) ke 28px karena di dalam kotak
       sebesar ini garis hamburger 20px terlihat kekecilan. */
    width: 44px;
    height: 44px;
    background: none;
    border: 0;
    color: var(--c-ink);
    /* Wajib di ATAS drawer, kalau tidak tombolnya ketutupan dan menu tidak
       bisa ditutup lagi. Keduanya bersaudara di stacking context yang sama
       (sama-sama anak .header__inner), jadi z-index cukup. */
    position: relative;
    z-index: calc(var(--z-drawer) + 1);
  }

  /* Drawer, isinya rata tengah — mulai TEPAT DI BAWAH header, bukan menutupi
     seluruh layar.

     ⚠️ Dulu `inset: 0` (layar penuh, termasuk area header), dan logo + tombol
     X "menang" cuma lewat z-index. Klien melaporkan 2026-10-05 dari HP: drawer
     terbuka tanpa logo dan tanpa tombol X — tidak ada jalan menutupnya.
     Pola yang dikenal di iOS Safari: elemen `position: fixed` di dalam induk
     `sticky` (header) dipromosikan ke lapisan komposit sendiri dan bisa
     dilukis di atas saudaranya tanpa peduli z-index. Emulator Chromium &
     WebKit Playwright TIDAK meniru perilaku komposit itu, jadi gejalanya tidak
     bisa direproduksi dari sini. Dengan drawer yang tidak menumpang header,
     baris logo + X tidak pernah tertutup di peramban mana pun — perbaikannya
     tidak lagi bergantung pada urutan lapisan sama sekali.
     --header-h di <=900 = 141px dan <=640 = 109px, persis tinggi header
     sesungguhnya (tokens.css). */
  .nav {
    position: fixed;
    top: var(--header-h);
    right: 0;
    bottom: 0;
    left: 0;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--sp-1);
    padding: var(--sp-8) var(--gutter) var(--sp-12);
    background: var(--c-white);
    box-shadow: none;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;   /* seirama dengan scrollbar halaman yang disembunyikan di base.css */
    z-index: var(--z-drawer);
    display: none;
  }

  .nav::-webkit-scrollbar { width: 0; }

  /* Header Home transparan di atas foto hero. Sejak drawer tidak lagi
     menutupi area header, baris logo + X akan duduk di atas foto selama menu
     terbuka — jadi header dipaksa putih, menyatu dengan drawer di bawahnya. */
  body.is-drawer-open .header { background: var(--c-white); }

  .nav-toggle .icon { width: 28px; height: 28px; }

  .nav.is-open { display: flex; }

  .nav__item { width: 100%; text-align: center; }

  .nav__link {
    display: block;
    padding-block: var(--sp-3);
    font-size: var(--fs-body);
  }

  /* .nav__item--has-menu > .nav__link tadinya inline-flex rata kiri —
     harus dipusatkan lagi supaya sejajar dengan menu lain. */
  .nav__item--has-menu > .nav__link {
    display: flex;
    justify-content: center;
  }

  /* Accordion Produk. Latar biru transparan versi desktop dilepas: di atas
     drawer putih hasilnya biru muda pucat dengan teks putih — nyaris tidak
     terbaca. Di sini cukup teks biasa yang sedikit diredupkan. */
  .nav__menu {
    position: static;
    translate: none;
    opacity: 1;
    visibility: visible;
    transform: none;
    display: none;
    min-width: 0;
    padding: 0 0 var(--sp-3);
    background: none;
    box-shadow: none;
  }

  .nav__item--has-menu.is-open .nav__menu { display: block; }

  .nav__menu a {
    padding: var(--sp-2) 0;
    color: var(--c-ink-soft);
    border-bottom: 0;
    text-align: center;
  }

  /* Chip + pilihan bahasa setelah dipindah ke dalam drawer. */
  .nav > .header__aside {
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-4);
    margin-top: var(--sp-8);
  }

  /* Garis pemisah antara chip FLEXITANK dan pilihan bahasa. Panjangnya tidak
     ditulis: .header__aside menyusut selebar anak terlebarnya (chip), lalu
     align-items:stretch membuat .lang ikut selebar itu — jadi garisnya selalu
     pas selebar chip, berapa pun teks chip-nya nanti. */
  .nav > .header__aside > .lang {
    justify-content: center;
    border-top: 1px solid var(--c-primary);
    padding-top: var(--sp-4);
  }
}

/* Pembungkus header melayang + hero. Memberi konteks posisi untuk
   .header--overlay supaya tidak bergantung pada body. */
.hero-stack { position: relative; }

/* Sisi kanan header: chip FLEXITANK + toggle bahasa. */
.header__aside {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
}

/* ------------------------------------------------------------
   HEADER FLEXIPACK (Flexitank, Bag in Box, Paper IBC, Pollination Bag)
   Dump 2026-10-05. Kerangka & perilakunya milik .header di atas — yang
   ditulis di sini cuma selisihnya.
   ------------------------------------------------------------ */

/* Logo SOLUFLEX (2026-10-23, menggantikan logo Flexipack): wordmark @3x
   642x84 dari klien + tagline "by Anaya Global Indonesia" yang sama dengan
   logo lama (Poppins Italic, 171px di artboard), jarak 10px — satu berkas
   642x154 = 214x51,3 di artboard. Tinggi jadi patokan. */
.header--flexipack .header__inner { --fp-logo-h: 51.33px; }
.header--flexipack .brand__img { --brand-h: var(--fp-logo-h); }

/* Dump: kotak logo mulai y=56 (logo Anaya y=37) — pita tetap 152px, jadi
   menu/chip/bahasa tetap terpusat pada pita seperti header Anaya. Logo
   yang lebih pendek (tablet) diturunkan setengah selisihnya supaya titik
   tengahnya tetap di tempat yang sama dengan versi desktop. */
@media (min-width: 900.02px) {
  .header--flexipack .header__inner > .brand {
    margin-top: calc(56px + (51.33px - var(--fp-logo-h)) / 2);
  }
}

/* HP 40px (167px lebar) — sama dengan tinggi logo Flexipack lama. */
@media (max-width: 900px) {
  .header--flexipack .header__inner { --fp-logo-h: 40px; }
}

/* Dump: chip berakhir x=1253, "ID | EN" mulai x=1277 -> 24px. */
.header--flexipack .header__inner > .header__aside { gap: var(--sp-6); }

/* Chip BERGARIS biru tanpa isian — "kembali ke Anaya". Dump Rectangle 3:
   178x34, border 1px #1C75BC, radius 20px; teks 16/20 w600 biru 136px ->
   padding 21px kiri-kanan. Hover tetap milik .chip (isi biru, teks putih). */
.chip--garis {
  --chip-garis: var(--c-primary);
  --chip-bg: transparent;
  --chip-shadow: none;
  padding-inline: 21px;
  /* Pil setinggi 34px tetap — teks yang patah baris meluber keluar garisnya
     ("kembali / ke / Anaya" bertumpuk, laporan klien di iPad 2026-10-07). */
  white-space: nowrap;
}

/* Header Flexipack di laptop kecil & iPad rebah (901..1279px).
   Grid `1fr auto 1fr` milik header Anaya memusatkan menu dengan membagi sisa
   ruang SAMA RATA ke kiri-kanan. Isi kanan Flexipack (chip 191px + ID|EN =
   263px) jauh lebih lebar daripada isi kanan Anaya, dan di bawah ~1250px
   kolom kanannya jadi lebih sempit daripada isinya: terukur chip 166px di
   1194 (patah 2 baris), 111px di 1024 (3 baris), dan logo tinggal 11px di
   901px. Di >=1280px ruangnya cukup, jadi desktop (sudah 0-4px dari dump)
   tidak disentuh.

   Di rentang ini: kolom `auto 1fr auto` (logo & sisi kanan selebar isinya,
   menu terpusat di sisa ruang), lalu logo, huruf menu, dan jarak menyusut
   bersama lebar layar. Disapu 901..1279px di keempat halaman ID & EN:
   jarak logo->menu & menu->chip >=18px, chip satu baris, tanpa geser. */
@media (min-width: 900.02px) and (max-width: 1279.98px) {
  .header--flexipack .header__inner {
    --fp-logo-h: clamp(36px, 3.6vw, 46px);
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: clamp(16px, 2vw, 24px);
  }
  .header--flexipack .header__inner > .nav {
    justify-self: center;
    gap: clamp(14px, calc(5.3vw - 34px), 36px);
  }
  .header--flexipack .nav__link { font-size: clamp(14px, 1.3vw, 16px); }
  .header--flexipack .header__inner > .header__aside { gap: var(--sp-4); }
  .header--flexipack .chip--garis {
    padding-inline: 14px;
    font-size: clamp(14px, 1.3vw, 16px);
  }
}

/* ------------------------------------------------------------
   INTRO PERUSAHAAN (Home)
   Proporsi kolom diambil dari dump: teks 546px, foto 585px.
   Ditulis sebagai fr supaya ikut menyusut, bukan lebar tetap.
   ------------------------------------------------------------ */

/* Dump Home: paragraf ini 16px/25 (546x141), bukan --fs-body (18px) yang
   terwarisi dari body. Selisihnya menambah 73px tinggi halaman. */
.intro p { font-size: var(--fs-body-sm); }

.intro {
  display: grid;
  grid-template-columns: minmax(0, 546fr) minmax(0, 585fr);
  align-items: start;
  gap: var(--sp-20);
}

.intro__actions { margin-top: var(--sp-8); }

.intro__media img {
  width: 100%;
  height: auto;
  border-radius: var(--r-md);
}

@media (max-width: 900px) {
  .intro {
    grid-template-columns: 1fr;
    gap: var(--sp-8);
  }
}

/*
 * Dump mobile: foto 340x238 (rasio 1,43). Berkas fotonya sendiri jauh lebih
 * melebar — terukur 344x140 di render, rasio 2,46 — jadi dengan `height:
 * auto` ia tampil sebagai pita tipis, hampir 100px lebih pendek dari desain.
 * Di mobile rasionya dipatok dan fotonya dipotong; `object-position: center`
 * menjaga bagian tengah gudang tetap terlihat.
 */
@media (max-width: 640px) {
  .intro__media img {
    aspect-ratio: 340 / 238;
    object-fit: cover;
    object-position: center;
  }
}

/* ------------------------------------------------------------
   KEPALA SECTION dengan aksi di kanan (section Blog)
   ------------------------------------------------------------ */

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  flex-wrap: wrap;
}

.section-head__title {
  font-size: var(--fs-section);
  font-weight: var(--fw-bold);
  color: var(--c-primary);
}

/* ------------------------------------------------------------
   SECTION PRODUK (Home)
   Latar molekul hanya menutupi bagian atas section — di desain tepi
   bawahnya memotong baris pertama kartu, jadi tingginya dikunci
   284px dan tidak mengikuti tinggi section.
   ------------------------------------------------------------ */

/* Foto band dipasang lewat atribut style di <section> sebagai background-image
   biasa. JANGAN dioper lewat custom property: url() relatif di dalam custom
   property diresolusi terhadap file CSS yang memakainya, bukan terhadap
   dokumen — 'assets/img/...' jadi dicari di 'assets/css/assets/img/...'.
   Sumbernya 2880x568, rasionya sama persis dengan band 1440x284, jadi
   background-size 100% x tinggi-band tidak menggepengkan gambar.

   Spesifisitas dinaikkan (.section.section--produk) agar padding atas tidak
   ikut dinolkan aturan .section + .section — padding itulah yang menempatkan
   judul di dalam band. */
.section.section--produk {
  --band-h: 284px;
  position: relative;
  padding-top: var(--sp-12);
  background-repeat: no-repeat;
  background-position: top center;
  background-size: 100% var(--band-h);
}

/* Lapisan putih 20% menurunkan kontras foto agar teks tetap terbaca. */
.section--produk::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: var(--band-h);
  background: rgba(255, 255, 255, 0.2);
  pointer-events: none;
}

/* Konten ikut jadi elemen terposisi supaya tergambar di atas lapisan putih,
   tanpa perlu main z-index negatif. */
.section--produk > * { position: relative; }

/* ------------------------------------------------------------
   JARAK ANTAR BLOK DALAM SECTION
   Ditulis sebagai aturan bertetangga, bukan utility margin di HTML,
   supaya markup tetap bersih dan nilainya hidup di satu tempat.
   ------------------------------------------------------------ */

.section-title + .section-lead { margin-top: var(--sp-3); }
.section-title + .icon-rail    { margin-top: var(--sp-12); }
.section-title + .marquee-group { margin-top: var(--sp-10); }

/* Dump: baris logo selebar 964px (Group 9) & 1011px (Group 8), terpusat —
   bukan selebar container 1200px. Lihat juga catatan proyek aturan #9: sempat
   full-bleed, lalu diperbaiki ke dalam .container, tapi 1200px masih ~190px
   lebih lebar dari desain. */
.marquee-group { max-width: 1011px; margin-inline: auto; }
.section-lead  + .cat-grid     { margin-top: var(--sp-16); }
/* Dua selektor, bukan satu: di prototipe `.cert-carousel` adalah saudara
   langsung `.section-title`, tapi di WordPress ia dibungkus
   `.cert-carousel-wrap` (pembungkus untuk panah navigasi, ditambahkan
   Fase 6). Pembungkus itu memutus kombinator `+` sehingga jarak 64px-nya
   hilang diam-diam — tidak ada error, cuma bagian Sertifikasi yang naik
   menempel ke judulnya. Setiap kali markup dibungkus elemen baru, periksa
   ulang aturan berpola `X + Y` yang menyangkut elemen itu. */
.section-title + .cert-carousel,
.section-title + .cert-carousel-wrap { margin-top: var(--sp-16); }
.section-head  + .grid-3       { margin-top: var(--sp-10); }

/* ------------------------------------------------------------
   KARTU NILAI (Tentang)
   Tiga kartu biru tembus pandang yang menumpang di tepi bawah hero.
   Karena latarnya semi-transparan, bagian atas kartu tampak lebih
   gelap (di atas foto) dan bagian bawah lebih terang (di atas putih) —
   efek gradasi itu datang sendiri, tidak perlu gradient.
   ------------------------------------------------------------ */

.section--values { padding-top: 0; }

.value-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-16);
  /* Dump: baris kartu 1043px (kartu 307px). Ditulis 1160px — SENGAJA lebih
     lebar dari dump. Alasannya font: baris pertama desain memuat "Layanan
     berkisar dari pasokan" dalam 249px, sementara Poppins butuh 278px untuk
     teks yang sama (~12% lebih lebar, lihat 01-design-system.md §2). Di
     lebar dump teks itu pecah jadi 7 baris (desain 5) dan kartunya membengkak
     dari 264px ke 314px. Di 1160px pecah barisnya kembali 5-4-5 dan tinggi
     kartu kembali 264px persis seperti desain — proporsi kartu meleset 11%
     di lebar, tapi seluruh sisanya kembali sama. Ini kompromi paling kecil
     yang tersedia; menyempitkan font di bawah 18px akan melanggar dump. */
  max-width: 1160px;
  margin-inline: auto;
  /* Naik menumpang hero. Nilainya dari dump: kartu mulai 66px sebelum
     foto hero berakhir. */
  margin-top: -66px;
  position: relative;
}

.card-value {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  min-height: 264px;
  padding: var(--sp-8);
  border-radius: var(--r-md);
  background: rgba(28, 117, 188, 0.65);
  color: var(--c-white);
}

.card-value .icon {
  width: 50px;
  height: 50px;
}

.card-value__text {
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
}

@media (max-width: 900px) {
  .value-grid {
    grid-template-columns: 1fr;
    gap: var(--sp-6);
    margin-top: var(--sp-8);   /* di layar sempit tumpang-tindih jadi berantakan */
  }
}

/* ------------------------------------------------------------
   PANEL ABU-ABU + DAFTAR BERTANDA BRAND (Misi, Tentang)
   ------------------------------------------------------------ */

.panel {
  background: var(--c-surface);
  border-radius: var(--r-md);
  padding: var(--sp-10);
}

.mission {
  display: grid;
  /* Dump: foto 433 (x 152..585), celah 54, kolom kanan 639..1287 = 648
     (penanda 20,16 + celah 20,84 + ruang teks 607). Perbandingan desain
     40 : 60.
     ⚠️ Digeser jadi 35 : 65 — aturan #28. Baris terpanjang poin misi
     ("...untuk kebutuhan bahan") butuh >=635px di Poppins, sementara ruang
     teks desain cuma 607px di Google Sans Flex. Di 582px yang dihasilkan
     perbandingan lama, poin pertama pecah jadi EMPAT baris padahal desain
     tiga — dan itu yang dilaporkan klien 2026-09-17.
     Disapu 620..700px per 1px: pecah baris sama persis dengan Figma pada
     635..675, jadi dipakai 655 (tengah, bantalan 20px ke dua arah).
     655 + 20 + 21 = 696 kolom kanan -> 376 sisa untuk foto (-13% terhadap
     dump). Yang digeser lebar KOTAKNYA, bukan ukuran hurufnya. */
  grid-template-columns: minmax(0, 376fr) minmax(0, 696fr);
  align-items: start;
  gap: var(--sp-12);
}

.mission__media img {
  width: 100%;
  height: auto;
  border-radius: var(--r-md);
}

.mission__title {
  font-size: var(--fs-section);
  font-weight: var(--fw-bold);
  color: var(--c-primary);
}

/* Daftar bertanda chevron brand, bukan bullet. */
/* Dump: item misi 18px/25 = rasio 1,39. --lh-body (1,7) yang terwarisi dari
   body membuatnya 31px — daftar pendek berbutir jadi seregang paragraf. */
.list-brand li { line-height: var(--lh-snug); }

.list-brand {
  margin: var(--sp-10) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--sp-8);
}

.list-brand > li {
  display: grid;
  grid-template-columns: 20px 1fr;
  /* ⚠️ 21px, bukan --sp-10 (40px). Dump menaruh penanda di x 639 (lebar
     20,16) dan teks di x 680 -> offset total 41px, jadi CELAHNYA 41 - 20 =
     21px. Yang 40px itu salah baca: selisih KOORDINAT KIRI penanda dan teks
     dibaca sebagai celah, padahal lebar penanda belum dikurangi. Akibatnya
     teks bergeser 20px terlalu jauh ke kanan DAN kotaknya 20px lebih sempit
     — ikut mendorong pecah baris lebih awal. */
  gap: 21px;
  align-items: start;
}

.list-brand .icon {
  width: 20px;
  height: 22px;
  margin-top: 0.35em;   /* sejajar dengan baris pertama teks */
  color: var(--c-primary);
}

@media (max-width: 900px) {
  .mission { grid-template-columns: 1fr; }
  .list-brand > li { gap: var(--sp-5); }
}

/* ------------------------------------------------------------
   DETAIL PRODUK (halaman Produk)
   ------------------------------------------------------------ */

/* Sidebar 290px tetap (dump), sisanya kolom detail. Gap 40px = jarak
   antara garis sidebar dan awal judul produk di dump. */
/* minmax(0, ...) di kedua kolom WAJIB ada. Tanpa itu, grid item punya
   min-width:auto bawaan = ukuran min-content anak-anaknya — dan
   `.spec-table` di dalam kolom kanan punya min-width:420px. Item grid
   pun dipaksa selebar itu (menyeret kolom kiri ikut melebar juga di
   layar sempit), sampai seluruh `.product-layout` meluber ke samping.
   `.spec-table-wrap { overflow-x:auto }` tidak pernah sempat bekerja
   karena overflow-nya sudah "bocor" ke level grid duluan. Ketahuan
   lewat tools/shot.py di 390px murni (Chrome --window-size biasa
   punya lantai ~512px, jadi bug ini tidak kelihatan di situ). */
.product-layout {
  display: grid;
  grid-template-columns: minmax(0, 290px) minmax(0, 1fr);
  gap: var(--sp-10);
  align-items: start;
}

.product-nav { width: 290px; }

/* Keterangan di dalam kotak sidebar saat kategori belum punya produk, atau
   saat pencarian tidak menemukan apa pun. Bentuknya sengaja mengikuti
   `.product-nav__item` (padding & garis bawah yang sama) supaya kotaknya
   tetap terbaca sebagai daftar, cuma isinya yang menjelaskan. */
.product-nav__kosong {
  padding: var(--sp-4) var(--sp-8);
  color: var(--c-ink-soft);
  font-size: var(--fs-body-sm);
}

/* Catatan pengganti tabel spesifikasi untuk produk yang datanya belum masuk.
   `flex-basis: 100%` karena induknya `.product-block` itu flex-wrap — lihat
   aturan #37 catatan proyek; tanpa ini paragrafnya cuma selebar teksnya. */
.product-block--catatan p {
  flex-basis: 100%;
  margin: 0;
  color: var(--c-ink-soft);
}

.product-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

/* 30px/800/primer/uppercase — nilai sama dengan hero title, terverifikasi
   sama di 3 halaman Produk (Standard/Industrial/Pharma Grade). */
.product-title {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
  color: var(--c-primary);
  text-transform: uppercase;
}

.product-grade {
  margin-top: var(--sp-2);
  font-size: var(--fs-body);
}

.product-photo {
  margin-top: var(--sp-6);
  border-radius: var(--r-md);
  overflow: hidden;
}

.product-photo img {
  width: 100%;
  height: auto;
  aspect-ratio: 883 / 337;
  object-fit: cover;
}

.product-feature {
  margin-top: var(--sp-8);
  font-size: var(--fs-body);
}

.product-feature dt {
  display: inline;
  font-weight: var(--fw-bold);
  text-transform: uppercase;
}

.product-feature dd {
  display: inline;
  margin-left: var(--sp-2);
}

/* Dump ("PACKAGING:" & isi daftarnya, "SERTIFIKASI:" & baris logo): label
   dan kontennya sejajar SATU BARIS (top sama persis, 1678px & 1776px),
   bukan label di atas lalu konten di bawahnya. Sempat ditulis stacked
   (.product-block__label pakai margin-bottom, container tanpa flex) —
   ketahuan pas dibandingkan lagi ke Preview.png. Pola ini sama seperti
   .product-feature (dt/dd) di atas untuk "Karakteristik Produk", cuma di
   sana kontennya teks polos (bisa display:inline), sedangkan Packaging
   (list) & Sertifikasi (baris logo) perlu tetap jadi block/flex sendiri —
   makanya baris label+konten di-flex di sini, bukan inline. */
.product-block {
  margin-top: var(--sp-10);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--sp-2) var(--sp-4);
}

.product-block__label {
  font-weight: var(--fw-bold);
  font-size: var(--fs-body);
  text-transform: uppercase;
  flex: none;
}

.packaging-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.packaging-list li {
  position: relative;
  padding-left: var(--sp-5);
  font-size: var(--fs-body);
}

.packaging-list li + li { margin-top: var(--sp-1); }

.packaging-list li::before {
  content: '';
  position: absolute;
  left: var(--sp-1);
  top: 0.7em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--c-ink);
}

/* Baris label:nilai sebaris — dipakai untuk field opsional produk
   (Packaging, Shelf Life) yang di beberapa grade (Industrial, Pharma)
   tampil satu baris, bukan daftar bullet seperti Standard Grade. */
.product-extra__line {
  margin-top: var(--sp-4);
  font-size: var(--fs-body);
  /* Induknya `.product-block` sengaja flex-wrap supaya LABEL bisa duduk
     sebaris dengan nilainya ("KARAKTERISTIK PRODUK: Kristal Putih").
     Efek sampingnya: dua paragraf ini ikut jadi flex item dan berdiri
     bersebelahan, sehingga "PACKAGING: ..." dan "SHELF LIFE: ..." tergabung
     jadi satu baris. Render Figma (Produk - KCL Pharma Grade) menaruhnya
     bertumpuk dua baris, jadi tiap paragraf mengambil satu baris flex penuh.
     Diwarisi dari prototipe Fase 2 (perilakunya sama persis di sana);
     ketahuan 2026-09-08 saat perbandingan berdampingan ke Figma. */
  flex-basis: 100%;
}

.product-extra__line strong {
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  margin-right: var(--sp-2);
}

/* Tabel spesifikasi berkolom banyak (mis. Chemical Analysis Industrial
   Grade: Typical/Min/Max) — kolom pertama tetap melebar, sisanya sama rata. */
table.spec-table.spec-table--wide td,
table.spec-table.spec-table--wide th {
  width: auto;
  text-align: center;
}

table.spec-table.spec-table--wide td:first-child,
table.spec-table.spec-table--wide th:first-child {
  text-align: left;
}

/* Lebar kolom diatur dari CMS (field `lebar`, dirender jadi <colgroup>).
   `table-layout: fixed` WAJIB: tanpa itu lebar pada <col> cuma jadi saran dan
   peramban tetap melebarkan kolom yang isinya panjang, sehingga angka yang
   diatur klien terlihat diabaikan.
   Di HP tabelnya tetap digeser — aturan min-width: max-content di bawah
   menang atas width:100%, jadi kolom sempit tidak ikut memeras teksnya. */
.spec-table--lebar { table-layout: fixed; width: 100%; }

/* <=768px: BIARKAN KOLOM SELEBAR ISINYA, jangan diperas.
   `.spec-table-wrap` memang sudah `overflow-x: auto` sejak aturan #14, jadi
   tabel yang lebih lebar dari layar tinggal digeser. Tapi `min-width: 420px`
   membuatnya berhenti melebar tepat di angka itu, sehingga kolomnya justru
   DIPERAS supaya muat 420 — dan yang dikorbankan adalah keterbacaan:
   terukur di 390px, judul "CHEMICAL ANALYSIS" pecah 2 baris (header 76px)
   dan "Potassium Chloride (KCL)" pecah 3 baris (baris 102px).

   `min-width: max-content` membuat lebarnya ditentukan isi, bukan angka
   karangan. Terukur pada katalog sekarang: tabel 4 kolom butuh 580px, tabel
   2 kolom 250-551px — cukup dekat sehingga gesernya pendek.

   ⚠️ Tetap dipasangkan dengan `width: 100%` yang sudah ada, dan urutannya
   penting untuk dipahami: lebar tabel jadi max(100%, max-content). Kalau
   isinya muat, tabel tetap melebar penuh seperti dulu (tidak menyusut jadi
   selebar isi); kalau tidak muat, barulah ia melar dan digeser.

   ⚠️ HANYA <=768px. Di 1024px ke atas tabel sudah 639-868px dan tidak ada
   yang pecah baris sama sekali, jadi menyentuh desktop cuma menambah risiko
   tanpa memperbaiki apa pun. */
@media (max-width: 768px) {
  .spec-table { min-width: max-content; }
}

/* ------------------------------------------------------------
   CTA FORM MELAYANG (halaman Produk & Flexitank)
   Teks di atas latar putih, foto band di bawahnya, kartu form
   ditarik naik lewat margin negatif sehingga bagian atasnya duduk
   di atas putih dan bagian bawahnya menumpang foto — persis dump:
   form (434 tinggi) mulai 204px sebelum foto, berakhir 112px di
   dalam foto (foto tinggi 342px).
   ------------------------------------------------------------ */

.produk-cta__lead {
  max-width: 800px;
  margin-inline: auto;
  text-align: center;
  font-size: var(--fs-section);
  font-weight: var(--fw-bold);
  color: var(--c-primary);
}

.produk-cta__form {
  position: relative;
  /* Tanpa z-index, foto di bawahnya (menyusul di DOM, ditarik naik lewat
     margin negatif) menimpa 112px bagian bawah kartu ini — termasuk tombol
     Submit — karena elemen belakangan menang di stacking context yang sama.
     Ketahuan saat screenshot: Submit "hilang" tertutup foto, bukan cuma
     soal warna/shadow. */
  z-index: 1;
  /* Dump (Rectangle 75, sama persis di Standard/Industrial/Pharma Grade &
     Flexitank): 814px, bukan 680px — sempat ditulis lebih sempit dari
     seharusnya, jadi kartu kelihatan "mengambang kekecilan" dibanding
     lebar foto/section di sekitarnya. */
  max-width: 814px;
  margin: var(--sp-10) auto 0;
  /* Alpha 90% (bukan putih solid) — kartu ini menumpang foto di bagian
     bawahnya, dump-nya rgba(255,255,255,.9), bukan var(--c-white) biasa. */
  background: rgba(255, 255, 255, 0.9);
}

/* Dump (Rectangle 73 vs Rectangle 75, Standard Grade — pola sama di semua
   varian): foto top=2414, tinggi342 -> bottom 2756. Kartu top=2210,
   tinggi434 -> bottom 2644. Overlap (bagian foto yang KETUTUP kartu) =
   2644-2414 = 230px, sisanya yang TERLIHAT di bawah kartu cuma 112px
   (2756-2644). Dua angka ini sempat KETUKAR — margin-top ditulis -112
   (dikira itu overlap-nya), padahal 112 itu justru bagian yang kelihatan.
   Akibatnya foto ketutup kartu kurang jauh; foto seharusnya naik sampai
   sejajar field "No telp/Whatsapp" (kira-kira pertengahan kartu), bukan
   cuma menyentuh sedikit di bawah tombol Submit. */
.produk-cta__photo {
  height: 342px;
  margin-top: -230px;
  background-size: cover;
  background-position: center;
}

/* Sama seperti .post-layout: sidebar daftar produk 290px membuat kolom
   detail tinggal 421-534px di rentang 901-1024px, sementara tabel
   spesifikasinya sendiri sudah min-width 420px. Bertumpuk mulai 1024px. */
@media (max-width: 1024px) {
  .product-layout { grid-template-columns: minmax(0, 1fr); }
  .product-nav { width: 100%; max-height: 320px; }
}

/* Garis pemisah antar section, selebar viewport.
   Di desain muncul di atas & di bawah section Klien. */
.rule {
  height: 1px;
  border: 0;
  background: var(--c-border);
}

/* Dump (Line 1, di atas "Solusi terpercaya..." — sama di semua halaman
   Produk & Flexitank): garis full-bleed BIRU, bukan abu-abu seperti
   .rule biasa. Sempat tidak ada sama sekali di section form CTA ini. */
.rule--primary { background: var(--c-primary); }

/* ------------------------------------------------------------
   NILAI PERUSAHAAN (Tentang) — section baru 2026-09-16
   Dump: judul y 1347; daftar & foto sama-sama mulai y 1441 dan sama-sama
   berakhir ~1832 (tinggi 391). Teks 455px di x 152, penanda di x 113,
   foto 645x391 di x 682. Container 113..1327 -> kolom 569 : 645.
   ------------------------------------------------------------ */

.nilai-grid {
  display: grid;
  /* Dump (container 1214): daftar 494 | celah 75 | foto 645.
     ⚠️ Celah ditulis sebagai `column-gap`, BUKAN dibiarkan jadi sisa ruang
     kolom kiri setelah `max-width` memotong daftar — itu yang dipakai
     sebelumnya dan ia RUSAK begitu container menyempit: kolom kiri turun di
     bawah max-width, tidak ada lagi yang dipotong, dan celahnya jadi NOL.
     Terukur 2026-09-17: 36px di >=1300px, tapi **0px di seluruh 901..1300**
     — teks benar-benar menempel foto di semua lebar tablet, dan tidak ada
     satu pun alat yang menandainya (tidak ada overflow, tidak ada luber).
     Persen, bukan px: ia mengikuti CONTAINER (bukan viewport seperti vw,
     lihat aturan #62), jadi celahnya menyusut proporsional dan tidak pernah
     hilang. 5,66% = 68px di container 1200.
     Kolom 548 : 584 -> daftar 548 (= penanda 20 + celah 19 + teks 509),
     foto 584. Ketiganya: 548 + 68 + 584 = 1200.
     ⚠️ Foto jadi 48,7% container, dump 53,1% — penyimpangan SADAR. Poppins
     menuntut kotak teks 509px (dump 455), dan di container 1200 ketiganya
     (teks Poppins + celah 75 + foto 645) butuh 1256px. Kelebihan 56px itu
     ongkos fontnya; dibagi proporsional antara celah dan foto supaya tidak
     ada satu elemen yang menanggung semuanya. */
  grid-template-columns: 548fr 584fr;
  column-gap: 5.66%;
  /* ⚠️ `start`, BUKAN stretch bawaan grid. Dengan stretch, foto diregangkan
     mengikuti tinggi daftar yang berubah-ubah menurut panjang teks, dan
     rasio 645x391 dari desain rusak. */
  align-items: start;
  /* Dump: judul 1347..1378, daftar mulai 1441 -> 63px. */
  margin-top: 63px;
}

/* Menumpang `.list-brand` (penanda & kisi 20px + teks sudah dari sana);
   yang ditimpa hanya jaraknya, karena dump Nilai berbeda dari dump Misi. */
.nilai-list {
  /* .list-brand bawaannya margin-top 40px; di sini daftar sudah dijarakkan
     oleh .nilai-grid, jadi dinolkan. */
  margin-top: 0;
  /* Dump: jarak antar-poin diukur dari koordinat ATAS (aturan #67), dan
     angkanya tidak seragam di sana (46 / 63 / 46 / 63 / 63 / 59) karena
     sebagian poin satu baris dan sebagian dua. Dipakai satu nilai: 21px,
     yaitu selisih untuk poin satu baris (46 - 25). Dengan itu poin dua baris
     otomatis mendapat jarak yang sama, bukan jarak yang berbeda-beda. */
  /* ⚠️ Jarak antar-poin di dump TIDAK seragam: 21px sesudah poin satu
     baris, 13px sesudah poin dua baris (diturunkan dari selisih koordinat
     ATAS 46/63/46/63/63/59 — aturan #67). Itu tata letak yang dirapikan
     dengan mata, bukan aturan. Dipakai satu nilai 15px, yang menghasilkan
     total jarak 6 x 15 = 90px — persis jumlah jarak di dump (390 - 12 baris
     x 25 = 90). Jadi tinggi daftarnya sama, sementara jaraknya konsisten. */
  gap: 15px;
  /* ⚠️ 548px, bukan 455px seperti dump. Poppins lebih lebar dari Google
     Sans Flex: di 455px ketujuh poin memakan 16 baris, sementara desain 12.
     Selisih 4 baris membuat daftar 529px sementara fotonya 386px — kolom
     kanan jadi menggantung kosong hampir 150px, padahal di desain keduanya
     sama tinggi (390 vs 391). Perluasan aturan #28 — yang digeser lebar
     kotaknya (+20%), bukan ukuran hurufnya.
     ⚠️ Angka ini adalah lebar DAFTAR (penanda 20 + celah 19 + kotak teks),
     jadi kotak teksnya = 548 - 39 = 509px. Kalibrasi lama memakai jumlah
     BARIS saja dan berhenti di 545; itu memberi pola 1-2-1-2-2-2-2 yang
     benar tetapi poin 2 & 6 pecah satu kata lebih awal dari Figma.
     Disapu ulang 485..545px per 1px terhadap TITIK PECAH-nya, bukan cuma
     jumlah baris: cocok persis pada kotak teks 491..528, jadi dipakai 509
     (tengah) -> daftar 548px.
     ⚠️ Angka itu sekarang hidup di `.nilai-grid` sebagai lebar KOLOM (548fr),
     bukan sebagai `max-width` di sini. Dua tempat menyatakan satu angka yang
     sama selalu berakhir lepas sinkron — dan yang `max-width` juga rusak di
     container sempit (lihat catatan celah di .nilai-grid). */
}

/* ⚠️ 19px, bukan 39px. Dump menaruh penanda di x 113 (lebar 20,16) dan teks
   di x 152 -> offset total 39px, jadi CELAHNYA 39 - 20 = 19px. Kesalahan yang
   sama persis dengan poin Misi: selisih koordinat kiri dibaca sebagai celah.
   Dikoreksi 2026-09-17. */
.nilai-list > li { gap: 19px; }

.nilai-foto {
  width: 100%;
  height: auto;
  /* ⚠️ 584/398, BUKAN 645/391 seperti dump — penyimpangan SADAR, dipilih
     klien 2026-09-17.
     Di dump kedua kolom SAMA TINGGI (daftar 390, foto 391) dan itulah yang
     mengunci tata letaknya. Di tema hal itu tidak bisa dicapai sekaligus:
     Poppins menuntut kotak teks 509px (dump 455), jadi foto setinggi daftar
     dengan rasio 1,65 menuntut lebar 656px — dan daftar 548 + celah 68 +
     656 = 1272, lewat 72px dari container 1200.
     Dipilih: kolom kanan terisi PENUH setinggi daftar (584x398, selisih 0px)
     dengan mengorbankan rasio kotaknya (1,467 vs 1,650). Alternatifnya —
     rasio setia, foto berakhir 44px lebih tinggi dari teks — ditolak karena
     kolom yang menggantung justru lebih terbaca "tidak sesuai desain"
     daripada kotak yang sedikit lebih persegi.
     ⚠️ Angka 398 diturunkan dari tinggi daftar SAAT INI (7 poin = 12 baris
     Poppins di 1200px). Kalau poin ditambah/dikurangi lewat CMS, foto tidak
     ikut menyesuaikan dan selisihnya kembali muncul — ukur ulang di sini,
     jangan mengubah ukuran huruf.
     ⚠️ `align-items: start` di .nilai-grid TETAP. Meregangkan foto dengan
     `stretch` sudah dicoba dan GAGAL: `<img>` sebagai grid item tanpa
     aspect-ratio menentukan tinggi barisnya sendiri dari dimensi intrinsik
     fotonya — terukur baris meledak jadi 1500px. Memperbaikinya menuntut
     elemen pembungkus baru, dan pembungkus baru memutus kombinator `+`
     (aturan #39). */
  aspect-ratio: 584 / 398;
  object-fit: cover;
  border-radius: var(--r-md);
}

@media (max-width: 900px) {
  .nilai-grid {
    grid-template-columns: 1fr;
    /* Menimpa `column-gap` di atas juga — satu kolom, jadi yang tersisa
       hanya jarak baris antara daftar dan fotonya. */
    gap: var(--sp-8);
    margin-top: var(--sp-10);
  }
}

/* ------------------------------------------------------------
   BARIS LOGO LEMBAGA (Tentang, di bawah judul Sertifikasi)
   Dump: Group 25 959x79 di y 2009, enam logo dengan proporsi
   berbeda-beda (ISO 76x75, TÜV NORD 170x79, SNI 69x61,
   Kemenperin 200x60, ESDM 80x76, BPOM 81x74).
   ------------------------------------------------------------ */

.lembaga-row {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Dihitung dari koordinat x di dump, bukan dari selisih lebar total:
     ISO 241..317, TÜV NORD 374..544, SNI 604..673, Kemenperin 723..923,
     ESDM 984..1064, BPOM 1119..1200 -> celah 57, 60, 50, 61, 55.
     Dipakai reratanya, 57px.
     (Versi pertama menulis 41px dari `(959 - 756) / 5`; angka 756 itu salah
     — jumlah lebar keenam logo 676, bukan 756.) */
  gap: 57px;
  flex-wrap: wrap;
  margin-top: var(--sp-10);
}

/* ⚠️ Aturan ini SENGAJA tidak menyetel width/height. Ukurannya datang dari
   atribut width/height di markup, yang dihitung dari dimensi berkas @3x —
   mekanisme yang sama dengan logo klien di marquee Home. Begitu CSS menyetel
   lebar, atribut itu kalah (ia cuma "presentational hint") dan SELURUH logo
   jadi seukuran, padahal proporsinya berbeda-beda. Lihat aturan #35. */
.lembaga-row__logo {
  display: block;
  max-width: 100%;
  height: auto;
}

@media (max-width: 768px) {
  .lembaga-row { gap: var(--sp-6); }
}

/* ------------------------------------------------------------
   BAND KCL (Home, di bawah "Produk Kami")
   Dump Home: Rectangle 63 setinggi 289px, teks 24/30 putih di kotak 677px
   (y 2059 = 72px dari tepi atas band), tombol biru 195x54 di y 2150
   (163px dari tepi atas). 72 + 145 + 72 = 289.
   ------------------------------------------------------------ */

.section-kcl {
  min-height: 289px;
  /* `align-content: center`, bukan tinggi mati: teks 24px dalam Poppins
     lebih lebar dari Google Sans Flex, jadi ia bisa memakan satu baris
     lebih. Dengan ini band-nya melar rapi alih-alih teksnya terpotong. */
  display: grid;
  align-content: center;
  padding-block: 72px;
  color: var(--c-white);
  background-size: cover;
  /* ⚠️ Dijangkar ke KANAN, bukan center.
     Foto sumbernya 5:1 sementara pita ini 4,4:1 (teks jadi 3 baris di
     Poppins), jadi `cover` selalu memotong sisi kiri-kanan. Dengan `center`
     potongannya dibagi rata: tangan tertarik ke tengah dan makin membesar,
     sementara sisi kiri yang di desain berisi butiran halus justru terpotong
     habis jadi bidang hitam polos — persis yang dilaporkan klien sebagai
     "kaya ada layer di belakangnya". Dengan `right`, yang dimakan potongan
     adalah tepi kiri yang memang paling kosong, dan komposisinya tetap sama
     dengan desain di lebar layar mana pun. */
  background-position: right center;
}

/* ⚠️ 750px, bukan 677px seperti dump. Poppins lebih lebar dari Google Sans
   Flex: di kotak 677px kalimat ini pecah jadi TIGA baris, sementara desain
   menampilkannya dua. Tiga baris menambah 30px dan mendorong tombol serta
   dasar pita ikut turun, sehingga seluruh proporsi band meleset dari desain —
   dan sisi kiri fotonya ikut terpotong lebih banyak karena rasio pitanya
   berubah. Disapu 660..1100px: 3 baris sampai 740, 2 baris mulai 750.
   Perluasan aturan #28 — yang digeser lebar kotaknya (+11%), bukan ukuran
   hurufnya. Versi Inggris sudah muat 2 baris bahkan di 660px. */
.section-kcl__teks {
  max-width: 750px;
  font-size: 24px;
  line-height: 30px;
}

/* ⚠️ 31px, dihitung dari KOORDINAT ATAS di dump, bukan dari tinggi kotak
   teksnya: teks mulai y 2059, tombol mulai y 2150 -> 91px, dikurangi dua baris
   teks (2 x 30) = 31px.
   Versi pertama memakai 38px karena tinggi kotak teks di dump dibaca 53px
   sebagai tinggi barisnya. 53px itu kotak INK hasil auto-height Figma, bukan
   kotak barisnya (2 x line-height = 60). Salah 7px, dan pita jadi 296px
   alih-alih 289px. Untuk jarak antar elemen, selisih koordinat ATAS selalu
   lebih bisa dipercaya daripada tinggi kotak. */
.section-kcl__aksi { margin-top: 31px; }

@media (max-width: 768px) {
  .section-kcl {
    min-height: 0;
    padding-block: var(--sp-12);
  }

  /* 24px terlalu besar di layar sempit -- teksnya jadi 5-6 baris dan band
     setinggi layar penuh. Diturunkan ke skala judul sub-bagian. */
  .section-kcl__teks {
    max-width: none;
    font-size: var(--fs-body);
    line-height: var(--lh-snug);
  }

  .section-kcl__aksi { margin-top: var(--sp-6); }
}

/* ------------------------------------------------------------
   BAND KCL — versi MOBILE (dump Home 412px, 2026-09-17)
   ------------------------------------------------------------ */

/*
 * ⚠️ Blok ini harus berada SESUDAH @media (max-width: 768px) di atas:
 * spesifisitasnya sama (0,1,0 / 0,2,0) dan media query tidak menambah
 * spesifisitas sedikit pun, jadi yang menang urutan muat.
 */
@media (max-width: 640px) {
  .section-kcl {
    /* Dump: band 412x252, teks mulai 45px dari atasnya. */
    min-height: 252px;
    padding-block: 45px;
    /* Jangkar untuk gradien di bawah. */
    position: relative;

    /*
     * ⚠️ 70%, bukan `right` seperti desktop — dan angkanya DIUKUR.
     * Foto sumbernya 2560x449 (5,7:1) sementara band mobile 412x252
     * (1,6:1), jadi `cover` cuma menampilkan ~29% lebarnya; jangkar
     * menentukan bagian mana. Dengan `right` yang tersisa hanyalah tangan
     * yang memenuhi frame — di Figma tangannya kecil di kanan bawah dengan
     * bubuk berhamburan dan banyak ruang gelap.
     * Disapu right/85/70/60/50/35/20/left lalu dipersempit 64..76%,
     * dibandingkan ke crop PNG rujukan dengan RMSE: `right` 90,58 dan 70%
     * **45,60** — separuhnya. Nilai di sekitarnya (72% 65,9; 74% 68,1)
     * semuanya lebih buruk, jadi 70% memang minimumnya, bukan kebetulan.
     *
     * ⚠️ Dump mobile sebenarnya menyebut berkas LAIN (`Banner Hand KCL.jpg`,
     * sementara desktop `Rectangle 63.png`) yang tidak pernah dikirim ke
     * sini. 70% adalah pendekatan terbaik dari foto yang ada; kalau berkas
     * mobilenya menyusul, jangkar ini perlu diukur ulang.
     */
    background-position: 70% center;
  }

  /*
   * ⚠️ GRADIEN GELAP yang sebelumnya TIDAK ADA sama sekali di mobile.
   * Dump menaruh Rectangle 91 — 257x251 menempel tepi kiri, `linear-gradient
   * (90deg, #000 40,82%, rgba(0,0,0,0) 98,95%)`. Di desktop bidang itu tidak
   * diperlukan karena fotonya sendiri sudah gelap di sisi kiri; begitu band
   * menyempit ke 412px, `cover` menarik bagian terang foto ke bawah teks dan
   * teks putihnya kehilangan latar. Klien melihatnya sebagai teks yang
   * "menempel" langsung di foto, beda dari Figma.
   */
  .section-kcl::before {
    content: '';
    position: absolute;
    inset: 0 auto 0 0;
    width: 257px;
    background: linear-gradient(90deg, #000 40.82%, rgba(0, 0, 0, 0) 98.95%);
    pointer-events: none;
  }

  /* Konten naik di atas gradien tanpa perlu z-index negatif. */
  .section-kcl > * { position: relative; }

  /*
   * Dump: kotak teks 256px (BUKAN selebar container), 15px/19 -> empat baris.
   * Sebelumnya `max-width: none` membuatnya melebar 344px dan jatuh ke tiga
   * baris, sehingga barisnya keluar dari bidang gelap 257px.
   */
  .section-kcl__teks {
    max-width: 256px;
    font-size: 15px;
    line-height: 19px;
  }

  /* Dump: teks mulai 45px dari atas band dan tombol 154px — selisih 109px,
     dikurangi empat baris teks (4 x 19 = 76) = 33px. Selisih KOORDINAT ATAS,
     bukan tinggi kotak (aturan #67). */
  .section-kcl__aksi { margin-top: 33px; }
}


/* ------------------------------------------------------------
   15. FOOTER
   ------------------------------------------------------------ */

.footer {
  background: var(--c-primary);
  color: var(--c-white);
}

.footer a { color: var(--c-white); }
.footer a:hover { opacity: 0.8; }

/* Tiga lajur, proporsinya langsung dari dump footer 2026-09-16 (kanvas 1440,
   isi membentang 113..1326 = 1213px):

     logo & alamat  113  ->  629   =  516
     menu           629  -> 1127   =  498   (di dalamnya dua lajur lagi)
     kontak        1127  -> 1326   =  199

   Ditulis sebagai `fr`, bukan px, supaya ikut menyusut di layar sedang tanpa
   mengubah perbandingannya. */
.footer__top {
  display: grid;
  grid-template-columns: 516fr 498fr 199fr;
  align-items: start;
  /* Dump: logo mulai di y 43 dari tepi atas footer; garis pemisah di y 237,
     sementara isi kolom terpanjang (kontak) berakhir di y 207. */
  padding-block: 43px 30px;
}

/* ⚠️ Ketiga lajur ditempatkan EKSPLISIT. Di halaman Flexitank .footer__nav
   tidak dirender sama sekali (footer--minimal), dan dengan penempatan otomatis
   blok kontak akan naik mengisi lajur tengah — kolom kanan jadi kosong dan
   kontaknya pindah ke tengah tanpa ada yang meminta. */
.footer__brand   { grid-column: 1; }
.footer__nav     { grid-column: 2; }
.footer__contact { grid-column: 3; }

/* Menu & kontak mulai 65px di bawah logo (dump: logo y 43, baris menu pertama
   dan baris telepon sama-sama y 108). */
.footer__nav,
.footer__contact { padding-top: 65px; }

/* Dump: alamat 334x55 di y 122, logo berakhir di y 98 -> jarak 24px.
   Lebarnya dipatok supaya pecah barisnya sama dengan desain (3 baris);
   tanpa itu ia melar selebar lajur 516px dan jadi 2 baris. */
.footer__alamat {
  /* Dump: 334px. Dipakai 335 — Poppins butuh tepat satu piksel lebih untuk
     memecah alamat jadi TIGA baris seperti desain; di 334px ia jatuh ke empat
     dan mendorong seluruh footer 25px lebih tinggi. Terukur dengan menyapu
     320..470px: 4 baris sampai 330, 3 baris mulai 335. Perluasan aturan #28
     — yang digeser lebar kotaknya, bukan ukuran hurufnya. */
  max-width: 335px;
  margin-top: var(--sp-6);
  font-size: var(--fs-body-sm);
  /* 16/25 dari dump, bukan --lh-snug (≈1,4). Selisihnya 2,7px per baris,
     dan pada blok 3 baris itu menggeser dasar kolom 8px — cukup untuk
     memindahkan garis pemisah dan seluruh baris hak cipta di bawahnya. */
  line-height: 25px;
}

/* ⚠️ .brand bawaannya `inline-flex`, jadi ia ikut membentuk LINE BOX dan
   induknya menambahkan ruang turunan huruf di bawah gambar — terukur logo
   berakhir di y 108, bukan 98, sehingga alamat di bawahnya meleset 10px
   walau margin-nya sudah benar. Dijadikan `flex` (block-level) supaya
   tingginya persis setinggi gambarnya. `width: max-content` menjaga area
   kliknya tetap selebar logo, bukan selebar kolom. */
.footer__brand .brand {
  display: flex;
  width: max-content;
}

/* Menu footer: DUA lajur, bukan satu baris mendatar seperti sebelumnya.
   `grid-auto-flow: column` + tiga baris tetap menaruh tiga item pertama di
   lajur kiri (Home, Tentang, Produk) dan sisanya di lajur kanan (Blog,
   Kontak) — persis dump, dan tetap masuk akal kalau klien menambah item:
   yang ke-6 turun ke dasar lajur kedua, bukan merusak susunannya.

   Lajur dalamnya 221 : 277, lagi-lagi dari dump (menu kiri x 629, kanan 850,
   batas kanan blok 1127). */
.footer__nav {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(3, auto);
  grid-template-columns: 221fr 277fr;
  row-gap: 17px;          /* dump: jarak antar baris 37px - tinggi baris 20px */
  align-content: start;
  font-size: var(--fs-body-sm);
  line-height: 20px;
}

/* Sama polanya dengan menu utama: nonaktif 300, yang sedang dibuka 700. */
.footer__nav a { font-weight: var(--fw-light); }
.footer__nav a[aria-current] { font-weight: var(--fw-bold); }

.footer__kontak {
  font-size: var(--fs-body-sm);
  line-height: 25px;   /* 16/25 dari dump — blok dua baris ini tepat 50px */
}

/* Dump: blok telepon/email 108..158, ikon medsos 29x29 di y 178. */
.footer__social {
  display: flex;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

.footer__social .icon { width: 29px; height: 29px; }

/* Garis pemisah PUTIH PENUH, bukan putih 40%. Sampel piksel dump footer:
   baris y=237 terbaca rgb(255,255,255) persis, sementara y=236 masih biru
   brand — jadi 1px solid, tanpa transparansi. */
.footer__bottom {
  padding-block: 31px 41px;
  border-top: 1px solid var(--c-white);
  /* Dump Home/Tentang/Produk sepakat 14px/18 untuk baris copyright —
     bukan 13px seperti tanggal artikel. */
  font-size: var(--fs-label);
  line-height: 18px;
  /* Dump BARU memusatkannya (pusat terukur 718,5 dari kanvas 720). Versi
     sebelumnya rata kanan, mengikuti dump lama. */
  text-align: center;
}

/* Varian minimal untuk halaman Flexitank: tanpa menu navigasi. */
.footer--minimal .footer__nav { display: none; }

@media (max-width: 900px) {
  /* Lajur kontak 199fr tinggal ~110px di lebar ini — "+62 21 2932 4688" saja
     butuh ~170px, jadi susunan tiga lajur harus dilepas SEBELUM angkanya
     memaksa teksnya pecah. Semua offset vertikal desktop ikut dilepas
     (aturan #21). */
  .footer__top {
    grid-template-columns: 1fr;
    gap: var(--sp-10);
    padding-block: var(--sp-12) var(--sp-10);
  }

  .footer__brand,
  .footer__nav,
  .footer__contact {
    grid-column: 1;
    padding-top: 0;
  }

  /* ⚠️ Aliran KOLOM dipertahankan, cuma lebar lajurnya yang disamakan.
     Sempat diubah ke `grid-auto-flow: row` — hasilnya item mengalir mendatar
     (Home, Tentang / Produk, Blog / Kontak), jadi menu terbaca melompat-lompat
     dan urutannya tidak lagi sama dengan versi desktop. Dengan aliran kolom,
     lajur kiri tetap Home-Tentang-Produk dan kanan Blog-Kontak. */
  .footer__nav {
    grid-template-columns: 1fr 1fr;
    row-gap: var(--sp-4);
  }

  .footer__alamat { max-width: none; }
}

/*
 * MOBILE (dump Home 412px, 2026-09-17): menu footer jadi SATU BARIS.
 *
 * Dump menaruh kelima item sebaris di y 4518 — Home x35, Tentang x102,
 * Produk x184, Blog x258, Kontak x313 — dengan jarak ~21px. Susunan dua
 * lajur yang dipakai di tablet menghabiskan 92px (tiga baris) untuk sesuatu
 * yang di desain cuma 20px; itu sendiri hampir seluruh sisa selisih tinggi
 * halaman terhadap dump.
 *
 * ⚠️ `grid-auto-flow: column` dari blok di atas HARUS dilepas juga, bukan
 * cuma kolomnya diubah — selama alirannya kolom, item tetap menumpuk ke
 * bawah lebih dulu.
 */
@media (max-width: 640px) {
  .footer__nav {
    display: flex;
    flex-wrap: wrap;
    /* `space-between` supaya barisnya mengisi lebar penuh seperti dump;
       `gap` jadi jarak MINIMUM, bukan jarak tetap. Di layar lebih sempit
       dari ~360px item terakhir membungkus turun — melar, bukan meluber. */
    justify-content: space-between;
    gap: var(--sp-3) 21px;
  }
  /*
   * ⚠️ Garis pemisah DILEPAS di mobile. Dump desktop punya garis putih penuh
   * di atas baris copyright (sampel piksel: y=237 tepat rgb(255,255,255));
   * dump MOBILE tidak — disapu 8550..9620 pada PNG rujukan, tidak ada satu
   * baris pun yang >85% putih. Paddingnya ikut dikecilkan karena garisnya
   * hilang.
   *
   * ⚠️ Copyright rata KIRI, bukan tengah. Tinta barisnya terukur x 39..334
   * pada kanvas 412 — pusatnya 186, sementara pusat container 206. Ia mulai
   * di gutter, sama seperti blok lain di atasnya.
   */
  .footer__bottom {
    border-top: 0;
    padding-block: var(--sp-6) var(--sp-8);
    text-align: left;
  }
}


/* ------------------------------------------------------------
   HALAMAN FLEXITANK
   Landing lini produk terpisah. Nilai geometri diambil dari dump
   FLEXITANK.txt (artboard 1440px).
   ------------------------------------------------------------ */

/* Hero: band air 329px, foto kontainer 1022px yang sengaja keluar dari
   tepi kiri viewport (dump: left -84px) dan menggantung di bawah band,
   panel teks kaca 537px di kanan. */
.hero-flexi {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.hero-flexi__band {
  position: absolute;
  inset: 0 0 auto;
  height: 329px;
  background-size: cover;
  background-position: center;
  z-index: -1;
}

.hero-flexi__inner {
  display: grid;
  /* 604 : 572 = perbandingan kolom di desain 1440px (kotak container 1200px
     dikurangi gap 24px). 572 itu panel 537px + offset 35px ke kiri dari tepi
     container (lihat .hero-flexi__panel) — kalau kolomnya dibuat 537px,
     margin-right-nya malah memakan lebar panel sendiri (jadi 502px).

     ⚠️ Ditulis sebagai PERBANDINGAN (`fr`), bukan `minmax(0,1fr) 572px`.
     Dengan panel dipatok 572px, penyempitan layar ditanggung KOLOM FOTO
     SENDIRIAN — terukur: di 1440px foto 938px berbanding panel 537px
     (rasio 1,75, sesuai desain), tapi di 1025px foto tinggal 418px
     berbanding panel yang tetap 537px. Rasionya jatuh ke 0,78: fotonya
     justru lebih KECIL daripada panelnya, kebalikan dari desain. Persis
     yang terlihat di tablet.
     Dengan 604fr : 572fr keduanya menyusut bersama, jadi proporsinya
     terjaga di lebar berapa pun. Di 1440px hasilnya tetap 604px & 572px
     persis seperti sebelumnya — angka desainnya tidak bergeser sedikit pun.

     minmax(0, ...) wajib: tanpa itu `min-width: auto` bawaan grid item
     membuat kolom dipaksa selebar konten minimumnya (aturan #14). */
  grid-template-columns: minmax(0, 604fr) minmax(0, 572fr);
  align-items: center;
  gap: var(--sp-6);
  padding-block: var(--sp-4) var(--sp-12);
}

/* Melebihi kolomnya ke kiri supaya kontainer menembus tepi layar.
   Dump: foto 1022px mulai di x = -84px, sementara kolomnya sendiri cuma
   ~639px di 1440 — makanya angkanya besar. Sisa yang keluar dipotong
   oleh overflow:hidden di .hero-flexi. */
.hero-flexi__product {
  /* Ukuran & posisi direkonstruksi dari SILUET kontainer di FLEXITANK.png,
     bukan dari kotak layer di dump. Kotak dump 1022x531 itu frame-nya
     (termasuk ruang kosong); gambarnya sendiri 938x531 — dicek silang:
     938 / 1,766 (rasio file 1876x1062) = 531,1 = tinggi dump. Kemarin
     sempat dipaksa 1022px + object-fit:cover, akibatnya kontainer ~8%
     kebesaran dan menjorok ~67px terlalu ke kiri sehingga margin kirinya
     tidak sejajar dengan section di bawahnya.
     Kolom kiri 604px -> 938/604 = 155,3%; tepi kiri gambar x=-8 (dihitung
     dari tepi kontainer terlihat x=80 dikurangi padding transparan 9,3%). */
  width: 155.3%;
  max-width: none;
  margin-left: -21.2%;
  /* Dump: gambar mulai y=122, yaitu 30px DI ATAS band air (152). */
  margin-top: -46px;
  height: auto;
  /* Foto kontainer digambar DI ATAS panel kaca, bukan di belakangnya —
     dicek lewat sampel piksel desain: di zona tumpang-tindih warna biru
     kontainernya tetap pekat, tidak dipudarkan overlay putih 49% milik
     panel. Tanpa z-index, panel yang menyusul di DOM otomatis menang. */
  position: relative;
  z-index: 1;
}

/* Dump: panel 748..1285 (537px) — TIDAK rata dengan tepi kanan .container
   (1320), tapi 35px di dalamnya. Konsekuensinya foto kontainer (-84..938)
   menindih panel 190px, bukan 155px seperti sebelumnya, dan sisa ruang di
   kanan jadi lebih lega — persis yang terlihat di Figma.
   Padding kiri 94px (dump: teks mulai x=842, panel x=748) memang besar:
   itu yang membuat teks tetap bebas dari foto kontainer yang menindih. */
.hero-flexi__panel {
  background: rgba(255, 255, 255, 0.49);
  /* 4,5px, bukan 2px. Nilainya TIDAK ada di dump (dump cuma mencatat
     `background: rgba(255,255,255,0.49)` + `border-radius: 20px`, dan export
     kode Figma pun tidak menyertakan efek background-blur) — jadi diukur
     langsung dari render Figma, sesuai aturan #10. Caranya: ambil dua
     wilayah di dalam panel yang bersih dari teks, blur render WordPress
     bertahap, lalu cari radius yang selisihnya paling kecil terhadap render
     Figma. Keduanya sepakat ~4,5px: selisih rata-rata turun dari 4,3/4,1
     jadi 1,1/1,6 — mendekati derau dasar 2,06 yang terukur di wilayah
     kontrol DI LUAR panel. Kecerahannya sendiri sudah pas sejak awal
     (219,8 vs 219,5), jadi yang meleset memang cuma ketajamannya. */
  -webkit-backdrop-filter: blur(4.5px);
          backdrop-filter: blur(4.5px);
  border-radius: var(--r-md);
  /* Padding kiri-kanan & offset kanan dinyatakan PERSEN, bukan px.
     Persentase padding/margin pada grid item dihitung terhadap lebar KOLOM
     (572px di 1440), jadi di lebar desain nilainya tetap persis 94px / 47px
     / 35px — tidak ada angka desain yang bergeser.
     Kenapa perlu: sejak kolomnya proporsional, panel ikut menyempit di
     tablet. Dengan padding tetap 94px, di 1025px kolom teks tinggal 233px
     dan judul pecah jadi 5 baris (desainnya 4, dipatok <br> dari field),
     sekaligus menaikkan tinggi panel dari 344px ke 478px. Padding yang ikut
     menyusut mengembalikan judul ke 4 baris.
     Padding atas & bawah tetap px: keduanya tidak bersaing dengan lebar
     teks, dan mengaitkannya ke lebar kolom justru membuat panel ikut
     berubah tinggi tanpa alasan. */
  padding: 45px 8.2168% 65px 16.4336%;
  margin-right: 6.1189%;

  /* Posisi & tinggi panel MENGIKUTI ANGKA DUMP, bukan hasil hitungan
     centering. Sebelumnya panel ikut `align-items: center` milik
     .hero-flexi__inner dan tingginya murni dari isinya, sehingga jatuh di
     245..577 (332px) — dump Rectangle 84 justru 252..596 (537x344). Meleset
     7px ke atas dan 12px terlalu pendek.

     Kenapa centering tidak bisa menghasilkan angka itu: kotak konten grid
     mulai y=168 dan tinggi 485px, jadi panel 344px yang di-center akan
     mendarat di y=238 — bukan 252. Panel memang tidak terpusat terhadap
     fotonya di desain. Makanya dipatok eksplisit: 84px dari tepi atas kotak
     konten (168 + 84 = 252).

     `min-height`, bukan `height`: kalau Poppins memecah deskripsi jadi lebih
     banyak baris daripada font desain (aturan #28), panel boleh tumbuh
     daripada teksnya terpotong. Dengan min-height ini padding-bawah 65px di
     atas berubah peran jadi batas minimum saja. */
  align-self: start;
  margin-top: 84px;
  min-height: 344px;
}

/* Dump: judul 30px/35px (1,17) dan deskripsi 18px/25px (1,39) — lebih
   rapat dari --lh-tight (1,25) & --lh-body (1,7) yang dipakai sebelumnya.
   Selisihnya menjadikan panel 365px, padahal desain 344px. */
.hero-flexi__title {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
  line-height: 1.17;
}

.hero-flexi__desc {
  /* dump: judul berakhir y=402, deskripsi mulai y=417 -> 15px */
  margin-top: var(--sp-4);
  font-size: var(--fs-body);
  line-height: var(--lh-snug);
}

/* Hero bertumpuk mulai 1024px, BUKAN 768px seperti section lain. Panel
   kaca lebarnya dipatok 572px (ukuran desain), jadi kolom fotonya yang
   menyusut: di 1024px tinggal 268px dan di 834px cuma 100px — fotonya
   praktis hilang. Di bawah 1024px foto ditaruh penuh di atas, panel di
   bawahnya, dan semua trik overlap versi desktop dilepas. */
@media (max-width: 1024px) {
  .hero-flexi__inner {
    grid-template-columns: 1fr;
    padding-block: 0 var(--sp-10);
  }

  .hero-flexi__product {
    width: 100%;
    margin-left: 0;
    margin-top: 0;
    aspect-ratio: auto;
  }

  .hero-flexi__panel {
    margin-right: 0;
    padding: var(--sp-8);
    /* Seluruh trik penempatan versi desktop DILEPAS bersamaan — aturan #21:
       satu trik overlap terdiri dari beberapa properti yang saling mengunci,
       kalau salah satunya direset semuanya harus. Di layar bertumpuk panel
       sudah selebar penuh, jadi offset 84px & tinggi minimum 344px justru
       menyisakan ruang kosong di bawah teks. */
    align-self: auto;
    margin-top: 0;
    min-height: 0;
  }
}

/* <=768px: KONTAINER DIPERBESAR — melampaui tepi layar.
   Di layar bertumpuk foto cuma selebar container (325px di HP 390px), dan
   yang benar-benar terlihat jauh lebih kecil lagi: berkasnya punya ruang
   TRANSPARAN yang lebar — terukur pada baris tengah, isinya cuma menempati
   14,7%..84,9% dari lebar berkas. Jadi kontainer birunya sendiri tinggal
   ~228px, terlihat mungil di tengah layar.

   Melebarkan elemennya melampaui viewport membuat ruang kosong itu terpotong
   `overflow: hidden` milik .hero-flexi, bukan ikut ditampilkan — kontainernya
   naik ke ~342px tanpa satu piksel pun isinya hilang. Angkanya dihitung dari
   pengukuran di atas, bukan dikira-kira: pada 125vw, tepi kiri isi jatuh di
   0,147x487 = 72px sementara yang terpotong cuma 48px, jadi masih ada 23px
   sisa aman; tepi kanan isi 414px sementara batas potong 439px.

   ⚠️ Ditempatkan lewat MARGIN, bukan `transform: translateX` — aturan #43:
   Firefox menghitung area gulir dokumen dari kotak TATA LETAK, sehingga
   pemusatan lewat transform membuat halaman bisa digeser ke samping ke ruang
   kosong. Di sini pun sudah dijaga `overflow: hidden`, tapi polanya tetap
   yang aman.

   ⚠️ Angka 125vw MENGANDALKAN ruang transparan pada foto hero sekarang.
   Kalau klien mengganti fotonya dengan yang isinya rata tepi, 12,5% di kiri
   dan kanan akan benar-benar terpotong. Tidak merusak tata letak (terpotong
   rapi), tapi kalau itu terjadi, ukur ulang dengan cara yang sama. */
@media (max-width: 768px) {
  .hero-flexi__product {
    width: 125vw;
    margin-left: calc(50% - 62.5vw);
  }

  /* Kartu ditarik NAIK supaya menempel ke kontainer, meniru hubungan yang
     ada di desain desktop (di sana kontainer memang menindih panel kaca).
     Di layar bertumpuk hubungan itu hilang: kartu terpisah oleh gap 24px
     DITAMBAH ruang kosong di bawah gambar, sehingga keduanya terbaca sebagai
     dua benda yang tak berhubungan.

     Aman karena yang dilewati bukan kontainernya: terukur dari berkasnya,
     isi gambar berhenti di 93% tinggi (7% terbawah transparan penuh) dan
     bodi kontainer sendiri sudah selesai di ~83% — sisanya cipratan air.
     Di 390px itu berarti ~19px transparan + ~28px cipratan.

     Foto tetap digambar DI ATAS kartu (z-index:1 di .hero-flexi__product),
     jadi cipratan airnya jatuh menimpa tepi atas kartu — persis seperti
     desktop, bukan kartu yang memotong foto.

     `max(-64px, -12vw)` = tarikan mengikuti lebar layar tapi berhenti di
     64px. Tanpa batas itu, di 768px tarikannya jadi 92px dan tepi atas
     kartu naik melewati bodi kontainer. */
  .hero-flexi__panel {
    margin-top: max(-64px, -12vw);
  }
}

/* Intro: teks 546px + foto 585px, jarak 83px (dump). minmax(0, ...) supaya
   kolom bisa menyusut di bawah lebar alami fotonya — pola sama dengan
   .intro (Home) dan .mission (Tentang), lihat catatan panjang di
   .product-layout soal kenapa ini wajib. */
.flexi-intro {
  display: grid;
  grid-template-columns: minmax(0, 546fr) minmax(0, 585fr);
  gap: var(--sp-20);
  align-items: center;
}

/* Dump: paragraf intro 16px dengan line-height 25px (1,56) — bukan
   --fs-body (18px)/--lh-body (1,7) bawaan. Dengan setelan bawaan teksnya
   jadi 7 baris setinggi 214px, padahal desain 6 baris/141px, dan
   kelebihan itu menggeser SELURUH section di bawahnya ~71px. */
.flexi-intro p {
  font-size: var(--fs-body-sm);
  line-height: 1.56;
}

.flexi-intro__photo {
  width: 100%;
  height: auto;
  border-radius: var(--r-md);
}

/* ------------------------------------------------------------
   HALAMAN PRODUK FLEXIPACK — Bag in Box, Paper IBC, Pollination Bag
   (dump 2026-10-05, ketiganya artboard 1440x3377)

   Satu template-part (template-parts/flexipack/halaman.php) untuk keduanya.
   Kelas `--fp` = aturan BERSAMA; `--bib` / `--ibc` / `--pb` = geometri khas tiap
   halaman (posisi & ukuran gambar). Komponen Flexitank dipakai ulang, jadi
   yang ditulis di sini cuma selisihnya. Semua angka dari dump kecuali
   disebut lain.

   ⚠️ Foto kemasan di Media Library SUDAH dipangkas ke isinya (kotak alpha),
   jadi kotak gambar = isi + bayangannya. Angka posisi di bawah dihitung dari
   KOTAK ISI di dump, bukan kotak layer Figma.
   ------------------------------------------------------------ */

/* ---------- Hero ----------
   Hanya >=1025px: di bawahnya hero menumpuk dan aturan bawaan .hero-flexi
   yang berlaku (aturan #21: trik overlap dilepas bersamaan). */
@media (min-width: 1024.02px) {
  .hero-flexi--fp .hero-flexi__product { align-self: start; }

  /* Rectangle 84 di kedua dump: 537x268 @ rgba(255,255,255,.7) — bukan 344px
     @ .49 seperti Flexitank. Teks mulai x=800 (52px dari tepi panel), berakhir
     x=1239 (46px sebelum tepi kanan). Persen terhadap lebar kolom 572px, sama
     alasannya dengan panel Flexitank (ikut menyusut di tablet). */
  .hero-flexi--fp .hero-flexi__panel {
    background: rgba(255, 255, 255, 0.7);
    padding: 45px 8.042% 19px 9.091%;
    min-height: 268px;
  }

  /* Hero berakhir tepat di dasar bayangan kemasan (y ~628 di kedua dump). */
  .hero-flexi--fp .hero-flexi__inner { padding-bottom: 0; }

  /* Bag in Box: isi x 106..666, y 227..628. Kolom kiri 604px mulai x=120,
     kotak konten grid mulai y=168 -> lebar 560/604, geser -14/604, turun 59. */
  .hero-flexi--bib .hero-flexi__product {
    width: 92.72%;
    margin-left: -2.32%;
    margin-top: 59px;
  }

  /* Paper IBC: isi x 230..623, y 230..628 -> 393/604, geser 110/604, turun 62. */
  .hero-flexi--ibc .hero-flexi__product {
    width: 65.07%;
    margin-left: 18.26%;
    margin-top: 62px;
  }

  /* Paper IBC: judul 3 baris mulai y=279 -> padding atas 27px (Bag in Box
     2 baris, y=297 -> 45px). */
  .hero-flexi--ibc .hero-flexi__panel { padding-top: 27px; }

  /* Pollination Bag: isi x 162..730, y 163..852 -> 568/604, geser 42/604,
     naik 5px (163 - 168). Kantongnya MENJULANG ke area intro — sampai y=852,
     bagian bawahnya akar & bayangan yang memudar — sementara intro mulai
     y=740. Jadi section intro menumpang 112px (di bawah). Judul 2 baris
     mulai y=279 -> padding atas 27px, sama dengan Paper IBC. */
  .hero-flexi--pb .hero-flexi__product {
    width: 94.04%;
    margin-left: 7%;
    margin-top: -5px;
  }
  .hero-flexi--pb .hero-flexi__panel { padding-top: 27px; }

  /* ⚠️ position + z-index WAJIB: .hero-flexi ber-position relative, jadi ia
     dilukis di lapisan elemen berposisi — DI ATAS section non-posisi yang
     datang sesudahnya. Tanpa ini teks & tombol intro tertindih kantong yang
     memudar, dan tombol "Lihat Detail" tidak bisa diklik (aturan #63). */
  .flexi-intro-section--pb {
    padding-top: 0;
    margin-top: -112px;
    position: relative;
    z-index: 1;
  }

  /* Bag in Box: sketsa intro mulai y=616, 13px DI ATAS dasar hero — section
     intro menumpang. Aman: di x itu (>=775) hero sudah kosong. */
  .flexi-intro-section--bib { padding-top: 0; margin-top: -13px; }

  /* Paper IBC: gambar intro mulai y=646, hero berakhir 628 -> 18px. */
  .flexi-intro-section--ibc { padding-top: 18px; }
}

/* Laptop kecil & iPad rebah (1025..1279px): tumpangan intro di atas DILEPAS.
   Angka -13/18/-112 dihitung di 1440px, di mana kemasan lebih tinggi daripada
   kartu kaca. Di lebar ini kartu justru lebih tinggi (teksnya membungkus
   lebih banyak baris, min-height 268px tetap) sehingga intro menabrak kartu:
   terukur kartu->intro -13px (BiB) & 18px (IBC) di 1025, 31/45px di 1194 —
   klien melaporkannya "dempet" 2026-10-07. Patokan Flexitank 52px.

   Pollination SENGAJA tetap menumpang: hero-nya diperpanjang akar kantong
   yang memudar, jadi tanpa tumpangan ada celah >200px. Tumpangannya
   diskalakan lebar layar — melewati dua titik ukur, 1025px -> -84px dan
   1279px -> -268px — supaya kartu->intro tetap 64-89px di seluruh rentang.

   Terukur kartu->intro: BiB 56..137, IBC 56..111, PB 64..89. Di >=1280px
   aturan desktop di atas berlaku lagi tanpa perubahan. */
@media (min-width: 1024.02px) and (max-width: 1279.98px) {
  .flexi-intro-section--bib,
  .flexi-intro-section--ibc { margin-top: 0; padding-top: 56px; }
  .flexi-intro-section--pb {
    padding-top: var(--sp-12);
    margin-top: calc(658px - 72.4vw);
  }
}

/* Di layar menumpuk kemasan TIDAK dilebarkan melampaui layar seperti
   kontainer Flexitank (trik 125vw di <=768px mengandalkan ruang transparan
   lebar di berkas Flexitank — berkas ini sudah dipangkas, jadi trik itu akan
   memotong kemasannya sendiri). Dibatasi ukuran desainnya. */
/* Layar menumpuk (<=1024px) — komposisinya MENIRU hero Flexitank versi HP
   (permintaan klien 2026-10-07, Flexitank jadi panduan). Terukur di 390px:
   isi kontainer Flexitank mulai 51px di bawah navbar, berhenti di dalam band
   329px, dan kartu kaca menumpang band 76px. Sebelumnya ketiga halaman
   Flexipack menempelkan kemasannya 1px di bawah navbar (berkasnya sudah
   dipangkas ke isi, tanpa ruang transparan di atas), Paper IBC memenuhi
   seluruh band, dan kartu Paper IBC/Pollination tidak menumpang band sama
   sekali.

   Jadi gambarnya diperkecil supaya MUAT DI DALAM band, diturunkan dari
   navbar, lalu kartu ditarik naik sampai tepat di dasar isinya. Semua angka
   px karena band-nya px (329) — gambar & kartu harus mengikuti band, bukan
   lebar layar. Rumus margin kartu:
     atas kartu = margin-top gambar + tinggi gambar + gap 24 + margin kartu
   dengan sasaran atas kartu ~250-265px dari tepi atas band (menumpang band
   64-79px, setara Flexitank).

   Lebar gambar dipatok <=300px supaya tetap utuh di HP 360px (container
   300px); max-width 100% menjaga layar yang lebih sempit lagi. */
@media (max-width: 1024px) {
  .hero-flexi--fp .hero-flexi__product {
    max-width: 100%;
    margin-inline: auto;
  }

  /* Kartu di ATAS gambar (kebalikan Flexitank, yang sengaja menaruh
     cipratan airnya di atas kartu): akar kantong Pollination Bag memudar
     panjang di bawah isinya, dan tanpa ini akar transparan itu tergambar
     menimpa judul kartu. Di bawah kartu ia ikut diburamkan backdrop-filter. */
  .hero-flexi--fp .hero-flexi__panel {
    position: relative;
    z-index: 2;
  }

  /* Bag in Box: berkas 1,395:1, isi 0..88% tinggi. 300px -> tinggi 215,
     isi 56..246 dari tepi band; kartu mulai 250 (56+215+24-45). */
  .hero-flexi--bib .hero-flexi__product { width: 300px; margin-top: 56px; }
  .hero-flexi--bib .hero-flexi__panel { margin-top: -45px; }

  /* Paper IBC: berkas hampir persegi (0,987:1) dan isinya rata tepi, jadi
     lebarnya yang harus turun paling banyak: 214px -> tinggi 217, isi
     52..269; kartu mulai 265 (menumpang bayangan palet 4px). */
  .hero-flexi--ibc .hero-flexi__product { width: 214px; margin-top: 52px; }
  .hero-flexi--ibc .hero-flexi__panel { margin-top: -28px; }

  /* Pollination Bag: berkas 0,825:1, kantong pekat 3,3..61,7% tinggi, sisanya
     akar memudar. 290px -> tinggi 352, isi pekat 56..261; kartu mulai 258
     dan menutup akarnya (lihat z-index kartu di atas). */
  .hero-flexi--pb .hero-flexi__product { width: 290px; margin-top: 44px; }
  .hero-flexi--pb .hero-flexi__panel { margin-top: -162px; }

  /* Padding atas --sp-1, sama dengan intro Flexitank: hero sudah membawa
     padding bawahnya sendiri, jadi padding section 80px menyisakan celah
     ~130px di bawah panel. */
  .flexi-intro-section--fp { padding-top: var(--sp-1); }
}

/* Di layar menumpuk kemasan dipusatkan menurut BENDANYA, bukan berkasnya.
   Berkas foto tidak simetris: Bag in Box membawa bayangan lembut ~23% di
   sisi KIRI (kardus baru mulai x 278 dari 1200 -> titik tengahnya di 60,8%
   lebar), Pollination Bag menyisakan ruang transparan di sisi KANAN
   (kantong di 43,7%). Di desktop itu memang komposisinya; begitu gambarnya
   dipusatkan di layar HP, kardus terlihat bergeser ~35px ke kanan dan
   kantong ~20px ke kiri. Paper IBC sudah 50% dan tidak disentuh.
   Diukur dari kanal alpha berkasnya (piksel alpha > 200), bukan dikira.
   ⚠️ `translate`, bukan margin: elemennya ber-`margin-inline: auto`, dan
   persen pada `translate` dihitung terhadap lebar GAMBAR itu sendiri — jadi
   satu angka benar di lebar layar berapa pun. Aman dari aturan #43:
   .hero-flexi ber-`overflow: hidden`, dan gambar ini tidak membungkus
   elemen ber-position fixed (aturan #60). Kalau fotonya diganti, ukur ulang. */
@media (max-width: 1024px) {
  .hero-flexi--bib .hero-flexi__product { translate: -10.8% 0; }
  .hero-flexi--pb .hero-flexi__product { translate: 6.3% 0; }
}

/* ---------- Intro ---------- */

.flexi-intro__gambar { height: auto; }

/* Bag in Box — dump: teks berakhir ~y 822, tombol y 848 -> 26px. */
.flexi-intro__btn { margin-top: var(--sp-6); }

/* Bag in Box: sketsa 460x368 di x=775, teks & tombol (697..902) terpusat
   terhadapnya (616..984) — pas dengan align-items:center .flexi-intro.
   ⚠️ Kolom teks 600px, bukan 546px (aturan #28): di 546px Poppins memecah
   paragrafnya 3 + 4 baris, desain 2 + 3. Disapu per 5px — tercapai di 600px.
   Sketsa tetap di x=775; yang dikorbankan celahnya (80 -> 55px). */
@media (min-width: 1024.02px) {
  .flexi-intro--bib {
    grid-template-columns: minmax(0, 600fr) minmax(0, 545fr);
    gap: 55px;
  }
  .flexi-intro--bib .flexi-intro__gambar { width: 84.4%; }
}

/* Sketsa berakhir y=984, judul "Produk yang Cocok" y=1054 -> 70px. */
.flexi-intro-section--bib { padding-bottom: 70px; }

/* Paper IBC: teks di x=112 mulai y=756; gambar (isi 677x352) di
   x 647..1324, y 646..998 — melewati tepi kanan container 4px. Teks TIDAK
   terpusat terhadap gambar: ia mulai 110px di bawah tepi atas gambar.

   ⚠️ Kolom teks 600px, bukan 546px (aturan #28): di 546px Poppins memecah
   paragrafnya 5 baris, desain 4 — tombol ikut turun 24px. 4 baris tercapai
   di 595px. Kolomnya jadi MENUMPANG gambar 73px (x 647..720), dan itu aman:
   diukur dari kanal alpha berkasnya, zona itu TRANSPARAN PENUH di sepanjang
   baris teks (y 756..856); bayangan palet baru mulai di bawahnya, jauh dari
   tombol (x 120..304). Kolom 600 + 600, gambar 677/600 = 112,83%, geser
   -73/600. */
@media (min-width: 1024.02px) {
  .flexi-intro--ibc {
    grid-template-columns: minmax(0, 600fr) minmax(0, 600fr);
    gap: 0;
    align-items: start;
  }
  .flexi-intro--ibc > :first-child { margin-top: 110px; }
  .flexi-intro--ibc .flexi-intro__gambar {
    width: 112.83%;
    max-width: none;
    margin-left: -12.17%;
  }
}

/* Paper IBC: teks 4 baris berakhir ~y 856, tombol y 889 -> 33px. */
.flexi-intro--ibc .flexi-intro__btn { margin-top: var(--sp-8); }

/* Paper IBC: gambar berakhir y=998, judul "Produk yang Cocok" y=1084 -> 86px. */
.flexi-intro-section--ibc { padding-bottom: 86px; }

/* Pollination Bag: teks 546px di x=112 dan foto 585x238 (bersudut 20px)
   di x=742, KEDUANYA mulai y=740 — rata atas. Kolom 546 + gap 76 + 578 =
   1200; foto 585/578 = 101,21% (melewati tepi kanan container 7px, sama
   dengan dump). Foto berakhir y=978, judul "Pengaplikasian Produk" y=1054
   -> 76px. */
@media (min-width: 1024.02px) {
  .flexi-intro--pb {
    grid-template-columns: minmax(0, 546fr) minmax(0, 578fr);
    gap: 76px;
    align-items: start;
  }
  .flexi-intro--pb .flexi-intro__gambar {
    width: 101.21%;
    max-width: none;
  }
}
.flexi-intro--pb .flexi-intro__gambar { border-radius: var(--r-md); }
.flexi-intro-section--pb { padding-bottom: 76px; }

/* (0,2,0) supaya menang atas aturan lebar per halaman di atas. */
@media (max-width: 1024px) {
  .flexi-intro .flexi-intro__gambar { width: 100%; max-width: 460px; margin-inline: auto; }
  .flexi-intro--ibc .flexi-intro__gambar { max-width: 677px; }
  .flexi-intro--pb .flexi-intro__gambar { max-width: 585px; }
}

/* ---------- Icon rail "Produk yang Cocok" ----------
   Lingkaran 97px berjarak 182px di kedua dump. Bag in Box 7 item (pusat
   174,5 ... 1266,5) -> kolom 108px + gap 74px tepat di container 1200px.
   Gap ditulis PERSEN supaya ikut menyusut bersama container; rumus garis
   penghubung .icon-rail memakai var(--rail-gap) juga.

   minmax(0, 1fr): label lebih lebar (desain 128px) daripada kolom 108px.
   Tanpa minmax, min-content label memaksa kolom melebar (aturan #14). */
.icon-rail--rapat {
  --rail-gap: 6.1667%;
  grid-auto-columns: minmax(0, 1fr);
}

/* 6 item (Paper IBC): jaraknya TETAP 182px, jadi rail-nya lebih sempit dari
   container — 6 x 182 - 74 = 1018px (84,833% dari 1200), terpusat. Gap
   persen dihitung terhadap lebar rail itu sendiri: 74/1018 = 7,269%. */
.icon-rail--rapat.icon-rail--n6 {
  --rail-gap: 7.269%;
  max-width: 84.833%;
  margin-inline: auto;
}

/* 3 item (Pollination Bag): 3 x 182 - 74 = 472px (39,333% dari 1200),
   terpusat — lingkaran di dump x 490 / 672 / 854. Gap 74/472 = 15,678%. */
.icon-rail--rapat.icon-rail--n3 {
  --rail-gap: 15.678%;
  max-width: 39.333%;
  margin-inline: auto;
}

/* width: max-content WAJIB: di flex column ber-align center, lebar label
   kalau tidak ditentukan dibatasi lebar kolom (108px) dan "Anggur Merah"
   pecah dua baris, desain satu. Batasnya 150px atau 168,5% kolom
   (= 182/108), mana yang lebih kecil — di layar sempit label tidak pernah
   menabrak tetangganya. 150px, bukan 146px (label terlebar di dump, "Cairan
   Kimia tidak Berbahaya"): di 146px Poppins memecahnya 3 baris, desain 2.
   "Pembersih Tangan" (Bag in Box) butuh 170px untuk satu baris, jadi tetap
   2 baris seperti desainnya. */
.icon-rail--rapat .icon-rail__label {
  width: max-content;
  max-width: min(150px, 168.5%);
}

.icon-rail__item:nth-child(7) { --i: 6; }

/* Dump: judul berakhir 25px sebelum garis rail di kedua halaman (bawaan
   .section-title + .icon-rail 48px). */
.section-title + .icon-rail--rapat { margin-top: 25px; }

/* Di bawah 1100px 6-7 lingkaran 97px tidak muat sebaris. Dibungkus 4 per
   baris, baris terakhir terpusat; garis penghubung dilepas karena tidak
   masuk akal lintas baris (sama seperti .icon-rail di <=768px). */
@media (max-width: 1100px) {
  .icon-rail--rapat,
  .icon-rail--rapat.icon-rail--n6,
  .icon-rail--rapat.icon-rail--n3 {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    row-gap: var(--sp-8);
    column-gap: 0;
    max-width: none;
  }
  .icon-rail--rapat::before,
  .icon-rail--rapat .icon-rail__item::before { display: none; }
  /* ⚠️ min-width: 0 + batas label dalam PX, bukan persen. Persen pada label
     dihitung terhadap lebar item, dan saat flexbox menghitung lebar MINIMUM
     item persen itu siklik sehingga diabaikan — label "Cairan Kimia tidak
     Berbahaya" lalu memaksa itemnya 240px (> 50%) dan di HP setiap ikon
     sesudah baris pertama jatuh satu per baris. Kolom tersempit di sini
     160px (50% dari 320px), jadi 150px selalu muat. */
  .icon-rail--rapat .icon-rail__item {
    flex: 0 0 25%;
    min-width: 0;
    padding-top: 0;
  }
  .icon-rail--rapat .icon-rail__label { max-width: 150px; }
}

@media (max-width: 600px) {
  .icon-rail--rapat .icon-rail__item { flex-basis: 50%; }
  /* Aturan rentang bawaan .icon-rail di <=768px (item terakhir ganjil
     dibentangkan 2 kolom) milik GRID — di sini flex & justify-content:center
     sudah memusatkannya. */
  .icon-rail--rapat .icon-rail__item:last-child:nth-child(odd) { grid-column: auto; }
}

/* ---------- Band teks ----------
   25/31 putih, overlay hitam 40% (Rectangle 9) di kedua dump. */
.cta-band--fp .cta-band__text { font-size: var(--fs-hero-sub); }
.cta-band--fp::after { background: rgba(0, 0, 0, 0.4); }

/* Paper IBC menebalkan sebagian kalimat ("dengan kapasitas muat hingga
   1100L"). Ditulis eksplisit: <b> bawaan peramban "bolder" bisa jatuh ke
   bobot yang tidak dimuat. */
.cta-band__text :is(b, strong) { font-weight: var(--fw-bold); }

/* ⚠️ Aturan #80: .cta-band adalah grid, dan penanda section setinggi NOL
   (.anaya-sec dari anaya_tandai_section) menjadi baris KEDUA-nya. Dengan
   `place-items: center` saja sisa ruang band dibagi ke dua baris, jadi teks
   turun ke paruh bawah (terukur 142px dari tepi atas, desain 93px).
   `align-content: start` memadatkan barisnya ke atas, lalu padding atas
   menaruh teks persis di angka dump. Kedua desain memang TIDAK terpusat. */
.cta-band--fp { align-content: start; }

/* Bag in Box: band y 1384, teks y 1477 -> 93px.
   ⚠️ 1040px, bukan 938px (aturan #28): di 938px Poppins memecah kalimatnya
   jadi 3 baris, desain 2. Disapu per 5px — 2 baris tercapai di 1035px. */
.cta-band--bib { padding-top: 93px; }
.cta-band--bib .cta-band__text { max-width: 1040px; }

/* Paper IBC: band y 1414, teks y 1517 -> 103px. Lebar 909px PERSIS dump —
   disapu, Poppins sudah 2 baris mulai 890px, jadi tidak perlu dilebarkan. */
.cta-band--ibc { padding-top: 103px; }
.cta-band--ibc .cta-band__text { max-width: 909px; }

/* Pollination Bag: band y 1384, teks y 1477 -> 93px (sama dengan Bag in
   Box). ⚠️ 1040px, bukan 938px (aturan #28): di 938px Poppins memecahnya
   4 baris, desain 3 — tercapai mulai 1035px, sama persis dengan Bag in Box. */
.cta-band--pb { padding-top: 93px; }
.cta-band--pb .cta-band__text { max-width: 1040px; }

/* Flexitank: band y 1384, teks y 1477 -> 93px, angka yang sama dengan
   Flexipack. Kena aturan #80 yang sama (terukur 119px sebelum diperbaiki).
   ⚠️ Lebar 881px dari dump DIPERTAHANKAN walau Poppins memecahnya 3 baris
   (desain 2): 2 baris baru tercapai di 1185px, +35% — hampir selebar
   container. Penyimpangan terkecil (aturan #28) di sini adalah menerima satu
   baris lebih; tinggi band tetap 284px karena isinya masih di bawah itu. */
.cta-band--ft {
  align-content: start;
  padding-top: 93px;
}

@media (max-width: 900px) {
  .cta-band--fp,
  .cta-band--ft {
    align-content: center;
    padding-top: var(--sp-12);
  }
}

/* Selama foto band belum diisi: latar gelap rata, supaya teks putih tetap
   terbaca. Warnanya dari rerata foto desain Bag in Box (cipratan cokelat). */
.cta-band--polos { background-color: #2a221c; }

/* ---------- "Kenapa …?" ----------
   Foto kiri, judul + poin bertanda chevron kanan; judul & penanda selalu
   mulai x=623 di kedua dump. */
.flexi-kenapa {
  display: grid;
  align-items: center;
}

.flexi-kenapa__foto {
  max-width: none;
  height: auto;
}

/* Bag in Box: isi foto (456x516) mulai x=98, 22px DI LUAR tepi kiri
   container -> kolom 434 : 697 + gap 69 = 1200, foto 105,07% geser -5,07%.
   Atas-bawah: band berakhir 1668, foto mulai 1720 (52px); foto berakhir
   2237, garis pemisah 2332 (95px). Teks terpusat terhadap foto. */
.flexi-kenapa-section--bib { padding-block: 52px 95px; }
.flexi-kenapa--bib {
  grid-template-columns: minmax(0, 434fr) minmax(0, 697fr);
  column-gap: 69px;
}
.flexi-kenapa--bib .flexi-kenapa__foto {
  width: 105.07%;
  margin-left: -5.07%;
}

/* Paper IBC: foto (471x438, persegi tanpa sudut membulat) di x=113, 7px di
   luar container -> kolom 464 : 697 + gap 39 = 1200. Judul mulai y=1774,
   foto y=1779 — rata ATAS, bukan terpusat (teksnya lebih panjang dari
   foto). Band berakhir 1698 -> 76px; poin terakhir berakhir ~2249, garis
   pemisah 2332 -> 83px. */
.flexi-kenapa-section--ibc { padding-block: 76px 83px; }
.flexi-kenapa--ibc {
  grid-template-columns: minmax(0, 464fr) minmax(0, 697fr);
  column-gap: 39px;
  align-items: start;
}
.flexi-kenapa--ibc .flexi-kenapa__foto {
  width: 101.51%;
  margin-left: -1.51%;
  margin-top: 5px;
}

/* Pollination Bag: foto 471x438 di x=113 — kolom sama dengan Paper IBC.
   Judul 1 baris y=1744, foto y=1751 (rata atas, foto turun 7px). Band
   berakhir 1668 -> 76px. Foto berakhir 2189, garis pemisah tetap y=2332
   seperti dua halaman lain -> 143px. */
.flexi-kenapa-section--pb { padding-block: 76px 143px; }
.flexi-kenapa--pb {
  grid-template-columns: minmax(0, 464fr) minmax(0, 697fr);
  column-gap: 39px;
  align-items: start;
}
.flexi-kenapa--pb .flexi-kenapa__foto {
  width: 101.51%;
  margin-left: -1.51%;
  margin-top: 7px;
}

.flexi-kenapa__judul {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
  line-height: 1.17;
  color: var(--c-primary);
}

/* Judul -> poin pertama 25px (Bag in Box) / 27px (Paper IBC); antar-poin
   (3 baris = 75px) rata-rata 26px di kedua dump. */
.flexi-kenapa__poin {
  margin-top: 25px;
  gap: 26px;
}

/* Penanda x 623 (lebar 20,16), teks x 660 -> celah 17px (aturan #70). */
.flexi-kenapa__poin > li { gap: 17px; }

.flexi-kenapa__poin-judul {
  display: block;
  font-weight: var(--fw-bold);
}

@media (max-width: 900px) {
  .flexi-kenapa-section { padding-block: var(--section-y); }
  .flexi-kenapa {
    grid-template-columns: 1fr;
    row-gap: var(--sp-8);
  }
  /* (0,2,0) supaya menang atas aturan geometri per halaman di atas. */
  .flexi-kenapa .flexi-kenapa__foto {
    width: 100%;
    max-width: 471px;
    margin: 0 auto;
  }
  .flexi-kenapa__poin > li { gap: var(--sp-4); }
}

/* Klaim kapasitas — 24px, rata tengah, satu blok teks kaya. */
.flexi-claim {
  max-width: 828px;
  margin-inline: auto;
  text-align: center;
  font-size: var(--fs-product);
  line-height: var(--lh-snug);
}

/* Band sertifikasi: latar abu #f4f4f4 selebar viewport, foto kontainer
   menggantung keluar dari band (dump: band 375px, foto 513px). */
/* Dump (Rectangle 128): band 1440x375. Fotonya (641x513) mulai 10px di
   bawah tepi atas band lalu MENGGANTUNG 148px ke bawah — bukan menggantung
   simetris atas-bawah seperti sebelumnya (margin-block -32px), yang bikin
   band jadi 506px, 131px lebih tinggi dari desain. */
.section.cert-band {
  background: var(--c-surface);
  min-height: 375px;
  align-content: center;
  /* padding-block section (0/80) ikut menambah tinggi band di luar 375px
     -> dinolkan, tingginya murni dari min-height + konten yang di-center. */
  padding-block: 0;
  /* Dump: band berakhir y=3205, garis pemisah berikutnya y=3396 -> 191px.
     Ruang ini WAJIB: fotonya menggantung 148px ke bawah band (lihat
     .cert-band__photo), jadi tanpa jarak ini foto menembus garis pemisah
     dan menabrak teks CTA di bawahnya. Sisa 43px jadi kelonggarannya. */
  margin-bottom: 191px;
}

.cert-band__inner {
  display: grid;
  grid-template-columns: minmax(0, 641fr) minmax(0, 573fr);
  gap: var(--sp-10);
  align-items: center;
}

.cert-band__photo {
  width: 100%;
  height: auto;
  /* Menggantung ke bawah saja (lihat catatan di .section.cert-band). */
  margin-top: 10px;
  margin-bottom: -148px;
}

.cert-band__logos {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-8) var(--sp-6);
  align-items: center;
  margin-top: var(--sp-8);
}

.cert-band__logos img {
  width: 100%;
  max-height: 86px;
  object-fit: contain;
}

/* ------------------------------------------------------------
   DIAGRAM BERANOTASI (Flexitank — Material & Spesifikasi)
   Bingkai memakai sistem koordinat dump: 1214 x 628 px. Garis &
   titik digambar sebagai SVG di atas foto supaya koordinatnya
   tetap presisi saat lebar berubah; labelnya HTML biasa agar
   tipografinya ikut design system.
   ------------------------------------------------------------ */

.flexi-diagram {
  position: relative;
  aspect-ratio: 1214 / 628;
  font-size: var(--fs-body-sm);
}

/* Ukuran huruf label IKUT MENYUSUT bersama diagramnya.
   Posisi tiap label dinyatakan persen (ikut menyusut) sementara ukuran
   hurufnya tetap px, jadi keduanya bergerak BERLAWANAN saat layar menyempit:
   ruang antar-label berkurang, teksnya justru bertambah baris. Terukur pada
   pasangan terapat (BAG -> CORRUGATED PAPER ROLL): 135px di 1366px, 54px di
   1200px, 9px di 1100px, lalu MINUS 13px di 1000px — bertumpuk, bukan
   sekadar rapat.
   Dengan huruf yang ikut skala, callout tetap sebangun dengan desain di
   lebar berapa pun; tata letak, posisi, dan gaya munculnya tidak berubah
   sama sekali.

   Rumusnya bukan kira-kira: lebar diagram = lebar viewport dikurangi dua
   gutter (80px masing-masing di rentang ini), dibatasi 1200px oleh
   .container. Jadi 16px x lebar/1200 = (100vw - 160px) / 75. Di >=1360px
   hasilnya >=16px sehingga dipatok balik ke nilai desain — lebar desain
   TIDAK bergeser sedikit pun. Batas bawah 12px supaya tetap terbaca.

   Hanya >900px: di bawah itu label sudah jadi daftar dengan ruang sendiri,
   dan ukurannya harus tetap normal. */
@media (min-width: 900.02px) {
  .flexi-diagram {
    font-size: clamp(12px, calc((100vw - 160px) / 75), var(--fs-body-sm));
  }
}

.flexi-diagram__img {
  position: absolute;
  left: 10.87%;
  top: 3.98%;
  width: 76.36%;
  height: 85.35%;
  object-fit: contain;
}

.flexi-diagram__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.flexi-diagram__line {
  fill: none;
  stroke: var(--c-ink);
  stroke-width: 1;
}

.flexi-diagram__dot { fill: var(--c-ink); }

.flexi-diagram__label {
  position: absolute;
  line-height: var(--lh-snug);
}

/* Label yang duduk di KIRI titiknya (Airvent) teksnya rata kanan supaya
   ujung teks menempel ke titik. Dump: kotak judul & kotak isinya sama-sama
   berakhir di x=708 (titik di 724,5) — sedangkan kalau rata kiri, teks
   Poppins yang lebih pendek berhenti di 622 dan callout-nya terlihat
   "berjauhan" dari titiknya. Label lain (BULK HEAD & yang di sisi kanan)
   tetap rata kiri, sesuai dump. */
.flexi-diagram__label--ke-kanan { text-align: right; }

/* Tanpa text-transform: dump menulis judul callout kapital SEMUA kecuali
   "3 inch VALVE" (kata "inch" huruf kecil). Kapitalisasi ditulis apa adanya
   di markup supaya pengecualian itu tidak ikut dipaksa jadi kapital. */
.flexi-diagram__label b {
  display: block;
  font-weight: var(--fw-bold);
}

.flexi-diagram__label span { display: block; margin-top: var(--sp-1); }

/* --- Animasi diagram: SELURUH elemen muncul BERSAMAAN dalam 200ms.
   (permintaan klien 2026-09-17)

   Sebelumnya berupa kaskade searah jarum jam — tiap callout menunggu yang
   sebelumnya tuntas, dan seluruh diagram baru selesai di **9,1 detik**
   (terukur, sejak diagram masuk layar). Itu yang diminta dipercepat.

   pathLength="1" di markup membuat semua garis punya panjang 1 satuan, jadi
   satu nilai dasharray cukup untuk garis sepanjang apa pun.

   ⚠️ Empat variabel di bawah adalah SATU-SATUNYA tempat yang perlu disentuh
   kalau iramanya diubah lagi — rumus `calc()`-nya tidak perlu diapa-apakan.
   Mengembalikan kaskade lamanya: --fx-jeda 1450ms, --fx-garis 600ms,
   --fx-awal 850ms, --fx-durasi tetap per-properti (600/250/380).

   `--i` di markup SENGAJA dipertahankan walau sekarang selalu dikalikan 0.
   Ia menyimpan urutan searah jarum jam (Airvent → Bag → Corrugated → Steel
   Bars → 3 inch Valve → Bulk Head) yang juga menentukan susunan daftar di
   <=900px; membuangnya berarti menulis ulang urutan itu kalau kaskadenya
   dikembalikan. */
.flexi-diagram {
  /* Jarak antar callout. 0 = keenamnya mulai berbarengan. */
  --fx-jeda: 0ms;
  /* Jatah menggambar garis sebelum titiknya muncul. 0 = bersamaan. */
  --fx-garis: 0ms;
  /* Jatah sebelum label muncul. 0 = bersamaan dengan garis & titik. */
  --fx-awal: 0ms;
  /* Durasi tiap animasi. Dicoba bertahap bersama klien pada 2026-09-17:
     200ms (terbaca sebagai kedipan) -> 300ms -> 500ms yang dipakai. */
  --fx-durasi: 500ms;
}

.flexi-diagram .flexi-diagram__line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.flexi-diagram .flexi-diagram__dot { transform: scale(0); transform-origin: center; transform-box: fill-box; }

.flexi-diagram .flexi-diagram__label { opacity: 0; transform: translateY(8px); }

.flexi-diagram.is-visible .flexi-diagram__line {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--fx-durasi) ease-out;
  transition-delay: calc(var(--i, 0) * var(--fx-jeda));
}

.flexi-diagram.is-visible .flexi-diagram__dot {
  transform: scale(1);
  /* Lengkung pegas dipertahankan — pada 200ms ia terbaca sebagai "pop"
     singkat, bukan pantulan yang memperlambat. */
  transition: transform var(--fx-durasi) cubic-bezier(0.34, 1.4, 0.64, 1);
  transition-delay: calc(var(--i, 0) * var(--fx-jeda) + var(--fx-garis));
}

.flexi-diagram.is-visible .flexi-diagram__label {
  opacity: 1;
  transform: none;
  transition: opacity var(--fx-durasi) ease-out, transform var(--fx-durasi) ease-out;
  transition-delay: calc(var(--i, 0) * var(--fx-jeda) + var(--fx-awal));
}

@media (prefers-reduced-motion: reduce) {
  .flexi-diagram .flexi-diagram__line { stroke-dashoffset: 0; }
  .flexi-diagram .flexi-diagram__dot { transform: none; }
  .flexi-diagram .flexi-diagram__label { opacity: 1; transform: none; }
  .flexi-diagram.is-visible :is(.flexi-diagram__line, .flexi-diagram__dot, .flexi-diagram__label) { transition: none; }
}

/* Di layar sempit garis penunjuk jadi tidak terbaca — diagram tampil
   sebagai foto biasa, labelnya turun jadi daftar di bawahnya. */
@media (max-width: 900px) {
  .flexi-diagram {
    aspect-ratio: auto;
    /*
       ⚠️ Blok ini dulu menyetel irama kaskade tersendiri untuk layar sempit
       (garis penunjuk disembunyikan di sini, jadi jatah waktunya berbeda).
       Sejak kaskadenya DIMATIKAN seluruhnya atas permintaan klien
       2026-09-17, tidak ada lagi yang perlu dibedakan: nilai dari blok
       utama (--fx-jeda 0, --fx-garis 0, --fx-awal 0, --fx-durasi 200ms)
       sudah benar di semua lebar, dan keenam label memang dimaksudkan
       muncul berbarengan.

       Kalau kaskadenya kelak dikembalikan, blok ini perlu hidup lagi:
       di sini `--fx-awal` HARUS 0 walau desktop memakai 850ms, karena
       850ms itu jatah menggambar garis — dan garisnya tidak ada di sini,
       jadi yang tersisa cuma layar diam sebelum label pertama.
    */
  }

  .flexi-diagram__img { position: static; width: 100%; height: auto; }
  .flexi-diagram__svg { display: none; }

  .flexi-diagram__labels {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--sp-6);
    margin-top: var(--sp-8);
  }

  /* width:auto melepas lebar kotak yang dihitung untuk versi desktop;
     text-align:left melepas .flexi-diagram__label--ke-kanan — di susunan
     bertumpuk semua label sebaiknya rata kiri seperti daftar biasa. */
  .flexi-diagram__label {
    position: static !important;
    width: auto !important;
    text-align: left;
  }
}

@media (max-width: 1024px) {
  .flexi-intro { grid-template-columns: 1fr; gap: var(--sp-10); }
  .cert-band__inner { grid-template-columns: 1fr; }
  .cert-band__logos { grid-template-columns: repeat(2, 1fr); }
  /* 7 logo di 2 kolom menyisakan satu sendirian di kolom kiri baris
     terakhir. Dibentangkan supaya jatuh di tengah (sama seperti
     .icon-rail__item, dan hanya berlaku di media query ini). */
  .cert-band__logos > *:last-child:nth-child(odd) { grid-column: 1 / -1; }

  /* Kolom jadi menumpuk -> semua trik overlap versi desktop DILEPAS.
     Foto yang menggantung 148px ke bawah (dan margin-bottom 191px di band
     untuk menampungnya) di layar sempit malah menabrak judul "Sertifikasi"
     & barisan logo, lalu menyisakan ruang kosong besar sebelum garis
     pemisah. Tinggi tetap 375px juga tidak relevan lagi di susunan
     vertikal. */
  .section.cert-band {
    min-height: auto;
    padding-block: var(--section-y);
    margin-bottom: 0;
  }

  .cert-band__photo { margin-top: 0; margin-bottom: 0; }
}

/* ------------------------------------------------------------
   PESAN HASIL FORMULIR (Fase 7)
   Desain Figma tidak pernah menggambarkan keadaan "berhasil terkirim" —
   komponen ini tambahan yang dibutuhkan supaya pengunjung tahu kiriman
   mereka sampai. Sengaja hanya memakai token yang sudah ada, tanpa
   memperkenalkan warna baru ke sistem.
   ------------------------------------------------------------ */

.form-notice {
  margin-bottom: var(--sp-6);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-sm);
  border-left: 4px solid;
  background: var(--c-surface);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-snug);
}

.form-notice--ok    { border-left-color: var(--c-whatsapp); }
.form-notice--galat { border-left-color: var(--c-danger); }

/* Di kartu form biru (Blog Detail) latar abu tidak terbaca — dibalik jadi
   putih tembus supaya tetap kontras di atas biru. */
.form-card--primary .form-notice {
  background: rgba(255, 255, 255, 0.92);
  color: var(--c-ink);
}

/* ------------------------------------------------------------
   KEADAAN KOSONG (arsip tanpa isi)
   Dipakai arsip Blog saat bahasa yang dibuka belum punya artikel.
   Sebelumnya cuma satu judul di atas halaman putih — jalan buntu.
   ------------------------------------------------------------ */

.empty-state {
  max-width: 620px;
  margin-inline: auto;
  padding-block: var(--sp-10);
  text-align: center;
}

.empty-state .section-lead { margin-top: var(--sp-4); }

.empty-state__aksi {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  justify-content: center;
  margin-top: var(--sp-8);
}

/* ------------------------------------------------------------
   TOMBOL "UBAH ISI BAGIAN INI"
   ------------------------------------------------------------
   Hanya tampil untuk pengguna yang boleh menyunting halaman ini —
   pengunjung tidak pernah melihatnya. Ditempelkan ke section
   terdekat lewat jangkar yang mendahuluinya.

   `position: sticky` DISENGAJA tidak dipakai: tombolnya harus
   menandai SATU bagian, dan yang menempel di layar justru
   kehilangan kaitannya dengan bagian mana yang dimaksud.
   ------------------------------------------------------------ */

/* Setinggi NOL — tidak boleh menggeser tata letak sedikit pun. */
.anaya-sec {
  position: relative;
  height: 0;
}

.anaya-jangkar {
  position: absolute;
  /* Header lengket setinggi ~96px menutupi tujuan lompatan kalau
     jangkarnya tepat di tepi atas section. */
  top: -110px;
}

.anaya-ubah-bagian {
  position: absolute;
  top: 12px;
  left: var(--gutter);
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 6px 14px 6px 10px;
  border-radius: var(--r-pill);
  background: var(--c-primary);
  color: var(--c-white);
  font-size: 12px;
  font-weight: var(--fw-medium);
  line-height: 1.4;
  text-decoration: none;
  box-shadow: var(--shadow-card);
  /* Redup sampai disentuh: ini alat bantu penyunting, bukan bagian
     dari desain halaman, jadi tidak boleh ikut menarik perhatian
     saat sekadar membaca. */
  opacity: 0.35;
  transition: opacity var(--t-fast);
}

.anaya-ubah-bagian:hover,
.anaya-ubah-bagian:focus-visible {
  opacity: 1;
  color: var(--c-white);
}

.anaya-ubah-bagian svg { flex: none; }

/* ------------------------------------------------------------
   ALAT BANTU HALAMAN PRODUK — pencarian + baris kategori
   yang MENEMPEL saat digulir (permintaan klien 2026-09-17).
   ------------------------------------------------------------ */

/* ⚠️ Berlaku di SEMUA lebar, bukan hanya saat sticky. Pembungkus
   `.produk-alat` memutus `.section + .section { padding-top: 0 }` yang
   selama ini menolkan jarak atas section sesudahnya (aturan #39), jadi
   tanpa baris ini halaman Produk bertambah 80px di setiap lebar. */
.produk-alat + .section { padding-top: 0; }

/*
 * ⚠️ Jarak 80px dipecah jadi MARGIN 56 + PADDING 24, dan pembagian itu bukan
 * kosmetik — ia satu-satunya cara memperkecil blok yang menempel tanpa
 * mengubah tinggi halaman.
 *
 * Versi pertama merampingkan PADDING saat blok menempel (kelas `.is-stuck`).
 * Itu gagal dengan cara yang tidak terduga: elemen `position: sticky` TETAP
 * berada di alur dokumen, jadi mengecilkan paddingnya mengecilkan tinggi
 * dokumen — terukur 3188px -> 3044px begitu blok menempel — dan posisi gulir
 * ikut tersentak (diminta 400, mendarat di 376). Halaman melompat di bawah
 * tangan pengguna, dan `verifikasi-wp.py` melaporkannya sebagai Produk -89px
 * (dari -39px) karena ia mengukur sesudah menggulir.
 *
 * MARGIN tidak dihitung sebagai tinggi elemen, jadi ia tidak pernah ikut
 * menempel — blok yang menempel tinggal 356px sementara jarak visualnya
 * tetap 80px di kedua sisi, sama persis seperti sebelum fitur ini ada.
 */
.produk-alat { margin-block: 56px; }
.produk-alat > .section:first-child { padding-top: var(--sp-6); }
.produk-alat > .section:last-child { padding-bottom: var(--sp-6); }

/* Penanda tak terlihat setinggi NOL tepat di atas blok, disisipkan JS.
   Dipakai IntersectionObserver untuk mengetahui kapan blok mulai menempel
   — lihat initProdukAlat() di main.js. Tidak boleh punya tinggi, margin,
   atau padding: ia berada di tengah alur dokumen. */
.produk-alat__sentinel {
  height: 0;
  margin: 0;
  padding: 0;
  pointer-events: none;
}

/*
 * ⚠️ DUA RENTANG: >=1200px DAN <=640px. Yang dikecualikan justru TENGAHNYA,
 * dan itu diukur bukan ditebak.
 *
 * Tinggi baris kategori melonjak begitu kartunya membungkus jadi 3 kolom:
 * 179px di 1200px, tapi 568px di 1024px dan 492px di 900px. Ditambah header
 * 152px, versi sticky di 1024px mengunci 785px dari layar 900px —
 * halamannya praktis tidak bisa dibaca lagi. Di rentang itu keduanya tetap
 * mengalir normal.
 *
 * Mobile DAN tablet dulunya ikut dikecualikan karena alasan yang sama
 * (kartu besar, baris kategori 419-568px). Angka itu berubah 2026-09-17
 * saat kartu kategori di SELURUH rentang <=1024px diganti 5 tile kecil:
 * baris kategori tinggal ~102-130px dan sidebar produk jadi dropdown 47px,
 * jadi blok yang menempel cuma ~175-250px.
 *
 * Auto-hide di bawah ini berlaku di semua rentang, jadi ruang baca kembali
 * penuh begitu pengunjung menggulir ke bawah.
 */
/*
 * ⚠️ TANPA gerbang lebar — dan itu hasil dua kali penyempitan, bukan
 * kelalaian.
 *
 * Mulanya `>=1200px` saja, karena baris kategori melonjak 179 -> 568px
 * begitu kartunya membungkus 3 kolom: versi sticky di 1024px mengunci
 * 785px dari layar 900px. Lalu `<=640px` ikut masuk saat kartu mobile jadi
 * 5 tile kecil (102px).
 *
 * 2026-09-17 kartu tile itu diperluas ke SELURUH rentang <=1024px, jadi
 * tidak ada lagi lebar yang bermasalah: blok yang menempel 235px di HP,
 * ~314px di tablet, 355px di desktop. Celah 1025..1199 yang tersisa justru
 * persis lebar iPad landscape (1194px) — persis perangkat yang dipakai
 * klien saat melaporkannya.
 *
 * Ruang baca dijaga auto-hide di bawah, bukan oleh gerbang lebar.
 */
.produk-alat {
  position: sticky;
  /* Menempel TEPAT di bawah navbar melayang. `--header-h` dipakai bersama
     scroll-padding-top di base.css, jadi jangkar dan blok ini tidak bisa
     lepas sinkron. */
  top: var(--header-h);
  /* Di atas isi produk & sidebar, DI BAWAH navbar — kalau tidak, ia lewat
     di depan dropdown navbar. */
  z-index: 20;
  /* WAJIB: tanpa latar, isi produk terbaca menembus di belakang kartu
     kategori. Putih, sama dengan latar body. */
  background: #fff;
}

/*
 * Satu-satunya hal yang berubah saat blok MENEMPEL: bayangan tipis,
 * supaya ia terbaca terpisah dari konten yang lewat di baliknya.
 * ⚠️ `box-shadow`, BUKAN `border-bottom` — border menambah tinggi elemen
 * dan itu akan menyentak tinggi dokumen persis seperti padding tadi.
 */
.produk-alat.is-stuck {
  box-shadow: 0 6px 12px -8px rgba(0, 0, 0, .18);
}

/*
 * AUTO-HIDE — jalan keluar dari tabrakan "alat mudah diakses" vs "ruang
 * baca cukup". Terukur sebelum ini: blok yang menempel permanen menyisakan
 * 243px ruang baca di laptop 1440x750 dan **193px** di 1280x700 — isi
 * produknya praktis tidak terbaca.
 *
 * Sekarang blok menyingkir saat pengguna menggulir ke BAWAH (sedang
 * membaca) dan turun lagi begitu menggulir sedikit ke ATAS (sedang mencari
 * navigasi). Ruang baca kembali penuh: 748px / 598px.
 *
 * ⚠️ `transform`, BUKAN mengubah tinggi/padding: transform tidak
 * mempengaruhi alur dokumen sama sekali, jadi tinggi halaman tetap dan
 * gulirnya tidak menyentak (aturan #76).
 * ⚠️ Aman dari aturan #60 — `.produk-alat` tidak memuat satu pun keturunan
 * `position: fixed` (yang ada di tema cuma `.header--overlay` dan drawer
 * `.nav`, keduanya di header).
 */
.produk-alat {
  transition: transform var(--t-base), box-shadow var(--t-base);
}

.produk-alat.is-stuck.is-sembunyi {
  transform: translateY(-100%);
  box-shadow: none;
}

/* Hormati preferensi sistem: yang hilang cuma animasinya, bukan
   perilakunya — blok tetap menyingkir, hanya tanpa transisi. */
@media (prefers-reduced-motion: reduce) {
  .produk-alat { transition: none; }
}

/*
 * SIDEBAR DAFTAR PRODUK ikut menempel — dan ini yang paling murah:
 * ia berada di KOLOM KIRI, jadi memakan 0 ruang vertikal. Pindah antar
 * produk tetap mungkin kapan saja meski blok alat sedang menyingkir.
 * `.product-layout` sudah `align-items: start`, jadi sticky-nya bekerja
 * tanpa perubahan lain.
 */
.product-nav {
  position: sticky;
  top: calc(var(--header-h) + var(--sp-4));
  /* Tingginya tidak boleh melebihi sisa layar, kalau tidak ujung daftarnya
     terpotong dan tidak bisa dijangkau. Scroll internal sudah ada sejak
     Fase 3 (`overflow-y: auto`). */
  max-height: min(620px, calc(100vh - var(--header-h) - var(--sp-12)));
  max-height: min(620px, calc(100dvh - var(--header-h) - var(--sp-12)));
}

/*
 * ⚠️ `.reveal` DIMATIKAN di dalam blok yang menempel.
 * Elemen ber-`.reveal` mulai dengan `opacity: 0` + `translateY(16px)`;
 * pada elemen sticky itu berarti kotak pencarian menggantung 16px dari
 * posisi seharusnya sampai observer menyalakannya — dan karena blok ini
 * berada di atas layar sejak awal, animasinya tidak pernah terlihat
 * sebagai animasi, cuma sebagai pergeseran.
 */
.produk-alat .reveal {
  opacity: 1;
  transform: none;
}

/*
 * Menu sertifikat memakai <details> bawaan peramban — tanpa JavaScript,
 * jadi ia sudah bisa keyboard & pembaca layar dan tetap bekerja kalau JS
 * mati. `position: relative` menjadikannya jangkar bagi daftarnya.
 */
.unduh-sert { position: relative; }

.unduh-sert > summary {
  /* `list-style: none` + ::-webkit-details-marker: membuang segitiga
     bawaan, yang kalau dibiarkan muncul DI DALAM tombol biru. */
  list-style: none;
  cursor: pointer;
}

.unduh-sert > summary::-webkit-details-marker { display: none; }
.unduh-sert > summary::marker { content: ''; }

/* Panah tombol ikut berputar saat menu terbuka — isyarat keadaan yang
   tidak bergantung warna. */
.unduh-sert > summary .icon,
.unduh-sert > summary svg {
  transition: transform var(--t-base);
}

.unduh-sert[open] > summary .icon,
.unduh-sert[open] > summary svg {
  transform: rotate(90deg);
}

.unduh-sert__daftar {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 5;
  min-width: 260px;
  margin: 0;
  padding: var(--sp-3) 0;
  list-style: none;
  background: #fff;
  border: 1px solid var(--c-border);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-card);
}

.unduh-sert__daftar a {
  display: block;
  padding: var(--sp-3) var(--sp-5);
  color: var(--c-ink);
  text-decoration: none;
}

.unduh-sert__daftar a:hover,
.unduh-sert__daftar a:focus-visible {
  background: var(--c-surface);
  color: var(--c-primary);
}

@media (max-width: 560px) {
  /* Di layar sempit menu mengambang gampang keluar tepi — biarkan mengalir
     di bawah tombolnya. */
  .unduh-sert__daftar {
    position: static;
    min-width: 0;
    margin-top: var(--sp-3);
  }
}

/* ------------------------------------------------------------
   LOKASI KANTOR (halaman Kontak) — peta Google Maps
   Menggantikan kartu info kontak, 2026-09-17.
   Rujukan tampilan klien: peta selebar container, rasio ~2:1
   (1213x591 pada kanvas 1440), sudut membulat.
   ------------------------------------------------------------ */

/*
 * Jarak judul -> peta, diukur dari PNG rujukan klien dengan sampel piksel
 * (kanvas 1440): garis pemisah y 1226, TINTA judul 1274..1298, peta
 * 1348..1910.
 *
 * ⚠️ Yang meleset bukan totalnya melainkan PEMBAGIANNYA. Sebelum ini
 * garis->peta sudah 118px (desain 122), tapi judulnya duduk 85px dari garis
 * dan cuma 10px dari peta — desain menuntut 48px dan 50px. Judul yang
 * menempel ke petanya itu yang dilaporkan klien.
 *
 * 43px, bukan 48: kotak baris judul mulai 5px DI ATAS tintanya
 * (line-height 37,5 vs font 30), dan padding mengatur kotak, bukan tinta.
 */
.lokasi { padding-top: 43px; }

/* 40px, bukan 50: tinta judul berakhir 10px sebelum dasar kotak barisnya. */
.lokasi .title-lg { margin-bottom: 40px; }

.lokasi-peta {
  /* Dump rujukan 1214x562 (diukur piksel, bukan dikira-kira) — rasio 2,160.
     Sempat ditulis 1213/591 dari pembacaan kasar, dan itu membuat petanya
     585px alih-alih 556px di container 1200.
     Dipatok supaya tinggi peta tidak berubah-ubah mengikuti apa pun —
     iframe tidak punya tinggi intrinsik yang berguna. */
  aspect-ratio: 1214 / 562;
  border-radius: var(--r-md);
  /* `overflow: hidden` WAJIB: sudut membulat pada pembungkus tidak memotong
     iframe di dalamnya, jadi tanpa ini petanya tetap bersudut siku. */
  overflow: hidden;
  /* Latar abu saat peta belum termuat (lazy) — kotak putih kosong terbaca
     seperti bagian yang rusak. */
  background: var(--c-surface);
}

.lokasi-peta iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

@media (max-width: 768px) {
  /* Di layar sempit rasio 2:1 membuat petanya terlalu pendek untuk
     dikenali — jalan di sekitarnya tidak terbaca. Dibuat lebih tinggi. */
  .lokasi-peta { aspect-ratio: 4 / 3; }
}


/* ------------------------------------------------------------
   MOBILE: kartu kategori menumpang band "Produk Kami"
   ------------------------------------------------------------ */

/*
 * ⚠️ Blok ini WAJIB berada di AKHIR berkas, bukan di media query mobile
 * bersama aturan kartu kategori lainnya.
 *
 * Aturan aslinya — `.section-lead + .cat-grid` dan `.section.section--produk`
 * — punya spesifisitas yang SAMA (0,2,0) dan ditulis BELAKANGAN di berkas
 * ini. Media query tidak menambah spesifisitas sedikit pun, jadi override
 * yang ditaruh lebih awal kalah oleh urutan muat dan tidak berefek apa pun:
 * terukur jaraknya tetap 64px dan band tetap 284px, tanpa satu pun gejala.
 *
 * Yang diatur di sini (dump mobile 412px): kartu kategori MENJOROK NAIK ke
 * dalam band berfoto, bukan mendarat tepat di batas bawahnya.
 */
@media (max-width: 640px) {
  /* Dump: paragraf berakhir y 2039, kartu mulai 2055 -> 16px.
     Sebelumnya 64px (--sp-16), yang menaruh kartu persis di batas band. */
  .section-lead + .cat-grid { margin-top: var(--sp-4); }

  /*
   * ⚠️ 269px, bukan 228px seperti dump. Paragraf "Produk Kami" di Poppins
   * setinggi 134px sementara dump 106px (+28px), jadi kartu mulai 236px dari
   * atas section — sudah lebih rendah dari band 228px, dan dengan angka dump
   * apa adanya kartunya justru jatuh DI BAWAH band alih-alih menumpang.
   * 269 = 236 (posisi kartu sesungguhnya) + 33 (jumlah menjorok di dump).
   * Perluasan aturan #28: yang digeser satu angka geometri, bukan hurufnya.
   */
  .section.section--produk { --band-h: 269px; }
}

/* ------------------------------------------------------------
   HERO HOME — versi MOBILE (dump Home 412px, 2026-09-17)
   ------------------------------------------------------------ */

/*
 * ⚠️ Blok ini WAJIB di AKHIR berkas: aturan yang ditimpanya
 * (`.hero-slider__slide`, `.hero-slider__dots`, `.hero__title`,
 * `.hero__subtitle`) punya spesifisitas yang sama dan ditulis lebih awal —
 * media query tidak menambah spesifisitas, jadi yang menang urutan muat.
 * Pelajaran yang sama sudah memakan satu putaran di band "Produk Kami".
 *
 * Dump hero mobile (hero 412x520):
 *   judul    342x65 di y 209, 26px/32, w800, rata tengah
 *   subjudul 328x25 di y 281, 20px/25
 *   tombol   298x54 di y 329
 *   dots     61x21  di y 423  -> 76px dari dasar hero
 */
@media (max-width: 640px) {
  /*
   * Posisi konten hero ditentukan padding SLIDE, bukan padding hero —
   * slide-lah yang membungkus judul/subjudul/tombol. 105px membawa judul
   * dari y 224 ke y 209 seperti dump.
   */
  /*
   * ⚠️ `align-content: start` WAJIB ikut. Tanpa itu slide memusatkan
   * kontennya secara vertikal, sehingga padding-top bukan lagi posisi judul
   * melainkan cuma salah satu suku dalam perhitungan pusat — mengubahnya 8px
   * menggeser judul 17px, dan setiap perubahan tinggi konten (mis. subjudul
   * yang jatuh ke dua baris di layar sempit) menggeser semuanya lagi.
   * Dengan `start`, padding-top = posisi judul, persis seperti dump.
   */
  .hero-slider__slide {
    align-content: start;
    padding-top: 209px;
  }

  /* Dump: 26px/32 dan 20px/25. Sebelumnya 24/30 dan 18/22,5 — token
     `--fs-hero` & `--fs-hero-sub` dipakai bersama halaman lain, jadi
     nilainya ditulis langsung di sini alih-alih menggeser tokennya. */
  .hero--home .hero__title {
    font-size: 26px;
    line-height: 32px;
    /*
     * ⚠️ Dilebarkan melewati container, sama seperti subjudul di bawah.
     * Font 26px dari dump SUDAH cukup untuk dua baris — yang kurang cuma
     * kotaknya. Di 390px container tema tinggal 325px dan judulnya jatuh ke
     * TIGA baris; disapu per-lebar, 26px muat dua baris di >=375px asalkan
     * kotaknya mencapai lebar layar dikurangi ~32px.
     * `calc(100% + 34px)` memberi 378px di 412, 359 di 390, 347 di 375, dan
     * 334 di 360 — semuanya di atas ambang, dan tidak pernah menyentuh tepi
     * layar (paling mepet 13px di 360px).
     * ⚠️ Relatif container, BUKAN `100vw`: vw termasuk batang gulir
     * (aturan #62).
     */
    width: calc(100% + 34px);
    margin-inline: -17px;

    /*
     * ⚠️ Dipatok DUA BARIS supaya tombol & dots tidak melompat antar slide.
     * Judul tiap slide beda panjang — "Flexitank for Bulk Liquids" muat satu
     * baris sementara sisanya dua, dan tanpa ini tombol slide itu naik 32px
     * sehingga carousel terlihat tersentak setiap kali berganti. Dengan
     * `min-height` judul pendek tetap memakan jatah dua baris.
     * Judul TIGA baris (naskah panjang di layar sempit) tetap melar apa
     * adanya — ini lantai, bukan langit-langit.
     */
    min-height: 64px;
  }

  .hero--home .hero__subtitle {
    font-size: 20px;
    line-height: 25px;
    /*
     * ⚠️ Melebar 14px ke tiap sisi supaya tetap SATU baris seperti dump.
     * "untuk industri minyak, gas dan kimia." butuh 372px di Poppins 20px,
     * sementara container di 412px cuma 344px — disapu 330..372px, satu
     * baris baru tercapai di 372. Dua baris menambah 25px dan mendorong
     * tombol serta dots keluar dari posisi dump. Perluasan aturan #28: yang
     * digeser lebar kotaknya, bukan ukuran hurufnya.
     *
     * ⚠️ `calc(100% + 28px)`, BUKAN `100vw` — vw termasuk batang gulir dan
     * sudah memakan korban di aturan #62. Relatif container, ia ikut
     * menyusut di layar lebih sempit: di 360px jadi 328px (16px dari tepi
     * layar, tidak meluber) dan teksnya memang kembali dua baris di sana.
     */
    width: calc(100% + 34px);
    margin-inline: -17px;

    /*
     * ⚠️ Font subjudul MENYESUAIKAN lebar layar, tidak bisa dipatok 20px.
     * Berbeda dari judul, melebarkan kotaknya saja tidak cukup: disapu
     * per-lebar, satu baris menuntut <=20px di 412px tapi <=19px di 390 dan
     * <=18px di 375 — artboard dump memang 412px, dan di bawahnya tidak ada
     * lebar kotak yang menyelamatkannya tanpa menyentuh tepi layar.
     * 4,86vw menghasilkan 20,0px tepat di 412 (nilai dump) dan turun mulus
     * ke 18px di 375. Ini penyimpangan yang diizinkan aturan #28 — huruf
     * baru dikecilkan SESUDAH lebar kotaknya dimaksimalkan, dan hanya di
     * lebar yang memang lebih sempit dari artboard.
     */
    font-size: clamp(18px, 4.86vw, 20px);
  }

  /* Dump: teks berakhir y 306 (281 + 25), tombol mulai 329 -> 23px.
     Selisih KOORDINAT ATAS, bukan tinggi kotak (aturan #67). */
  .hero--home .hero__actions { margin-top: 23px; }

  /* Dump: dots di y 423 dari hero 520px -> 76px dari dasar (sebelumnya 32px,
     yang menaruhnya 44px terlalu rendah). */
  .hero-slider__dots { bottom: 76px; }
}

/*
 * ⚠️ Layar lebih sempit dari artboard dump (412px).
 *
 * Padding hero TIDAK lagi perlu dikecilkan di sini. Sebelum judul & subjudul
 * dilebarkan, di 360..411px judul jatuh ke tiga baris dan subjudul ke dua,
 * sehingga tombol berakhir y 440 dan menimpa dots di 423 — waktu itu
 * ditambal dengan padding-top 150px. Sesudah kotak teksnya dilebarkan ke
 * lebar layar, judul kembali dua baris dan subjudul satu baris mulai 375px,
 * jadi kontennya sependek di 412px dan padding 209px dari dump berlaku apa
 * adanya.
 *
 * Yang tersisa lebar di BAWAH 375px, di mana judul memang masih tiga baris
 * (butuh 25px, sementara dump 26px) dan di 320px subjudul ikut jadi dua.
 * Terukur di 320px tombol berakhir y 440 sementara dots duduk di 423 —
 * bertabrakan. Paddingnya dikecilkan hanya di sana; dots TIDAK digeser karena
 * posisinya datang dari dump dan sama di semua lebar.
 *
 * ⚠️ Ambangnya 374px, yaitu satu piksel di bawah lebar terkecil yang sudah
 * sempurna (375px). Di 375px ke atas padding 209px dari dump berlaku apa
 * adanya dan tidak boleh ikut dikecilkan.
 */
@media (max-width: 374px) {
  .hero-slider__slide { padding-top: 184px; }
}

/* ============================================================
   HALAMAN PRODUK — MOBILE (dump Figma 412x4015 + Product.png @2x)
   ------------------------------------------------------------
   Ditulis di AKHIR berkas dengan sengaja: media query tidak menambah
   spesifisitas sama sekali, jadi aturan di sini hanya menang kalau ia
   datang SESUDAH aturan yang ditimpanya. Sudah dua kali blok mobile
   ditaruh lebih awal dan tidak berefek apa pun.
   ============================================================ */

@media (max-width: 640px) {

  /* --- Header: pita 109px (lihat --header-h di tokens.css) --- */
  .header__inner { padding-block: 25px 40px; }

  /*
   * --- Hero polos: 237px, bukan 329px ---
   * Dump: Rectangle 102 = 412x237 mulai y=109 (tepat di bawah header).
   * `.hero--home` TIDAK ikut — ia punya angkanya sendiri (520px) dan
   * sudah disamakan ke dump Home.
   */
  .hero:not(.hero--home) {
    min-height: 237px;
    padding-block: var(--sp-12);
  }

  /* Dump: judul 342x65 = dua baris 25/31. Token --fs-hero turun ke 24px di
     <=768px; dump mobile menuntut 25px. */
  .hero:not(.hero--home) .hero__title { font-size: 25px; }

  /*
   * --- Kolom pencarian: tinggi 47px ---
   * Ditulis sebagai `height`, bukan dihitung dari padding + line-height:
   * tinggi input bergantung pada font yang sedang terpakai, dan Poppins
   * memberi angka berbeda dari Google Sans Flex. Satu nilai pasti lebih
   * murah daripada mengejar padding yang benar di dua font.
   */
  .searchbar__input {
    height: 47px;
    padding-block: 0;
    padding-left: var(--sp-5);
    font-size: 15px;
  }

  /* Dump: search berakhir y=419, kartu kategori mulai y=446. */
  .searchbar { margin-bottom: 27px; }
}

/* ------------------------------------------------------------
   Baris kategori: 5 tile sebaris, label DI BAWAH tile.
   Dump mobile: tile di x 35/106/176/247/317 (lebar 60), label y=516
   (11/15), tile y=446 — jarak tile->label 10px, isi baris 342px.

   ⚠️ Berlaku sampai 1024px, BUKAN cuma 640px. Di rentang 641..1024 kartu
   versi desktop membungkus jadi 3+2 kolom dan tingginya melonjak
   419-568px — satu layar tablet nyaris habis sebelum produknya terlihat.
   Batasnya 1024px karena di situ pula `.product-layout` berhenti jadi satu
   kolom: di atasnya sidebar & kartu 5-sebaris versi desktop memang sudah
   pas.
   ------------------------------------------------------------ */
@media (max-width: 1024px) {
  .cat-row {
    flex-wrap: nowrap;
    align-items: start;   /* tile rata atas walau label 1 vs 2 baris */
    /* 5x60 + 4x10,5 = 342 (persis lebar isi di 412px); melar mengikuti
       container di tablet, dibatasi 18px supaya tidak menganga. */
    gap: clamp(10.5px, 3%, 18px);
    justify-content: center;
    max-width: none;
  }

  /* Menimpa `flex: 0 1 calc(...)` dari blok <=1024 & <=560 — keduanya
     membungkus baris jadi beberapa baris, yang justru dibuang di sini.
     ⚠️ `max-width` menahan tile supaya tidak ikut melar jadi ~125px di
     tablet: proporsi mobile (tile 17,5% lebar isi) menghasilkan kotak yang
     kelewat besar begitu containernya 696px, dan ikonnya ikut membengkak. */
  .cat-row > * { flex: 1 1 0; max-width: 110px; min-width: 0; }

  /* ⚠️ `min-width: 0` + pemenggalan kata WAJIB berpasangan (2026-10-09).
     Item flex tidak menyusut di bawah lebar KATA terpanjang labelnya, dan
     tile-nya `aspect-ratio: 1` selebar item — jadi "Pharmaceutical" di situs
     Inggris membuat tile-nya 88px sementara keempat lainnya 48px (390px).
     min-width:0 mengembalikan kelimanya ke lebar yang sama; labelnya lalu
     dipenggal ("Pharma-ceutical", butuh lang="en" di <html>, dipasang
     Polylang).
     ⚠️ SENGAJA tanpa overflow-wrap:anywhere: di peramban tanpa kamus
     pemenggalan ia memotong di huruf mana saja ("Pharmac/eutical").
     Tanpa itu labelnya tetap SATU baris dan — karena ia item flex kolom
     ber-align-items:center — terpusat di bawah tile, menjorok sama rata
     ke celah kiri-kanan (~9px di 390px). Tile-nya sendiri tetap sama besar. */
  .cat-row .card-cat--stacked {
    hyphens: auto;
  }

  /* Kartu berhenti menjadi kotak: ia cuma pembungkus tile + label.
     :hover ikut ditulis karena `.card-cat:hover` berspesifisitas sama
     (0,2,0) — yang menentukan urutan, dan blok ini memang paling akhir. */
  .cat-row .card-cat--stacked,
  .cat-row .card-cat--stacked:hover {
    aspect-ratio: auto;
    min-height: 0;
    padding: 0;
    gap: 10px;
    background: none;
    box-shadow: none;
    color: var(--c-ink);
    /* 11px dari dump di 412px, naik pelan ke 13px di tablet — 11px pada
       layar 834px terbaca kelewat kecil dibanding sekitarnya. */
    font-size: clamp(11px, 1.6vw, 13px);
    line-height: 1.36;
  }

  .cat-row .card-cat__kotak {
    display: grid;
    place-items: center;
    width: 100%;
    aspect-ratio: 1;
    background: var(--c-white);
    border-radius: 10px;
    /* Dump: 0px 4px 15px rgba(0,0,0,0.2) — bayangan tile sendiri, BUKAN
       --shadow-card maupun bayangan kartu desktop (2 5 20 / .25). */
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
  }

  /* Ukuran ikon dinyatakan RELATIF terhadap tile (34/60 = 57%), bukan px:
     satu nilai melayani 60px di HP dan 110px di tablet tanpa angka kedua
     yang harus dijaga sinkron. */
  .cat-row .card-cat .icon {
    width: 57%;
    height: auto;
    aspect-ratio: 1;
  }

  /* Kategori aktif: yang membiru TILE-nya, labelnya tetap hitam seperti
     yang lain — di rujukan kelima label berwarna sama. */
  .cat-row .card-cat.is-active .card-cat__kotak { background: var(--c-primary); }
  .cat-row .card-cat.is-active .icon { color: var(--c-white); }
}

/* ------------------------------------------------------------
   Dropdown produk — menggantikan sidebar daftar produk di <=1024px.
   Dump Rectangle 109: pill 342x47, #D9D9D9, radius pill, teks 18px di
   x=55 (= padding kiri 20px), chevron gelap di kanan.

   ⚠️ `<details>`, BUKAN `<select>`. Popup `<select>` diposisikan peramban
   sendiri — Chrome mensejajarkan opsi TERPILIH dengan kotaknya, jadi produk
   yang berada di tengah daftar membuat sebagian besar popup mendarat DI
   ATAS pill. Tidak ada properti CSS yang bisa mengubahnya. `<details>`
   adalah konten biasa, jadi ia selalu terbuka ke bawah.

   ⚠️ Sampai 1024px, sama seperti baris kategori: di rentang tablet
   `.product-layout` satu kolom, jadi sidebar daftar produk membentang
   selebar halaman dan memakan 320px tinggi sebelum produknya terbaca.
   ------------------------------------------------------------ */

/* Desktop: pembungkusnya tidak ada artinya — <nav> di dalamnya kembali
   menjadi grid item `.product-layout` persis seperti sebelum <details>
   ini ada. */
.product-pilih { display: contents; }
.product-pilih__tombol { display: none; }

@media (max-width: 1024px) {
  .product-pilih {
    display: block;
    position: relative;
  }

  .product-pilih__tombol {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    height: 47px;
    padding-inline: var(--sp-5);
    border-radius: var(--r-pill);
    background: var(--c-pilih-bg);
    color: var(--c-ink);
    font-size: var(--fs-body);
    cursor: pointer;
    /* Segitiga bawaan <summary> dibuang; chevronnya digambar sendiri di
       kanan supaya cocok dengan rujukan. */
    list-style: none;
  }

  .product-pilih__tombol::-webkit-details-marker { display: none; }

  /* ⚠️ Label produk di proyek ini = judul + grade (anaya_label_produk),
     jadi ia sering lebih panjang dari pill. Mock Figma kebetulan memakai
     nama pendek ("Potassium Chloride") sehingga panjangnya tidak terlihat
     jadi masalah di sana. */
  .product-pilih__teks {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .product-pilih__tombol::after {
    content: '';
    flex: none;
    width: 0;
    height: 0;
    border-inline: 7px solid transparent;
    border-top: 9px solid var(--c-ink);
    transition: rotate var(--t-fast);
  }

  .product-pilih[open] .product-pilih__tombol::after { rotate: 180deg; }

  /*
   * ⚠️ Panel mengambang HANYA saat JS memegang kendali (`.is-dropdown`).
   * Tanpa JS `<details>` tetap `open` — dan kalau daftarnya tetap
   * `position: absolute` ia akan menutupi isi halaman selamanya. Dengan
   * penjagaan ini, halaman tanpa JS cuma menampilkan daftar tautan biasa
   * yang mengalir normal, dan navigasinya tetap berfungsi penuh.
   */
  .product-pilih.is-dropdown[open] .product-nav {
    position: absolute;
    top: calc(100% + var(--sp-2));
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 320px;
    overflow-y: auto;
    padding-right: 0;
    border: 1px solid var(--c-border-strong);
    border-radius: var(--r-md);
    background: var(--c-white);
    box-shadow: var(--shadow-float);
  }
}

/* ------------------------------------------------------------
   Jarak vertikal blok atas halaman Produk di mobile.
   Dump: hero berakhir 346 -> search 372 (26px); kartu kategori berakhir
   548 -> dropdown 583 (35px). Di desktop jarak itu 80px dan sengaja
   dipecah margin 56 + padding 24 demi blok sticky; di mobile blok ini
   TIDAK pernah menempel (sticky-nya >=1200px), jadi pembagian itu tidak
   diperlukan dan angkanya boleh ditulis langsung.
   ------------------------------------------------------------ */
@media (max-width: 640px) {
  .produk-alat { margin-block: 0; }
  .produk-alat > .section:first-child { padding-top: 26px; }
  .produk-alat > .section:last-child { padding-bottom: 35px; }

  /*
   * Judul hero TIDAK terpusat vertikal di dump — ia duduk 74px dari tepi
   * atas hero sementara sisa bawahnya 98px. `place-items: center` milik
   * `.hero` menaruhnya 13px terlalu rendah.
   */
  .hero:not(.hero--home) {
    /*
     * ⚠️ `align-content`, BUKAN hanya `align-items`.
     *
     * `.hero` adalah grid, dan di halaman ber-"Edit Konten" ia punya anak
     * KEDUA setinggi nol (penanda `.anaya-sec`). Dua anak = dua BARIS grid,
     * dan sisa ruang hero dibagi rata ke keduanya — jadi judul mendarat di
     * y=140 (Blog) dan y=124 (Kontak) walau `align-items: start` sudah
     * dipasang, karena yang diratakan isi baris, bukan letak barisnya.
     * `align-content: start` memadatkan barisnya ke atas.
     */
    align-items: start;
    align-content: start;
    padding-block: 74px 0;
  }
}

/* Dump: dropdown berakhir 630 -> judul produk 655 (25px). Jaraknya ditaruh
   di `gap` grid, bukan di margin dropdown: saat JavaScript mati dropdown
   diganti daftar tautan, dan margin yang menempel pada dropdown ikut hilang
   bersamanya sehingga jaraknya berbeda di dua keadaan. */
@media (max-width: 1024px) {
  .product-layout { gap: 25px; }
}

/* ------------------------------------------------------------
   Blok detail produk & CTA — mobile.
   ------------------------------------------------------------ */
@media (max-width: 640px) {
  /*
   * ⚠️ Membalik keputusan 2026-09-10 untuk mobile, DENGAN SENGAJA.
   * Waktu itu `min-width: max-content` dipasang supaya kolom tabel tidak
   * diperas; dump mobile klien justru MENUNJUKKAN tabel yang muat 342px
   * dengan label membungkus ("CHEMICAL ANALYSIS" dua baris, "Potassium
   * Chloride (KCL)" dua baris). Desainnya menerima tampilan itu.
   *
   * `min-width: 100%`, bukan `auto`: jaring pengamannya tetap ada —
   * `.spec-table-wrap` masih `overflow-x: auto`, jadi tabel yang benar-benar
   * tidak muat walau sudah membungkus (kolomnya lebih banyak dari katalog
   * sekarang) tetap bisa digeser, bukan meluberkan halaman.
   */
  .spec-table {
    min-width: 100%;
    /* Dump: 14px/18px. `line-height` WAJIB ikut ditulis — --lh-body (1,7)
       yang terwarisi dari body memberi 24px per baris, dan pada tabel yang
       hampir setiap labelnya membungkus dua baris selisih 6px itu menjadi
       ~180px di tinggi satu tabel. */
    font-size: 14px;
    line-height: 18px;
  }

  /* Dump: kolom 1 mulai x=35 sementara teksnya x=46 -> padding 11px.
     Dengan 16px bawaan, label 2 baris di dump jadi 3 baris di sini dan
     tabelnya tidak lagi muat 342px. */
  .spec-table th,
  .spec-table td { padding: 12px 11px; }

  /* Dump: tombol unduh selebar isi (342px), bukan selebar teksnya. */
  .product-block > .btn,
  .product-block > .unduh-sert > summary {
    display: flex;
    justify-content: center;
    width: 100%;
  }

  /* Dump: teks CTA 341px, 20/25 (bukan --fs-section 21px). */
  .produk-cta__lead {
    max-width: 341px;
    font-size: 20px;
    line-height: 25px;
  }

  /* Dump: teks CTA berakhir 2877 -> kartu form 2892. */
  .produk-cta__form { margin-top: 15px; }

  /*
   * Dump mobile: foto 412x282 mulai 3198, kartu 2892..3326 -> kartu menutupi
   * 128px bagian atas foto. Angka desktop (342 / -230) berasal dari artboard
   * 1440 dan tidak berlaku di sini.
   */
  .produk-cta__photo {
    height: 282px;
    margin-top: -128px;
  }
}

/* Dump: garis pemisah 2717 -> teks CTA 2754 (37px), bukan 80px section biasa.
   Disaring ke body halaman Produk & arsip kategorinya, BUKAN ke `#penawaran`
   umum: blok form yang sama dipakai halaman lain yang tidak sedang diubah,
   dan menggesernya di sana berarti mengubah halaman yang tidak diminta. */
@media (max-width: 640px) {
  .single-produk #penawaran,
  .tax-kategori_produk #penawaran { padding-top: 37px; }

  /* Dump: tombol unduh 47px, sama tinggi dengan kolom pencarian & dropdown. */
  .product-unduh > .btn,
  .product-unduh > .unduh-sert > summary {
    min-height: 47px;
    padding-block: 0;
    align-items: center;
  }
}

/* Dump: judul produk 23px/30, bukan --fs-hero-sm 24px. Selisih 1px itu
   menentukan pecah barisnya: di 24px "POTASSIUM CHLORIDE 99% KCL" jatuh
   tiga baris, di 23px dua baris persis seperti rujukan. */
@media (max-width: 640px) {
  .product-title { font-size: 23px; }
}


/* ------------------------------------------------------------
   Hero Home bisa digeser dengan jari.
   `pan-y` menyerahkan gulir VERTIKAL ke peramban dan menyisakan gerakan
   mendatar untuk kita — tanpa itu, peramban menelan kedua arah dan geser
   mendatarnya tidak pernah sampai ke JavaScript.
   ⚠️ Dipasang pada track, bukan pada `.hero`: tombol CTA & titik berada di
   lapisan lain, dan menyetel `touch-action` di sana tidak diperlukan.
   ------------------------------------------------------------ */
.hero-slider__track {
  touch-action: pan-y;
}


/* ------------------------------------------------------------
   OPTIMASI SENTUH — iOS & Android (2026-10-05)

   Hasil tools/audit-perangkat.py (8 profil perangkat x 10 halaman: iPhone
   di WebKit, Android di Chromium, HP & tablet). Ditaruh di AKHIR berkas
   supaya menang atas aturan komponen berspesifisitas sama.
   ------------------------------------------------------------ */

/* 1. Kotak isian WAJIB >= 16px di layar sentuh.
   iOS Safari otomatis MEMPERBESAR halaman saat kotak isian berhuruf < 16px
   disentuh — dan tidak mengecil lagi sesudahnya, jadi pengunjung harus
   mencubit layar untuk kembali. Di <=640px --fs-body-sm turun ke 15px, dan
   itu mengenai SEMUA formulir (Kontak, form penawaran Produk/Flexipack) plus
   kolom cari produk — terukur 180 temuan di 4 profil iPhone/iPad.
   Desktop tidak berubah (sudah 16px). */
@media (max-width: 1024px) {
  .field__input,
  .searchbar__input { font-size: 16px; }
}

/* Bayangan dalam & sudut bawaan iOS pada kotak isian. Border, latar, dan
   radius sudah ditulis sendiri oleh komponennya — appearance bawaan cuma
   menambahkan gradasi abu di tepi atas yang tidak ada di desain. */
.field__input,
.searchbar__input {
  -webkit-appearance: none;
          appearance: none;
}

/* 2. Target sentuh menu footer — 20px tinggi (di bawah ambang WCAG 2.2
   SC 2.5.8 24px, jauh di bawah 44px rekomendasi Apple/Google). Di HP menunya
   satu baris rapat, dan itu tautan yang paling sering diketuk di dasar
   halaman. Bidang sentuhnya diperbesar lewat padding, lalu DITARIK BALIK
   dengan margin negatif yang sama: tata letak & tinggi footer tidak
   bergeser sepiksel pun, yang bertambah cuma area yang bisa diketuk.
   <=900px ATAU perangkat tanpa hover: iPad rebah (1194px) memakai tata
   letak desktop tapi penunjuknya tetap jari — dengan gerbang lebar saja ia
   terlewat (terukur di audit). Desktop bermouse tidak tersentuh. */
@media (max-width: 900px), (hover: none) {
  .footer__nav a {
    display: inline-block;
    /* 8px, bukan lebih: di 641..900px menunya dua lajur berjarak baris 16px —
       20 + 2x8 = 36px pas mengisi celah tanpa bidang sentuh antarbaris
       saling tumpang. */
    padding-block: 8px;
    margin-block: -8px;
  }
}

/* 2b. Pilihan bahasa ID | EN — 16x27px. Bidang sentuh dilebarkan 4px ke
   kiri-kanan (24px), lagi-lagi ditarik balik dengan margin supaya "ID | EN"
   tidak bergeser. Lebih dari 4px akan menumpang garis pemisah "|" dan
   pasangannya. */
@media (max-width: 900px), (hover: none) {
  .lang a {
    display: inline-block;
    padding: 4px;
    margin: -4px;
  }
}

/* 3. Titik carousel hero — 21x21px. Bidang sentuh jadi 33x33px dengan pola
   yang sama (padding + margin negatif 6px), jadi lingkarannya tetap 13/21px
   dan jaraknya tetap seperti desain. */
.hero-slider__dot {
  box-sizing: content-box;
  padding: 6px;
  margin: -6px;
}

/* 4. Hover yang "lengket" di layar sentuh.
   Android (dan iOS untuk elemen yang punya penangan sentuh) menerapkan
   :hover saat elemen diketuk dan MEMPERTAHANKANNYA sampai bagian lain
   diketuk. Untuk tautan itu tidak masalah — halamannya keburu berpindah.
   Untuk marquee logo klien masalah nyata: sekali disentuh ia berhenti dan
   TETAP berhenti. Jeda-saat-hover sengaja hanya untuk perangkat yang
   benar-benar punya hover (mouse/trackpad). */
@media (hover: none) {
  .marquee:hover .marquee__track { animation-play-state: running; }
}

/* 5. Drawer menu: pemusatan yang AMAN.
   `justify-content: center` pada flex yang isinya lebih tinggi dari
   wadahnya membuang luapan ke DUA arah — bagian atas yang terpotong tidak
   bisa dicapai dengan menggulir (scrollTop tidak bisa negatif). Terukur di
   iPhone rebah: drawer 202px, isi 480px, item "Home" duduk di y=34, DI ATAS
   tepi drawer (141), tidak terjangkau sama sekali. Margin auto di anak
   pertama & terakhir memusatkan selama muat, dan jatuh ke rata atas begitu
   tidak muat — tanpa bergantung dukungan `safe center`. */
@media (max-width: 900px) {
  .nav { justify-content: flex-start; }
  .nav > :first-child { margin-top: auto; }
  .nav > :last-child { margin-bottom: auto; }
}

/* 6. HP REBAH (layar pendek, mis. iPhone 852x393 / Pixel 915x412).
   Tinggi tampilnya cuma ~340-360px. Header 141px memakan 40% layar, dan blok
   cari + kategori Produk (307px) yang muncul saat menggulir naik menutupi
   isi produk SEPENUHNYA — terukur ruang baca minus 92..105px.
   - Header dirampingkan ke 72px (tombol menu 44px + 14px atas-bawah);
     --header-h ikut, jadi drawer, scroll-padding, dan apa pun yang memakai
     token itu tetap sinkron.
   - Blok alat Produk TIDAK menempel: di layar sependek ini ia selalu
     menang melawan isinya. Transform auto-hide ikut dinolkan — JS tetap
     memasang .is-sembunyi, dan pada elemen yang tidak menempel transform itu
     akan menggeser blok ke atas menimpa konten.
   Hanya <=900px: di atasnya header desktop dipatok pada pita 152px. */
@media (max-height: 500px) and (orientation: landscape) and (max-width: 900px) {
  :root { --header-h: 72px; }
  .header__inner { padding-block: 14px; }

  .produk-alat { position: relative; top: auto; }
  .produk-alat.is-stuck,
  .produk-alat.is-stuck.is-sembunyi {
    transform: none;
    box-shadow: none;
  }
}

/* ==========================================================================
   LATAR RESPONSIF (2026-10-22) — foto hero per ukuran layar
   --------------------------------------------------------------------------
   Latar CSS tidak punya srcset. anaya_latar_attr() (inc/helpers.php)
   menitipkan sampai tiga berkas sebagai custom property, dan
   `background-image` sebaris membaca --latar-pilih yang diisi di sini:

     --latar-hp  potongan tegak, <=640px
     --latar-1x  berkas lama (hero 1440px, band 1920px)
     --latar-2x  layar lebih lebar dari berkas 1x, atau berkerapatan tinggi

   ⚠️ Media query di sini HARUS sama dengan anaya_latar_media() (inc/seo.php)
   yang menulis preload-nya. Kalau berbeda, preload mengunduh berkas yang
   tidak dipakai — gagal diam dan menambah bobot LCP.
   Versi yang tidak ada jatuh ke --latar-1x lewat cadangan var().
   ========================================================================== */
[data-latar] { --latar-pilih: var(--latar-1x); }

@media (max-width: 640px) {
  [data-latar] { --latar-pilih: var(--latar-hp, var(--latar-1x)); }
}

@media (min-width: 1440.02px), (min-width: 640.02px) and (min-resolution: 1.2dppx), (min-width: 640.02px) and (-webkit-min-device-pixel-ratio: 1.2) {
  [data-latar="1440"] { --latar-pilih: var(--latar-2x, var(--latar-1x)); }
}

@media (min-width: 1920.02px), (min-width: 640.02px) and (min-resolution: 1.5dppx), (min-width: 640.02px) and (-webkit-min-device-pixel-ratio: 1.5) {
  [data-latar="1920"] { --latar-pilih: var(--latar-2x, var(--latar-1x)); }
}
