/* ============================================================
   LANDING PAGE
   Aturan gaya yang diambil dari bond.now:
   1. Heading BESAR tapi weight 400 — bukan bold.
   2. letter-spacing negatif agresif (-.055em) di display type.
   3. Tanpa shadow di permukaan besar. Kedalaman datang dari
      border 1px + kontras permukaan.
   4. Bagian tengah halaman adalah SATU panel yang di-pin, bukan
      deretan section statis. Lihat blok "PINNED SCROLL".
   ============================================================ */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

/* Latar ambien hangat di bawah seluruh halaman. Bukan hiasan:
   backdrop-filter tidak terlihat sama sekali di atas warna rata,
   jadi kaca butuh sesuatu untuk dibiaskan. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(58vw 48vw at 80% -10%, rgba(253, 221, 134, .30), transparent 62%),
    radial-gradient(50vw 44vw at 4% 24%, rgba(193, 118, 27, .08), transparent 60%);
}

/* Grain kertas di atas gradien ambien. Lapisan terpisah karena butuh
   mix-blend-mode sendiri — kalau digabung ke ::before, multiply-nya
   ikut menggelapkan gradien hangatnya.
   Opacity ditahan rendah: begitu grain-nya kelihatan sebagai "efek",
   dia berhenti terasa seperti bahan.
   (assets/paper.svg salah nama — isinya lingkaran glow, bukan tekstur.
   Yang tekstur beneran: assets/paper-grain.svg) */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: url("../assets/paper-grain.svg") repeat;
  background-size: 220px 220px;
  opacity: .5;
  mix-blend-mode: multiply;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 24px;
}

/* ── Tipografi ─────────────────────────────────────────── */
.display,
h1,
h2 {
  font-weight: 400;
  letter-spacing: -.055em;
  line-height: .98;
  margin: 0;
}

h1 {
  font-size: clamp(42px, 8.5vw, 76px);
}

h2 {
  font-size: clamp(32px, 5.5vw, 52px);
}

h3 {
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -.02em;
  line-height: 1.3;
  margin: 0;
}

p {
  margin: 0;
}

.lede {
  font-size: clamp(16px, 2.2vw, 19px);
  color: var(--ink-2);
  max-width: 46ch;
}

.eyebrow {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ── Tombol ────────────────────────────────────────────── */
/* Resep dari usewombat.app, diterjemahkan ke latar terang.
   Kuncinya: TIDAK ADA properti `border`. Cincin 1px dibuat dari
   box-shadow inset — tidak menambah kotak layout, dan tidak
   pernah tampak seperti garis yang digambar.

   Empat lapis, urutannya penting:
     1. rim   — cincin dalam 1px, menegaskan tepi
     2. spec  — highlight tipis di atas (cahaya datang dari atas)
     3. sink  — bayangan tipis di bawah dalam, memberi ketebalan
     4. lift  — bayangan ambien + kontak di luar
   Hilangkan salah satu, tombolnya langsung terasa murah. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 26px;
  border-radius: var(--radius-btn);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.012em;
  text-decoration: none;
  cursor: pointer;
  border: 0;
  /* Tombol pil TIDAK boleh pecah dua baris: radius 100px + dua baris teks
     bikin bentuknya jadi kapsul gemuk dan navbar terlihat rusak. Ini yang
     terjadi pada "Mulai gratis" di 360px sebelum baris ini ada. */
  white-space: nowrap;
  transition: transform .14s ease, box-shadow .18s ease, filter .18s ease;
}

/* Resep fikristudio.com. Bedanya dengan Wombat: cincinnya SOLID
   dan sewarna tombol tapi lebih tua (--accent-ring), bukan putih
   transparan. Itu yang membedakan rasa "permen timbul" dari
   rasa "kaca".
   Lapis `0 3px 0 var(--accent-lo)` adalah tepi bawah tebal —
   itu yang bikin tombolnya kelihatan bisa ditekan. */
.btn-primary {
  background: var(--grad-accent);
  color: var(--accent-ink);
  box-shadow:
    0 0 0 1.5px var(--accent-ring),
    var(--spec),
    0 3px 0 var(--accent-lo),
    0 4px 4px rgba(0, 0, 0, .12),
    0 10px 22px var(--accent-glow);
}

.btn-primary:hover {
  filter: brightness(1.04);
  box-shadow:
    0 0 0 1.5px var(--accent-ring),
    var(--spec),
    0 4px 0 var(--accent-lo),
    0 6px 8px rgba(0, 0, 0, .13),
    0 14px 30px var(--accent-glow);
}

.btn-ghost {
  background: var(--grad-card);
  color: var(--ink);
  box-shadow:
    var(--rim-dark), var(--spec-soft),
    inset 0 -1px 0 rgba(22, 25, 26, .05),
    var(--lift-1);
}

.btn-ghost:hover {
  box-shadow:
    var(--rim-dark), var(--spec-soft),
    inset 0 -1px 0 rgba(22, 25, 26, .05),
    var(--lift-2);
}

/* Ditekan: tombol turun setinggi tepi bawahnya, dan tepi itu ikut
   menipis. Kalau cuma digeser tanpa tepinya menyusut, tombolnya
   terasa melayang, bukan tertekan. */
.btn:active {
  transform: translateY(2px);
}

.btn-primary:active {
  box-shadow:
    0 0 0 1.5px var(--accent-ring),
    0 1px 0 var(--accent-lo),
    0 1px 2px rgba(0, 0, 0, .14);
}

.btn-ghost:active {
  transform: translateY(1px);
  box-shadow: var(--rim-dark), inset 0 1px 3px rgba(21, 22, 30, .09);
}

.btn:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 3px;
}

.btn-lg {
  padding: 16px 30px;
  font-size: 16px;
}

.btn-sm {
  padding: 10px 18px;
  font-size: 14px;
}

/* ══════════════════════════════════════════════════════════
   HEADER — nav + hero
   Struktur & nilai mengikuti frame "Hero" di Figma Olympus
   Landing; tombol utamanya pakai resep Fikri Studio di atas.
   ═════════════════════════════════════════════════════════ */

/* ── Navbar ────────────────────────────────────────────────
   Di puncak halaman: transparan penuh, menyatu dengan langit.
   Begitu di-scroll: jadi kaca. */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
}

.nav-in {
  margin: 0 auto;
  max-width: 1240px;
  display: flex;
  align-items: center;
  gap: 28px;
  height: 72px;
  padding: 0 28px;
  background: transparent;
  transition: background .28s ease, box-shadow .28s ease, backdrop-filter .28s ease;
}

.nav.is-stuck .nav-in {
  background: var(--grad-glass);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 1px 0 var(--line-soft), var(--lift-1);
}

/* margin-right:auto pindah ke .nav-brand — kalau tetap di .logo,
   ikon acak terdorong ke kanan dan tidak lagi "di samping logo". */
.nav-brand {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-right: auto;
  min-width: 0;
}

/* Wordmark pakai sans (Manrope 700), BUKAN --font-display — supaya
   nama merek tidak terbaca sebagai judul halaman.
   Tiga angka di bawah saling terikat, jangan diubah sendiri-sendiri:
   700 supaya wordmark punya bobot setara ikonnya; -.03em karena sans
   pada ukuran logo terbaca renggang tanpa tracking negatif; dan
   ukurannya clamp, bukan angka tetap.

   Lantai clamp() itu konsekuensi langsung dari PANJANG nama merek,
   jadi angkanya wajib ditinjau ulang tiap kali produknya berganti
   nama — bukan diwariskan begitu saja:

     "Berdua"            6 huruf — muat di ukuran apa pun
     "Once Upon A Date" 16 huruf — pada 22px tetap, wordmark-nya
                        membungkus jadi dua baris di tengah navbar,
                        dan pecah di "Once Upon A / Date" terbaca
                        sebagai layout rusak. Lantainya diturunkan
                        ke 15px supaya tetap satu baris
     "Datealarm"          9 huruf — muat lagi, jadi lantainya kembali
                        naik ke 19px. Tanpa itu, nama sependek ini
                        tampil mungil tanpa alasan di layar kecil

   nowrap yang melarang pembungkusannya; clamp yang menjaga lockup
   tetap muat bersama tombol + hamburger di layar 360px. */
.logo {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font);
  font-size: clamp(19px, 4.1vw, 22px);
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  color: var(--ink);
}

.logo img {
  width: 34px;
  height: 34px;
}

/* ── Akses cepat ngobrol acak ────────────────────────────────
   Garis pemisah di kiri itu bukan hiasan: tanpa itu ikon kamera
   menempel ke nama brand dan terbaca sebagai bagian dari logo.
   ─────────────────────────────────────────────────────────── */
.nav-live {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 14px;
  color: var(--ink-2);
  text-decoration: none;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -.012em;
  border-radius: var(--radius-pill);
  transition: color .16s ease, background .16s ease;
}

.nav-live::before {
  /* pemisah dari logo */
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 18px;
  background: var(--line);
}

.nav-live:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, .5);
}

.nav-live:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 2px;
}

.nav-live-ic {
  position: relative;
  display: inline-flex;
}

.nav-live-ic svg {
  width: 19px;
  height: 19px;
  display: block;
}

/* Titik live nempel di pojok ikon, bukan sebaris dengan teks —
   supaya tetap masuk akal waktu labelnya disembunyikan. */
.nav-live-ic .live {
  position: absolute;
  top: -2px;
  right: -3px;
  width: 6px;
  height: 6px;
}

/* ≤760px: ikon acak, Masuk, dan bahasa pindah ke .nav-menu. */
@media (max-width: 760px) {
  .nav-brand .nav-live {
    display: none;
  }

  .nav-actions .btn-ghost {
    display: none;
  }

  .nav-actions .lang-switch--bar {
    display: none;
  }
}

@media (min-width: 761px) {
  .nav-menu-panel .lang-switch--menu {
    display: none;
  }
}

/* ── Menu ringkas (mobile) ───────────────────────────────────
   <details> murni CSS. Panelnya diberi lapisan kaca yang sama
   dengan navbar saat di-scroll supaya terbaca sebagai bagian
   dari navbar, bukan kotak yang mengambang lepas. */
.nav-menu {
  position: relative;
  display: none;
}

.nav-menu>summary {
  list-style: none;
  cursor: pointer;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: var(--grad-card);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-1);
}

.nav-menu>summary::-webkit-details-marker {
  display: none;
}

.nav-menu>summary:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 2px;
}

/* Tiga garis dibuat dari satu span + dua bayangan — tidak perlu
   tiga elemen untuk bentuk sesederhana ini. */
.nav-menu>summary span {
  width: 15px;
  height: 1.6px;
  border-radius: 2px;
  background: var(--ink);
  box-shadow: 0 -5px 0 var(--ink), 0 5px 0 var(--ink);
}

.nav-menu[open]>summary span {
  background: var(--ink);
}

.nav-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 10px);
  z-index: 60;
  min-width: 208px;
  padding: 6px;
  border-radius: 18px;
  background: var(--grad-glass);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-3);
}

.nav-menu-panel .lang-switch--menu {
  justify-content: center;
  margin: 4px 6px 8px;
}

.nav-menu-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 13px;
  border-radius: 12px;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -.012em;
  color: var(--ink);
  text-decoration: none;
}

.nav-menu-item:hover {
  background: rgba(255, 255, 255, .6);
}

.nav-menu-item em {
  margin-left: auto;
  font-style: normal;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--brand-1);
}

@media (max-width: 760px) {
  .nav-menu {
    display: block;
  }
}

/* ── Pemilih bahasa (segmented) ───────────────────────────── */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(21, 22, 30, .06);
  flex: none;
}

.lang-opt {
  min-width: 34px;
  padding: 6px 9px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-3);
  font: 600 11.5px/1 var(--font);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color .16s ease, background .16s ease, box-shadow .16s ease;
}

.lang-opt:hover {
  color: var(--ink-2);
}

.lang-opt.is-on {
  background: var(--bg-card);
  color: var(--ink);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-1);
}

.lang-opt:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 1px;
}

/* Navbar isinya cuma logo + dua aksi. Menu tengah (.nav-links)
   sudah dihapus dari markup, jadi style-nya ikut dibuang — bukan
   disembunyikan, supaya tidak ada CSS mati yang menyesatkan nanti.
   Konsekuensi bagusnya: tidak ada lagi link yang lenyap di mobile,
   jadi hamburger memang tidak pernah dibutuhkan. */

.nav-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* flex:none wajib — sebagai flex item, tombol boleh menyusut di bawah
   lebar teksnya sendiri. Di 360px "Mulai gratis" tergencet 2px dan
   hurufnya terpotong tipis; nowrap saja tidak menyelesaikan itu. */
.nav-actions .btn {
  flex: none;
}

@media (max-width: 900px) {
  .nav-in {
    padding: 0 18px;
  }
}

/* Di bawah 400px semua elemen navbar harus mengalah sedikit, kalau
   tidak logo + ikon acak + tombol tidak muat dalam satu baris. */
@media (max-width: 400px) {
  .nav-in {
    gap: 12px;
    padding: 0 14px;
  }

  /* Ukurannya sudah diurus clamp() di .logo — yang tersisa di sini
     cuma ikonnya, yang memang tidak ikut menyusut sendiri. */
  .logo img {
    width: 28px;
    height: 28px;
  }

  .nav-brand {
    gap: 8px;
  }

  .nav-live {
    padding: 5px 8px 5px 10px;
  }
}

/* Masuk disembunyikan di layar terkecil; "Mulai gratis" yang bertahan
   karena itu satu-satunya aksi yang benar-benar penting di sana. */
@media (max-width: 560px) {
  .nav-actions .btn-ghost {
    display: none;
  }
}

/* ── Hero ────────────────────────────────────────────────────
   Judul duduk di atas krem polos, bukan di atas awan. Versi
   sebelumnya menaruh judul hijau tepat di atas gumpalan awan
   paling ramai — kontrasnya berubah-ubah per huruf dan praktis
   tidak terbaca. Awan sekarang turun jadi atmosfer di tepi bawah,
   di-mask supaya hilang total sebelum sampai ke area teks.
   ─────────────────────────────────────────────────────────── */
.hero {
  --font-hand: 'Caveat', 'Segoe Script', cursive;
  position: relative;
  isolation: isolate;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding: calc(72px + 44px) 0 76px;
  overflow: hidden;
  text-align: center;
}

/* Tiga lapis latar, semuanya sengaja lemah. Aturannya: tidak ada
   satu pun yang boleh punya kontras cukup untuk bersaing dengan
   teks di atasnya. */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}

.hero-clouds {
  position: absolute;
  left: 50%;
  bottom: -8%;
  width: min(1800px, 150%);
  height: auto;
  transform: translateX(-50%);
  opacity: .42;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 100%, #000 0%, #000 20%, transparent 62%);
  mask-image: radial-gradient(120% 90% at 50% 100%, #000 0%, #000 20%, transparent 62%);
}

/* Scrim di kaki hero. Dua tugas: melembutkan pertemuan awan ke section
   berikutnya, DAN menjaga sepertiga bawah tetap cukup polos untuk teks.
   Baris "Khusus 18 tahun ke atas" jatuh di ~74% tinggi hero — tanpa
   scrim ini dia mendarat tepat di gumpalan awan paling ramai dan hilang.
   Kalau nanti ada yang menambah baris di bawah CTA, cek lagi di sini. */
.hero-bg::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 48%;
  /* Alpha WAJIB kembali ke 0 di ujung bawah. Versi sebelumnya berhenti
     di .94 tepat di tepi hero: krem pekat itu menutupi grain kertas
     (body::after, multiply) di DALAM hero, sementara di bawah hero
     grain-nya kelihatan. Hasilnya garis horizontal tipis yang terbaca
     seperti bayangan antar-section — padahal itu cuma pertemuan dua
     permukaan yang teksturnya beda.
     Puncaknya digeser ke 76% supaya area teks tetap terlindungi. */
  background: linear-gradient(to bottom,
      rgba(247, 241, 230, 0) 0%,
      rgba(247, 241, 230, .62) 42%,
      rgba(247, 241, 230, .88) 76%,
      rgba(247, 241, 230, .95) 90%,
      rgba(247, 241, 230, 1) 100%);
  pointer-events: none;
}

/* Orbit tetap dipakai, tapi jauh lebih samar dari sebelumnya —
   perannya sekarang cuma memberi struktur pelan di belakang foto. */
.hero-orbits {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(1100px, 118vw);
  aspect-ratio: 1;
  transform: translate(-50%, -48%);
  background: url("../assets/orbits.svg") center / contain no-repeat;
  opacity: .35;
  pointer-events: none;
}

/* Cahaya hangat dari atas — menjaga arah cahaya yang diasumsikan
   seluruh sistem bayangan (design.md §2). */
.hero-glow {
  position: absolute;
  left: 50%;
  top: -34%;
  width: min(1100px, 130vw);
  height: 900px;
  transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, rgba(255, 255, 255, .9) 0%, rgba(255, 253, 249, 0) 70%);
  pointer-events: none;
}

/* width:100% + min-width:0 itu wajib, bukan gaya-gayaan: sebagai
   flex item, kolom ini punya minimum otomatis sebesar konten
   terlebarnya. Baris polaroid di mobile lebarnya ±526px, jadi tanpa
   ini seluruh kolom melar dan tombol CTA terpotong di layar 375px —
   terpotong diam-diam, karena .hero punya overflow:hidden. */
.hero-in {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 720px;
  min-width: 0;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* drop-shadow, BUKAN box-shadow — dan itu konsekuensi langsung dari
   ganti logo. Logo lama berupa kotak membulat yang mengisi penuh
   kotak elemen, jadi box-shadow menempel pas di tepinya. Mawar ini
   PNG transparan: box-shadow tetap menggambar bayangan KOTAK 88x88,
   dan hasilnya kartu putih melayang di belakang bunganya. filter
   drop-shadow mengikuti alpha, jadi yang berbayang siluet bunganya. */
.hero-mark {
  width: 88px;
  height: 88px;
  margin-bottom: 20px;
  filter: drop-shadow(0 8px 18px rgba(104, 19, 35, .26))
          drop-shadow(0 2px 4px rgba(104, 19, 35, .18));
}

/* Judul --ink di atas ivory = kontras ±15:1. Burgundy dipakai hanya
   untuk SATU frasa, dan burgundy yang gelap (--grad-brand), bukan
   merah tombol. */
.hero-title {
  font-family: var(--font-display);
  font-weight: var(--wt-display);
  font-size: clamp(40px, 6.6vw, 74px);
  line-height: .98;
  letter-spacing: -.055em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

/* font-style: normal, bukan italic — dan itu wajib, bukan selera.
   Outfit tidak punya potongan italic; kalau <em> dibiarkan miring,
   browser memiringkannya sendiri (synthetic oblique), dan pada sans
   setebal ini hasilnya condong kaku dengan sudut huruf yang pecah.
   Penekanannya sudah dibawa gradien burgundy — itu cukup, dan
   itulah kenapa <em>-nya tetap <em> di HTML. */
.hero-title em {
  font-style: normal;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* Tanpa dukungan background-clip:text, teks tetap terbaca hijau
   solid — bukan transparan alias hilang. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero-title em {
    -webkit-text-fill-color: currentColor;
    color: var(--brand-1);
    background: none;
  }
}

.hero-sub {
  margin: 22px 0 0;
  max-width: 44ch;
  font-size: clamp(16px, 2.1vw, 18.5px);
  line-height: 1.55;
  color: var(--ink-2);
}

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 34px;
}

.hero-cta .btn-primary {
  font-size: 17px;
  padding: 16px 30px;
}

/* .hero-note & .dot sudah dihapus — barisnya dicabut dari hero karena
   menyangkal sesuatu di kalimat pembuka justru menanam dugaan itu.
   Alasan lengkapnya di komentar index.html; batasannya sekarang hidup
   di section Keamanan dan FAQ. */

/* ── Instal aplikasi ──────────────────────────────────────────
   Secara semantik ini button karena memicu prompt instal, tetapi
   secara visual tetap kartu. Hero sudah punya dua .btn; bentuk yang
   berbeda menjaga hierarki CTA utama tetap jelas.
   ─────────────────────────────────────────────────────────── */
.hero-free {
  display: inline-flex;
  align-items: center;
  gap: 13px;
  margin-top: 30px;
  padding: 10px 18px 10px 10px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--grad-glass);
  -webkit-backdrop-filter: saturate(170%) blur(14px);
  backdrop-filter: saturate(170%) blur(14px);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-2);
  text-decoration: none;
  text-align: left;
  color: inherit;
  font: inherit;
  cursor: pointer;
  max-width: 100%;
  transition: transform .18s ease, box-shadow .18s ease;
}

.hero-free:hover {
  transform: translateY(-2px);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-3);
}

.hero-free:active {
  transform: translateY(0);
}

.hero-free:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 3px;
}

.hero-free:disabled {
  cursor: default;
}

.hero-free:disabled:hover {
  transform: none;
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-2);
}

/* Chip ikon pakai resep tombol yang sama supaya terbaca "bisa
   diklik" walau kartunya sendiri tidak berbentuk tombol. */
.hero-free-icon {
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: var(--grad-accent);
  color: var(--accent-ink);
  box-shadow: 0 0 0 1.5px var(--accent-ring), var(--spec), 0 2px 0 var(--accent-lo);
}

.hero-free-icon svg {
  width: 21px;
  height: 21px;
  display: block;
}

.hero-free-t {
  min-width: 0;
}

.hero-free-t b {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -.012em;
  color: var(--ink);
}

.hero-free-t small {
  display: block;
  margin-top: 1px;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--ink-2);
}

/* Titik "live" — menandakan ada orang di sana SEKARANG. Sengaja
   tanpa angka: jumlah online palsu di hari pertama itu klaim yang
   gampang dibantah user sendiri. */
.live {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--accent);
  box-shadow: 0 0 0 0 rgba(141,35,55, .55);
  animation: live-pulse 2.2s ease-out infinite;
}

@keyframes live-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(141,35,55, .55);
  }

  70% {
    box-shadow: 0 0 0 7px rgba(141,35,55, 0);
  }

  100% {
    box-shadow: 0 0 0 0 rgba(141,35,55, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .live {
    animation: none;
  }
}

@media (max-width: 560px) {
  .hero-free {
    gap: 11px;
    padding: 9px 15px 9px 9px;
  }

  .hero-free-icon {
    width: 38px;
    height: 38px;
  }

  .hero-free-t small {
    font-size: 12px;
  }
}

/* Dialog fallback untuk Safari/iOS dan browser yang tidak mengekspos
   beforeinstallprompt. Elemen <dialog> memberi Escape, focus trap, dan
   pemulihan fokus tanpa menambah pustaka. */
.install-guide {
  width: min(430px, calc(100% - 32px));
  max-width: none;
  padding: 0;
  border: 0;
  border-radius: var(--radius-card);
  color: var(--ink);
  background: transparent;
  box-shadow: var(--lift-3);
}

.install-guide:not([open]) {
  display: none;
}

.install-guide::backdrop {
  background: rgba(21, 22, 30, .42);
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
}

.install-guide-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 30px;
  border-radius: inherit;
  background: var(--bg-card);
  box-shadow: var(--rim-dark), var(--spec-soft);
  text-align: center;
}

.install-guide-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--bg-alt);
  color: var(--ink-2);
  font: 400 26px/1 var(--font);
  cursor: pointer;
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-1);
}

.install-guide-close:focus-visible,
.install-guide-ok:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 3px;
}

.install-guide-mark {
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
  margin-bottom: 18px;
  border-radius: 18px;
  background: var(--bg-alt);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-2);
}

.install-guide-mark img {
  display: block;
  border-radius: 12px;
}

.install-guide h2 {
  margin: 0;
  font: var(--wt-display) 34px/1 var(--font-display);
  letter-spacing: -.035em;
}

.install-guide p {
  margin: 10px 0 0;
  color: var(--ink-2);
  font-size: 14px;
  line-height: 1.5;
}

.install-guide ol {
  width: 100%;
  margin: 20px 0 24px;
  padding-left: 25px;
  color: var(--ink-2);
  text-align: left;
  font-size: 14px;
  line-height: 1.55;
}

.install-guide li + li {
  margin-top: 8px;
}

.install-guide li::marker {
  color: var(--brand-2);
  font-weight: 700;
}

.install-guide-ok {
  justify-content: center;
  min-width: 150px;
}

@media (max-width: 560px) {
  .install-guide-card {
    padding: 26px 22px 24px;
  }
}

/* ── Polaroid ────────────────────────────────────────────────
   Pengganti kartu pesan kaca yang lama. Bingkai putih dengan tepi
   bawah lebih tebal — proporsi itu yang bikin otak langsung
   membacanya sebagai foto cetak. Wajah orang di sini bukan hiasan:
   itu satu-satunya elemen di hero yang bikin layanan ini terasa
   dijalankan manusia, bukan aplikasi.
   Foto dikunci 1:1 lewat aspect-ratio supaya potret apa pun aman.
   ─────────────────────────────────────────────────────────── */
.pola {
  margin: 0;
  padding: 9px 9px 0;
  width: 172px;
  background: #fff;
  border-radius: 4px;
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-3);
}

.pola img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  background: var(--bg-alt);
  border-radius: 2px;
}

.pola figcaption {
  padding: 9px 3px 12px;
  text-align: left;
  font-family: var(--font-hand);
  font-size: 16px;
  line-height: 1.25;
  color: var(--ink-2);
}

.pola .who {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 5px;
}

.pola .on {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--online);
  flex: none;
}

/* ── Wajah talent diburamkan ─────────────────────────────────
   Pola yang dipakai Yubo: fotonya tetap tajam, hanya area wajah
   yang diburamkan lewat lingkaran ber-backdrop-filter. Ini
   keputusan produk, bukan gaya — talent tidak boleh bisa dikenali
   dari halaman publik sebelum mereka sendiri yang membuka.

   Fallback tanpa backdrop-filter: SELURUH foto diburamkan.
   Arahnya sengaja begitu — kalau efeknya gagal, hasilnya harus
   lebih tertutup, bukan lebih terbuka. Jangan pernah dibalik.
   ─────────────────────────────────────────────────────────── */
.pola-ph {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 2px;
}

.pola-ph img {
  filter: blur(10px);
  transform: scale(1.08);
}

.pola-blur {
  display: none;
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pola-ph img {
    filter: none;
    transform: none;
  }

  .pola-blur {
    display: block;
    position: absolute;
    left: 50%;
    top: 37%;
    width: 68%;
    aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 50%;
    -webkit-backdrop-filter: blur(13px);
    backdrop-filter: blur(13px);
  }
}

/* Sebar di kanan-kiri kolom teks. Nilainya persen supaya ikut
   melar, dan semuanya di luar kolom tengah 720px. */
.polas {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

.polas .pola {
  position: absolute;
}

.polas .p1 {
  top: 22%;
  left: 3.5%;
  transform: rotate(-6deg);
}

.polas .p2 {
  top: 58%;
  left: 8%;
  transform: rotate(3.5deg);
  width: 152px;
}

.polas .p3 {
  top: 17%;
  right: 4%;
  transform: rotate(5deg);
}

.polas .p4 {
  top: 60%;
  right: 8.5%;
  transform: rotate(-4deg);
  width: 152px;
}

/* Ayunan sangat pelan — cukup untuk terasa hidup, tidak cukup
   untuk mengganggu saat membaca. */
@keyframes bob {

  0%,
  100% {
    translate: 0 0;
  }

  50% {
    translate: 0 -13px;
  }
}

.polas .pola {
  animation: bob 8s ease-in-out infinite;
}

.polas .p2 {
  animation-delay: -2s;
  animation-duration: 9s;
}

.polas .p3 {
  animation-delay: -4s;
  animation-duration: 8.5s;
}

.polas .p4 {
  animation-delay: -6s;
  animation-duration: 9.5s;
}

/* Layar sempit: foto TIDAK dibuang, cuma pindah jadi baris yang
   bisa digeser. Rasa "manusia" itu justru paling dibutuhkan di
   layar yang paling banyak dipakai. */
.pola-strip {
  display: none;
}

@media (max-width: 1100px) {
  .polas {
    display: none;
  }

  /* Carousel yang jalan terus-menerus, bukan strip geser manual.
     .pola-track digandakan 2x di HTML (isinya identik); animasi
     menggeser sejauh 50% lebar total (= lebar satu track), jadi
     begitu track pertama habis, track kedua sudah pas menggantikan
     posisinya — loop tanpa jeda maupun lompatan.
     PENTING soal padding vertikal: kartu miring + bayangannya butuh
     ruang di dalam kotak, karena itu padding-y tetap ada meski
     overflow sekarang disembunyikan (bukan discroll manual lagi). */
  .pola-strip {
    display: flex;
    margin-top: 26px;
    width: 100%;
    min-width: 0;
    padding: 26px 0 42px;
    overflow: hidden;
  }

  .pola-track {
    display: flex;
    gap: 14px;
    flex: none;
    padding-left: 14px;
    animation: marquee 32s linear infinite;
  }

  .pola-strip:hover .pola-track,
  .pola-strip:focus-within .pola-track {
    animation-play-state: paused;
  }

  @keyframes marquee {
    from {
      translate: 0 0;
    }

    to {
      translate: -100% 0;
    }
  }

  .pola-strip .pola {
    flex: none;
    width: 150px;
  }

  .pola-track .pola:nth-child(odd) {
    transform: rotate(-3deg);
  }

  .pola-track .pola:nth-child(even) {
    transform: rotate(2deg);
  }
}

@media (max-width: 720px) {
  .hero {
    min-height: 0;
    padding: calc(72px + 30px) 0 58px;
  }

  .hero-in {
    padding: 0 20px;
  }

  .hero-cta {
    width: 100%;
  }

  .hero-cta .btn {
    flex: 1 1 auto;
    justify-content: center;
  }

  .pola-strip {
    margin: 40px -20px 0;
    width: calc(100% + 40px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .polas .pola {
    animation: none;
  }

  .pola-track {
    animation: none;
  }

  .pola-strip {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* ════════════════════════════════════════════════════════
   PINNED SCROLL — inti halaman
   .pin setinggi (--n × 100svh). Di dalamnya .stage nempel
   di layar sepanjang scroll itu, dan babnya berganti.
   ════════════════════════════════════════════════════════ */
/* DASAR = versi bertumpuk biasa. Ini juga yang tampil kalau JS
   mati total atau user minta reduced motion — halaman tetap utuh
   dan terbaca, cuma tanpa efek pin. */
.pin {
  position: relative;
}

.stage {
  padding: var(--pad-section) 0;
}

.stage-in {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 24px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
  align-items: center;
}

.chapters {
  display: flex;
  flex-direction: column;
  gap: 76px;
}

.ch .eyebrow {
  margin-bottom: 16px;
}

.ch p {
  margin-top: 20px;
  font-size: 17px;
  color: var(--ink-2);
  max-width: 38ch;
}

.phone-wrap {
  display: none;
}

.pips {
  display: none;
  gap: 8px;
  margin-top: 34px;
}

.pip {
  width: 26px;
  height: 3px;
  border-radius: 2px;
  background: var(--line);
  transition: background .3s ease;
}

.pip.is-on {
  background: var(--accent);
}

/* ── Bingkai HP ────────────────────────────────────────── */
/* ── Bingkai HP ──────────────────────────────────────────────
   Dibuat menyerupai iPhone sungguhan, tanpa aset gambar sama sekali.
   Yang bikin bingkai CSS biasanya terlihat palsu ada tiga, dan
   ketiganya ditangani di sini:

     1. Rangka rata satu warna. Rangka titanium itu MEMANTUL — sisi
        yang menghadap cahaya terang, sisi lain gelap. Gradiennya
        dibuat menyudut, bukan vertikal.
     2. Tidak ada bezel. Layar asli punya dua tepi: rangka logam,
        lalu garis hitam tipis sebelum piksel. Itu inset ring hitam.
     3. Layar terlalu rata. Kaca selalu menangkap sedikit cahaya —
        diambil dari kilau diagonal di .screens::after.
   ─────────────────────────────────────────────────────────── */
.phone {
  position: relative;
  width: 268px;
  aspect-ratio: 1180 / 2400;
  border-radius: 46px;
  padding: 11px;
  background: linear-gradient(145deg, #4A4E55 0%, #23252A 22%, #0C0D10 52%, #191B1F 78%, #3C4046 100%);
  box-shadow:
    inset 0 0 0 1.2px rgba(255, 255, 255, .22),
    /* kilau tepi luar rangka */
    inset 0 0 0 4px #08090B,
    /* bezel hitam sebelum layar */
    0 2px 3px rgba(0, 0, 0, .18),
    0 30px 72px rgba(0, 0, 0, .30);
  flex: none;
}

/* Tombol samping. Dua di kiri (volume) + satu di kanan (power),
   semuanya dari box-shadow satu elemen — tidak perlu markup tambahan
   karena .phone dipakai berulang di beberapa tempat. */
.phone::before {
  content: "";
  position: absolute;
  left: -2px;
  top: 21%;
  width: 2.5px;
  height: 30px;
  border-radius: 2px;
  background: linear-gradient(90deg, #05060700, #3C4046);
  /* Offset box-shadow TIDAK menerima persen — calc(100% + …) bikin
     seluruh deklarasi ini dibuang browser tanpa peringatan. Karena
     .phone lebarnya tetap 268px, offset-nya ditulis px langsung. */
  box-shadow:
    0 44px 0 #3C4046;
    /* tombol volume bawah — power di kanan dihapus: di mode pin
       bayangannya terpotong overflow dan terbaca sebagai garis liar */
  z-index: 4;
}

.phone::after {
  /* dynamic island */
  content: "";
  position: absolute;
  top: 22px;
  left: 50%;
  translate: -50% 0;
  width: 76px;
  height: 21px;
  border-radius: 12px;
  background: #000;
  box-shadow: 0 0 0 .5px rgba(255, 255, 255, .10);
  z-index: 5;
}

.screens {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 35px;
  overflow: hidden;
  background: var(--bg-card);
}

/* Kilau kaca. pointer-events:none wajib — tanpa itu lapisan ini
   menelan klik ke seluruh layar. */
.screens::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  background: linear-gradient(118deg, rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, .05) 26%, rgba(255, 255, 255, 0) 46%);
}

.screen {
  position: absolute;
  inset: 0;
  padding: 42px 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  opacity: 0;
  transform: scale(1.03);
  transition: opacity .45s ease, transform .45s cubic-bezier(.22, 1, .36, 1);
}

.screen.is-on {
  opacity: 1;
  transform: none;
}

.scr-title {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -.02em;
  margin-bottom: 4px;
}

/* Layar 1 — daftar talent */
.row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px;
  border-radius: 14px;
  background: var(--grad-card);
  border: 0;
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-1);
}

/* Avatar dulunya gradien datar — sekarang foto asli yang diburamkan.
   Gradien itu bikin layar HP terasa seperti wireframe; foto (walau
   buram) langsung bikin daftarnya terasa berisi orang sungguhan.
   Blur-nya diskalakan ke ukuran avatar: 3.5px di 32px, 7px di 74px.
   Tanpa penskalaan itu, avatar besar terlihat cuma sedikit kabur. */
/* Pemotongan lingkaran ada di .ava-img, BUKAN di .ava.
   Dulu .ava sendiri yang punya overflow:hidden — akibatnya titik
   online ikut terpotong lingkaran avatar. Sekarang .ava cuma
   kotak posisi, jadi .ava-on bisa menonjol keluar dengan utuh. */
.ava {
  position: relative;
  width: 32px;
  height: 32px;
  flex: none;
}

.ava-img {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-alt);
}

.ava img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: blur(3.5px);
  transform: scale(1.2);
}

.ava.sm {
  width: 30px;
  height: 30px;
}

.ava.lg {
  width: 74px;
  height: 74px;
}

.ava.lg img {
  filter: blur(7px);
}

/* Titik online menempel di avatar, bukan di ujung baris — menghemat
   lebar, dan itu memang tempatnya di aplikasi chat mana pun. */
.ava-on {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--online);
  box-shadow: 0 0 0 2px var(--bg-card);
}

.ava.lg .ava-on {
  width: 15px;
  height: 15px;
  right: 3px;
  bottom: 3px;
}

.night .ava-on {
  box-shadow: 0 0 0 2px #0B0B12;
}

.row-t {
  flex: 1;
  min-width: 0;
}

.row-t b {
  display: block;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: -.01em;
}

.row-t span {
  font-size: 10px;
  color: var(--ink-3);
}

/* Spek: tarif, rating, kota. Ini yang orang cari sebelum memesan —
   jadi ditaruh di baris utama, bukan disembunyikan di halaman detail. */
.row-spec {
  display: block;
  font-size: 9.5px;
  letter-spacing: -.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Kota dilepas di bingkai HP versi bertumpuk (232px, mengecil sampai
   ~210px di 375px). Di lebar itu spek lengkap kena ellipsis dan justru
   tarif — bagian paling penting — ikut terpotong. Yang dibuang bagian
   paling tidak menentukan keputusan memesan. */
/* Kota dilepas di SEMUA bingkai HP — bahkan yang desktop (246px isi)
   tidak muat memuat tarif + rating + kota tanpa ellipsis. Tetap ditulis
   di markup, bukan dihapus: di halaman /jelajah nanti lebarnya normal
   dan kota justru penting untuk layanan ketemuan. */
.spec-x {
  font-style: normal;
}

.phone .spec-x {
  display: none;
}

/* Masih kurang: di 210px, avatar + tombol suara + gelombang menyisakan
   ~70px untuk teks, sementara tarif saja butuh ~85px. Gelombang mini
   ikut dilepas — tombol play sudah cukup menandakan ada perkenalan
   suara, sedangkan tarif tidak bisa ditawar untuk dipotong. */
.ch .phone .vw {
  display: none;
}

.ch .phone .row-spec {
  font-size: 9px;
}

/* Perkenalan suara. Dikasih bentuk tombol karena inilah daya tarik
   utama layar ini — kalau cuma ikon pasif, orang tidak sadar bisa
   mendengar mereka dulu sebelum memesan. */
.voice {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
}

.vp {
  width: 19px;
  height: 19px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  font-size: 7px;
  background: var(--grad-accent);
  color: var(--accent-ink);
  box-shadow: 0 0 0 1px var(--accent-ring), var(--spec);
}

.vw {
  display: flex;
  align-items: center;
  gap: 1.5px;
  height: 14px;
}

.vw i {
  width: 1.8px;
  border-radius: 1px;
  background: var(--ink-3);
  opacity: .5;
}

.vw i:nth-child(1) {
  height: 30%
}

.vw i:nth-child(2) {
  height: 70%
}

.vw i:nth-child(3) {
  height: 45%
}

.vw i:nth-child(4) {
  height: 90%
}

.vw i:nth-child(5) {
  height: 55%
}

.vw i:nth-child(6) {
  height: 32%
}

.scr-title {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.scr-title em {
  font-style: normal;
  font-size: 10px;
  font-weight: 500;
  color: var(--ink-3);
}

/* Kepala layar chat — menggantikan .scr-title polos. Wajah + tarif di
   sini menjawab "aku lagi ngobrol sama siapa, dan ini biayanya berapa"
   tanpa harus keluar dari layar. */
.chat-head {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: none;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line);
}

/* Baris spek di layar telepon & sleepcall. */
.scr-spec {
  font-size: 10px;
  color: var(--ink-3);
  letter-spacing: -.01em;
}

.night .scr-spec {
  color: #8B8BA0;
}

/* Layar 2 — chat */
.bub {
  max-width: 78%;
  padding: 8px 12px;
  border-radius: 16px;
  font-size: 11.5px;
  line-height: 1.4;
}

.bub.them {
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-bottom-left-radius: 5px;
  align-self: flex-start;
}

.bub.me {
  background: var(--accent);
  color: #fff;
  border-bottom-right-radius: 5px;
  align-self: flex-end;
}

.typing {
  display: flex;
  gap: 4px;
  align-self: flex-start;
  padding: 11px 13px;
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: 16px;
  border-bottom-left-radius: 5px;
}

.typing i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ink-3);
  animation: blink 1.3s infinite;
}

.typing i:nth-child(2) {
  animation-delay: .18s;
}

.typing i:nth-child(3) {
  animation-delay: .36s;
}

@keyframes blink {

  0%,
  60%,
  100% {
    opacity: .3;
  }

  30% {
    opacity: 1;
  }
}

/* Layar 3 — telepon */
.call {
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 14px;
}

.call .ava {
  width: 74px;
  height: 74px;
}

.call b {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.02em;
}

.call .timer {
  font-size: 12px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.wave {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 30px;
}

.wave i {
  width: 3px;
  border-radius: 2px;
  background: var(--accent);
  animation: eq 1.1s ease-in-out infinite;
}

.wave i:nth-child(1) {
  height: 40%;
  animation-delay: 0s
}

.wave i:nth-child(2) {
  height: 75%;
  animation-delay: .1s
}

.wave i:nth-child(3) {
  height: 50%;
  animation-delay: .2s
}

.wave i:nth-child(4) {
  height: 95%;
  animation-delay: .3s
}

.wave i:nth-child(5) {
  height: 60%;
  animation-delay: .4s
}

.wave i:nth-child(6) {
  height: 35%;
  animation-delay: .5s
}

.wave i:nth-child(7) {
  height: 80%;
  animation-delay: .6s
}

@keyframes eq {

  0%,
  100% {
    transform: scaleY(.45);
  }

  50% {
    transform: scaleY(1);
  }
}

.hang {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: #E5484D;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  margin-top: 4px;
}

/* Layar 4 — sleepcall */
.screen.night {
  background: #0B0B12;
  color: #E8E8F0;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 12px;
}

.moon {
  font-size: 34px;
}

.screen.night .timer {
  font-size: 26px;
  font-weight: 300;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}

.screen.night small {
  font-size: 11px;
  color: #8B8BA0;
  max-width: 22ch;
  line-height: 1.5;
}

@media (prefers-reduced-motion: reduce) {

  .typing i,
  .wave i {
    animation: none;
  }
}

/* ── Mode PIN — hanya desktop lebar ────────────────────────
   Disiplin yang sama dengan bond: efek pin cuma untuk layar
   besar (mereka pakai `hidden min-[1180px]:block`). Kelas
   .js-pin dipasang skrip inline di <head>, dan TIDAK dipasang
   kalau user minta prefers-reduced-motion — mereka otomatis
   dapat versi bertumpuk yang sudah jadi default di atas.
   ──────────────────────────────────────────────────────── */
/* Layar HP milik masing-masing bab — dipakai di mode bertumpuk */
.ch .phone {
  margin-top: 30px;
  /* Dipusatkan mendatar. `.phone` punya lebar tetap + flex: none,
     jadi di aliran blok biasa dia menempel kiri sementara teks di
     atasnya memenuhi lebar — terbaca seperti tata letak yang meleset,
     bukan pilihan. margin auto, bukan text-align: isinya bukan teks. */
  margin-inline: auto;
  width: 232px;
}

@media (min-width: 1100px) {
  html.js-pin .pin {
    height: calc(var(--n, 4) * 100vh);
    height: calc(var(--n, 4) * 100svh);
  }

  html.js-pin .stage {
    position: sticky;
    top: 0;
    padding: 0;
    height: 100vh;
    height: 100svh;
    display: flex;
    align-items: center;
    overflow: hidden;
  }

  html.js-pin .stage-in {
    grid-template-columns: 1fr auto;
    gap: 64px;
  }

  html.js-pin .chapters {
    display: block;
    position: relative;
    min-height: 260px;
  }

  html.js-pin .ch {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    opacity: 0;
    transform: translateY(20px);
    pointer-events: none;
    transition: opacity .5s ease, transform .5s cubic-bezier(.22, 1, .36, 1);
  }

  html.js-pin .ch.is-on {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }

  html.js-pin .ch h2 {
    max-width: 13ch;
  }

  html.js-pin .ch .phone {
    display: none;
  }

  /* di mode pin, HP-nya cuma satu */
  html.js-pin .phone-wrap {
    display: block;
  }

  html.js-pin .pips {
    display: flex;
  }
}

/* ── Section biasa ─────────────────────────────────────── */
.section {
  padding: var(--pad-section) 0;
}

/* ══════════════════════════════════════════════════════════
   ORNAMEN LATAR — aset Figma "Olympus"
   Satu aturan yang mengikat semuanya: tidak boleh ada ornamen
   yang punya kontras cukup untuk bersaing dengan teks. Karena
   itu opacity-nya rendah, posisinya di tepi, dan semuanya
   aria-hidden + pointer-events:none + loading="lazy".

   Tiap ornamen dipilih karena MAKNANYA, bukan untuk mengisi
   ruang kosong: figur menjangkau di Layanan, patung tunggal di
   Talent, segel di kartu Keamanan, merpati di penutup. Kalau
   menambah ornamen baru, pertanyaannya sama — kenapa benda ITU
   yang ada di section INI?
   ═════════════════════════════════════════════════════════ */
.section,
.closer {
  position: relative;
  overflow: hidden;
}

.section>.wrap,
.closer>.wrap {
  position: relative;
  z-index: 1;
}

.deco {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  user-select: none;
  /* img { max-width:100% } global bikin ornamen ikut menyusut
     mengikuti section, padahal ukurannya memang sengaja melebihi
     tepi supaya kepotong rapi. */
  max-width: none;
  height: auto;
}

/* Layanan — figur baroque menjangkau, keluar dari tepi kanan.
   Di-mask dari arah bawah-kiri supaya kakinya larut ke latar,
   bukan berhenti dengan garis potong. */
.deco-figur {
  right: -120px;
  top: 30px;
  width: 470px;
  opacity: .14;
  -webkit-mask-image: linear-gradient(205deg, #000 26%, transparent 86%);
  mask-image: linear-gradient(205deg, #000 26%, transparent 86%);
}

/* Ornamen bintang (assets/figma/bintang.webp) DIBUANG, jangan dipakai
   lagi: bentuk asterisk/starburst-nya terbaca sebagai logo Claude, jadi
   di halaman ini dia menempelkan merek pihak lain ke brand sendiri.
   Aset-nya sengaja ditinggal di assets/figma/ kalau nanti mau dipakai
   dalam bentuk yang sudah diubah, tapi bukan dengan bentuk aslinya. */

/* Ornamen patung dada (assets/figma/patung-dada.webp) DIBUANG, alasan
   lengkapnya di komentar section #talent di index.html. Ringkasnya:
   wajah manusia terpotong di tepi layar, di section yang mengajak
   orang jadi talent — nadanya meleset. Berkasnya juga dicoret dari
   build.sh, jadi jangan pasang <img>-nya lagi tanpa mengembalikan
   keduanya; penjaga aset di build.sh akan menggagalkan build. */

/* FAQ — pita awan di kepala section, memisahkan blok tanya-jawab
   tanpa perlu garis pembatas. */
.deco-awan {
  top: -70px;
  left: 50%;
  translate: -50% 0;
  width: min(1500px, 145%);
  opacity: .5;
  -webkit-mask-image: radial-gradient(78% 100% at 50% 0%, #000 18%, transparent 76%);
  mask-image: radial-gradient(78% 100% at 50% 0%, #000 18%, transparent 76%);
}

/* Penutup — merpati di belakang kalimat terakhir. */
.deco-merpati {
  left: 50%;
  top: 4%;
  translate: -50% 0;
  width: 380px;
  opacity: .3;
}

/* Segel di kartu Keamanan. Aset-nya putih timbul, jadi di atas
   kartu yang juga hampir putih dia butuh drop-shadow — tanpa itu
   embossing-nya hilang total dan kartunya terlihat kosong. */
.safety .card {
  position: relative;
  overflow: hidden;
}

.safety .card>*:not(.deco) {
  position: relative;
  z-index: 1;
}

.deco-segel {
  right: -40px;
  top: -34px;
  width: 172px;
  opacity: .9;
  filter: drop-shadow(0 1px 1.5px rgba(60, 44, 16, .13));
}

@media (max-width: 900px) {

  /* Di layar sempit ornamen besar lebih banyak menghalangi daripada
     memberi suasana — yang bertahan cuma yang kecil & di sudut. */
  .deco-figur {
    display: none;
  }

  .deco-merpati {
    width: 260px;
    opacity: .22;
  }

  .deco-segel {
    width: 138px;
    right: -32px;
    top: -28px;
  }
}

.section-head {
  max-width: 40ch;
  margin-bottom: 52px;
}

.section-head h2 {
  margin-top: 14px;
}

.section-head .lede {
  margin-top: 18px;
}

.grid {
  display: grid;
  gap: 14px;
}

.grid-4 {
  grid-template-columns: repeat(4, 1fr);
}

.grid-3 {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 900px) {
  .grid-4 {
    grid-template-columns: repeat(2, 1fr);
  }

  .grid-3 {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  .grid-4 {
    grid-template-columns: 1fr;
  }
}

.card {
  background: var(--grad-card);
  border: 0;
  border-radius: var(--radius-card);
  padding: 30px 26px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-1);
  transition: transform .2s ease, box-shadow .2s ease;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-3);
}

.card-icon {
  font-size: 26px;
  line-height: 1;
  margin-bottom: 8px;
}

.card p {
  font-size: 14.5px;
  color: var(--ink-2);
}

.price {
  margin-top: auto;
  padding-top: 18px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -.01em;
}

.price span {
  color: var(--ink-3);
  font-weight: 400;
}

/* Angkanya ditulis ulang dari /api/layanan, jadi dia butuh elemen
   sendiri — dan elemen itu TIDAK boleh kebagian warna redup di atas,
   yang ditujukan untuk satuannya ("/ jam"). Dirantai lewat kelas
   supaya menang tanpa !important: (0,2,0) di atas (0,1,1). */
.price .js-harga {
  color: inherit;
  font-weight: inherit;
}

/* Kartu yang SELURUH layanannya dimatikan admin disembunyikan dari
   js/layanan-harga.js. `[hidden]` sendirian kalah dari `display: flex`
   milik .card — jebakan yang sudah empat kali kena di berkas lain,
   jadi pasangannya ditulis di sini sekalian. */
.card[hidden] {
  display: none;
}

/* ── Panel talent ──────────────────────────────────────── */
.panel {
  background: var(--grad-card);
  border: 0;
  border-radius: var(--radius-card);
  padding: clamp(34px, 6vw, 68px);
  box-shadow: var(--rim-dark), var(--spec-soft), var(--lift-2);
}

.panel-split {
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  gap: 56px;
  align-items: center;
}

@media (max-width: 900px) {
  .panel-split {
    grid-template-columns: 1fr;
    gap: 36px;
  }
}

.checklist {
  list-style: none;
  margin: 30px 0 0;
  padding: 0;
  display: grid;
  gap: 16px;
}

.checklist li {
  display: flex;
  gap: 13px;
  font-size: 15px;
  color: var(--ink-2);
}

.checklist strong {
  color: var(--ink);
  font-weight: 500;
  display: block;
  letter-spacing: -.01em;
}

.check {
  flex: none;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  margin-top: 2px;
}

.safety {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 900px) {
  .safety {
    grid-template-columns: 1fr;
  }
}

/* ── FAQ ───────────────────────────────────────────────── */
.faq {
  border-top: 1px solid var(--line);
}

.faq details {
  border-bottom: 1px solid var(--line);
}

.faq summary {
  list-style: none;
  cursor: pointer;
  padding: 24px 40px 24px 0;
  position: relative;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -.02em;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: "+";
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 21px;
  font-weight: 300;
  color: var(--ink-3);
  transition: transform .2s ease;
}

.faq details[open] summary::after {
  transform: translateY(-50%) rotate(45deg);
}

.faq .answer {
  padding: 0 52px 26px 0;
  font-size: 15px;
  color: var(--ink-2);
}

/* ── Closer & footer ───────────────────────────────────── */
.closer {
  text-align: center;
  padding: var(--pad-section) 0;
}

.closer h2 {
  max-width: 18ch;
  margin: 0 auto;
}

.closer .hero-cta {
  justify-content: center;
  margin-top: 36px;
}

.footer {
  border-top: 1px solid var(--line);
  padding: 56px 0 44px;
}

.footer-in {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  justify-content: space-between;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
}

/* :not(.logo) itu wajib. `.footer a` (0,1,1) menang atas `.logo`
   (0,1,0), jadi tanpa pengecualian ini wordmark "Datealarm" di footer
   ikut turun ke 14px dan --ink-2 — mengecil jadi seukuran tautan nav
   di sebelahnya dan tidak lagi terbaca sebagai logo, padahal gambar
   34px-nya tetap tampil. Tampak seperti logonya hilang. */
.footer a:not(.logo) {
  font-size: 14px;
  color: var(--ink-2);
  text-decoration: none;
}

.footer a:not(.logo):hover {
  color: var(--ink);
}

.footer small {
  font-size: 13px;
  color: var(--ink-3);
  display: block;
  margin-top: 14px;
}

/* ── Reveal ────────────────────────────────────────────────
   .reveal TAMPIL secara default. Keadaan tersembunyi hanya
   aktif kalau <html> dapat kelas .js-reveal dari skrip inline
   di <head>. Kalau dibalik, satu kegagalan JS bikin seluruh
   halaman blank — fatal untuk landing page.
   ──────────────────────────────────────────────────────── */
html.js-reveal .reveal {
  opacity: 0;
  transform: translateY(18px);
}

html.js-reveal .reveal.in {
  opacity: 1;
  transform: none;
  transition: opacity .55s ease, transform .55s cubic-bezier(.22, 1, .36, 1);
}

/* Scroll reveal bidirectional — elemen keluar viewport saat scroll
   balik ke atas, lalu masuk lagi saat discroll turun. */
html.js-reveal .reveal.reveal-out {
  opacity: 0;
  transform: translateY(14px);
}

/* Bab panel pin punya visibility sendiri — jangan campur reveal. */
html.js-reveal .pin .ch.reveal,
html.js-reveal .pin .ch.reveal.in,
html.js-reveal .pin .ch.reveal.reveal-out {
  opacity: unset;
  transform: unset;
  transition: none;
}

@media (prefers-reduced-motion: reduce) {

  html.js-reveal .reveal,
  html.js-reveal .reveal.in {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
