/* ============================================================
   CVN — style.css
   Tema: dark sinematik + glitch/scramble effect
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=Inter:opsz,wght@14..32,100..900&display=swap');

/* Warna, font, dan garis datang dari tokens.css (lapisan data-surface='web').
   Font: --font-body untuk seluruh isi, --font-display untuk navbar.

   'opsz' 32 adalah potongan Display milik Inter. Inter yang dilayani
   Google Fonts adalah font variabel dengan sumbu optical size 14-32;
   tanpa dipatok, browser memilih sendiri menurut ukuran teksnya dan
   teks kecil tidak akan memakai potongan Display-nya. */
:root {
  /* Warna identitas yang sedang berlaku: dipakai kurung <> dan huruf
     yang sedang diacak. Variabel tersendiri, bukan --accent langsung:
     pembuka tiap divisi memasang warnanya di sini, dan kalau yang
     dipakai --accent, seluruh aksen di layar divisi ikut berubah —
     tombol, ikon akordeon, kategori kartu — bukan cuma dua hal itu. */
  --identitas: var(--accent);
  /* Kurung <> punya variabelnya sendiri, bawaannya ikut identitas.
     Dipisah karena VON memakai warna kurung yang berbeda dari warna
     fractal dan teks acaknya — kalau satu variabel, mengubah salah
     satunya ikut mengubah keduanya. */
  --kurung: var(--identitas);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* Ruang bilah gulir dipesan permanen. Tanpa ini, mengunci gulir saat
     layar divisi/karya dibuka membuat bilah gulir halaman lenyap, dan
     lebar blok penampung awal (ICB) melonjak 15px. Elemen position:fixed
     diukur dari ICB — jadi tombol tutup yang dipatok right:26px ikut
     melompat 15px ke kanan tepat saat layarnya muncul. Diukur: 1028 ->
     1043, tombolnya bergeser 1002 -> 1017.

     Dipasang di <html>, bukan <body>: yang dikunci nanti body, dan
     scrollbar-gutter memang tidak berlaku pada elemen yang overflow-nya
     hidden. Di <html> ia tetap berlaku, dan itu cukup — ICB-nya yang
     dijaga. */
  scrollbar-gutter: stable;
}

::selection {
  background-color: var(--ink-bright);
  color: var(--ink-invert);
}

/* Tambahan untuk kompatibilitas browser lama (Firefox) */
::-moz-selection {
  background-color: var(--ink-bright);
  color: var(--ink-invert);
}
body {
  background: var(--bg-base);
  color: var(--ink-bright);
  font-family: var(--font-body);
  font-variation-settings: 'opsz' 32;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

.wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 32px; }
.mono { font-family: var(--font-body); }

/* ============================================================
   SCRAMBLE / GLITCH TEXT  — bisa dipakai di spot mana pun
   Cukup beri class .scramble + atribut data-text pada elemen,
   lalu JS akan menganimasikannya.
   ============================================================ */
.scramble { display: inline-block; }
/* karakter yang sedang diacak diberi warna aksen biar terasa "hidup" */
.scramble .dud { color: var(--identitas); opacity: 0.85; }

/* ============================================================
   NAVBAR
   ============================================================ */
nav {
  /* diwariskan ke logo dan tautannya; tidak ada satu pun anak navbar
     yang menyebut nama muka hurufnya sendiri */
  font-family: var(--font-display);
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; align-items: center; justify-content: space-between;
  /* Isinya dikurung dan dipusatkan lewat PADDING, bukan max-width +
     margin auto. Sebabnya nav::before — lapisan latar dan blur-nya —
     mengikuti kotak <nav>; kalau <nav> yang dipersempit, pita blurnya
     ikut menyempit dan tidak lagi menutup selebar layar.

     1720px adalah batas terjauh yang masih aman. Pita terlarang yang
     ditandai berakhir di x=82 pada layar 1919, dan angka ini menaruh
     tepi kiri logo di x=92 — lega 10px. Pada 1740px logo mendarat
     tepat di 82, yaitu menyentuh pita itu. Sisi KIRI yang membatasi,
     bukan kanan: menu masih lega 30px di sana.

     Catatan: 100% di sini adalah lebar nav tanpa scrollbar (1904 pada
     layar 1919), jadi padding jatuh di 92, bukan 89.5. Pada layar
     sempit max() jatuh ke 32px, yaitu padding lama. */
  padding: 20px max(32px, calc((100% - 1720px) / 2));
}

/* Latar, blur, dan pudarnya dipindah ke lapisan tersendiri yang
   menjulur 35px di bawah navbar.

   Dua alasan kenapa tidak bisa dipasang langsung di <nav>:
   mask-image di elemennya akan ikut memudarkan logo dan tautannya,
   dan backdrop-filter selalu berhenti tegas di tepi elemen — itu yang
   menghasilkan garis lurus melintang di atas hero. Lapisan yang lebih
   tinggi daripada isinya bisa dipudarkan tanpa menyentuh isi itu. */
nav::before {
  content: ''; position: absolute;
  left: 0; right: 0; top: 0; bottom: -35px;
  z-index: -1; pointer-events: none;
  /* tanpa latar gelap: navbar tidak lagi menjatuhkan bayangan ke hero */
  transition: backdrop-filter 0.3s;
  -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 35px), transparent 100%);
  mask-image: linear-gradient(to bottom, black calc(100% - 35px), transparent 100%);
}
nav.scrolled::before {
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
}

.logo {
  /* Tanpa tulisan di sampingnya, tandanya sendiri yang jadi logo —
     jadi ukurannya dipatok langsung di .logo-mark, bukan lewat em
     yang dulu ikut font-size tulisan itu. gap tidak lagi berguna. */
  display: flex; align-items: center;
  font-family: inherit; letter-spacing: 1px;
  text-decoration: none; color: var(--ink-bright);
}
/* ---- tanda logo ----
   Delapan pecahan sebagai satu SVG. Saat diam, pecahannya berjarak
   seperti pada berkas aslinya; saat di-hover semuanya merapat.

   Jarak rapatnya dihitung, bukan dikira-kira: tiap pecahan didorong
   mendatar ke arah pusat selangkah demi selangkah sampai tepat
   menyentuh tetangganya, lalu hasilnya dipanggang ke dalam --g di tiap
   polygon. Jadi tidak ada satu angka global yang bisa membuat dua
   pecahan saling menembus. */
/* Keadaan diam dan keadaan rapat bukan sekadar beda posisi: sudut-sudut
   yang bertetangga DILAS jadi satu titik supaya sisinya berimpit, jadi
   yang berubah adalah bentuk tiap kepingnya. Karena itu rendernya pakai
   clip-path pada <i>, bukan <polygon> SVG: clip-path bisa ditransisikan
   CSS selama jumlah titiknya tetap, sedangkan atribut points tidak bisa.

   Posisi rapatnya diturunkan dari video: selisih pusat tiap pecahan
   antara frame renggang dan frame rapat, lalu sudutnya dilas dengan
   ambang sebesar ukuran pecahannya sendiri — kalau ambangnya seragam,
   serpihan hijau yang tipis ikut tergencet sampai hilang. */
.logo-mark {
  position: relative; display: block;
  height: 46px; aspect-ratio: 1916 / 1164;
}
.logo-mark i {
  position: absolute; inset: 0;
  transition: clip-path 0.42s cubic-bezier(0.4, 0, 0.2, 1);
}

.logo-mark .s0 { background: var(--logo-pink); clip-path: polygon(5.17% 54.81%, 45.67% 83.68%, 0.00% 100.00%); }
.logo:hover .logo-mark .s0, .logo:focus-visible .logo-mark .s0 { clip-path: polygon(18.15% 42.49%, 65.22% 76.41%, 12.89% 94.60%); }
.logo-mark .s1 { background: var(--logo-blue); clip-path: polygon(11.59% 0.00%, 38.94% 8.68%, 7.67% 31.27%); }
.logo:hover .logo-mark .s1, .logo:focus-visible .logo-mark .s1 { clip-path: polygon(22.06% 4.42%, 53.94% 14.12%, 18.15% 42.49%); }
.logo-mark .s2 { background: var(--logo-yellow); clip-path: polygon(48.85% 11.94%, 58.87% 78.95%, 11.90% 42.10%); }
.logo:hover .logo-mark .s2, .logo:focus-visible .logo-mark .s2 { clip-path: polygon(53.94% 14.12%, 65.22% 76.41%, 18.15% 42.49%); }
.logo-mark .s3 { background: var(--logo-pink); clip-path: polygon(67.69% 17.53%, 65.50% 75.86%, 54.75% 13.57%); }
.logo:hover .logo-mark .s3, .logo:focus-visible .logo-mark .s3 { clip-path: polygon(70.50% 19.31%, 65.22% 76.41%, 53.94% 14.12%); }
.logo-mark .s4 { background: var(--logo-green); clip-path: polygon(72.76% 19.07%, 76.93% 20.45%, 75.63% 72.94%, 71.03% 74.57%); }
.logo:hover .logo-mark .s4, .logo:focus-visible .logo-mark .s4 { clip-path: polygon(70.50% 19.31%, 75.23% 21.17%, 74.44% 72.06%, 65.22% 76.41%); }
.logo-mark .s5 { background: var(--logo-blue); clip-path: polygon(80.43% 21.56%, 89.93% 67.78%, 81.47% 70.79%); }
.logo:hover .logo-mark .s5, .logo:focus-visible .logo-mark .s5 { clip-path: polygon(75.23% 21.17%, 85.08% 66.12%, 74.44% 72.06%); }
.logo-mark .s6 { background: var(--logo-yellow); clip-path: polygon(84.08% 22.59%, 90.08% 24.57%, 93.37% 64.60%, 83.66% 23.20%); }
.logo:hover .logo-mark .s6, .logo:focus-visible .logo-mark .s6 { clip-path: polygon(75.23% 21.17%, 82.61% 24.72%, 85.08% 66.12%, 75.23% 21.17%); }
.logo-mark .s7 { background: var(--logo-green); clip-path: polygon(100.00% 64.18%, 96.45% 65.38%, 93.32% 26.03%); }
.logo:hover .logo-mark .s7, .logo:focus-visible .logo-mark .s7 { clip-path: polygon(89.80% 64.76%, 85.08% 66.12%, 82.61% 24.72%); }

@media (prefers-reduced-motion: reduce) {
  .logo-mark i { transition: none; }
}

.nav-links { display: flex; align-items: center; gap: 32px; list-style: none; }
.nav-links > li > a,
.nav-drop-toggle {
  color: var(--ink-bright); text-decoration: none; font-size: 14px; font-weight: 500;
  letter-spacing: 0.5px; opacity: 0.85; transition: opacity 0.2s;
}
.nav-links > li > a:hover,
.nav-drop-toggle:hover { opacity: 1; }
.nav-toggle { display: none; background: none; border: none; color: var(--ink-bright); font-size: 26px; cursor: pointer; }

/* ============================================================
   NAV DROPDOWN (Works)
   ============================================================ */
.has-drop { position: static; }

.nav-drop-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; cursor: pointer;
  font-family: inherit; padding: 0;
}
.chev {
  width: 13px; height: 13px; fill: none; stroke: currentColor;
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.25s ease;
}
.has-drop.open .nav-drop-toggle { opacity: 1; }
.has-drop.open .chev { transform: rotate(180deg); }

/* Pembungkus: padding atas jadi "jembatan" agar kursor tidak lepas
   saat bergerak dari tombol Works ke kartunya. */
.drop {
  position: absolute; top: 100%; right: 32px; left: auto; z-index: 120;
  padding-top: 14px;
  opacity: 0; visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 0.22s ease, transform 0.22s ease, visibility 0.22s;
}
.has-drop.open > .drop { opacity: 1; visibility: visible; transform: translateY(0); }

.drop-card {
  width: min(430px, calc(100vw - 64px));
  display: flex; flex-direction: column; gap: 4px;
  padding: 14px;
  border-radius: 20px;
  background: rgba(20, 28, 16, 0.72);
  -webkit-backdrop-filter: blur(22px) saturate(1.5);
  backdrop-filter: blur(22px) saturate(1.5);
  border: 1px solid rgba(255,255,255,0.10);
  box-shadow: 0 24px 60px rgba(0,0,0,0.55);
}

.drop-item {
  display: grid; grid-template-columns: 34px 1fr; align-items: start; gap: 12px;
  padding: 12px; border-radius: 14px;
  text-decoration: none; color: var(--ink-bright);
  transition: background 0.2s;
}
.drop-item:hover, .drop-item:focus-visible { background: rgba(255,255,255,0.06); }

.drop-ico { display: flex; align-items: center; justify-content: center; padding-top: 2px; color: var(--ink-bright); }
.drop-ico svg {
  width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

.drop-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.drop-title {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 17px; font-weight: 700; letter-spacing: 0.2px; line-height: 1.3;
}
.drop-sub { font-size: 13px; color: var(--ink-muted); line-height: 1.45; }

/* Ikon amplop hanya dipakai oleh keping Contact di menu ponsel.
   Di desktop tautannya tetap teks polos seperti tautan nav lain. */
.kontak-ikon { display: none; }

.badge {
  font-size: 11px; font-weight: 500; letter-spacing: 0.3px;
  padding: 3px 10px; border-radius: 999px; white-space: nowrap;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative; min-height: 100vh;
  /* flex-start, bukan center: dengan centering, menaikkan blok berarti
     mengakali padding bawah, dan hasilnya bergeser lagi tiap kali jarak
     antar barisnya diubah. Dipatok dari atas, posisinya jadi satu angka
     yang bisa disetel sendiri. */
  display: flex; flex-direction: column; justify-content: flex-start;
  padding: 17vh 32px 8vh; overflow: hidden;
}
.hero::before {
  content: ''; position: absolute; inset: 0; z-index: 0;
  /* Tinggal hitam polos: cahayanya sekarang datang dari .spectral.
     Kalau kedua gradasi lama dibiarkan, keduanya menumpuk dan hijaunya
     jadi rata, bukan berupa pita. */
  background: var(--bg-base);
}
/* ---- spectral noise ----
   Wadah untuk latar shader (spectral.js). Diisi <canvas> sendiri, jadi
   elemennya cukup kosong di HTML.

   z-index 1: di atas .hero::before yang sekarang jadi lapisan dasar
   hitam, di bawah .hero-inner yang memuat tulisannya. */
.spectral {
  position: absolute; inset: 0; z-index: 1;
  overflow: hidden; pointer-events: none;
  background: var(--bg-base);
  /* mengurung mix-blend-mode lapisan foto di dalam wadah ini saja */
  isolation: isolate;
}
.spectral-canvas {
  /* dirender di bawah resolusi layar lalu diregangkan — gambarnya
     seluruhnya gradasi lembut, jadi peregangannya tidak terlihat */
  width: 100%; height: 100%; display: block;
}

/* Foto yang mengintip dari balik noise.

   mix-blend-mode membaur dengan apa pun yang ada di bawahnya dalam
   konteks penumpukan yang sama; 'isolation: isolate' di .spectral
   mengurungnya supaya tidak ikut membaur dengan halaman di belakangnya. */
.spectral-photo {
  position: absolute; inset: 0;
  background-size: cover;
  background-position: center;
  mix-blend-mode: color-dodge;
  will-change: transform;
  animation: spectralNapas 16s ease-in-out infinite;
}

/* Membesar lalu kembali. Satu putaran penuh dibagi dua: separuh
   waktunya membesar, separuhnya mengecil. */
@keyframes spectralNapas {
  0%   { transform: scale(1); }
  50%  { transform: scale(var(--zoom, 1.10)); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .spectral-photo { animation: none; transform: scale(1.04); }
}

.hero-inner {
  position: relative; z-index: 2; max-width: 1200px; margin: 0 auto; width: 100%;

  /* Dipasang di pembungkusnya, bukan di tiap barisnya: text-shadow
     diwariskan, jadi SEE, kata besar, tagline, END, dan teks acaknya
     ikut sekaligus tanpa lima aturan yang harus dijaga tetap sama.

     Dua lapis. Yang rapat memberi tepi supaya hurufnya tidak lumer di
     atas cahaya fractal; yang lebar dan sangat tipis menurunkan
     terangnya latar tepat di belakang teks. Satu lapis saja tidak
     cukup: dibuat cukup gelap untuk terbaca, bayangannya jadi terlihat
     sebagai garis; dibuat lembut saja, tidak menolong apa-apa. */
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.38),
    0 6px 26px rgba(0, 0, 0, 0.42);
}

.hero-see {
  font-family: var(--font-body);
  /* 800: Anton yang digantikan Inter adalah muka huruf display yang
     sangat padat. Inter di bobot biasa terbaca jauh lebih ringan pada
     ukuran sebesar ini, jadi bobotnya dinaikkan supaya kepadatannya
     sebanding. */
  font-weight: 800;
  font-size: clamp(48px, 8vw, 96px); line-height: 0.95; letter-spacing: 1px;
}
.hero-see small {
  display: block; font-family: var(--font-body);
  font-size: clamp(11px, 1.4vw, 15px); letter-spacing: 4px;
  color: var(--ink-bright); margin-top: 14px; font-weight: 700;
}

.hero-vision {
  font-family: var(--font-body); font-weight: 800;
  font-size: clamp(44px, 9vw, 120px); line-height: 1; letter-spacing: 2px;
  margin: 8vh 0; text-align: center;
  display: flex; align-items: center; justify-content: center; gap: 0.1em; flex-wrap: wrap;
}
/* Kurungnya membawa warna identitas, hurufnya putih — jadi yang
   berganti tiap divisi cuma kurungnya, dan V-nya tetap jadi jangkar
   yang sama di semua halaman. */
.bracket { color: var(--kurung); }
.bracket-v { color: var(--ink-bright); font-weight: inherit; }
.hero-word { display: inline-block; color: var(--ink-bright); min-width: 4ch; }

.hero-bottom {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
  flex-wrap: wrap; margin-top: 5vh;
}
.hero-tagline { font-size: clamp(14px, 1.6vw, 18px); max-width: 340px; color: var(--ink-bright); line-height: 1.5; }
.hero-tagline b { font-weight: 700; }
.hero-end {
  font-family: var(--font-body); font-weight: 800; text-align: right;
  font-size: clamp(40px, 6vw, 80px); line-height: 0.95;
}
.hero-end small {
  display: block; font-family: var(--font-body); font-weight: 700;
  font-size: clamp(10px, 1.2vw, 14px); letter-spacing: 3px; margin-top: 6px; color: var(--ink-bright);
}

/* ============================================================
   SERVICES
   ============================================================ */
.services { padding: 100px 32px; background: var(--bg-base); }
.section-title {
  font-family: var(--font-body); text-align: center; letter-spacing: 8px;
  font-size: clamp(18px, 2.4vw, 26px); text-transform: uppercase; margin-bottom: 48px; font-weight: 700;
}
.accordion { max-width: 760px; margin: 0 auto; }
.acc-item { border-bottom: 1px solid var(--line-soft); }
.acc-head {
  width: 100%; background: none; border: none; color: var(--ink-bright);
  display: flex; align-items: center; justify-content: space-between;
  padding: 24px 4px; cursor: pointer; text-align: left;
  font-family: var(--font-body);
  font-size: clamp(18px, 2.4vw, 26px); font-weight: 500; letter-spacing: 2px;
  text-transform: uppercase; transition: color 0.2s;
}
.acc-head:hover { color: var(--accent); }
.acc-icon { font-size: 22px; transition: transform 0.3s; color: var(--ink-muted); }
.acc-item.open .acc-icon { transform: rotate(45deg); color: var(--accent); }
.acc-body { max-height: 0; overflow: hidden; transition: max-height 0.35s ease; color: var(--ink-muted); font-size: 15px; }
.acc-body-inner { padding: 0 4px 28px; }

/* ---- kategori tiap layanan ----
   Deret pil yang terhubung satu garis, lalu satu gambar besar. */
.layanan-jalur {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  margin: 4px 0 18px;
}
/* Garis penghubungnya digambar di belakang, membentang penuh; yang
   membuatnya tampak terputus di tiap pil adalah latar pil itu sendiri,
   bukan potongan garis satu per satu. */
.layanan-jalur::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 1px; background: var(--line-soft);
}
.layanan-pil {
  position: relative;            /* di atas garis */
  background: var(--bg-base);
  border: 1px solid var(--line-soft); border-radius: 999px;
  color: var(--ink-muted); cursor: pointer;
  font: inherit; font-size: 13.5px; line-height: 1;
  padding: 12px 20px; white-space: nowrap;
  transition: color .22s ease, border-color .22s ease;
}
.layanan-pil:hover { color: var(--ink-bright); border-color: rgba(255,255,255,0.3); }
.layanan-pil.aktif { color: var(--accent); border-color: var(--accent); }

.layanan-gambar {
  position: relative; overflow: hidden;
  border-radius: 10px; background: var(--bg-surface);
  aspect-ratio: 16 / 7;
}
.layanan-gambar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.layanan-tautan { display: block; height: 100%; }
/* berkas yang belum ada menyisakan namanya, bukan kotak kosong */
.layanan-gambar.kosong {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-size: 12px; color: var(--ink-faint);
}
.layanan-catatan { margin-top: 12px; font-size: 13.5px; color: var(--ink-muted); }

/* Di layar sempit pilnya MEMBUNGKUS, tidak digulir mendatar.

   Versi sebelumnya memilih gulir supaya nama pil tidak terpotong, tapi
   gulir mendatar di dalam halaman yang juga digulir tegak mudah
   terlewat — pil ketiga praktis tak terlihat. Mengecilkan saja tidak
   cukup: kelompok terpanjang ('Company Profile / Event Documentation /
   Creative Content') butuh 349px bahkan pada font 11px, sementara yang
   tersedia 303px. Jadi satu-satunya jalan yang menjaga nama tetap utuh
   adalah membungkus ke baris berikutnya.

   Garis penghubungnya ikut dimatikan di sini: ia satu garis mendatar di
   tengah wadah, dan begitu pilnya dua baris, garis itu memotong
   keduanya alih-alih menghubungkannya. */
@media (max-width: 640px) {
  .layanan-jalur {
    flex-wrap: wrap; justify-content: flex-start;
    gap: 8px; overflow: visible;
  }
  .layanan-jalur::before { display: none; }
  .layanan-pil { padding: 9px 14px; font-size: 12px; }
  .layanan-gambar { aspect-ratio: 4 / 3; }
}

/* ============================================================
   ABOUT
   ============================================================ */
.about { padding: 100px 32px; background: var(--bg-base); }
.about-grid { display: grid; grid-template-columns: 200px 1fr; gap: 60px; max-width: 1000px; margin: 0 auto; align-items: start; }
/* ---- Rel logo klien (bergulir vertikal, tanpa jeda) ---- */
.logo-rail {
  position: relative; height: 430px; overflow: hidden;
  /* pudar di tepi atas & bawah, seperti pada referensi */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 14%, black 86%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, black 14%, black 86%, transparent 100%);
}
.logo-track {
  list-style: none; margin: 0; padding: 0;
  /* flex column: margin antar item tidak saling luruh, sehingga tinggi track
     tepat 2x satu salinan dan translateY(-50%) menyambung tanpa loncat */
  display: flex; flex-direction: column;
  animation: logoScroll 30s linear infinite;
}
/* jeda saat kursor di atasnya, supaya logo bisa diamati */
.logo-rail:hover .logo-track,
.logo-rail:focus-within .logo-track { animation-play-state: paused; }

/* margin-bottom (bukan gap) agar tinggi tiap sel seragam
   dan perulangan -50% benar-benar mulus */
.logo-cell {
  height: 64px; margin-bottom: 56px;
  display: flex; align-items: center;
}
.logo-cell img {
  max-height: 100%; max-width: 170px; object-fit: contain;
  /* logo warna apa pun jadi putih bersih di latar hitam */
  filter: brightness(0) invert(1);
  opacity: 0.55; transition: opacity 0.25s;
}
.logo-cell img:hover { opacity: 1; }

/* tampil bila berkas logo belum ada */
.logo-fallback {
  font-family: var(--font-body); font-size: 22px; letter-spacing: 1px;
  color: var(--ink-faint); transition: color 0.2s;
}
.logo-fallback:hover { color: var(--ink-bright); }

@keyframes logoScroll {
  from { transform: translateY(0); }
  to   { transform: translateY(-50%); }
}
/* Versi mendatar untuk layar sempit. -50% tetap jadi titik ulang karena
   isinya dua salinan yang sama persis — sama seperti versi tegak. */
@keyframes logoScrollX {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.about-content h2 { font-family: var(--font-body); letter-spacing: 8px; font-size: clamp(18px,2.4vw,26px); text-transform: uppercase; margin-bottom: 24px; }
.about-content p { color: var(--ink-muted); max-width: 560px; margin-bottom: 40px; }
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; max-width: 460px; }
.stat .num { font-family: var(--font-body); font-size: clamp(32px,5vw,48px); }
.stat .lbl { font-size: 13px; color: var(--ink-muted); letter-spacing: 1px; }

/* ============================================================
   NETWORK — graf jaring-jaring
   ============================================================ */
.network { padding: 20px 32px 100px; background: var(--bg-base); }
.net-wrap {
  max-width: 1200px; margin: 0 auto;
  height: clamp(340px, 52vh, 560px);
}
#netCanvas { display: block; width: 100%; height: 100%; }

/* ============================================================
   PENYESUAIAN HERO BERANDA

   Dibatasi :not(.hero-layar). Hero halaman divisi memakai kelas yang
   sama persis, jadi tanpa pembatas ini setiap angka di bawah ikut
   mengubah ketiga halaman divisi juga.

   SEE dan END disamakan ukurannya dan dibuat lebih besar daripada kata
   tengah, lalu didorong ke sudutnya masing-masing: wadahnya dilebarkan
   supaya SEE bergeser ke kiri dan END ke kanan sekaligus, tanpa
   menggeser kata tengah yang tetap berada di sumbu.
   ============================================================ */
.hero:not(.hero-layar) { padding-top: 10vh; }
.hero:not(.hero-layar) .hero-inner { max-width: 1470px; }
.hero:not(.hero-layar) .hero-see { font-size: clamp(56px, 11vw, 148px); }
.hero:not(.hero-layar) .hero-end { font-size: clamp(48px, 11vw, 148px); }
/* 24vh, bukan 9vh: margin ini beradu dengan margin-bawah .hero-vision
   (8vh) dan yang menang hanya yang terbesar, jadi tambahan efektifnya
   15vh — itu yang menurunkan END ke sudut bawah. */
.hero:not(.hero-layar) .hero-bottom { margin-top: 24vh; }

/* ============================================================
   HAK CIPTA
   Sisa dari footer lama; posisinya dibuat sama dengan dulu
   (rata kanan, selebar .wrap) supaya letaknya tidak berpindah.
   ============================================================ */
.hak-cipta {
  max-width: 1200px; margin: 0 auto; padding: 48px 32px 40px;
  text-align: right; color: var(--ink-faint); font-size: 13px;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 768px) {
  /* ---- navbar kaca, khusus layar sempit ----
     Tint tipis + blur yang menyala sejak awal (bukan hanya setelah
     digulir), supaya bilahnya punya bentuk sendiri tanpa perlu garis
     pemisah. Di desktop navbar tetap seperti semula.

     Tintnya sengaja sangat tipis. Latar gelap dulu dibuang karena
     tampak sebagai pita melintang di atas hero; yang menyelamatkan di
     sini mask 35px di bawahnya — tepinya memudar, jadi tidak ada batas
     tegas. Jangan hapus salah satunya tanpa yang lain. */
  nav::before {
    background: linear-gradient(to bottom,
                rgba(10, 12, 14, 0.26), rgba(10, 12, 14, 0.12));
    -webkit-backdrop-filter: blur(16px) saturate(1.5);
    backdrop-filter: blur(16px) saturate(1.5);
    transition: background 0.3s, backdrop-filter 0.3s;
  }
  /* Setelah digulir dipekatkan: di atas isi halaman yang ramai, tint
     setipis itu tidak cukup menjaga logo dan tombol menu tetap terbaca. */
  nav.scrolled::before {
    background: linear-gradient(to bottom,
                rgba(10, 12, 14, 0.48), rgba(10, 12, 14, 0.28));
    -webkit-backdrop-filter: blur(22px) saturate(1.6);
    backdrop-filter: blur(22px) saturate(1.6);
  }

  /* ---- bilah nav diturunkan dari tepi atas ----
     20px di layar lebar terasa pas karena ada ruang di kiri-kanan yang
     ikut memberi napas; di ponsel napas itu tidak ada, jadi logo dan
     tombol menu menempel ke tepi. Atas dinaikkan, bawah justru
     dikurangi — yang kurang itu jarak ke tepi layar, bukan tinggi
     bilahnya. */
  nav { padding-top: 32px; padding-bottom: 16px; }
  /* Hero ikut turun. Bilahnya sekarang setinggi 94px sementara 10vh
     hanya 81px di layar 812 — tanpa ini huruf SEE masuk ke bawah nav. */
  .hero:not(.hero-layar) { padding-top: 14vh; }

  /* ---- kata tengah: wajib satu baris ----
     Pada 44px, "<V>IZUALIZE" mengukur 311px — persis selebar ruang
     yang tersedia (375 - 2x32 padding). Jadi kata yang sudah mengunci
     pun sudah mentok, dan begitu TextScramble mengganti hurufnya
     dengan glif acak yang lebih lebar (W dan — ada di charset-nya),
     barisnya pecah jadi dua.

     Ukurannya dipatok dari kasus TERBURUK, bukan dari kata jadinya.
     Diukur langsung di DOM, 500 undian 8-huruf acak per kombinasi:

       34px ls2 pad22 -> mentok      38px ls0 pad16 -> mentok
       36px ls0 pad22 -> sisa  7px   36px ls0 pad16 -> sisa 14px

     Yang dipakai baris terakhir. Dua hal yang membelinya: padding
     samping 16px dan letter-spacing 2px dibuang — pada 36px, 2px per
     huruf itu sendiri sudah memakan 22px, lebih mahal daripada
     selisih ukuran hurufnya.

     Dinyatakan sebagai 9.6vw supaya sisa 14px itu ikut berskala: di
     320px jadi 30.7px, di 414px jadi 39.7px, perbandingannya tetap.
     nowrap pengaman terakhir — kalau suatu saat charset atau katanya
     bertambah panjang, lebih baik kelihatan mentok daripada diam-diam
     jadi dua baris lagi. */
  .hero { padding-left: 16px; padding-right: 16px; }
  .hero-vision {
    font-size: clamp(28px, 9.6vw, 44px);
    letter-spacing: 0;
    flex-wrap: nowrap; white-space: nowrap;
    /* jarak atas dan bawah dibuat sama persis. Angkanya harus ditulis
       dua kali: margin-bawah .hero-vision luruh dengan margin-atas
       .hero-bottom dan yang menang hanya yang terbesar, jadi kalau
       hanya salah satu yang diubah, jaraknya tidak jadi simetris. */
    margin: 14vh 0;
  }
  .hero:not(.hero-layar) .hero-bottom { margin-top: 14vh; }

  /* ---- kartu melayang, bukan bilah sisi ----
     Perilakunya disamakan dengan dropdown Works di desktop: satu kartu
     kecil yang menggantung di bawah navbar. Isinya cuma empat baris,
     jadi panel setinggi layar berarti 500px ruang kosong yang tidak
     dipakai apa-apa — dan selama terbuka ia menutup seluruh halaman,
     yang justru terasa berat, bukan minimalis.

     top 100px = tinggi navbar di ponsel (32 + 46 + 16 = 94) ditambah
     6px jarak, supaya kartunya menggantung, bukan menempel. */
  .nav-links {
    position: fixed; top: 100px; right: 14px; left: auto; bottom: auto;
    height: auto; width: min(92vw, 360px);
    max-height: calc(100vh - 120px); overflow-y: auto;
    padding: 12px; border-radius: 20px;
    background: rgba(18, 22, 20, 0.62);
    -webkit-backdrop-filter: blur(26px) saturate(1.6);
    backdrop-filter: blur(26px) saturate(1.6);
    border: 1px solid rgba(255, 255, 255, 0.11);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    flex-direction: column; align-items: stretch; justify-content: flex-start;
    gap: 8px; z-index: 90;
    /* Munculnya seperti dropdown desktop: memudar sambil turun sedikit,
       bukan menggeser masuk dari tepi kanan. visibility ikut
       dianimasikan — tanpa itu kartu yang sudah tak terlihat masih
       menangkap sentuhan di separuh layar. */
    opacity: 0; visibility: hidden; transform: translateY(-10px);
    transition: opacity 0.22s ease, transform 0.22s ease, visibility 0.22s;
  }
  .nav-links.open { opacity: 1; visibility: visible; transform: translateY(0); }
  .has-drop { width: 100%; }

  /* ============================================================
     MENU PONSEL: hanya tiga divisi + Contact
     ============================================================
     Di layar sempit, menu diringkas jadi tujuan yang benar-benar
     dituju orang: ketiga divisi, lalu satu ajakan menghubungi.
     "Works" tidak lagi jadi tombol yang harus dibuka dulu — isinya
     langsung tergelar, karena di ponsel satu ketukan tambahan untuk
     membuka daftar yang cuma berisi tiga baris itu tidak membeli apa
     pun. Services dan About Us disembunyikan: keduanya bagian dari
     halaman yang sama dan tetap terlewati saat menggulir.
     ============================================================ */
  .nav-sekunder { display: none; }
  /* ID ikut disebut supaya menang atas .nav-links .nav-drop-toggle di bawah */
  #nav .nav-drop-toggle { display: none; }
  /* Isi Careers tergelar tepat di bawah tiga divisi; garis ini yang
     memisahkannya dari daftar divisi karena judul grupnya disembunyikan. */
  #careersItem { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line-soft); }

  /* Kartu dropdown dilucuti jadi daftar biasa — panelnya sendiri
     sudah jadi permukaan kacanya, jadi kartu kedua di dalamnya hanya
     menumpuk latar di atas latar. */
  .nav-links .drop {
    max-height: none; overflow: visible; padding-top: 0;
  }
  .drop-card {
    width: 100%; padding: 0; gap: 4px;
    background: none; border: 0; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  /* Kolom ikon dirampingkan dan padding samping dipangkas semata-mata
     untuk memberi ruang judul. "Breaker Creative" + label "Video
     Production" butuh 244px; dengan angka lama kolomnya 242px, kurang
     2px, dan labelnya jatuh ke baris kedua. Sekarang 259px. */
  .drop-item { padding: 11px 6px; grid-template-columns: 28px 1fr; gap: 10px; }
  .drop-title { font-size: 16px; gap: 7px; }
  .badge { font-size: 10px; padding: 3px 8px; }
  .drop-sub { font-size: 12.5px; }

  /* ---- keping Contact ----
     Bentuknya sengaja meniru .badge divisi (isian 0.13, garis 0.22 dari
     warna yang sama) supaya terbaca sebagai anggota keluarga yang sama,
     hanya beda warna — jingga lembut, bukan hijau, karena ini satu-
     satunya butir yang bukan tujuan di dalam halaman. */
  .nav-links .nav-kontak > a {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    margin-top: 14px; padding: 14px 18px; border-radius: 14px;
    font-size: 15px; font-weight: 600; letter-spacing: 0.2px;
    color: var(--accent-2);
    background: color-mix(in srgb, var(--accent-2) 13%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent-2) 24%, transparent);
    opacity: 1;
    transition: background 0.2s, border-color 0.2s, color 0.2s;
  }
  /* :active ikut disebut, bukan cuma :hover — di layar sentuh tidak ada
     hover sama sekali, jadi tanpa ini keping Contact tidak pernah
     memberi tanda bahwa sentuhannya diterima. */
  .nav-links .nav-kontak > a:hover,
  .nav-links .nav-kontak > a:focus-visible,
  .nav-links .nav-kontak > a:active {
    background: color-mix(in srgb, var(--accent-2) 24%, transparent);
    border-color: color-mix(in srgb, var(--accent-2) 46%, transparent);
    color: var(--accent-2-hi);
  }
  .nav-kontak .kontak-ikon {
    display: block; width: 18px; height: 18px; flex: 0 0 auto;
    fill: none; stroke: currentColor;
    stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  }

  /* Tautan menu dibiarkan berupa teks saja — tanpa keping.
     Konsekuensinya: tidak ada lagi backdrop-filter bersarang di dalam
     panel, jadi panelnya boleh diburamkan penuh lagi (lihat .nav-links
     di atas). Panel itulah yang sekarang memisahkan teks dari isi
     halaman di baliknya. */
  .nav-links > li > a,
  .nav-links .nav-drop-toggle {
    display: flex; align-items: center;
    width: 100%; box-sizing: border-box;
    padding: 10px 2px;
  }
  .nav-drop-toggle { justify-content: space-between; }
  .drop {
    position: static; padding-top: 12px; left: auto; right: auto;
    transform: none; visibility: visible; opacity: 1;
    max-height: 0; overflow: hidden; padding-bottom: 0;
    transition: max-height 0.3s ease;
  }
  .has-drop.open > .drop { max-height: 420px; }
  .drop-card { width: 100%; }
  .nav-toggle { display: block; z-index: 100; }
  .hero-bottom { flex-direction: column; align-items: flex-start; }
  .hero-end { text-align: left; align-self: flex-start; }
  .about-grid { grid-template-columns: 1fr; gap: 40px; }
  /* ---- deret logo klien: mendatar di layar sempit ----
     Versi tegak memakan 260px tinggi hanya untuk lima logo — mahal di
     ponsel, dan logo yang berjejer ke bawah terbaca seperti daftar,
     bukan deret. Mendatar lebih padat dan lebih lazim di ponsel.

     Tiga hal harus berubah bersamaan, kalau tidak hasilnya patah:
     arah flex, sumbu animasi, dan arah mask pudarnya. */
  .logo-rail {
    height: auto;
    -webkit-mask-image: linear-gradient(to right, transparent 0, black 12%, black 88%, transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, black 12%, black 88%, transparent 100%);
  }
  .logo-track {
    flex-direction: row; align-items: center;
    animation-name: logoScrollX;
    /* lebih cepat sedikit: jarak tempuh mendatar lebih pendek daripada
       tinggi deret tegaknya, jadi laju yang sama terasa lamban */
    animation-duration: 24s;
    width: max-content;
  }
  /* margin-right menggantikan margin-bottom; tingginya ikut isi */
  .logo-cell {
    height: 46px; margin-bottom: 0; margin-right: 52px;
    flex: 0 0 auto;
  }
  .network { padding: 10px 20px 70px; }
  .stats { grid-template-columns: 1fr 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .scramble .dud { color: inherit; }
  .drop, .chev { transition: none; }
  .logo-track { animation: none; }
}

/* ============================================================
   LAYAR — halaman brand & detail karya sebagai overlay penuh
   Bukan pindah halaman: dilapis di atas beranda, dengan rute hash
   (#isadaya, #isadaya/<slug>) supaya tombol kembali tetap bekerja.
   ============================================================ */
.layar {
  position: fixed; inset: 0; z-index: 200;
  background: var(--bg-base);
  overflow-y: auto; overscroll-behavior: contain;
  opacity: 0; visibility: hidden;
  transform: scale(0.985) translateY(14px);
  transition: opacity 0.34s ease, transform 0.34s ease, visibility 0.34s;
}
.layar.buka { opacity: 1; visibility: visible; transform: none; }

/* Tanpa backdrop-filter, dan itu disengaja: elemen ber-backdrop-filter
   menjadi acuan bagi keturunannya yang `position: fixed`, sehingga
   keduanya — tombol tutup di pojok dan tombol "Other Project" yang
   melayang — ikut tergulir alih-alih diam. Latarnya sendiri 94% pekat,
   jadi blur di belakangnya praktis tidak terlihat. */
.layar-detail {
  z-index: 210;
  background: rgba(6, 8, 5, 0.97);
}

.layar-tutup {
  position: fixed; top: 22px; right: 26px; z-index: 20;
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-bright); cursor: pointer;

  /* Kaca yang sama dengan tombol "Other Project" — tinta gelap tipis,
     blur kecil, garis terang di tepi dalam. Alasannya juga sama:
     tombol ini melayang di atas isi karya yang bisa terang mana saja,
     dan putih tipis akan ikut memutih di situ. */
  background: rgba(8, 10, 12, 0.16);
  border: 1px solid rgba(255,255,255,0.20);
  -webkit-backdrop-filter: blur(4px) saturate(1.5);
  backdrop-filter: blur(4px) saturate(1.5);
  /* Bayang luarnya jauh lebih rapat daripada milik tombol itu:
     lingkaran 44px dengan bayang selebar 30px akan terbaca sebagai
     noda gelap, bukan sebagai benda yang melayang. */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.16),
    0 3px 10px rgba(0,0,0,0.30);
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
.layar-tutup:hover {
  background: rgba(8, 10, 12, 0.28);
  border-color: rgba(255,255,255,0.32);
  transform: rotate(90deg);
}
.layar-tutup svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round;
  /* drop-shadow, bukan text-shadow: silangnya garis SVG, dan
     text-shadow tidak berlaku pada goresan SVG. */
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.45));
}

/* pembuka di dalam layar sedikit lebih pendek daripada beranda */
.hero-layar { min-height: 78vh; }

/* ---- daftar karya ---- */
.karya { padding: 40px 32px 120px; max-width: 1200px; margin: 0 auto; }
.karya-judul {
  font-family: var(--font-body);
  font-size: clamp(44px, 9vw, 132px); line-height: 0.95;
  letter-spacing: 1px; text-align: center; margin-bottom: 28px;
}
.karya-sub {
  text-align: center; color: var(--ink-muted); font-size: 15px;
  max-width: 720px; margin: 0 auto 36px;
}

.karya-alat {
  display: flex; gap: 16px; align-items: center; flex-wrap: wrap;
  margin-bottom: 32px;
}
.cari-kotak {
  position: relative; flex: 1 1 320px; min-width: 220px;
  display: flex; align-items: center;
}
.cari-ikon {
  position: absolute; left: 14px; width: 16px; height: 16px;
  fill: none; stroke: var(--ink-muted); stroke-width: 2; stroke-linecap: round;
  pointer-events: none;
}
#cariKarya {
  width: 100%; padding: 12px 16px 12px 40px;
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--line-soft); border-radius: 999px;
  color: var(--ink-bright); font-family: inherit; font-size: 14px;
  transition: border-color 0.2s, background 0.2s;
}
#cariKarya::placeholder { color: var(--ink-faint); }
#cariKarya:focus {
  outline: none; border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: rgba(255,255,255,0.08);
}
#cariKarya::-webkit-search-cancel-button { filter: invert(1); opacity: 0.5; }

.karya-sortir {
  flex: 0 0 auto; min-width: 170px;
  padding: 12px 16px; border-radius: 12px;
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--line-soft);
  color: var(--ink-bright); font-family: inherit; font-size: 14px; cursor: pointer;
}
.karya-sortir:focus { outline: none; border-color: color-mix(in srgb, var(--accent) 50%, transparent); }
.karya-sortir option { background: var(--bg-raised); color: var(--ink-bright); }

.karya-petunjuk {
  text-align: center; color: var(--ink-faint); font-size: 14px;
  padding: 48px 0;
}
.karya-petunjuk[hidden] { display: none; }

/* ---- layar Careers ----
   Tanpa pembuka hero seperti layar brand, jadi judulnya diberi ruang
   sendiri di bawah tombol tutup yang melayang. */
.layar-karier .karya { padding-top: 120px; max-width: 860px; }
.karier-daftar { display: flex; flex-direction: column; gap: 16px; }
.karier-kartu {
  padding: 24px 26px; border-radius: 20px;
  background: var(--bg-surface);
  border: 1px solid var(--line-soft);
}
.karier-judul {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 22px; font-weight: 700; line-height: 1.3;
}
.karier-meta { margin-top: 4px; font-size: 13px; color: var(--ink-muted); }
.karier-ringkas { margin-top: 14px; font-size: 15px; line-height: 1.6; }
.karier-syarat {
  margin: 12px 0 0 18px; font-size: 14px; line-height: 1.6; color: var(--ink-muted);
}
.karier-apply {
  display: inline-flex; margin-top: 18px; padding: 10px 22px; border-radius: 999px;
  font-size: 14px; font-weight: 600; text-decoration: none;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  transition: background 0.2s, border-color 0.2s;
}
.karier-apply:hover, .karier-apply:focus-visible {
  background: color-mix(in srgb, var(--accent) 24%, transparent); border-color: color-mix(in srgb, var(--accent) 46%, transparent);
}
@media (max-width: 768px) {
  .layar-karier .karya { padding: 84px 20px 80px; }
  .karier-kartu { padding: 20px; }
}

.karya-grid {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

.karya-kartu {
  display: flex; flex-direction: column; gap: 12px;
  padding: 0; background: none; border: none; cursor: pointer;
  text-align: left; color: var(--ink-bright); font-family: inherit;
  animation: karyaMasuk 0.34s ease both;
}
@keyframes karyaMasuk {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.karya-media {
  position: relative; display: block; aspect-ratio: 4 / 3;
  border-radius: 14px; overflow: hidden;
  background: var(--bg-raised); border: 1px solid var(--line-hair);
}
.karya-media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* seirama dengan pita judulnya */
  transition: transform .68s cubic-bezier(.22,.61,.36,1);
}
.karya-kartu:hover .karya-media img { transform: scale(1.05); }

/* ---- pita judul saat kursor lewat ---- */
/* 0,68 dtk — 0,28 semula ditambah 0,4. Pitanya juga naik sedikit
   sambil memudar masuk; gerakan kecil itu yang membuatnya terasa
   mengalir, bukan sekadar muncul. */
.karya-hover {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px;
  opacity: 0; pointer-events: none;
  transition: opacity .68s cubic-bezier(.22,.61,.36,1);
}
.karya-hover .karya-pita,
.karya-hover .karya-pita-kaki {
  transform: translateY(10px);
  transition: transform .68s cubic-bezier(.22,.61,.36,1);
}
.karya-hover .karya-pita-kaki { transition-delay: .06s; }

.karya-kartu:hover .karya-hover,
.karya-kartu:focus-visible .karya-hover { opacity: 1; }
.karya-kartu:hover .karya-pita,
.karya-kartu:hover .karya-pita-kaki,
.karya-kartu:focus-visible .karya-pita,
.karya-kartu:focus-visible .karya-pita-kaki { transform: translateY(0); }

.karya-pita {
  width: 100%; overflow: hidden; background: rgba(0,0,0,0.74);
  padding: 10px 0; display: block;
}
.karya-jalur {
  display: inline-flex; align-items: center; gap: 14px; white-space: nowrap;
  /* jalur digandakan, jadi geser 50% berarti kembali ke titik yang sama */
  animation: pitaJalan 14s linear infinite;
}
.karya-kartu:hover .karya-jalur { animation-play-state: running; }
.karya-pita-teks {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 15px; font-weight: 700; letter-spacing: .4px;
  text-transform: uppercase; color: var(--ink-bright);
}
.karya-pita-teks.tipis { font-weight: 400; font-size: 13px; color: rgba(255,255,255,0.72); }
.karya-pita-titik { color: rgba(255,255,255,0.45); font-size: 11px; }
.karya-pita-kaki {
  font-family: var(--font-body); font-size: 9.5px; letter-spacing: 2.4px;
  text-transform: uppercase; color: rgba(255,255,255,0.8);
  text-align: center; padding: 0 12px;
}
@keyframes pitaJalan {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .karya-jalur { animation: none; }
  .karya-hover, .karya-hover .karya-pita, .karya-hover .karya-pita-kaki,
  .karya-media img { transition: none; }
}
.karya-kartu:focus-visible .karya-media { outline: 2px solid var(--accent); outline-offset: 3px; }

/* tampil bila berkas gambar belum ada */
.karya-media.kosong {
  display: flex; align-items: center; justify-content: center;
  padding: 16px; text-align: center;
  font-family: var(--font-body); font-size: 12px;
  color: var(--ink-faint); letter-spacing: 1px;
  background: repeating-linear-gradient(45deg, var(--stripe-a), var(--stripe-a) 10px, var(--stripe-b) 10px, var(--stripe-b) 20px);
}

.karya-kat {
  display: inline-block; margin-top: 6px;
  font-size: 11px; letter-spacing: 0.3px; padding: 3px 10px; border-radius: 999px;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}

/* ---- detail satu karya ---- */
.detail { max-width: 1000px; margin: 0 auto; padding: 88px 32px 100px; }
.detail-media {
  border-radius: 18px; overflow: hidden; margin-bottom: 32px;
  background: var(--bg-raised); border: 1px solid var(--line-hair);
}
.detail-media img { width: 100%; height: auto; display: block; }
.detail-media.kosong {
  aspect-ratio: 16 / 9; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-body); color: var(--ink-faint); font-size: 13px;
  background: repeating-linear-gradient(45deg, var(--stripe-a), var(--stripe-a) 14px, var(--stripe-b) 14px, var(--stripe-b) 28px);
}
.detail h2 {
  font-family: var(--font-body); font-size: clamp(28px, 5vw, 52px);
  line-height: 1.05; margin-bottom: 14px;
}
.detail-meta { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 24px; }
.detail-berkas {
  font-family: var(--font-body); font-size: 12px; color: var(--ink-faint);
}
.detail-tag { display: flex; gap: 8px; flex-wrap: wrap; }
.detail-tag span {
  font-size: 12px; padding: 4px 11px; border-radius: 999px;
  color: var(--ink-muted); border: 1px solid var(--line-soft);
}

/* Mengunci di sini menghilangkan scrollbar, dan lebar viewport melonjak
   selebar scrollbar itu. kunciGulir() di script.js mengganti ruangnya
   dengan padding-right supaya lebar isinya tidak berubah — keduanya satu
   paket, jangan diubah sendiri-sendiri.

   scrollbar-gutter: stable sempat dicoba dan TIDAK bekerja: properti itu
   tidak berlaku pada elemen yang overflow-nya hidden. */
body.layar-terbuka { overflow: hidden; }

/* ============================================================
   MODE KANVAS (penyusun halaman)
   ============================================================
   Dipakai hanya ketika halaman ini dimuat sebagai kanvas builder
   (?kanvas=1). Aturannya ada DI SINI, bukan disuntikkan builder ke
   dalam iframe setelah 'load', karena waktunya yang menentukan:
   suntikan baru menempel sesudah dokumen baru tergambar, jadi ada
   jendela ~60ms di mana navbar dan halaman situs sempat berkedip
   sebelum tersembunyi — itu yang terasa sebagai "glitch seperti
   refresh" tiap kali divisi diganti. Lewat style.css, aturannya sudah
   berlaku pada gambar pertama.

   Tanpa kelas .cvn-kanvas di <html>, seluruh blok ini mati — jadi
   halaman terbit tidak terpengaruh sama sekali. */
html.cvn-kanvas #layarBrand,
html.cvn-kanvas .kaki-karya,
html.cvn-kanvas #karyaTutup { display: none; }
html.cvn-kanvas #layarKarya { background: var(--bg-base); }

/* Beranda tidak ikut digambar sama sekali di kanvas.

   Sebelumnya ia tetap ada di belakang, hanya tertutup lapisan karya
   yang dibuat pekat. Itu menyisakan dua kerugian: kalau lapisan
   karyanya belum sempat terbuka, yang terlihat beranda; dan selama
   menyusun, hero beserta shader latarnya, graf jaringan, dan deret logo
   tetap berjalan di balik layar padahal tidak pernah terlihat.

   Ditulis sebagai "semua anak langsung <body> KECUALI .layar" supaya
   bagian yang ditambahkan ke beranda nanti ikut tersembunyi dengan
   sendirinya — tidak ada daftar yang harus diingat untuk diperbarui.
   #layarBrand kebetulan ber-.layar juga, karena itu ia disebut sendiri
   di aturan atas. */
html.cvn-kanvas body > :not(.layar) { display: none; }
html.cvn-kanvas body { background: var(--bg-base); }
/* Popup kontak memakai kunci gulir yang sama. Kelasnya dipisah, bukan
   ikut .layar-terbuka, karena kunci itu dihitung ulang oleh kunciGulir()
   dari dua layar brand/karya saja — kalau popup ini ikut memakai kelas
   yang sama, membuka lalu menutup salah satu layar itu akan melepas
   kuncinya padahal popupnya masih terbuka. */
body.kontak-terbuka { overflow: hidden; }

/* ============================================================
   POPUP KONTAK
   ============================================================ */
.kontak-layar {
  position: fixed; inset: 0; z-index: 300;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.62);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0; visibility: hidden;
  transition: opacity 0.26s ease, visibility 0.26s;
}
.kontak-layar.buka { opacity: 1; visibility: visible; }

.kontak-kartu {
  position: relative;
  width: min(100%, 420px);
  padding: 26px 22px 22px;
  border-radius: 24px;
  background: rgba(18, 22, 20, 0.72);
  -webkit-backdrop-filter: blur(26px) saturate(1.6);
  backdrop-filter: blur(26px) saturate(1.6);
  border: 1px solid rgba(255, 255, 255, 0.11);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6);
  /* kartunya naik sedikit saat muncul — latar belakangnya memudar,
     kartunya bergerak, jadi yang ditangkap mata kartunya */
  transform: translateY(12px) scale(0.98);
  transition: transform 0.26s ease;
}
.kontak-layar.buka .kontak-kartu { transform: none; }

.kontak-tutup {
  position: absolute; top: 14px; right: 14px;
  width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--ink-bright); cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
}
.kontak-tutup:hover, .kontak-tutup:focus-visible {
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.28);
}
.kontak-tutup svg {
  width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round;
}

.kontak-judul {
  font-family: var(--font-body); font-size: 21px; font-weight: 700;
  letter-spacing: 0.2px; margin: 0 0 4px; padding-right: 40px;
}
.kontak-sub { font-size: 13.5px; color: var(--ink-muted); margin: 0 0 18px; }

.kontak-opsi {
  display: grid; grid-template-columns: 44px 1fr; align-items: center; gap: 13px;
  padding: 13px; border-radius: 16px;
  text-decoration: none; color: var(--ink-bright);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.09);
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
.kontak-opsi + .kontak-opsi { margin-top: 10px; }
/* :active ikut disebut: di layar sentuh tidak ada hover sama sekali,
   jadi tanpa ini tombolnya tidak pernah memberi tanda bahwa
   sentuhannya diterima. */
.kontak-opsi:hover, .kontak-opsi:focus-visible, .kontak-opsi:active {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.2);
}

/* Ubin ikon: warnanya yang membedakan kedua saluran, bukan ukuran atau
   letaknya — barisnya tetap seragam. */
.opsi-ubin {
  width: 44px; height: 44px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
}
.opsi-ubin svg { width: 22px; height: 22px; }
/* Lambang WhatsApp memang bentuk padat, amplopnya bentuk garis. Keduanya
   duduk di ubin seukuran dan sewarna-nada, jadi perbedaan itu terbaca
   sebagai dua lambang, bukan sebagai dua gaya ikon yang tidak sepakat. */
.ikon-isi { fill: currentColor; stroke: none; }
.ikon-garis {
  fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.opsi-wa .opsi-ubin {
  color: var(--whatsapp);
  background: color-mix(in srgb, var(--whatsapp) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--whatsapp) 26%, transparent);
}
.opsi-mail .opsi-ubin {
  color: var(--accent-2);
  background: color-mix(in srgb, var(--accent-2) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent-2) 26%, transparent);
}

.opsi-teks { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.opsi-nama {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 15.5px; font-weight: 700; letter-spacing: 0.2px; line-height: 1.25;
}
.opsi-det {
  font-size: 12.5px; color: var(--ink-muted); line-height: 1.4;
  /* alamat emailnya panjang; di layar sempit lebih baik dipotong rapi
     daripada melebarkan kartunya */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (max-width: 420px) {
  .kontak-kartu { padding: 22px 16px 18px; border-radius: 20px; }
  .kontak-opsi { grid-template-columns: 40px 1fr; gap: 11px; padding: 11px; }
  .opsi-ubin { width: 40px; height: 40px; border-radius: 12px; }
  .opsi-nama { font-size: 14.5px; }
  .opsi-det { font-size: 11.5px; }
}


@media (max-width: 768px) {
  .karya { padding: 24px 20px 90px; }
  .karya-alat { flex-direction: column; align-items: stretch; }
  .karya-sortir { width: 100%; }
  .layar-tutup { top: 14px; right: 14px; }
  .detail { padding: 72px 20px 80px; }
}

@media (prefers-reduced-motion: reduce) {
  .layar { transition: opacity 0.01s; transform: none; }
  .karya-kartu { animation: none; }
  .karya-kartu:hover .karya-media img { transform: none; }
  .layar-tutup:hover { transform: none; }
}

/* ============================================================
   BLOK — penyusun halaman karya
   Tiap blok membawa pengaturannya sendiri lewat atribut style inline
   (jarak, warna latar, warna teks, perataan, lebar maks) — nilai-nilai
   itulah yang nanti diatur dari panel CMS.
   ============================================================ */
.blok { width: 100%; }
.blok-dalam { margin: 0 auto; padding: 0 32px; max-width: 1200px; }
.blok-dalam.penuh { max-width: none; padding: 0; }

.hanya-pembaca {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* ---- hero ----
   Gambarnya memenuhi seluruh blok: tanpa margin, tanpa batas lebar, dan
   dipotong 'cover' — berkas kecil pun tetap penuh, tidak menyisakan
   ruang kosong di tepinya. Subjudul melayang di atasnya. */
.blok-hero { position: relative; }
.blok-hero .blok-dalam {
  min-height: 60vh; position: relative; z-index: 1;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 20px;
  padding-top: 64px; padding-bottom: 64px;
}
.hero-logo {
  position: absolute; inset: 0; z-index: 0;
  display: block; margin: 0; max-width: none; width: 100%;
}
.hero-logo img, .hero-logo video {
  width: 100%; height: 100%; object-fit: cover; object-position: center;
  display: block;
}
.hero-logo.kosong {
  position: relative; inset: auto; width: auto; max-width: 340px;
  padding: 28px; border: 1px dashed rgba(255,255,255,0.35); border-radius: 12px;
  font-family: var(--font-body); font-size: 12px; text-align: center;
}
.hero-sub {
  font-family: var(--font-body); font-weight: 500;
  letter-spacing: 6px; font-size: clamp(12px, 1.5vw, 17px); text-transform: uppercase;
}
.blok-tombol {
  display: inline-block; margin-top: 8px;
  padding: 8px 18px; border-radius: 999px;
  background: rgba(255,255,255,0.16); border: 1px solid rgba(255,255,255,0.3);
  color: inherit; text-decoration: none; font-size: 13px;
  transition: background 0.2s;
}
.blok-tombol:hover { background: rgba(255,255,255,0.28); }

/* ---- bar meta ---- */
.meta-grid {
  display: grid; gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.meta-label { font-size: 11px; opacity: 0.55; margin-bottom: 4px; }
.meta-nilai { font-size: 14px; font-weight: 700; }

/* ---- dua kolom ---- */

/* ---- galeri ---- */
.galeri-grid { display: grid; gap: 16px; }
.galeri-sel {
  margin: 0; overflow: hidden; border-radius: 12px;
  background: rgba(0,0,0,0.06);
  display: flex; align-items: center; justify-content: center;
}
.galeri-sel img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- gambar penuh ---- */
.gambar-penuh { margin: 0; display: block; }
.gambar-penuh img { width: 100%; height: auto; display: block; }

/* ---- teks ---- */
.teks-judul { font-size: clamp(18px, 2.2vw, 26px); font-weight: 700; margin-bottom: 18px; }
.teks-isi { font-size: 15px; line-height: 1.75; max-width: 760px; }
.teks-catatan {
  list-style: none; margin-top: 26px; padding: 0;
  font-family: var(--font-body); font-size: 12px; line-height: 1.9; opacity: 0.65;
}

/* Penanda media yang berkasnya belum ada, di dalam blok.

   min-height sengaja kecil. Nilai lamanya 180px mengalahkan aspect-ratio
   begitu kolomnya lebih sempit dari 320px: tingginya terkunci 180 sementara
   lebarnya terus menyusut, jadi penandanya berubah dari 16:9 menjadi lebih
   tinggi daripada lebar — ia berhenti mengikuti lebar. Yang tersisa di sini
   hanya lantai supaya penandanya tetap cukup besar untuk diklik; tinggi
   sebenarnya ditentukan rasio, yaitu oleh lebarnya. */
.galeri-sel.kosong, .gambar-penuh.kosong {
  min-height: 56px; padding: 16px; text-align: center;
  font-family: var(--font-body); font-size: 12px;
  color: rgba(128,128,128,0.9);
  background: repeating-linear-gradient(45deg, rgba(128,128,128,0.08), rgba(128,128,128,0.08) 12px, transparent 12px, transparent 24px);
}

@media (max-width: 860px) {
  .galeri-grid { grid-template-columns: repeat(2, 1fr) !important; }
  .blok-dalam { padding: 0 20px; }
}
@media (max-width: 560px) {
  .galeri-grid { grid-template-columns: 1fr !important; }
}

/* video & gif di dalam blok diperlakukan sama dengan gambar */
.galeri-sel video, .gambar-penuh video, .karya-media video, .detail-media video,
.hero-logo video {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.gambar-penuh video { height: auto; }

/* tombol berdiri sendiri (Preview button pada mode template) */
.blok-tombol.tombol-garis {
  background: transparent; border: 1px solid currentColor;
  padding: 11px 26px; font-size: 13px; letter-spacing: 0.4px;
}
.blok-tombol.tombol-garis:hover { background: currentColor; }
.blok-tombol.tombol-garis:hover { color: var(--ink-bright); }
.blok-tombol.tombol-garis:hover { mix-blend-mode: normal; }

/* Rasio TIDAK dipaksa di sini: bawaannya 'auto', artinya gambar tampil
   utuh apa adanya — landscape maupun potret. Kotak 16:9 hanya dipakai
   kalau blok itu memang mengaturnya, dan itu dipasang dari JS.
   Placeholder kosong tetap perlu tinggi supaya bisa diklik dan dijatuhi. */
.blok-image .gambar-penuh { overflow: hidden; }
.blok-image .gambar-penuh img,
.blok-image .gambar-penuh video { width: 100%; display: block; }
.blok-image .gambar-penuh.kosong { aspect-ratio: 16 / 9; }

/* ---- blok primitif: teks, media, grid, jarak ---- */
.isi-heading { font-family: var(--font-body); font-size: clamp(28px, 4vw, 56px); line-height: 1.05; margin: 0; }
.isi-paragraph { font-size: 15px; line-height: 1.75; margin: 0; }
.blok-media { margin: 0; overflow: hidden; display: block; max-width: 100%; }
.blok-media img, .blok-media video { width: 100%; height: 100%; display: block; }
.blok-media.kosong {
  min-height: 160px; display: flex; align-items: center; justify-content: center;
  padding: 18px; text-align: center;
  font-family: var(--font-body); font-size: 12px; color: rgba(128,128,128,.9);
  background: repeating-linear-gradient(45deg, rgba(128,128,128,.08), rgba(128,128,128,.08) 12px, transparent 12px, transparent 24px);
}
/* Kaki halaman karya. Tombolnya sendiri melayang (lihat .dok-bungkus),
   jadi yang tersisa di alur halaman cuma ruang kosong — supaya blok
   terakhir tidak tertutup tombol saat digulir sampai dasar. */
.kaki-karya {
  height: 132px;
  background: var(--paper);
}
@media (max-width: 720px) {
  .kaki-karya { height: 104px; }
}

/* Melayang di atas isi apa saja — gelap, terang, atau gambar — jadi
   warnanya tidak bisa ikut latar seperti dulu. Pil putih buram plus
   bayang tipis terbaca di semua keadaan. */
/* Kaca buram: yang di belakangnya tetap terlihat, hanya diburamkan.

   Latarnya harus tipis supaya blur-nya ada gunanya — pada 0.92 seperti
   sebelumnya, tidak ada yang tembus dan blur-nya sia-sia. Tulisannya
   ikut jadi putih: di atas latar setipis ini yang tampak di belakangnya
   adalah isi halaman yang gelap, dan tulisan gelap akan hilang. */
.kaki-karya .blok-tombol,
.dok-bungkus .blok-tombol {
  color: var(--ink-bright);
  border-color: rgba(255,255,255,0.20);
  /* Tinta gelap, bukan putih tipis.

     Putih 10% mengambil warna apa pun yang lewat di belakangnya — di
     atas bagian halaman yang terang, tombolnya ikut memutih dan
     tulisannya hilang. Tinta gelap selalu menggelapkan, berapa pun
     terangnya latar, jadi tombolnya terbaca di mana saja tanpa
     kehilangan sifat kacanya. */
  background: rgba(8, 10, 12, 0.16);
  /* Blur kecil: bentuk di belakangnya masih bisa dikenali, cuma
     dilunakkan — kaca tipis, bukan kaca es. Saturasi tetap dinaikkan
     supaya warnanya ikut terbawa dan tidak jatuh jadi abu-abu. */
  -webkit-backdrop-filter: blur(4px) saturate(1.5);
  backdrop-filter: blur(4px) saturate(1.5);
  /* garis terang tipis di tepi dalam — yang membuat kaca terasa punya
     ketebalan, bukan sekadar kotak tembus pandang */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.16),
    0 10px 30px rgba(0,0,0,0.35);
  /* Tulisannya sendiri diberi bayang tipis. Latar kaca ini meneruskan
     apa pun yang ada di belakangnya, jadi tulisan putih bisa jatuh
     tepat di atas bagian halaman yang terang dan ikut hilang. */
  text-shadow: 0 1px 2px rgba(0,0,0,0.35), 0 2px 10px rgba(0,0,0,0.30);
}
.dok-bungkus .blok-tombol:hover {
  background: rgba(8, 10, 12, 0.28);
  border-color: rgba(255,255,255,0.32);
}

/* ---- dok karya lain ----
   Panel melayang di atas tombol "Other Project", mengambil rasa bar
   macOS: batang membulat buram, isinya membesar dan terangkat saat
   disentuh kursor. Bedanya thumbnail di sini 4:3, bukan 1:1.

   Panel dan tombol dibungkus satu elemen supaya kursor yang bergerak
   dari tombol ke panel tidak pernah keluar dari area hover. Jaraknya
   dibuat dari padding panel, bukan margin — margin akan meninggalkan
   celah mati yang membuat panelnya berkedip. */
/* Melayang: tetap di tempat ke mana pun halaman digulir.
   `position: fixed` di dalam .layar aman karena .layar.buka
   transform-nya `none` — elemen bertransform akan jadi acuan fixed dan
   membuat tombolnya ikut tergulir. Tombol tutup di pojok layar memakai
   cara yang sama. Saat layarnya tertutup, `visibility: hidden` milik
   .layar ikut menyembunyikan tombol ini. */
.dok-bungkus {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  z-index: 15;
  text-align: center;
}
@media (max-width: 720px) {
  .dok-bungkus { bottom: 18px; }
}

.dok-panel {
  position: absolute;
  bottom: 100%;
  left: 50%;
  padding-bottom: 4px;
  transform-origin: 50% 100%;
  transform: translate(-50%, 14px) scale(0.94);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity .34s cubic-bezier(.22,.61,.36,1),
    transform .44s cubic-bezier(.22,.61,.36,1);
}
/* focus-within: bisa dibuka lewat Tab, bukan hanya kursor */
.dok-bungkus:hover .dok-panel,
.dok-bungkus:focus-within .dok-panel {
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
  pointer-events: auto;
}

/* Tanpa latar: yang melayang cuma keempat thumbnail-nya. Padding tetap
   ada sebagai ruang tumbuh saat salah satunya membesar, sekaligus
   jembatan kursor dari tombol ke panel. */
.dok-bar {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  /* Padding atas = ruang tumbuh saat salah satunya membesar.
     Padding bawah = jembatan kursor dari tombol ke panel; dikecilkan
     supaya deretnya duduk lebih dekat ke tombolnya. */
  padding: 30px 26px 2px;
}

.dok-item {
  position: relative;
  display: block;
  width: 72px;
  text-decoration: none;
  color: var(--paper-ink);
  /* Tiga hal menumpuk di satu properti transform, jadi masing-masing
     dipegang variabel sendiri: kalau ditulis sebagai deklarasi terpisah
     yang terakhir akan menghapus yang lain. Nilainya tetap beranimasi
     karena yang ditransisikan transform-nya, bukan variabelnya. */
  --geser: 0px;
  --naik: 0px;
  --miring: 0deg;
  transform: translateX(var(--geser)) translateY(var(--naik)) rotate(var(--miring));
  transition: transform .38s cubic-bezier(.22,.61,.36,1);
}

/* Datar: tidak ada naik-turun maupun miring. --naik dan --miring
   dibiarkan ada dan bernilai nol — keduanya masih dipakai transform
   yang sama dengan --geser, dan membuangnya berarti menulis ulang
   aturan geseran di bawah. */

/* Yang membesar tidak menggeser tetangganya sendiri — scale tidak
   mengubah alur — jadi tetangganya yang diminta minggir. Yang
   bersebelahan minggir penuh, yang berjarak dua setengahnya.
   :has() dipakai untuk memilih tetangga di sebelah kiri; browser yang
   belum mendukungnya melewatkan aturannya dan yang disentuh tetap
   membesar, hanya tanpa geseran. */
.dok-item:hover + .dok-item { --geser: 17px; }
.dok-item:has(+ .dok-item:hover) { --geser: -17px; }
.dok-item:hover + .dok-item + .dok-item { --geser: 8px; }
.dok-item:has(+ .dok-item + .dok-item:hover) { --geser: -8px; }

/* yang sedang disentuh naik ke depan; tanpa ini tepinya bisa tertimpa
   tetangga yang belum selesai minggir */
.dok-item:hover, .dok-item:focus-visible { z-index: 2; }

.dok-thumb {
  display: block;
  width: 72px;
  aspect-ratio: 4 / 3;
  border-radius: 13px;
  overflow: hidden;
  background: var(--paper-tile);
  /* tipis dan menyebar lembut: bayangnya menandai ketinggian, bukan
     menggambar kotak kedua di bawahnya */
  box-shadow: 0 8px 18px rgba(0,0,0,0.10), 0 1px 3px rgba(0,0,0,0.05);
  transform-origin: 50% 100%;
  transition:
    transform .38s cubic-bezier(.22,.61,.36,1),
    box-shadow .38s cubic-bezier(.22,.61,.36,1);
}
.dok-thumb img, .dok-thumb video {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
}
/* media yang gagal dimuat tetap menyisakan nama berkasnya */
.dok-thumb .penanda-media {
  display: block; padding: 6px;
  font-size: 9px; line-height: 1.3; color: var(--paper-muted);
  word-break: break-all;
}

.dok-item:hover .dok-thumb,
.dok-item:focus-visible .dok-thumb {
  transform: scale(1.55) translateY(-10px);
  box-shadow: 0 16px 30px rgba(0,0,0,0.16), 0 2px 6px rgba(0,0,0,0.06);
}

/* Jendela sempit tapi tetap pakai kursor: barnya dikecilkan supaya
   tidak lebih lebar dari layar — panelnya melayang, jadi kelebihannya
   akan memunculkan gulir mendatar, bukan sekadar terpotong. */
@media (max-width: 560px) {
  .dok-bar { gap: 10px; padding: 26px 20px 2px; }
  .dok-item, .dok-thumb { width: 60px; }
}

/* Tanpa kursor tidak ada hover: di perangkat sentuh tombolnya kembali
   berdiri sendiri, tidak ada panel yang tidak bisa dibuka. */
@media (hover: none) {
  .dok-panel { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .dok-panel, .dok-item, .dok-thumb { transition-duration: .01ms; }
}

/* ---- hover media & tombol ----
   Nilainya datang dari builder sebagai variabel CSS; yang tidak diatur
   jatuh ke nilai bawaan sehingga elemennya diam saja. */
/* --zoom dipasang builder untuk crop, --hover-skala untuk efek hover.
   Keduanya dikalikan supaya gambar yang sudah di-crop tetap bisa
   membesar saat disentuh kursor. */
.blok-media img, .blok-media video,
.gambar-penuh img, .gambar-penuh video { transform: scale(var(--zoom, 1)); }

.blok-media.punya-hover img, .blok-media.punya-hover video,
.gambar-penuh.punya-hover img, .gambar-penuh.punya-hover video {
  transition: transform .5s cubic-bezier(.22,.61,.36,1), opacity .35s ease;
}
.blok-media.punya-hover:hover img, .blok-media.punya-hover:hover video,
.gambar-penuh.punya-hover:hover img, .gambar-penuh.punya-hover:hover video {
  transform: scale(calc(var(--zoom, 1) * var(--hover-skala, 1)));
  opacity: var(--hover-opasitas, 1);
}

.blok-tombol.punya-hover { transition: background .2s ease, color .2s ease, border-color .2s ease; }
/* !important wajib: warna dasar tombol dipasang sebagai gaya sebaris
   dari builder, dan gaya sebaris selalu menang atas aturan stylesheet. */
.blok-tombol.punya-hover:hover {
  color: var(--h-warna, inherit) !important;
  background: var(--h-latar, rgba(255,255,255,0.28)) !important;
  border-color: var(--h-garis, currentColor) !important;
}

.isi-grid { display: grid; align-items: start; }
/* min-width: 0 wajib — tanpa itu kolom grid menolak menyusut
   dan gambar lebar mendorong kolom lain keluar */
.isi-sel { min-width: 0; display: flex; flex-direction: column; }
/* blok di dalam kolom tidak perlu bingkai lebar sendiri */
.isi-sel > .blok > .blok-dalam { padding: 0; max-width: none; }
/* Grid kiri-kanan ditumpuk di layar sempit. Grid atas-bawah sudah
   bertumpuk, jadi tidak perlu diapa-apakan — makanya aturannya dibatasi
   pada yang punya lebih dari satu kolom. */
@media (max-width: 720px) {
  .isi-grid:not([data-arah="baris"]) { grid-template-columns: 1fr !important; }
}

