/* Self-hosted Inter (variable 300-700, subset latin) - satu-satunya font, dipakai
   body & heading (Playfair dicoba lalu dibuang - kerasa lebay). Nggak request ke
   Google. Ganti/rename -> update preload di semua HTML. font-display: swap. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("assets/fonts/inter-latin.woff2") format("woff2");
}

:root {
  --color-green: #5c5c5c;
  --color-gold: #22201c;
  --color-gold-d: #16140f;
  /* Primary button color (Sep 2026, Wayan opsi B) - terpisah dari --color-gold
     dengan sengaja: gold/soft-black masih dipakai buat aksen lain (judul section,
     divider, nav, state aktif), hijau ini KHUSUS tombol aksi utama biar lebih
     "manggil mata" tanpa nyampur peran sama warna lain. */
  --color-cta: #3d5c46;
  --color-cta-d: #2f4737;
  /* Gold BENERAN (Sep 2026, Wayan) - dipisah dari --color-gold (yang sekarang soft-black,
     bukan gold literal) buat elemen yang gold-nya punya makna konvensi visual, bukan
     cuma aksen: bintang rating, harga, badge "Popular"/featured. Selain 3 itu TETAP
     --color-gold (soft-black) - jangan ikut disamain kalau nemu lagi. */
  --color-amber: #c9a45c;
  --color-amber-d: #b08d43;
  --color-cream: #f8f8f8;
  --line: #e7e4dd;
  --font-body: "Inter", system-ui, sans-serif;
  /* Satu font: Inter buat body & heading (Playfair udah dibuang). */
  --font-head: "Inter", system-ui, sans-serif;
  /* ---- Type scale (DRY): base 16px, ratio 1.25 -> 16/20/25/31/39 ----
     Display/h2 sengaja diturunin dari step formal (31-39 / 25) - lebih kecil
     & bobot lebih ringan kerasa lebih tenang buat heading sans satu font. */
  --fs-display: clamp(1.75rem, 4vw, 2.5rem);
  --fs-h2: 1.125rem; /* was 1.375rem - Wayan, trim step B */
  --fs-h3: 0.875rem; /* was 1rem - Wayan, samain sama --fs-strong */
  --fs-strong: 0.875rem; /* was 1rem - Wayan, samain sama --fs-h3 */
  --fs-body: 0.8rem; /* Sep 2026, Wayan: semua teks paragraf/deskripsi/label/meta
    dikecilin ke 0.8rem - H1/H2/H3, harga, dan tombol TIDAK ikut (masing-masing
    unhooked ke nilai eksplisit sendiri biar gak ke-drag token ini). */
  --fs-field: 0.8rem; /* was 0.875rem - Wayan, samain sama --fs-body/--fs-small */
  --fs-small: 0.8rem;
  --fs-label: 0.64rem;
  --lh-body: 1.6;
  --lh-heading: 1.15;
  /* ---- Spacing scale (8px base): 8/16/24/32/48/64 ---- */
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2rem;
  --space-5: 3rem;
  --space-6: 4rem;
  /* Jarak vertikal seragam antar-section homepage (Sep 2026, Wayan): 36px.
     Sengaja di antara space-4 (32) & space-5 (48) - dipakai sbg MARGIN gap. */
  --section-gap: 2.25rem;
  /* ---- Container widths (Agu 2026, Wayan): 4 tingkat resmi biar margin kiri/kanan
     antar-halaman selaras. Tiap halaman WAJIB pilih salah satu, jangan bikin lebar
     baru. `--container` wide (listing/homepage/guide hub) · `--container-mid` halaman
     konten tengah (contact/about/faq/charter) · `--container-read` kolom baca sempit
     (legal/artikel guide) - sengaja lebih sempit demi panjang baris yang enak dibaca.
     Booking detail (`.tour-layout--book`, ~1280px) layout khusus, TIDAK ikut token ini.
     `--container-x` = padding kiri/kanan seragam (juga jaga jarak tepi di tablet). */
  --container: 1200px;
  --container-mid: 1080px;
  --container-read: 720px;
  --container-x: var(--space-3);
  /* ---- Border radius scale (Agu 2026, Wayan): 5 tingkat resmi biar sudut konsisten.
     Dulu berserakan 5/6/7/8/9/10/11/12/13/14/16/20/22px - hasil nambah komponen dari
     waktu ke waktu, beda tipis gak kebedaan di mata. Semua di-snap ke tangga terdekat
     (geser maks ~2px). YANG DIBIARIN: `50%` (bulat/avatar), `2px`/`3px` (bar tipis mis.
     underline judul - sengaja kecil, jangan ikut dibulatin), `0` (no-radius eksplisit). */
  --r-sm: 8px;   /* chip, tag, pay-chip, field kecil, kalender */
  --r-md: 12px;  /* field, kartu kecil, faq item, modal box, booking card */
  --r-lg: 16px;  /* kartu (experience/review/driver), panel, container kartu */
  --r-xl: 22px;  /* modal besar, hero card, box charter, sudut atas sheet */
  --r-pill: 999px; /* tombol, chip pill, toggle */
  /* ---- Shadow scale (Agu 2026, Wayan minta subtle): 4 tingkat elevasi neutral +
     focus-ring. Sengaja HALUS (opacity rendah) - kartu "nempel halus" ke background,
     bukan ngambang berat. DIBIARIN (jangan di-merge, itu disengaja): bayangan green-tint
     `rgba(31,61,43,x)` (kehangatan brand: booksidebar, driver hover, navbar), directional/
     offset-negatif (trip-bar, panel akun geser, book-bar - nyorot ke atas/samping), animasi
     glow booksidebar, focus-ring error merah, hairline `0 0 0 1px`. */
  /* NO ELEVATION SHADOWS, WITH EXACTLY ONE EXCEPTION: --shadow-card (27 Sep 2026).
     Earlier that day every shadow came out (Wayan: "hilangin shadow di semua web
     gaada lagi shadow di bawah navbar, di bawah card") and --shadow-sm/md/lg/xl were
     DELETED, not set to none - a token set to none leaves dozens of shadow-md classes
     reading like they do something. 53 usages went in that commit.

     Then the listing card turned out to have had no OTHER boundary. Measured: #fff
     card on a #fff section on a #fff body, border 0px none - so it stopped being
     visible as a card at all, and its 16px radius had nothing to round. Asked whether
     he wanted a hairline border or a shadow back, Wayan picked the shadow: "pakai
     shadow aja dah bro, tapi setipis mungkin ya". So this one token exists and no
     other does.

     The value is MEASURED, not taste - darkest pixel just below the card edge against
     the page white, at 1280: none = 0 (literally invisible), .06 = 10, .09 = 15,
     .12 = 18. .09 is the thinnest that still reads as a card. Want it thinner again:
     change this one number, it is the only definition.

     Used by exactly three card families, so listing / homepage / guide cards cannot
     drift apart: CARD in ListingRow, CARD_FRAME in cardClasses, FRAME in HomepageCard.
     ReviewCard is deliberately NOT one of them - it already carries border-line and
     reads as a card without help; giving it both would be the only doubled edge on
     the site.

     Everything else still drawn with box-shadow, because none of it is elevation:
     --focus-ring below (keyboard focus - accessibility, not decoration), the
     invalid-field ring in formClasses.js, the charter row inset 1px (a border), three
     flag hairlines (0 offset / 0 blur / 1px spread), and the hero slider dot halo
     (0 0 2px, keeps a white dot readable on a bright photo).

     Guarded by verify-noshadow.mjs: no computed box-shadow anywhere may carry a real
     offset or blur EXCEPT this one, AND the card shadow must still be THERE. That
     second half matters - a sweep quietly deleting it is exactly how the cards went
     invisible the first time, with every gate green. Re-adding any other shadow is a
     decision, not a stray class. */
  --shadow-card: 0 1px 2px rgba(34, 32, 28, 0.09);
  --focus-ring: 0 0 0 3px rgba(34, 32, 28, 0.18);
  /* ---- Motion (Agu 2026): durasi transisi + easing dipusatin biar animasi satu ritme.
     Cuma buat `transition:` (feedback interaksi: hover/focus/state). DIBIARIN: durasi
     `animation:` entrance (0.4-0.6s, choreography sengaja), fade lambat 0.5s, dan special
     (marquee 35s, glow booksidebar 2-3s). Keyword `ease` juga dibiarin (udah konsisten). */
  --dur-fast: 0.15s; /* hover kecil, state cepet */
  --dur: 0.2s;       /* default transisi */
  --dur-slow: 0.3s;  /* transform lebih gede */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);      /* standar (material) */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* entrance (expo-out), buat masuk halus */
  /* ---- Icon size (Agu 2026): ikon kecil inline dulu berserakan 13-23px (diketik manual
     per komponen), di-snap ke 3 tingkat (geser maks ~3px). DIBIARIN: ikon besar 30-56px
     (avatar, lingkaran step, ikon sukses centang) - itu beda peran, bukan ikon inline. */
  --icon-sm: 16px; /* ikon meta (jam/lokasi/pax), kontak, chip, sosmed */
  --icon-md: 20px; /* nav cart/akun, book-bar, toggle, search */
  --icon-lg: 24px; /* ikon aksi lebih besar */
  /* ---- Form control height (Agu 2026): tinggi field/select standar biar semua form
     seragam (dulu contact 33px vs booking/charter 46px). Varian compact 2.7rem (itinerary
     builder, hero mobile) sengaja lebih pendek, dibiarin. */
  --field-h: 2.1rem; /* ~33px - form dikecilin nyesuain body text 0.8rem (Wayan) */
  /* ---- Button height (Sep 2026, Wayan pilih "A" = SEMUA tombol aksi satu ukuran
     kecil). Nilainya sama dengan --field-h hari ini, TAPI sengaja token sendiri:
     kalau tinggi field diubah lagi, tombol gak ikut kegeser diam-diam.
     Ini NGE-OVERRIDE catatan lama "CTA sengaja 2.9rem, boleh lebih tinggi dari
     field" - Wayan ngeliat hasil ukurnya dulu (67 tombol di halaman build asli,
     nol halaman melar, dokumen malah memendek) baru mutusin. */
  --btn-h: 2.1rem; /* 33.6px */
  /* ---- DRY tokens (nilai sama, dipusatin) ---- */
  --color-muted: #7a7466;
  --color-gold-l: #cfc9ba; /* kicker/label di atas foto gelap — tetap terang (bukan hitam), biar kebaca */
  --color-ok: #2e7d54; /* status sukses/booked */
  --color-err: #9a4a3f; /* error/warning/hapus */
  --color-ink: #46453f;
  --gold-edge: linear-gradient(150deg, var(--color-gold), rgba(34, 32, 28, 0.25));
}

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

html {
  scroll-behavior: smooth;
  /* clip (bukan hidden) biar nyegah scroll horizontal TAPI position:sticky tetap jalan */
  overflow-x: clip;
  /* No visible scroll-button/track chrome anywhere on the site (Sep 2026, Wayan):
     page still scrolls exactly the same via wheel/touch/keyboard, only the browser's
     own scrollbar UI is hidden. Same pattern already used on cards/modals/panels. */
  scrollbar-width: none;
}
html::-webkit-scrollbar {
  display: none;
}

body {
  font-family: var(--font-body);
  color: var(--color-green);
  background-color: #fff;
  overflow-x: clip;
}

/* ===== Animation keyframes (referenced by Tailwind animate-[name...] in components) ===== */
@keyframes navbarIn {
  from { opacity: 0; }
}
@keyframes heroTextIn {
  from { opacity: 0; transform: translateY(16px); }
}
@keyframes heroCardIn {
  from { opacity: 0; transform: translateY(14px); }
}
@keyframes bookcardNoteIn {
  from { opacity: 0; transform: translateY(-2px); }
  to { opacity: 1; transform: none; }
}
@keyframes guestScroll {
  to { transform: translateX(-50%); }
}
@keyframes heroFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
/* Modal/popup card entrance (Sep 2026 - Wayan: no popup should just snap into view).
   Mirrors Modal.jsx's own transition values (translateY(14px) scale(0.96) -> normal)
   so every modal/confirm-dialog that mounts fresh (SHELL/BOX in modalClasses.js) gets
   the same soft pop-in via `animate-[popCardIn_...]` instead of a CSS transition
   (transitions don't fire on first mount - a keyframe animation does). */
@keyframes popCardIn {
  from { opacity: 0; transform: translateY(14px) scale(0.96); }
  to { opacity: 1; transform: none; }
}

/* The chat's "Wayan is typing" dots. A keyframe rather than a transition because
   there is no state change to transition FROM - the row appears already running,
   and it is the only thing on screen telling the guest this is live. Opacity
   only, so it does not move anything. */
@keyframes chatdot {
  0%, 80%, 100% { opacity: 0.3; }
  40% { opacity: 1; }
}

/* Cahyana coin: one full roll, then rests (about 4s) before the next.
   Decoration, not feedback, so it is a keyframe; motion-reduce:animate-none stops it. */
@keyframes coinRoll {
  0% { transform: rotate(0deg); }
  30%, 100% { transform: rotate(360deg); }
}

/* Homepage Coin Rewards strip: a metal shine sweeps the still coin (1.5s), then rests (1.5s), every 3s.
   Off the motion scale on purpose (Wayan, 13 Oct 2026); motion-reduce removes it (CoinBand.jsx). */
@keyframes coinShine {
  0% { left: -60%; }
  50%, 100% { left: 130%; }
}

/* Homepage Coin Rewards strip: a metal shine sweeps the still coin (1.5s), then rests (1.5s), every 3s.
   Off the motion scale on purpose (Wayan, 13 Oct 2026); motion-reduce removes it (CoinBand.jsx). */
@keyframes coinShine {
  0% { left: -60%; }
  50%, 100% { left: 130%; }
}


/* ===== Global element / behaviour rules (the "reset" half of this file) ===== */
/* Scroll-lock toggled by JS while a bottom-sheet / dropdown is open (overflow:hidden
   only - NOT position:fixed, which makes the page jump). Both <html> AND <body> get
   the class (useBodyLock.js): desktop/Chrome scroll via <body>, but iOS Safari very
   often scrolls via <html> instead - body-only left the page scrollable under every
   popup on iPhone (Wayan, Sep 2026). */
html.hs-locked,
body.hs-locked {
  overflow: hidden;
}
/* Mobile: hold all form controls at --fs-field so no field creeps back up to a
   bigger size on phones than it has on desktop.
   NOTE: this rule used to claim it stopped iOS auto-zoom on focus. It does the
   opposite - iOS zooms when a focused control computes UNDER 16px, and --fs-field
   is 12.8px, so this guarantees the zoom instead of preventing it. The zoom is
   handled at the viewport instead (iOS-only maximum-scale clamp in app/layout.jsx),
   because Wayan wants the 12.8px text kept. Do not "fix" this by raising the font
   here - that changes the look of every form on the site. */
@media (max-width: 992px) {
  input,
  select,
  textarea {
    font-size: var(--fs-field) !important;
  }
}
/* Inline bold (b/strong) capped at 600 to match the type scale. */
b,
strong {
  font-weight: 600;
}

/* HP = gutter 16px (Sep 2026, Wayan: "samain 16px semua biar rapi"). Slider full-bleed
   nge-inset kartu pertamanya 1rem, jadi kalau container-nya tetep 24px judul section
   dan kartu pertama gak lurus - ini yang bikin kerasa berantakan. Breakpoint-nya 992px
   BIAR SAMA persis sama band-nya BLEED_MOBILE; kalau dipasang di 768 nanti di 769-992
   mismatch-nya balik lagi. Desktop tetep 1.5rem. */
@media (max-width: 992px) {
  :root { --container-x: 1rem; }
}

/* Japanese pages: Inter has no Japanese glyphs, so they fall back to the device's own Japanese font (brief #19). */
html[lang="ja"] {
  --font-body: "Inter", "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Yu Gothic", "YuGothic", "Meiryo", "Noto Sans JP", "Noto Sans CJK JP", system-ui, sans-serif;
  --font-head: "Inter", "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Yu Gothic", "YuGothic", "Meiryo", "Noto Sans JP", "Noto Sans CJK JP", system-ui, sans-serif;
}

/* Simplified Chinese pages: Inter has no Chinese glyphs either, so they fall back to the device's own Simplified Chinese font. */
html[lang="zh-Hans"] {
  --font-body: "Inter", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", "Noto Sans CJK SC", system-ui, sans-serif;
  --font-head: "Inter", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", "Noto Sans CJK SC", system-ui, sans-serif;
}

/* Korean pages: Inter has no Hangul, so they fall back to the device's own Korean font. */
html[lang="ko"] {
  --font-body: "Inter", "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", "Noto Sans CJK KR", system-ui, sans-serif;
  --font-head: "Inter", "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", "Noto Sans CJK KR", system-ui, sans-serif;
}
