# DOCUMENTATION — Kontur v1.0.0

Arsitektur, alur data, dan API konfigurasi.

## 1. Arsitektur

Framework-free, dua file JS yang dimuat berurutan di bawah `<body>`:

```
index.html
 ├── assets/css/style.css   ← design token + komponen (urutan: reset → token → base → layout → komponen → responsive)
 ├── assets/js/config.js    ← deklarasi objek global KONTUR (data murni, tanpa perilaku)
 └── assets/js/main.js      ← IIFE "use strict" (perilaku, tanpa data)
```

Prinsip pemisahan: **config.js tahu *apa*, main.js tahu *bagaimana*.**
Menambah fitur tidak boleh menambah field yang di-hardcode di main.js.

## 2. Alur render

1. HTML sudah berisi konten default (statistik, teks fallback) → halaman tetap valid tanpa JS.
2. `config.js` membuat `window.KONTUR`.
3. `main.js` membaca preferensi tersimpan (`localStorage` key `kontur:prefs`)
   → menerapkan tema → menerapkan niche → mengisi elemen `[data-cfg="…"]`
   → memasang event listener.

### Kontrak `data-cfg`

Setiap elemen dengan atribut `data-cfg="<key>"` akan diganti `textContent`-nya
dari `KONTUR.niches[<niche>].copy[<key>]`, atau dari properti root
(`brand`, `footerTag`, `navCta`). Key yang tidak ada di config dibiarkan apa adanya.

## 3. API konfigurasi (`assets/js/config.js`)

```js
KONTUR = {
  brand: string,                 // nama brand (default "Kontur")
  footerTag: string,             // tagline footer
  navCta: string,                // label tombol CTA di header
  defaultNiche: 'saas'|'studio'|'commerce',
  defaultTheme: 'auto'|'light'|'dark',
  niches: {
    <nama>: {
      label: string,
      colors: {
        accent: string,          // warna aksen (CSS color)
        accentHover: string,
        accentSoft: string,      // transparan, untuk hover/active
        onAccent: string         // teks di atas aksen
      },
      copy: { [dataCfgKey]: string }
    }
  }
}
```

### Menambah niche baru

Tambahkan entry di `KONTUR.niches`, lalu tombolnya di HTML:

```html
<button type="button" class="chip" data-niche-btn="fintech">Fintech</button>
```

`main.js` mengikat semua `[data-niche-btn]` secara otomatis — tidak ada perubahan JS.

## 4. Tema (light/dark)

- `html[data-theme="light|dark"]` mengganti seluruh token warna di `:root` / `[data-theme="dark"]`.
- `defaultTheme: 'auto'` mengikuti `prefers-color-scheme`; perubahan sistem diikuti live.
- Preferensi niche + theme disimpan sebagai JSON di `localStorage["kontur:prefs"]`
  di dalam `try/catch` (aman di private mode).
- Niche menulis variabel via `element.style.setProperty`, sehingga menang atas CSS
  tapi tetap di-reset saat niche diganti.

## 5. State UI (main.js)

| Modul | Mekanisme | State |
|---|---|---|
| Mobile nav | class `.is-open` + `aria-expanded` | tutup saat klik link / `Esc` |
| Theme toggle | `data-theme` + `aria-pressed` | `localStorage` |
| Niche switch | `data-niche` + class `.is-active` | `localStorage` |
| Pricing toggle | `aria-checked`, ganti `data-monthly`/`data-yearly` | sesi saja |
| FAQ | native `<details>` — hanya satu `open` sekaligus | — |
| Reveal scroll | `IntersectionObserver` sekali jalan | — |
| Form demo | validasi regex, `.is-ok` / `.is-error` | tidak mengirim apa pun |

## 6. Aksesibilitas

- Landmark: `header`, `nav` (label unik), `main`, `footer`.
- Skip link ke `#main`.
- Semua kontrol interaktif: `button` + `aria-*`, bukan `div` klik.
- `:focus-visible` outline 3px warna aksen.
- `prefers-reduced-motion`: animasi & reveal dimatikan.
- Kontras teks body ≥ 4.5:1 pada kedua theme.

## 7. Performa

- Tanpa font eksternal, tanpa framework, tanpa gambar hero (grid CSS murni).
- JS defer-free tapi di akhir body; total ≤ 12 KB uncompressed.
- `scroll` listener memakai `{ passive: true }`.
- Marquee & transisi memakai `transform` (GPU-friendly).

## 8. Troubleshooting

| Gejala | Penyebab | Solusi |
|---|---|---|
| Niche tidak berganti | typo key `data-cfg` | cocokkan dengan key di `config.js` |
| Warna tidak berubah | `data-niche` belum ada | `main.js` mengatur otomatis; pastikan `config.js` dimuat duluan |
| Form tidak muncul pesan | `#formMsg` hilang | kembalikan elemen `p.form-msg` |
| Teks config tidak terpakai | JS error di console | cek urutan load `config.js` → `main.js` |
