/* Section pdp-end. Dua blok penutup halaman produk.

   Disalin apa adanya dari clvn-desk/src/components/pdp/end.css, 313 baris,
   seluruhnya. Yang berubah HANYA nama kelas:
     .xsell  -> .section-pdp-cross-sell__figure
     .faq    -> .section-pdp-faq
   plus dua nama global sedokumen yang ikut diberi prefiks supaya tidak
   bentrok dengan berkas section lain di folder yang sama:
     --xsell-view    -> --pdp-cross-sell-view
     xsell-parallax  -> pdp-cross-sell-parallax
   dan satu selektor placeholder: .ph -> .u-placeholder, nama yang dipakai
   situs ini di tokens.css.

   Semua angka di berkas ini hasil ukur. Jangan dirapikan, jangan
   dibulatkan, jangan disusun ulang. Sebagian sudah dikunci test.

   Nama produk milik sumber TIDAK ikut disalin, termasuk yang ada di
   komentar. Diganti istilah umum.

   Muat setelah tokens.css, bersama berkas section lain. */

/* Dua section penutup PDP, hasil ukur sumber @1280x800 (root 8.8832).
   Semua ukuran memakai token di tokens.css, tidak ada px yang ditulis
   langsung kecuali hasil ukur. Lihat 15_coterie-teardown.md */

/* === Cross sell, banner produk lain ============================= */

/* Figure setinggi viewport penuh, latar transparan. Tingginya TIDAK
   diset di sini: figcaption di bawah yang membawa min-height 100svh dan
   figure ikut karena caption ada di aliran normal. Itu susunan sumber,
   dan hasilnya sama persis: 1280x800 @1280x800, 1280x720 @1280x720.
   svh dipakai supaya tidak melompat saat toolbar browser mobile muncul.

   clip, BUKAN hidden. `hidden` membuat scroll container, dan timeline
   view() mengukur visibilitas terhadap scroller TERDEKAT. Dengan hidden,
   media tidak pernah bergerak relatif ke container itu, jadi progres
   animasinya konstan dan parallax-nya beku. `clip` memotong sama persis
   tapi tidak membuat scroll container. */
.section-pdp-cross-sell__figure {
  position: relative;
  margin: 0;
  background: transparent;
  overflow: clip;
}

/* Container parallax: absolute inset 0, setinggi figure, overflow clip.
   Dialah yang memotong, bukan figure, dan dialah yang mendefinisikan
   rentang timeline. Subject timeline sengaja container INI, bukan mover,
   karena mover sedang ditransform oleh animasi yang rentangnya diukur
   dari kotak itu sendiri. Nama timeline di sini, dipakai anaknya. */
.section-pdp-cross-sell__parallax {
  position: absolute;
  inset: 0;
  height: 100%;
  overflow: clip;
  view-timeline-name: --pdp-cross-sell-view;
}

/* Elemen yang benar-benar digeser. Setinggi container, TANPA overscan.
   Sumber juga tanpa overscan, dan itu memang aman pada faktor 0.125:
   saat ty = -100 celah ada di 100px terbawah figure, tapi pada momen itu
   figure baru masuk dari bawah dan bagian yang terlihat cuma 100px
   teratasnya. Celah dan area terlihat tidak pernah beririsan. Cek
   aljabarnya: dengan t = progres 0..1, tepi bawah area terlihat ada di
   1600t, celah mulai di 700 + 200t, dan 1600t > 700 + 200t hanya benar
   saat t > 0.5, padahal celah bawah cuma ada saat t < 0.5. */
.section-pdp-cross-sell__mover {
  height: 100%;

  /* Amplitudo terukur 100px ke tiap arah, faktor 0.125, yaitu 1px gerak
     media per 8px scroll. Ditulis sebagai custom property karena dipakai
     dua kali di keyframes. */
  --parallax: 100px;

  /* Parallax scroll-driven. ponytail: pakai animation-timeline bawaan
     CSS, bukan listener scroll di JS. Kalau browser belum mendukung,
     media tampil statis tanpa parallax, tidak rusak.

     JANGAN pakai shorthand `animation` di sini. Shorthand menyetel
     animation-duration ke 0s, dan dengan timeline scroll itu bikin
     animasinya BEKU di satu nilai: terdaftar, playState running, tapi
     transform tidak pernah berubah sepanjang scroll. Terlihat persis
     seperti animasi yang tidak ada. Duration wajib `auto`. */
  animation-name: pdp-cross-sell-parallax;
  animation-duration: auto;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --pdp-cross-sell-view;
  /* entry 0% sampai exit 100% mencakup seluruh perjalanan figure
     melintasi viewport, panjangnya tinggi viewport ditambah tinggi
     figure. Karena figure 100svh, rentangnya 2x tinggi viewport.
     Di viewport 800 tinggi itu 1600px scroll, dan 1600 * 0.125 = 200px,
     persis total perjalanan dari -100px sampai +100px. Terverifikasi di
     sumber: tepi atas figure di y=800 -> ty=-100, di y=0 -> ty=0,
     di y=-800 -> ty=+100. */
  animation-range: entry 0% exit 100%;
}

/* Scroll turun membuat figure naik. Media ikut naik lebih lambat, jadi
   relatif terhadap figure ia bergerak TURUN: -100px menuju +100px.
   Murni translate, TANPA scale. Terukur: matrix skala tetap 1. */
@keyframes pdp-cross-sell-parallax {
  from {
    transform: translate3d(0, calc(var(--parallax) * -1), 0);
  }
  to {
    transform: translate3d(0, var(--parallax), 0);
  }
}

/* Latar placeholder digelapkan. BUKAN hasil ukur, ini kompromi supaya
   section tetap terbaca selama slot media masih placeholder abu #d9d9d9.
   Overlay di figcaption sudah hasil ukur dan tetap dipakai apa adanya.
   Hapus rule ini begitu aset asli masuk. */
.section-pdp-cross-sell__parallax .u-placeholder {
  background: #4a4a4a;
}

/* Figcaption RELATIVE, bukan absolute. Ia ada di aliran normal dan
   dialah yang memberi tinggi ke figure. min-height 100svh dari class
   screen-h di sumber. Overlay hasil ukur: satu lapis rata 20% hitam
   plus radial 20% hitam yang justru lebih gelap di tengah, tepat di
   belakang teks putih. Itu cara sumber menjaga kontras di atas foto. */
.section-pdp-cross-sell__caption {
  position: relative;
  z-index: 2;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  background-image:
    linear-gradient(to right, rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.2) 100%),
    radial-gradient(circle, rgba(0, 0, 0, 0.2) 25%, rgba(0, 0, 0, 0) 100%);
}

/* Banner TIDAK punya width di desktop. Lebar 902.40 datang dari h3 di
   dalamnya, karena banner adalah flex item yang menyusut ke isi.
   Tinggi 372.53 = isi 212.64 + padding 9rem dua sisi (159.90). */
.section-pdp-cross-sell__banner {
  padding: 9rem 0;
  color: var(--white);
  text-align: center;
}

/* h3 yang memegang lebar banner: 18 kolom + 17 gutter = 902.40 @1280.
   margin-bottom 3rem = 26.6496 terukur. */
.section-pdp-cross-sell__heading {
  margin: 0 0 3rem;
  width: calc(18 * var(--col) + 17 * var(--gutter));
}

/* Paragraf 8 kolom + 7 gutter = 391.55 @1280, sengaja lebih sempit dari
   banner supaya panjang barisnya tetap enak dibaca. margin 0 auto 4rem,
   jadi 35.5328 ke tombol. pre-wrap supaya line break datang dari konten,
   sama seperti heading. */
.section-pdp-cross-sell__body {
  margin: 0 auto 4rem;
  width: calc(8 * var(--col) + 7 * var(--gutter));
  white-space: pre-wrap;
}

/* Mobile dan tablet memakai grid 12 kolom, jadi 18 kolom tidak ada di
   sana. Banner turun ke 12 kolom + 11 gutter, menempel ke bawah, dan
   dapat padding bawah 8rem. Judul dan paragraf melepas lebarnya. */
@media (max-width: 1023px) {
  .section-pdp-cross-sell__banner {
    width: calc(12 * var(--col) + 11 * var(--gutter));
    align-self: flex-end;
    padding-bottom: 8rem;
  }
  .section-pdp-cross-sell__heading {
    width: auto;
    margin-bottom: 1.2rem;
  }
  .section-pdp-cross-sell__body {
    width: auto;
    margin-bottom: 3rem;
  }
}

/* === FaqAccordion, daftar tanya jawab =========================== */

/* Section cuma membawa warna. Padding ada di container, bukan di sini.
   Tinggi 884.63 di sumber datang dari isi, tidak diset di mana pun. */
.section-pdp-faq {
  background: var(--stone);
}

/* padding 12rem 0 = 106.598 dua sisi. */
.section-pdp-faq__container {
  width: var(--grid-width);
  margin: 0 auto;
  max-width: var(--max-width);
  padding: 12rem 0;
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: space-between;
}

/* Judul shrink-to-fit. Lebarnya ditentukan isi teksnya, bukan kelipatan
   kolom, jadi sisa ruang jatuh ke list di kanan. Sticky di desktop,
   offset calc(header-height-fixed + 2rem) = 76.284 terukur. */
.section-pdp-faq__heading {
  margin: 0;
  position: sticky;
  top: calc(var(--header-height-fixed) + 2rem);
  color: var(--black);
}

/* List 12 kolom + 11 gutter = 595.89 @1280. */
.section-pdp-faq__list {
  width: calc(12 * var(--col) + 11 * var(--gutter));
  border-top: 1px solid var(--hairline);
}

.section-pdp-faq__entry {
  width: 100%;
  border-bottom: 1px solid var(--hairline);
}

/* Padding 4rem yang menentukan tinggi header (71.0656), bukan teks atau
   ikon. Tinggi total 92.48 = 71.0656 + 21.42 baris pertanyaan.
   Tanpa justify-content: ikon yang mendorong dirinya ke kanan lewat
   margin-left auto, persis seperti sumber. */
.section-pdp-faq__head {
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  padding: 4rem 0;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--black);
  text-align: left;
}

/* Pertanyaan menyusut ke isinya, TIDAK melar. Jarak ke ikon datang dari
   padding kanan 1.6rem = 14.2131 terukur. */
.section-pdp-faq__q {
  padding: 0 1.6rem 0 0;
}

/* Kotak ikon 19.53 = svg 1.2rem (10.656) + padding 0.5rem dua sisi.
   align-self flex-start, bukan center: itu hasil ukur. Rotasi tidak
   mengubah layout, jadi bounding box X yang membesar 1.414x jadi 15.07
   saat diputar 45 derajat tidak menambah tinggi header. */
.section-pdp-faq__cross {
  display: inline-flex;
  align-self: flex-start;
  margin-left: auto;
  padding: 0.5rem;
}
.section-pdp-faq__cross svg {
  width: 1.2rem;
  height: 1.2rem;
  transform: rotate(-45deg);
  transition: transform 0.6s var(--ease-in-overshoot);
}
.section-pdp-faq__head[aria-expanded='true'] .section-pdp-faq__cross svg {
  transform: rotate(-90deg);
}

/* Panel pakai grid-template-rows, cara menganimasikan height auto tanpa
   mengukur di JS. Sumber memakai library yang menulis tinggi konkret ke
   style dan mentransisikan `height`; durasi dan easing-nya sama persis
   (0.4s cubic-bezier(0.26,1.04,0.54,1) plus visibility 0.4s), jadi kurva
   tingginya identik. Bedanya cuma properti yang dianimasikan.

   top -2rem terukur: panel ditarik naik 17.7664 sehingga jawaban lebih
   rapat ke pertanyaan, dan sisa 17.7664 itulah jarak baris terakhir ke
   garis bawah. Karena relative, tinggi entry tidak berubah. */
.section-pdp-faq__panel {
  position: relative;
  top: -2rem;
  display: grid;
  grid-template-rows: 0fr;
  overflow: clip;
  visibility: hidden;
  transition:
    grid-template-rows 0.4s var(--ease-media),
    visibility 0.4s;
}
.section-pdp-faq__panel[data-open='true'] {
  grid-template-rows: 1fr;
  visibility: visible;
}
/* min-height 0 wajib. Tanpa itu grid item punya tinggi minimum auto dan
   baris 0fr tidak pernah benar-benar mengecil ke nol. */
.section-pdp-faq__inner {
  min-height: 0;
}
/* Panel TIDAK punya padding. Jarak antar paragraf 1rem = 8.8832, dan
   paragraf terakhir tanpa margin, itu yang bikin tinggi panel pas. */
.section-pdp-faq__a {
  margin: 0 0 1rem;
  color: var(--black7);
}
.section-pdp-faq__a:last-child {
  margin-bottom: 0;
}

/* Di bawah 1024 jadi satu kolom, judul di atas list dan berhenti sticky.
   Padding container turun ke 6rem, jarak antar kolom 6rem. */
@media (max-width: 1023px) {
  .section-pdp-faq__container {
    flex-direction: column;
    align-items: stretch;
    padding: 6rem 0;
    gap: 6rem;
  }
  .section-pdp-faq__heading {
    position: static;
  }
  .section-pdp-faq__list {
    width: 100%;
  }
}

/* === Aksesibilitas ============================================== */

/* Hormati prefers-reduced-motion. Parallax dimatikan total, accordion
   tetap berfungsi tapi tanpa transisi. */
@media (prefers-reduced-motion: reduce) {
  .section-pdp-cross-sell__mover {
    animation-name: none;
    transform: none;
  }
  .section-pdp-faq__cross svg,
  .section-pdp-faq__panel {
    transition-duration: 0.01ms;
  }
}
