/* ============================================================
   PORTAL SISTEM INFORMASI TERINTEGRASI — PERUMDA AIR MINUM
   DUASUDARA BITUNG
   ============================================================ */

/* ============================================================
   PALET AIR — biru, biru tosca, gradien biru muda.
   Nilai sengaja dijaga cukup gelap di bagian atas supaya teks putih
   tetap terbaca, lalu menua ke tosca & biru muda di bawah seperti
   air yang terkena cahaya dari permukaan.
   ============================================================ */
:root{
  --water-900:#042A47;   /* biru laut dalam — dasar */
  --water-800:#064566;
  --water-700:#06607F;
  --water-600:#0A7E96;
  --tosca-500:#12A3B4;   /* biru tosca */
  --tosca-400:#1FC3CE;
  --aqua-300:#5BD9E6;    /* biru muda terang */
  --aqua-200:#9DECF5;

  --ink-100:#f2fdff;
  --ink-300:#c3e9f4;
  --ink-400:#8fc6d8;
  --green-500:#2ee08a;
  --green-300:#8ff5c4;

  --glass-bg:rgba(255,255,255,.08);
  --glass-bg-strong:rgba(255,255,255,.13);
  --glass-border:rgba(216,247,255,.22);
  --glass-border-hover:rgba(95,226,240,.6);

  --font-display:'Poppins',ui-sans-serif,system-ui,sans-serif;
  --font-body:'Inter',ui-sans-serif,system-ui,sans-serif;

  /* dual-ring orbit: inner = 4 sistem inti, outer = 5 sistem operasional/pengawasan.
     Radius orbit TIDAK ditetapkan di sini — dihitung di orbit.js dari ruang nyata
     yang tersedia (elips, mengikuti layar lanskap), lalu di-clamp agar tidak pernah
     keluar viewport maupun menabrak logo tengah. */
  /* Tanpa kartu: yang mengorbit kini IKON BESAR + teks di bawahnya.
     --card-w/--card-h tetap dipakai sebagai ukuran AWAL kotak tiap item
     (orbit.js mengukur ulang tinggi sebenarnya dari isinya). */
  --card-w:188px;
  --card-h:150px;   /* tinggi MINIMUM; tinggi nyata diukur ulang di orbit.js */
  --icon-size:84px; /* jauh lebih besar — ikon kini elemen utama, bukan hiasan kartu */
  --logo-size:216px;

  /* Lama satu putaran penuh. Makin BESAR angkanya, makin LAMBAT rotasinya.
     28s → 38s (2026-09-16) → 90s (2026-10-04) → 120s (2026-10-14).
     Alasan 90s: portal dipakai untuk peragaan ke tamu dan diklik operator.
     Pada 38s kartu melaju ±107 px/dtk, jadi butuh ~2 dtk saja untuk bergeser
     selebar dirinya sendiri — melelahkan dilihat dan sulit dibidik kursor.
     Pada 90s lajunya ±45 px/dtk: masih jelas berputar, tapi tenang dan mudah
     dikejar kursor. Catatan: begitu kursor menyentuh kartu, orbit BERHENTI
     (hover-pause di orbit.js), jadi mengeklik tidak pernah mengejar sasaran. */
  --orbit-duration:120s;
}

*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
/* Kolom flex setinggi layar: header & footer memakai tinggi alaminya, sisanya
   diberikan ke .hero. Sebelumnya tinggi hero dihitung manual (100dvh dikurangi
   angka tetap), dan angka itu meleset beberapa piksel dari tinggi header+footer
   yang sebenarnya — halaman jadi sedikit lebih tinggi dari layar sehingga
   header tampak terpotong di atas. */
body{
  margin:0;
  min-height:100dvh;
  display:flex;
  flex-direction:column;
  font-family:var(--font-body);
  color:var(--ink-100);
  background:var(--water-900);
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
img{max-width:100%;display:block}
button{font:inherit}
a{color:inherit}
::selection{background:rgba(31,195,206,.45);color:#fff}

/* ---------------------------------------------------------
   BACKGROUND — gradient, glow blobs, particles, ripple
--------------------------------------------------------- */
.bg-layer{
  position:fixed;
  inset:0;
  z-index:0;
  overflow:hidden;
  pointer-events:none;
}
.bg-gradient{
  position:absolute;
  inset:0;
  /* Air dilihat dari dalam: biru pekat di atas, menua jadi tosca lalu biru
     muda ke bawah, dengan kolam cahaya seperti sinar menembus permukaan. */
  background:
    radial-gradient(1200px 760px at 20% 6%, rgba(91,217,230,.20), transparent 62%),
    radial-gradient(980px 700px at 84% 14%, rgba(31,195,206,.18), transparent 58%),
    radial-gradient(1300px 900px at 50% 104%, rgba(157,236,245,.26), transparent 64%),
    linear-gradient(168deg,
      var(--water-900) 0%,
      var(--water-800) 28%,
      var(--water-700) 50%,
      var(--water-600) 68%,
      var(--tosca-500) 86%,
      var(--tosca-400) 100%);
}
/* Berkas cahaya miring — kesan sinar matahari menembus air */
.bg-gradient::after{
  content:'';
  position:absolute; inset:-20% -10%;
  background:repeating-linear-gradient(104deg,
    rgba(255,255,255,.055) 0 2px,
    transparent 2px 170px);
  mask-image:radial-gradient(ellipse 80% 70% at 50% 0%, #000 10%, transparent 75%);
  -webkit-mask-image:radial-gradient(ellipse 80% 70% at 50% 0%, #000 10%, transparent 75%);
  pointer-events:none;
}
.bg-grid{
  position:absolute;
  inset:-2px;
  background-image:
    linear-gradient(rgba(170,235,250,.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(170,235,250,.07) 1px, transparent 1px);
  background-size:46px 46px;
  mask-image:radial-gradient(ellipse 75% 65% at 50% 45%, #000 40%, transparent 78%);
  -webkit-mask-image:radial-gradient(ellipse 75% 65% at 50% 45%, #000 40%, transparent 78%);
}

#particle-canvas{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  opacity:0;
  transition:opacity 1.6s ease;
}
body.is-ready #particle-canvas{opacity:.85}

.glow-blob{
  position:absolute;
  border-radius:50%;
  filter:blur(70px);
  opacity:0;
  transition:opacity 1.8s ease 200ms;
  will-change:transform;
}
body.is-ready .glow-blob{opacity:1}
.glow-blob--a{
  width:520px;height:520px; left:-120px; top:-140px;
  background:radial-gradient(circle at 35% 35%, rgba(31,195,206,.50), transparent 70%);
  animation:driftA 22s ease-in-out infinite;
}
.glow-blob--b{
  width:620px;height:620px; right:-180px; top:10%;
  background:radial-gradient(circle at 60% 40%, rgba(91,217,230,.42), transparent 70%);
  animation:driftB 26s ease-in-out infinite;
}
.glow-blob--c{
  width:560px;height:560px; left:50%; bottom:-260px; transform:translateX(-50%);
  background:radial-gradient(circle at 50% 50%, rgba(157,236,245,.38), transparent 70%);
  animation:driftC 30s ease-in-out infinite;
}
@keyframes driftA{
  0%,100%{transform:translate(0,0) scale(1)}
  50%{transform:translate(60px,40px) scale(1.12)}
}
@keyframes driftB{
  0%,100%{transform:translate(0,0) scale(1)}
  50%{transform:translate(-50px,50px) scale(1.08)}
}
@keyframes driftC{
  0%,100%{transform:translate(-50%,0) scale(1)}
  50%{transform:translate(calc(-50% + 40px),-30px) scale(1.1)}
}

/* Riak air — dipancarkan dari titik pusat orbit (= pusat logo).
   left/top 50% di sini mengacu ke .orbit-system, bukan ke layar, jadi
   posisinya otomatis ikut logo di ukuran layar mana pun. */
.ripple-wrap{
  position:absolute;
  left:50%; top:50%;
  width:0; height:0;
  transform:translate(-50%,-50%);
  pointer-events:none;
  z-index:1;   /* di belakang cincin orbit, logo (z-5), dan kartu (z-4) */
}
/* Di mode grid logo pindah ke atas dan .orbit-system tidak lagi jadi
   panggung melingkar, sehingga titik tengahnya tidak lagi berimpit dengan
   logo — riak disembunyikan daripada memancar dari tempat yang salah. */
.orbit-system:has(.orbit.is-grid) .ripple-wrap,
body.grid-mode .ripple-wrap{display:none}
.ripple{
  position:absolute;
  left:0; top:0;
  width:120px;height:120px;
  margin:-60px 0 0 -60px;
  border-radius:50%;
  border:1px solid rgba(190,243,255,.45);
  opacity:0;
  animation:rippleOut 6.5s ease-out infinite;
}
.ripple:nth-child(2){animation-delay:2.15s}
.ripple:nth-child(3){animation-delay:4.3s}
@keyframes rippleOut{
  0%{opacity:0; transform:scale(.3)}
  12%{opacity:.55}
  100%{opacity:0; transform:scale(6.2)}
}

/* ---------------------------------------------------------
   TETESAN AIR JATUH
   Bentuk tetes dibuat di ::before (sudut lancip lewat border-radius
   + rotate), sementara elemen induknya yang BERGERAK — dipisah supaya
   rotasi bentuk tidak saling menimpa dengan transform animasi jatuh.
--------------------------------------------------------- */
.droplets{position:absolute; inset:0; overflow:hidden}
.droplet{
  position:absolute;
  top:-12%;              /* mulai di ATAS layar, lalu jatuh ke bawah */
  opacity:0;
  animation-name:dropFall;
  animation-timing-function:cubic-bezier(.35,0,.7,1); /* sedikit memburu seperti benda jatuh */
  animation-iteration-count:infinite;
}
.droplet::before{
  content:'';
  display:block; width:100%; height:100%;
  /* Sudut lancip di KIRI-ATAS; setelah diputar 45° ujungnya menghadap KE ATAS.
     Ini bentuk tetesan air yang sebenarnya saat jatuh: bagian bulat memimpin
     di bawah, ekor lancipnya tertinggal di atas. JANGAN dibalik mengikuti arah
     gerak — pernah dibalik ke bawah dan hasilnya salah. */
  border-radius:0 50% 50% 50%;
  transform:rotate(45deg);
  background:
    radial-gradient(circle at 34% 28%, rgba(255,255,255,.62), rgba(255,255,255,.12) 52%, transparent 70%),
    linear-gradient(145deg, rgba(190,243,255,.34), rgba(31,195,206,.14));
  border:1px solid rgba(205,245,255,.45);
  box-shadow:inset 0 2px 7px rgba(255,255,255,.4), 0 4px 14px rgba(4,42,71,.3);
}
@keyframes dropFall{
  0%{opacity:0; transform:translateY(0) translateX(0) scale(.85)}
  8%{opacity:.55}
  90%{opacity:.4}
  100%{opacity:0; transform:translateY(118vh) translateX(var(--drift,30px)) scale(1)}
}

/* ---------------------------------------------------------
   HEADER
--------------------------------------------------------- */
.site-header{
  position:relative;
  z-index:20;
  display:flex;
  align-items:center;
  gap:14px;
  max-width:1180px;
  margin:0 auto;
  padding:18px 24px;
  opacity:0;
}
.site-header .h-logo{
  width:42px; height:42px; object-fit:contain;
  filter:drop-shadow(0 0 10px rgba(157,236,245,.5));
}
.site-header .h-text{line-height:1.25}
.site-header .h-title{
  font-family:var(--font-display);
  font-weight:700;
  font-size:14.5px;
  letter-spacing:.2px;
  color:var(--ink-100);
}
.site-header .h-sub{
  font-size:12px;
  color:var(--ink-400);
  letter-spacing:.2px;
}

/* ---------------------------------------------------------
   HERO / ORBIT SYSTEM
--------------------------------------------------------- */
.hero{
  position:relative;
  z-index:10;
  flex:1 1 auto;
  /* Lantai tinggi dibuat rendah. Dulu 520px — angka itu memaksa halaman lebih
     tinggi dari layar (muncul scrollbar) di jendela pendek. Sekarang orbit
     sudah bisa mengecil sendiri mengikuti ruang yang ada, jadi lantai setinggi
     itu tidak lagi dibutuhkan. */
  min-height:280px;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:14px 16px;
}
.orbit-system{
  position:relative;
  width:100%;
  height:100%;
  max-width:1560px;
  display:flex;
  align-items:center;
  justify-content:center;
}

/* orbit guide ellipses — sized by orbit.js to match the real computed radii exactly */
.orbit-ring{
  position:absolute;
  left:50%; top:50%;
  width:0; height:0;
  border-radius:50%;
  transform:translate(-50%,-50%);
  pointer-events:none;
  opacity:0;
  transition:opacity 1.4s ease 300ms;
}
body.is-ready .orbit-ring{opacity:1}
.orbit-ring--main{
  border:1px solid rgba(190,243,255,.3);
  box-shadow:0 0 28px rgba(157,236,245,.16), inset 0 0 28px rgba(157,236,245,.09);
}
.orbit-ring--inner{
  border:1px dashed rgba(190,243,255,.26);
}

/* center glass logo.
   Dipusatkan dengan inset:0 + margin:auto, BUKAN left/top 50% + translate(-50%,-50%).
   Alasannya: `transform` pada elemen ini dikuasai GSAP (animasi zoom saat masuk)
   dan ukurannya diubah JS saat orbit menyusut. Selama pemusatan ikut menumpang
   di `transform`, setiap kali transform itu tertimpa, kosong, atau tertinggal di
   ukuran lama, logo langsung melenceng tepat setengah ukurannya ke kanan-bawah.
   Dengan margin:auto, pemusatan ditangani model kotak dan SELALU mengikuti ukuran
   terkini — transform bebas dipakai murni untuk animasi skala. */
.center-logo{
  position:absolute;
  inset:0;
  margin:auto;
  transform:scale(.4);
  width:var(--logo-size);
  height:var(--logo-size);
  border-radius:50%;
  display:flex;
  align-items:center;
  justify-content:center;
  background:
    radial-gradient(circle at 32% 28%, rgba(255,255,255,.14), rgba(255,255,255,.02) 60%),
    var(--glass-bg);
  border:1px solid var(--glass-border);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
  /* Pendar disetel ke nuansa air; bayangan dalam memakai biru tua, BUKAN
     hitam — di latar tosca yang terang, hitam membuat lingkaran tampak keruh. */
  box-shadow:
    0 0 0 1px rgba(157,236,245,.22),
    0 0 60px rgba(31,195,206,.40),
    0 0 130px rgba(157,236,245,.26),
    inset 0 1px 0 rgba(255,255,255,.4),
    inset 0 -18px 42px rgba(4,42,71,.28);
  opacity:0;
  z-index:5;
}
.center-logo::before,
.center-logo::after{
  content:'';
  position:absolute;
  inset:-14px;
  border-radius:50%;
  border:1px solid rgba(157,236,245,.4);
  animation:pulseRing 3.6s ease-out infinite;
}
.center-logo::after{animation-delay:1.8s}
@keyframes pulseRing{
  0%{transform:scale(.88); opacity:.65}
  100%{transform:scale(1.18); opacity:0}
}
.center-logo img{
  width:64%;
  height:64%;
  object-fit:contain;
  filter:drop-shadow(0 4px 18px rgba(0,0,0,.35));
}

/* orbit — posisi kartu ditulis per-frame oleh orbit.js (jalur elips), sehingga
   kartu tegak lurus dengan sendirinya; tidak perlu counter-rotation. */
.orbit{
  position:absolute;
  inset:0;
  z-index:4;
}
/* Tinggi slot dibiarkan AUTO (mengikuti isi kartu), dan pemusatan dilakukan
   lewat translate(-50%,-50%) di dalam transform yang ditulis orbit.js — bukan
   negative-margin berbasis --card-h. Sebelumnya kartu tumbuh melebihi tinggi
   slot yang ditetapkan, sehingga hitungan jarak antar-orbit meleset dan kartu
   dua ring bisa bertabrakan walau perhitungannya "aman". */
.orbit-slot{
  position:absolute;
  left:50%; top:50%;
  width:var(--card-w);
  transform:translate(-50%,-50%);
  opacity:0;
  will-change:transform;
}

/* ---------------------------------------------------------
   MODUL — TANPA KARTU
   Yang tampil hanya IKON BESAR + nama modul di bawahnya. Blok itu sendiri
   yang menjadi tautan, jadi area kliknya justru lebih luas daripada tombol
   "Masuk" kecil yang dulu ada di dalam kartu.
--------------------------------------------------------- */
.module-card{
  position:relative;
  width:100%;
  min-height:var(--card-h);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:10px;
  padding:4px 2px;
  text-decoration:none;
  color:inherit;
  cursor:pointer;
  /* sengaja TANPA background, bingkai, blur, maupun bayangan kotak */
  background:none;
  border:0;
  transition:transform .35s cubic-bezier(.2,.9,.25,1);
}

.mc-icon{
  position:relative;
  width:var(--icon-size);
  height:var(--icon-size);
  display:grid;
  place-items:center;
  font-size:calc(var(--icon-size) * .82);
  line-height:1;
  /* bayangan & pendar menempel pada BENTUK ikon, bukan pada kotak */
  filter:
    drop-shadow(0 8px 16px rgba(3,32,54,.55))
    drop-shadow(0 0 20px rgba(91,217,230,.45));
  transition:transform .4s cubic-bezier(.2,.9,.25,1), filter .35s ease;
}
/* pendar air di belakang ikon saat disorot — bukan kartu, hanya cahaya */
.mc-icon::after{
  content:'';
  position:absolute; inset:-16%;
  border-radius:50%;
  background:radial-gradient(circle at 50% 50%, rgba(157,236,245,.26), transparent 68%);
  opacity:0;
  transition:opacity .35s ease;
  pointer-events:none;
  z-index:-1;
}

.mc-dot{
  position:absolute;
  right:0; top:4%;
  width:12px; height:12px;
  border-radius:50%;
  background:var(--green-500);
  box-shadow:0 0 0 2px rgba(4,42,71,.55), 0 0 12px rgba(46,224,138,.9);
  animation:statusPulse 2.2s ease-out infinite;
}
@keyframes statusPulse{
  0%{box-shadow:0 0 0 0 rgba(46,224,138,.6), 0 0 12px rgba(46,224,138,.9)}
  70%{box-shadow:0 0 0 9px rgba(46,224,138,0), 0 0 12px rgba(46,224,138,.9)}
  100%{box-shadow:0 0 0 0 rgba(46,224,138,0), 0 0 12px rgba(46,224,138,.9)}
}

.mc-title{
  font-family:var(--font-display);
  font-weight:600;
  font-size:14px;
  line-height:1.3;
  text-align:center;
  color:var(--ink-100);
  /* tanpa kartu, teks berdiri langsung di atas gradien — bayangan inilah
     yang menjaga keterbacaannya di bagian latar yang terang */
  text-shadow:0 2px 10px rgba(3,32,54,.85), 0 1px 3px rgba(3,32,54,.95);
  display:-webkit-box;
  -webkit-line-clamp:3;
  -webkit-box-orient:vertical;
  overflow:hidden;
}

.orbit-slot:hover .module-card,
.orbit-slot:focus-within .module-card{ transform:translateY(-6px); }
.orbit-slot:hover .mc-icon,
.orbit-slot:focus-within .mc-icon{
  transform:scale(1.16);
  filter:
    drop-shadow(0 10px 20px rgba(3,32,54,.6))
    drop-shadow(0 0 30px rgba(157,236,245,.85));
}
.orbit-slot:hover .mc-icon::after,
.orbit-slot:focus-within .mc-icon::after{opacity:1}
.orbit-slot:hover .mc-title,
.orbit-slot:focus-within .mc-title{color:#fff}

.module-card:focus-visible{
  outline:2px solid var(--aqua-300);
  outline-offset:6px;
  border-radius:14px;
}

/* keadaan memuat setelah diklik */
.module-card.is-loading .mc-icon{opacity:.4}
.module-card .spinner{
  display:none;
  position:absolute; left:50%; top:calc(var(--icon-size) / 2);
  width:28px; height:28px; margin:-14px 0 0 -14px;
  border-radius:50%;
  border:3px solid rgba(255,255,255,.32);
  border-top-color:#fff;
  animation:spin .7s linear infinite;
}
.module-card.is-loading .spinner{display:block}
@keyframes spin{to{transform:rotate(360deg)}}

/* status selain online */
.module-card.status-maint .mc-dot{background:#fbbf24; box-shadow:0 0 0 2px rgba(4,42,71,.55), 0 0 12px rgba(251,191,36,.9); animation:none}
.module-card.status-off .mc-dot{background:#f87171; box-shadow:0 0 0 2px rgba(4,42,71,.55), 0 0 10px rgba(248,113,113,.85); animation:none}
.module-card.status-off .mc-icon{opacity:.72; filter:grayscale(.65) drop-shadow(0 8px 16px rgba(3,32,54,.5))}

.mc-ripple{
  position:absolute;
  border-radius:50%;
  background:radial-gradient(circle, rgba(255,255,255,.55), rgba(157,236,245,.25) 60%, transparent 72%);
  transform:scale(0);
  animation:mcRipple .6s ease-out forwards;
  pointer-events:none;
}
@keyframes mcRipple{to{transform:scale(1); opacity:0}}

/* ---------------------------------------------------------
   FOOTER
--------------------------------------------------------- */
.site-footer{
  position:relative;
  z-index:20;
  text-align:center;
  padding:22px 16px 26px;
  /* TINTA GELAP, bukan terang. Footer duduk di ~92% tinggi layar, tepat di
     ujung gradien yang paling terang (tosca muda). Dengan warna terang warisan
     tema gelap, kontrasnya hanya 1,15 — praktis tak terbaca. Warna gelap ini
     terukur 6,5 di latar yang sama. */
  color:rgba(4,42,71,.84);
  font-size:12px;
  line-height:1.8;
  opacity:0;
}
.site-footer strong{color:#042A47; font-weight:700}
.site-footer .ver{
  display:inline-block;
  margin-top:2px;
  font-size:11px;
  letter-spacing:.3px;
  font-weight:600;
  color:#064566;
}

/* ---------------------------------------------------------
   RESPONSIVE
   Orbit (10 kartu) butuh ruang lebar untuk tetap terbaca, jadi ambang
   orbit->grid kini 1280px. Riwayatnya: 640px (versi 4 modul) → 1024px
   (versi 9 modul) → 1280px (versi 10 modul, karena di 1024 semua judul
   terpotong dan tombol tinggal 20px). Perangkat SENTUH selalu grid
   berapa pun lebarnya — lihat `(pointer: fine)` di orbit.js.
--------------------------------------------------------- */
/* Ukuran penuh hanya untuk layar besar. Di bawahnya kartu & logo mengecil
   bertahap — bukan sekadar demi estetika: radius orbit dihitung dari sisa
   ruang setelah dikurangi ukuran kartu, jadi kartu yang terlalu besar di
   layar sedang justru MENYEMPITKAN orbit sampai audit geometri gagal dan
   tampilan turun ke grid. Nilai di bawah sudah diuji lolos audit. */
@media (max-width:1599px) and (min-width:1280px){
  :root{ --card-w:170px; --card-h:138px; --icon-size:74px; --logo-size:180px; }
  .mc-title{font-size:13px}
}
/* 1024-1279px kini SELALU mode grid (bukan orbit lagi). Nilai di sini hanya
   memengaruhi ukuran logo & ikon di tampilan grid. */
@media (max-width:1279px) and (min-width:1024px){
  :root{ --icon-size:68px; --logo-size:158px; }
  .mc-title{font-size:13px}
}

/* MODE GRID — berlaku di LEBAR BERAPA PUN, bukan hanya layar kecil.
   orbit.js bisa menyalakan .is-grid di layar lebar juga (kalau audit geometri
   menyatakan kartu bakal bertabrakan), jadi aturan grid ini TIDAK BOLEH
   dikurung di dalam media query layar kecil — dulu begitu, akibatnya di
   jendela yang gagal audit semua kartu menumpuk di tengah menutupi logo. */
.orbit.is-grid{
  position:relative;
  inset:auto;
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:14px;
  padding:0 2px;
  width:100%;
}
.orbit.is-grid .orbit-slot{
  position:relative;
  left:auto; top:auto;
  width:auto; height:auto;
  margin:0;
  transform:none !important;
}
.orbit.is-grid .module-card{min-height:0; padding:14px 6px; gap:12px}
/* Di mode grid kartunya lebih tinggi dan ruangnya menganggur, jadi judul
   panjang tidak perlu dipangkas jadi 2 baris seperti di orbit. */
.orbit.is-grid .mc-title{
  -webkit-line-clamp:3;
  min-height:calc(1.26em * 3);
}
/* Saat grid aktif, sistem orbit berhenti jadi panggung melingkar: logo naik
   ke atas sebagai judul, cincin panduan disembunyikan, tinggi mengikuti isi. */
.orbit-system:has(.orbit.is-grid),
body.grid-mode .orbit-system{
  display:block;
  height:auto;
  max-height:none;
}
.orbit-system:has(.orbit.is-grid) .orbit-ring,
body.grid-mode .orbit-ring{display:none}
.orbit-system:has(.orbit.is-grid) .center-logo,
body.grid-mode .center-logo{
  position:relative;
  inset:auto;
  transform:none;
  margin:0 auto 28px;
}
/* Lihat catatan di markGridMode() (orbit.js): memutus lingkaran
   scrollbar-muncul → layout-ulang → scrollbar-hilang → berulang. */
body.orbit-mode{ overflow-y:hidden; }

.hero:has(.orbit.is-grid),
body.grid-mode .hero{
  flex:0 0 auto;
  min-height:0;
  align-items:flex-start;
}

/* TABLET + MOBILE: selalu grid (orbit tidak pernah dicoba di bawah 1280px) */
@media (max-width:1279px){
  :root{ --logo-size:140px; }
  .hero{flex:0 0 auto; min-height:0; padding:20px 16px 6px}
  .orbit-system{
    width:100%; height:auto; max-height:none;
    display:block;
  }
  .orbit-ring{display:none}
  .center-logo{
    position:relative;
    inset:auto;
    transform:none;
    margin:0 auto 28px;
  }
  .orbit{position:relative; inset:auto}
  .mc-title{font-size:12.5px}
  .site-header .h-title{font-size:13px}
}
@media (max-width:640px){
  .site-header{padding:14px 16px; gap:10px}
  .site-header .h-title{font-size:12.5px}
  .site-header .h-sub{font-size:10.5px}
}
@media (max-width:479px){
  .orbit.is-grid{grid-template-columns:repeat(2, 1fr)}
  .mc-title{font-size:12px}
}

/* ---------------------------------------------------------
   REDUCED MOTION
--------------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  .glow-blob, .ripple, .droplet, .center-logo::before, .center-logo::after, .mc-dot{
    animation:none !important;
  }
  .module-card, .mc-icon{transition:none !important}
}
body.reduce-motion .orbit{animation:none !important}
