/* ==========================================================================
   BASE: reset, tipografi, layout primitif, dan lapisan latar global.
   ========================================================================== */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 24px);
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--f-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--text-2);
  background: var(--bg);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
body.is-locked { overflow: hidden; }

img, svg, video, canvas { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }
::selection { background: var(--accent-fill); color: var(--text); }

/* Scrollbar bertema */
* { scrollbar-width: thin; scrollbar-color: var(--surface-4) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb {
  background: var(--surface-3);
  border-radius: var(--r-full);
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--surface-4); }

:focus-visible {
  outline: 2px solid var(--accent-3);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ======================== TIPOGRAFI ======================== */
h1, h2, h3, h4, h5 {
  font-family: var(--f-display);
  color: var(--text);
  font-weight: 600;
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-tight);
}
h1 { font-size: var(--fs-3xl); line-height: var(--lh-tight); }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }
p  { color: var(--text-2); }
strong { color: var(--text); font-weight: 600; }

/* Label kecil bergaya mono untuk "eyebrow" di atas judul section. */
.kicker {
  font-family: var(--f-mono);
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  line-height: 1;
}
.kicker::before {
  content: '';
  width: 26px; height: 1px;
  background: var(--grad-accent);
  background-size: 200% 100%;
}
.kicker--center::after {
  content: '';
  width: 26px; height: 1px;
  background: var(--grad-accent);
  background-size: 200% 100%;
}

/* Teks berisian gradien. Fallback ke warna solid bila background-clip mati. */
.accent-text {
  background: var(--grad-accent);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.chrome-text {
  background: var(--grad-chrome);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 2px 14px rgba(255, 255, 255, 0.14));
}
.chrome-text--cool { background-image: var(--grad-chrome-cool); }
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .accent-text, .chrome-text { color: var(--text); background: none; }
}

/* ======================== LAYOUT ======================== */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gut);
}
.container--narrow { max-width: var(--container-n); }
.container--wide   { max-width: 1600px; }

.section { position: relative; padding-block: var(--sec-y); }
.section--tight { padding-block: clamp(48px, 7vh, 96px); }
.section--flush-top { padding-top: 0; }

.sec-head {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-bottom: clamp(40px, 6vh, 76px);
  max-width: 780px;
}
.sec-head--center { align-items: center; text-align: center; margin-inline: auto; }
.sec-head--split {
  max-width: none;
  flex-direction: row;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  flex-wrap: wrap;
}
.sec-head p { font-size: var(--fs-lg); color: var(--muted); max-width: 62ch; }

.stack   { display: flex; flex-direction: column; }
.row     { display: flex; align-items: center; }
.wrap    { flex-wrap: wrap; }
.gap-8   { gap: 8px; }  .gap-12 { gap: 12px; } .gap-16 { gap: 16px; }
.gap-24  { gap: 24px; } .gap-32 { gap: 32px; } .gap-48 { gap: 48px; }
.mt-auto { margin-top: auto; }
.center  { text-align: center; }
.hidden  { display: none !important; }

.grid { display: grid; gap: clamp(18px, 2.2vw, 30px); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
@media (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 680px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .sec-head--split { flex-direction: column; align-items: flex-start; }
}

/* Pembatas garis dengan kilau aksen di tengah */
.hr-accent {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg, transparent, var(--line-2) 20%, var(--accent-2) 50%, var(--line-2) 80%, transparent);
  opacity: 0.6;
}

/* ======================== LAPISAN LATAR GLOBAL ======================== */
/* Disuntikkan sekali per halaman oleh shell.js */
.fx-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-bg);
}

/* Grain film halus. Di atas putih, bintik putih tidak terlihat sama sekali,
   jadi lapisannya dijadikan gelap lewat mix-blend-mode dan kepekatannya
   diturunkan supaya hanya terasa sebagai tekstur, bukan kotoran. */
.fx-grain::after {
  content: '';
  position: absolute;
  inset: -200%;
  opacity: 0.022;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grainShift 0.9s steps(4) infinite;
}

/* Kisi perspektif: grid horizon statis di belakang seluruh halaman. */
.fx-grid {
  background-image:
    linear-gradient(to right, rgba(13, 13, 18, 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(13, 13, 18, 0.05) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(ellipse 110% 78% at 50% 0%, #000 12%, transparent 76%);
  -webkit-mask-image: radial-gradient(ellipse 110% 78% at 50% 0%, #000 12%, transparent 76%);
  opacity: 0.55;
}

/* Blob cahaya yang mengambang perlahan di latar.

   CATATAN KINERJA. Blok ini dulu memakai `filter: blur(90px)`. Pada elemen
   selebar 46vw (sekitar 660 piksel di layar 1440), blur seradius itu memaksa
   compositor merasterisasi buffer raksasa setiap kali lapisannya perlu
   digambar ulang, dan itu terjadi terus-menerus selama halaman digulir.
   Pengukuran dengan pelambatan CPU 4x menunjukkan halaman tertahan di 17,5 fps
   dengan 98,7 persen frame tersendat; begitu blob disembunyikan, angkanya
   langsung 60 fps dengan 0 persen tersendat. Efek lain (backdrop-filter,
   grain, vignette, box-shadow) diuji satu per satu dan tidak berpengaruh.

   Blur-nya dibuang, bukan dikecilkan. Sumber blob memang sudah berupa
   radial-gradient yang lembut, jadi memblur gradien lembut hampir tidak
   menambah apa pun secara visual. Kelembutan yang hilang diganti dengan
   hentian gradien tambahan supaya peredupannya tetap bertahap. */
.fx-blobs { overflow: hidden; }
/* Di atas putih, warna setengah transparan tampak lebih samar daripada di atas
   hitam, jadi kepekatannya perlu dinaikkan agar semburatnya masih terasa. Tapi
   0,85 ternyata kelewatan: sudut kiri atas terukur #fbf6e9, krem yang jelas,
   bukan putih. 0,55 menahannya di sekitar #fdfaf2, cukup untuk memberi kesan
   cahaya tanpa membuat halaman berhenti terbaca sebagai putih. */
.fx-blob {
  position: absolute;
  border-radius: 50%;
  opacity: 0.55;
  will-change: transform;
}
.fx-blob--1 {
  width: 46vw; height: 46vw; top: -14vw; left: -10vw;
  background: radial-gradient(circle,
    rgba(212, 160, 23, 0.16) 0%,
    rgba(212, 160, 23, 0.11) 30%,
    rgba(212, 160, 23, 0.05) 52%,
    rgba(212, 160, 23, 0.015) 68%,
    transparent 82%);
  animation: blobDrift1 26s var(--ease-in-out) infinite alternate;
}
.fx-blob--2 {
  width: 40vw; height: 40vw; top: 32vh; right: -12vw;
  background: radial-gradient(circle,
    rgba(156, 116, 16, 0.15) 0%,
    rgba(156, 116, 16, 0.10) 30%,
    rgba(156, 116, 16, 0.045) 52%,
    rgba(156, 116, 16, 0.014) 68%,
    transparent 82%);
  animation: blobDrift2 32s var(--ease-in-out) infinite alternate;
}
.fx-blob--3 {
  width: 34vw; height: 34vw; bottom: -12vw; left: 26vw;
  background: radial-gradient(circle,
    rgba(240, 198, 69, 0.085) 0%,
    rgba(240, 198, 69, 0.058) 30%,
    rgba(240, 198, 69, 0.026) 54%,
    rgba(240, 198, 69, 0.008) 70%,
    transparent 84%);
  animation: blobDrift3 38s var(--ease-in-out) infinite alternate;
}

/* Vignette. Di tema gelap ia menggelapkan tepi; di tema terang kebalikannya,
   memutihkan tepi supaya pandangan tetap jatuh ke tengah tanpa membuat
   halaman terasa kotor. */
.fx-vignette {
  background: radial-gradient(ellipse 130% 90% at 50% 40%, transparent 46%, rgba(255, 255, 255, 0.55) 100%);
}

/* ======================== AKSESIBILITAS ======================== */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: fixed;
  top: 12px; left: 12px;
  z-index: var(--z-toast);
  padding: 12px 20px;
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--text);
  transform: translateY(-160%);
  transition: transform var(--t) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

/* Placeholder gambar saat URL kosong / gagal dimuat. */
.img-ph {
  display: grid;
  place-items: center;
  background:
    linear-gradient(135deg, var(--surface-2), var(--surface)),
    var(--bg);
  color: var(--faint);
  font-family: var(--f-mono);
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

/* ======================== IKON ========================
   Setiap SVG dari icon() membawa kelas .ic. Tanpa ukuran eksplisit, SVG
   diperlakukan peramban sebagai elemen tergantikan berukuran 300x150, dan
   itulah yang membuat ikon tampak raksasa. Ukuran relatif terhadap teks di
   sekitarnya dipakai sebagai bawaan; aturan komponen (.btn svg, .icon-box svg,
   dan sejenisnya) punya kekhususan lebih tinggi sehingga tetap menang. */
.ic {
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
  display: inline-block;
  vertical-align: -0.16em;
}

/* Konteks yang butuh ikon lebih besar atau lebih kecil dari ukuran teksnya. */
.img-ph .ic       { width: 34px; height: 34px; }
.nav__caret       { width: 13px; height: 13px; }
.team-card__go .ic,
.svc-row__go .ic,
.lightbox__close .ic,
.lightbox__nav .ic,
.acc__ico .ic,
.up-grid__add .ic { width: 18px; height: 18px; }
.list-row__thumb .ic { width: 19px; height: 19px; }

/* ======================== PERATAAN TEKS PANJANG ========================
   Blok bacaan yang panjang diratakan kiri-kanan agar tepinya rapi.

   Perataan ini sengaja TIDAK dipakai di mana-mana. Pada kolom sempit seperti
   kartu, tiap baris hanya memuat sekitar 30 sampai 45 huruf, sehingga justify
   memaksa jarak antar kata melebar dan muncul celah putih memanjang ke bawah.
   Karena itu hanya kolom dengan sekitar 50 huruf per baris ke atas yang
   diratakan; kartu, blurb footer, kutipan, dan teks rata tengah dibiarkan
   rata kiri. */
.prose p,
.about-lead,
.about-story,
.prof-bio,
.hero__sub,
.page-hero p,
.post-hero p,
.svc-row__desc,
.svc-bukti__sub,
.vm-card p,
.vm-list li,
.tl-item p,
.acc__body p,
.card__desc,
.resp-card__desc,
.pf-card__ringkas,
.post-card p,
.prep-box__note,
.sec-head:not(.sec-head--center) p {
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
}

/* Bio pada halaman profil tim; gayanya dipindahkan ke sini dari atribut
   style agar bisa ikut aturan perataan di atas. */
.prof-bio {
  font-size: var(--fs-lg);
  line-height: 1.8;
  margin-top: 8px;
}

/* Lebar kolom teks tidak selalu mengikuti lebar layar: pada lebar layar yang
   sama, sebuah paragraf bisa lebar (satu kolom) atau sempit (dua kolom).
   Karena itu wadahnya dijadikan konteks container query, sehingga aturan di
   bawah membaca lebar kolom yang sebenarnya. */
.about-split > .stack,
.vm-card,
.card,
.resp-card,
.pf-card,
.post-card,
.timeline {
  container-type: inline-size;
}

/* Ambangnya 320 piksel, bukan 460. Pada kolom 387 piksel yang lazim di ponsel,
   satu baris masih memuat sekitar 51 huruf, dan pada lebar itu justify tetap
   rapi. Ambang lama membuat hampir seluruh teks di ponsel kembali rata kiri,
   padahal kolomnya sudah cukup lebar. Yang benar-benar sempit, di bawah 320
   piksel, tetap rata kiri karena di sana jarak antar katanya mulai menganga. */
@container (max-width: 320px) {
  .about-lead,
  .about-story,
  .vm-card p,
  .vm-list li,
  .card__desc,
  .resp-card__desc,
  .post-card p,
  .tl-item p { text-align: left; }
}


