/* stellar-motion.css — primitif motion Hub front page (post 125), production-1.1.
 * Spec: docs/superpowers/specs/2026-08-03-hub-motion-video-design.md
 *
 * File ini TIDAK tahu apa-apa soal isi halaman Hub. Ia hanya mendefinisikan
 * kelas yang dipasang markup dan dinyalakan stellar-motion.js.
 *
 * ATURAN PENTING: keadaan tersembunyi (.hub-rv) hanya berlaku setelah JS
 * memasangnya. Jangan pernah menulis opacity:0 langsung ke [data-reveal] —
 * satu error JS akan meninggalkan halaman kosong permanen. */

/* ===================== PARALLAX KEDALAMAN ===================== */
/* Frame: mengunci rasio & memotong. Layer: LEBIH TINGGI dari frame sebanyak
 * --px-travel di atas dan di bawah, jadi geseran maksimum (±--px-travel)
 * tidak pernah menyingkap celah hitam. --px-travel ditulis JS dari data-depth.
 *
 * position:relative di sini cuma default untuk frame yang mengalir normal.
 * Dua frame yang harus absolute (#home .hub-hero-bg dan #contact .hub-contact-bg)
 * menang lewat spesifisitas ID di stellar-hub.css — file ini dimuat BELAKANGAN,
 * jadi selector berspesifisitas sama akan mengalahkannya. */
.hub-px {
  position: relative;
  overflow: hidden;
}
.hub-px > .hub-px-layer {
  position: absolute;
  top: calc(-1 * var(--px-travel, 0px));
  left: 0;
  width: 100%;
  height: calc(100% + 2 * var(--px-travel, 0px));
  object-fit: cover;
  display: block;
  /* Untuk layer yang berupa <div> ber-background (Contact), bukan <img>/<video>. */
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

/* PEMBAGIAN PROPERTI YANG PENTING:
 *   translate  -> deviasi parallax, ditulis JS TIAP FRAME, tanpa transisi
 *   transform  -> kedalaman masuk 3D, dianimasikan transisi CSS
 * Dua-duanya properti terpisah (translate sudah properti sendiri sejak
 * Chrome 104 / Safari 14.1 / Firefox 72), jadi bisa berjalan bersamaan tanpa
 * saling memutus. Kalau keduanya ditumpuk di `transform`, tulisan JS tiap
 * frame akan membuat transisi CSS-nya tidak pernah selesai. */

/* ===================== REVEAL ===================== */
.hub-rv {
  opacity: 0;
  transform: translateY(24px);
}
/* KARTU 3D PER SECTION.
 * Yang masuk dengan gerak 3D adalah SECTION-nya sebagai satu kartu utuh —
 * bukan tiap elemen di dalamnya sendiri-sendiri. Kartu berangkat dari jauh
 * (translateZ negatif) lalu maju ke bidang layar.
 *
 * Kedalaman per-lapisan (data-depth) tetap ada, tapi tugasnya khusus parallax
 * saat scroll lewat properti `translate` — bukan animasi masuk. */
.hub-rv[data-card] {
  transform: perspective(1500px) translateZ(-320px);
  transform-origin: 50% 30%;
}
.hub-rv-anim {
  transition:
    opacity   .8s cubic-bezier(.22, .61, .36, 1),
    transform 1.05s cubic-bezier(.22, .61, .36, 1);
}
.hub-rv.is-in {
  opacity: 1;
  transform: none;
}
.hub-rv[data-card].is-in {
  transform: perspective(1500px) translateZ(0);
}

/* Tombol suara DIHAPUS pada 2026-08-03: video di halaman ini tidak pernah
 * bersuara, jadi tidak ada yang perlu dinyalakan. Jangan dikembalikan tanpa
 * keputusan baru — audio-nya sudah ikut dibuang dari perilaku JS juga. */

/* ===================== LAYAR MUAT (hero jadi splash) ===================== */
/* Kelas `hub-loading` dipasang JS, bukan CSS. Kalau ditulis di CSS, satu error
 * JS akan meninggalkan halaman terkunci tidak bisa di-scroll selamanya. */
body.hub-loading { overflow: hidden !important; }
body.hub-loading #masthead { opacity: 0 !important; }
/* Section di bawah hero disembunyikan supaya splash-nya benar-benar bersih. */
body.hub-loading #about,
body.hub-loading #brands,
body.hub-loading #whats-on,
body.hub-loading #career,
body.hub-loading #contact { visibility: hidden; }

/* Logo bernapas pelan selama memuat, lalu MENGENDAP dengan fade — bukan
 * berhenti mendadak di tengah siklus napasnya. */
body.hub-loading .hub-hero-mark { animation: hubBreathe 2.2s ease-in-out infinite; }
/* HANYA opacity. `transform` TIDAK boleh dianimasikan di sini: animasi CSS
 * menang atas inline style, jadi keyframe transform akan MENGHAPUS
 * translate(-50%,-50%) yang dipasang mekanisme pin — logo terlempar ke
 * left:50%/top:0 mentah, yaitu pojok kanan-atas. Terukur meleset +75px
 * horizontal dan -285px vertikal selama splash. */
@keyframes hubBreathe {
  0%, 100% { opacity: .55; }
  50%      { opacity: 1; }
}
/* HANYA opacity yang ditransisi. Transform TIDAK boleh — mekanisme pin
 * menulis transform tiap frame, dan transisi 0,9s membuatnya tidak pernah
 * menyusul: logo tertinggal jauh di luar layar saat user scroll balik. */
.hub-hero-mark { transition: opacity .9s ease; }
body.hub-loaded .hub-hero-mark { opacity: 1; }

/* Section di bawah hero muncul kembali dengan fade, bukan langsung ada. */
body.hub-loading #about,
body.hub-loading #brands,
body.hub-loading #whats-on,
body.hub-loading #career,
body.hub-loading #contact { opacity: 0; }
body.hub-loaded #about,
body.hub-loaded #brands,
body.hub-loaded #whats-on,
body.hub-loaded #career,
body.hub-loaded #contact { transition: opacity .8s ease .1s; opacity: 1; }

/* Garis kemajuan tipis di bawah logo. Lebarnya tidak berpura-pura tahu
 * persentase muat — ia hanya menandakan "sedang bekerja".
 *
 * IKUT fixed seperti logonya. Logo diangkat keluar dari alur normal oleh
 * mekanisme pin; kalau garis ini dibiarkan di alur, keduanya terpisah jauh
 * dan splash-nya terlihat tidak sejajar. --hub-logo-h ditulis JS dari tinggi
 * logo yang sebenarnya. */
.hub-loader {
  display: block;
  width: min(180px, 42vw);
  height: 2px;
  margin: 0;
  background: rgba(255, 255, 255, .18);
  overflow: hidden;
  opacity: 0;
  transition: opacity .4s ease;
  position: fixed;
  left: 50%;
  top: 0;
  z-index: 4;
  /* Menempel ke posisi logo yang SEBENARNYA (--hub-logo-y ditulis pinTick tiap
   * frame), bukan mematok top:50%. Dengan patokan 50% ia menganggap logo
   * selalu di tengah layar — begitu halaman dimuat pada posisi scroll selain
   * 0, logonya bergeser naik dan barnya tertinggal jauh di bawah. */
  transform: translate(-50%, calc(var(--hub-logo-y, 50vh) + var(--hub-logo-h, 180px) / 2 + 26px));
  pointer-events: none;
}
body.hub-loading .hub-loader { opacity: 1; }
.hub-loader::before {
  content: "";
  display: block;
  width: 40%;
  height: 100%;
  background: var(--hub-fg, #fff);
  transform: translateX(-100%);
  animation: hubLoaderSweep 1.15s cubic-bezier(.65, 0, .35, 1) infinite;
}
@keyframes hubLoaderSweep {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* ===================== DEGRADASI ===================== */
@media (prefers-reduced-motion: reduce) {
  .hub-px > .hub-px-layer { translate: none !important; }
  .hub-rv-anim { transition: none !important; }
  .hub-rv,
  .hub-rv[data-card] { opacity: 1; transform: none; }
  body.hub-loading .hub-hero-mark { animation: none; opacity: 1; }
  .hub-loader::before { animation: none; width: 100%; transform: none; }
}
