Bagian terakhir menguji klaim terbesar dari arsitektur token kita: bila seluruh komponen hanya merujuk token semantik, maka seluruh tema — bukan hanya satu komponen — dapat berganti dengan menimpa beberapa deklarasi di satu blok. Kita menambahkan tema gelap [data-theme="gelap"], lalu menata komponen dokumentasi: grid swatch untuk memajang warna token dan blok kode untuk contoh penggunaan. Dokumentasi adalah konsumen terbesar sebuah library; kalau dokumentasinya rapi, pustaka itu terasa selesai.

Tujuan Bagian dan Prasyarat #

Target bagian ini pada styles/komponen.css:

  • Blok [data-theme="gelap"] yang menimpa tujuh token semantik: latar, permukaan, teks, teks redup, garis, primer lunak, dan bayangan.
  • .tema-sampel: wadah pratinjau yang membaca --color-bg sehingga warnanya mengikuti tema apa pun di sekitarnya.
  • Komponen dokumentasi: .docs-grid, .swatch, .swatch-nama, dan .contoh-kode.

Materi pendukungnya adalah Dark Mode , Theme Switching Overview , dan Prefers Color Scheme ; cara menyusun pustaka agar layak dipakai ulang diulas pada Reusable Design System . Kita hanya memakai pola override token yang sudah lazim dibahas di sana.

Override Token untuk Tema Gelap #

Tulis blok berikut di ujung styles/komponen.css. Selector atribut [data-theme="gelap"] dapat dipasang di elemen apa pun: di <html> untuk seluruh halaman, atau di satu wadah untuk pratinjau terisolasi.

css styles/komponen.css — Bagian 4 (tema)
[data-theme="gelap"] {
  --color-bg: #18181b;
  --color-surface: #27272a;
  --color-text: #fafafa;
  --color-muted: #a1a1aa;
  --color-border: #3f3f46;
  --color-primary-soft: rgb(20 184 166 / 16%);
  --shadow-md: 0 4px 12px rgb(0 0 0 / 40%);
}

.tema-sampel {
  padding: var(--space-6);
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

Dua deklarasi berbeda tema hidup berdampingan dalam satu halaman:

html index.html — dua tema berdampingan
<article class="card kartu-terang">
  <div class="card-badan">
    <h3 class="card-judul">Kartu di tema terang</h3>
  </div>
</article>

<div class="tema-sampel" data-theme="gelap">
  <span class="badge">Mode Gelap</span>
  <article class="card kartu-gelap">
    <div class="card-badan">
      <h3 class="card-judul">Kartu di tema gelap</h3>
      <p class="card-teks">Komponen tidak berubah satu baris pun.</p>
    </div>
  </article>
  <button class="btn btn-kedua btn-kecil">
    <img src="assets/ikon-tema.svg" width="16" height="16" alt="">
    Ganti Tema
  </button>
</div>

Hasil di Browser:

text
Di luar wadah, kartu tetap berlatar rgb(255, 255, 255) dengan
border rgb(228, 228, 231). Di dalam wadah data-theme="gelap",
latar wadah menjadi rgb(24, 24, 27) dengan border rgb(63, 63, 70),
kartu berganti ke rgb(39, 39, 42), teks redup menjadi
rgb(161, 161, 170), dan badge berlatar rgba(20, 184, 166, 0.16).

Komponen Halaman Dokumentasi #

Dua komponen terakhir menyajikan token kepada pembaca dokumentasi:

css styles/komponen.css — Bagian 4 (dokumentasi)
.docs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.swatch {
  display: block;
  width: 64px;
  height: 40px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.swatch-nama {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-muted);
}

.contoh-kode {
  padding: var(--space-3) var(--space-4);
  background-color: var(--zinc-900);
  color: var(--zinc-200);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  border-radius: var(--radius-md);
  overflow-x: auto;
}
html index.html — swatch dan blok kode
<div class="docs-grid">
  <div>
    <span class="swatch" style="background-color: var(--color-primary)"></span>
    <span class="swatch-nama">--color-primary</span>
  </div>
  <div>
    <span class="swatch" style="background-color: var(--color-surface)"></span>
    <span class="swatch-nama">--color-surface</span>
  </div>
</div>

<pre class="contoh-kode"><code>.btn-primer {
  background-color: var(--color-primary);
}</code></pre>

Bedah Mekanisme Tema #

  1. Override, bukan komponen baru: blok [data-theme="gelap"] hanya mendeklarasikan ulang token semantik. Karena custom property diwariskan ke seluruh keturunan, setiap komponen di dalam wadah membaca nilai baru saat berikutnya dihitung ulang — tidak ada satu pun aturan .btn atau .card yang disentuh.
  2. --color-primary-soft ikut ditimpa: alpha 10% yang enak di permukaan putih menjadi terlalu tipis di atas permukaan gelap, sehingga tema gelap menaikkannya ke 16%. Ini contoh nyata bahwa token semantik menyembunyikan keputusan desain, bukan sekadar alias warna.
  3. Primitif tidak ditimpa: .contoh-kode sengaja memakai --zinc-900 dan --zinc-200, sehingga blok kode tetap gelap di kedua tema. Praktik ini menunjukkan kapan memakai primitif secara langsung adalah pilihan yang benar.
  4. Tema otomatis mengikuti sistem: untuk pengguna yang memilih mode gelap di sistem operasinya, cukup duplikasi token di dalam media query — tanpa menyentuh komponen:
css opsional: tema otomatis via media query
@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #18181b;
    --color-surface: #27272a;
  }
}

Uji Bagian Ini #

Halaman uji bagian ini tersedia di /tests/css/proyek/component-library/themes-dan-documentation.html , dengan spesifikasi lengkap pada tests/themes-dan-documentation.spec.js:

ElemenPropertiDiharapkan
bodybackground-colorrgb(250, 250, 250)
.kartu-terangbackground-colorrgb(255, 255, 255)
.tema-sampelbackground-colorrgb(24, 24, 27)
.tema-sampelborder-top-colorrgb(63, 63, 70)
.kartu-gelapbackground-colorrgb(39, 39, 42)
.teks-gelapcolorrgb(161, 161, 170)
.badge-gelap--color-surface#27272a
.badge-gelapbackground-colorrgba(20, 184, 166, 0.16)
.swatchwidth64px
.swatchheight40px
.contoh-kodebackground-colorrgb(24, 24, 27)
.contoh-kodefont-size14px

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

styles/komponen.css

Unduh berkas
css
/* =========================================================
   Proyek: Component Library (Rakit UI) — styles/komponen.css
   File utuh library yang berkembang mengikuti empat bagian:
   Bagian 1 (Design Tokens), Bagian 2 (Buttons dan Inputs),
   Bagian 3 (Cards dan Navigation), Bagian 4 (Themes dan
   Documentation). Komentar "Bagian N" menandai kelompok
   aturan yang dibahas pada setiap bagian.
   ========================================================= */

/* Bagian 1: Design Tokens --------------------------------- */

:root {
  /* Token primitif: skala netral zinc */
  --zinc-50: #fafafa;
  --zinc-100: #f4f4f5;
  --zinc-200: #e4e4e7;
  --zinc-400: #a1a1aa;
  --zinc-500: #71717a;
  --zinc-600: #52525b;
  --zinc-700: #3f3f46;
  --zinc-800: #27272a;
  --zinc-900: #18181b;

  /* Token primitif: skala teal untuk warna primer */
  --teal-500: #14b8a6;
  --teal-600: #0d9488;
  --teal-700: #0f766e;

  /* Token primitif: warna status */
  --hijau-600: #16a34a;
  --merah-600: #dc2626;

  /* Token semantik: peran, bukan warna */
  --color-bg: #fafafa;
  --color-surface: #ffffff;
  --color-text: #18181b;
  --color-muted: #52525b;
  --color-border: #e4e4e7;
  --color-primary: #0d9488;
  --color-primary-hover: #0f766e;
  --color-on-primary: #ffffff;
  --color-primary-soft: rgb(13 148 136 / 10%);
  --color-success: #16a34a;
  --color-danger: #dc2626;

  /* Skala spasi (kelipatan 4px) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  /* Radius */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-full: 999px;

  /* Bayangan */
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 6%);
  --shadow-md: 0 4px 12px rgb(0 0 0 / 10%);

  /* Tipografi */
  --font-sans: system-ui, sans-serif;
  --font-mono: ui-monospace, monospace;
  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 16px;
  --text-lg: 20px;
  --text-xl: 24px;
}

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

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--color-text);
  background-color: var(--color-bg);
}

.wadah {
  max-width: 960px;
  margin: 0 auto;
  padding: var(--space-6);
}

.badge {
  display: inline-flex;
  align-items: center;
  column-gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-full);
  background-color: var(--color-primary-soft);
  color: var(--color-primary);
  font-size: var(--text-sm);
  font-weight: 500;
}

/* Bagian 2: Buttons dan Inputs ---------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  column-gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 500;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  transition: background-color 150ms ease, border-color 150ms ease,
    color 150ms ease;
}

.btn-primer {
  background-color: var(--color-primary);
  color: var(--color-on-primary);
}

.btn-primer:hover {
  background-color: var(--color-primary-hover);
}

.btn-kedua {
  background-color: var(--color-surface);
  color: var(--color-text);
  border-color: var(--color-border);
}

.btn-hantu {
  background-color: transparent;
  color: var(--color-primary);
}

.btn-kecil {
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
}

.btn-besar {
  padding: var(--space-3) var(--space-6);
  font-size: var(--text-lg);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.field {
  display: grid;
  row-gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.label {
  font-size: var(--text-sm);
  font-weight: 500;
}

.input {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  font: inherit;
  color: var(--color-text);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.input:focus {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-color: var(--color-primary);
}

.input:disabled {
  background-color: var(--color-bg);
  color: var(--color-muted);
  cursor: not-allowed;
}

.input-sukses {
  border-color: var(--color-success);
}

.input-galat {
  border-color: var(--color-danger);
}

.hint {
  font-size: var(--text-xs);
  color: var(--color-muted);
}

.hint-galat {
  color: var(--color-danger);
}

/* Bagian 3: Cards dan Navigation -------------------------- */

.navbar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  column-gap: var(--space-4);
  padding: var(--space-3) var(--space-6);
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.nav-brand {
  display: inline-flex;
  align-items: center;
  column-gap: var(--space-2);
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--color-text);
  text-decoration: none;
}

.nav-menu {
  display: flex;
  column-gap: var(--space-6);
  list-style: none;
}

.nav-tautan {
  color: var(--color-muted);
  font-weight: 500;
  text-decoration: none;
}

.nav-tautan:hover {
  color: var(--color-primary);
}

.tabs {
  display: flex;
  column-gap: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}

.tab {
  padding: var(--space-2) var(--space-3);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-muted);
  background-color: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}

.tab-aktif {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}

.grid-kartu {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
  margin-top: var(--space-6);
}

.card {
  display: flex;
  flex-direction: column;
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.card-shadow {
  box-shadow: var(--shadow-md);
}

.card-badan {
  display: grid;
  row-gap: var(--space-2);
  padding: var(--space-6);
}

.card-judul {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--color-text);
}

.card-teks {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-muted);
}

.card-aksi {
  display: flex;
  column-gap: var(--space-2);
  margin-top: var(--space-2);
}

/* Bagian 4: Themes dan Documentation ---------------------- */

[data-theme="gelap"] {
  --color-bg: #18181b;
  --color-surface: #27272a;
  --color-text: #fafafa;
  --color-muted: #a1a1aa;
  --color-border: #3f3f46;
  --color-primary-soft: rgb(20 184 166 / 16%);
  --shadow-md: 0 4px 12px rgb(0 0 0 / 40%);
}

.tema-sampel {
  padding: var(--space-6);
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.docs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.swatch {
  display: block;
  width: 64px;
  height: 40px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.swatch-nama {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-muted);
}

.contoh-kode {
  padding: var(--space-3) var(--space-4);
  background-color: var(--zinc-900);
  color: var(--zinc-200);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  border-radius: var(--radius-md);
  overflow-x: auto;
}

tests/buttons-dan-inputs.spec.js

Unduh berkas
javascript
// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 2: Buttons dan Inputs
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
//   /tests/css/proyek/component-library/buttons-dan-inputs.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.

const asersi = [
  // .btn-primer: geometri dari kelas dasar, warna dari token semantik.
  { elemen: ".btn-primer", properti: "background-color", diharapkan: "rgb(13, 148, 136)" },
  { elemen: ".btn-primer", properti: "color", diharapkan: "rgb(255, 255, 255)" },
  { elemen: ".btn-primer", properti: "padding-top", diharapkan: "8px" },
  { elemen: ".btn-primer", properti: "padding-left", diharapkan: "16px" },
  { elemen: ".btn-primer", properti: "border-radius", diharapkan: "10px" },
  { elemen: ".btn-primer", properti: "font-weight", diharapkan: "500" },

  // .btn-besar: ukuran menimpa padding dan font-size kelas dasar.
  { elemen: ".btn-besar", properti: "font-size", diharapkan: "20px" },
  { elemen: ".btn-besar", properti: "padding-top", diharapkan: "12px" },

  // .btn-kedua: permukaan putih dengan border dari token garis.
  { elemen: ".btn-kedua", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
  { elemen: ".btn-kedua", properti: "color", diharapkan: "rgb(24, 24, 27)" },
  { elemen: ".btn-kedua", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },

  // .btn:disabled: pseudo-class pada tombol dengan atribut disabled.
  { elemen: "button.btn[disabled]", properti: "opacity", diharapkan: "0.55" },
  { elemen: "button.btn[disabled]", properti: "cursor", diharapkan: "not-allowed" },

  // .input: border, radius, dan tipografi dari token.
  { elemen: ".input", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },
  { elemen: ".input", properti: "border-radius", diharapkan: "6px" },
  { elemen: ".input", properti: "font-size", diharapkan: "16px" },
  { elemen: ".input", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },

  // .input-galat: border berganti ke warna bahaya.
  { elemen: ".input-galat", properti: "border-top-color", diharapkan: "rgb(220, 38, 38)" },

  // .hint: teks bantu kecil dan redup.
  { elemen: ".hint", properti: "font-size", diharapkan: "12px" },
  { elemen: ".hint", properti: "color", diharapkan: "rgb(82, 82, 91)" },

  // .field: grid dengan jarak baris 8px dan pemisah antar field 16px.
  { elemen: ".field", properti: "row-gap", diharapkan: "8px" },
  { elemen: ".field", properti: "margin-bottom", diharapkan: "16px" },
];

tests/cards-dan-navigation.spec.js

Unduh berkas
javascript
// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 3: Cards dan Navigation
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
//   /tests/css/proyek/component-library/cards-dan-navigation.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.

const asersi = [
  // .navbar: menempel di atas halaman dengan z-index tinggi.
  { elemen: ".navbar", properti: "position", diharapkan: "sticky" },
  { elemen: ".navbar", properti: "top", diharapkan: "0px" },
  { elemen: ".navbar", properti: "z-index", diharapkan: "100" },
  { elemen: ".navbar", properti: "padding-top", diharapkan: "12px" },
  { elemen: ".navbar", properti: "column-gap", diharapkan: "16px" },

  // .nav-menu: flex dengan jarak antar tautan dari token spasi.
  { elemen: ".nav-menu", properti: "display", diharapkan: "flex" },
  { elemen: ".nav-menu", properti: "column-gap", diharapkan: "24px" },

  // .card: permukaan putih, border token, radius dari token bentuk.
  { elemen: ".card", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
  { elemen: ".card", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },
  { elemen: ".card", properti: "border-radius", diharapkan: "10px" },

  // .card-badan: padding token space-6, jarak baris token space-2.
  { elemen: ".card-badan", properti: "padding-top", diharapkan: "24px" },
  { elemen: ".card-badan", properti: "row-gap", diharapkan: "8px" },

  // .card-judul dan .card-teks: tipografi dari token teks.
  { elemen: ".card-judul", properti: "font-size", diharapkan: "20px" },
  { elemen: ".card-judul", properti: "font-weight", diharapkan: "600" },
  { elemen: ".card-teks", properti: "font-size", diharapkan: "14px" },
  { elemen: ".card-teks", properti: "color", diharapkan: "rgb(82, 82, 91)" },

  // .tab-aktif: garis bawah 2px primer di atas garis transparan.
  { elemen: ".tab-aktif", properti: "color", diharapkan: "rgb(13, 148, 136)" },
  { elemen: ".tab-aktif", properti: "border-bottom-width", diharapkan: "2px" },
  { elemen: ".tab-aktif", properti: "border-bottom-color", diharapkan: "rgb(13, 148, 136)" },

  // .kartu-galeri: bukti perhitungan grid tiga kolom pada wadah 960px.
  { elemen: ".kartu-galeri", properti: "width", diharapkan: "288px" },
];

tests/design-tokens.spec.js

Unduh berkas
javascript
// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 1: Design Tokens
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
//   /tests/css/proyek/component-library/design-tokens.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.

const asersi = [
  // Token tersimpan di :root (elemen html) dan terbaca apa adanya.
  { elemen: "html", properti: "--color-primary", diharapkan: "#0d9488" },
  { elemen: "html", properti: "--space-6", diharapkan: "24px" },
  { elemen: "html", properti: "--radius-md", diharapkan: "10px" },
  { elemen: "html", properti: "--text-base", diharapkan: "16px" },

  // body mengonsumsi token semantik: latar zinc-50, teks zinc-900.
  { elemen: "body", properti: "background-color", diharapkan: "rgb(250, 250, 250)" },
  { elemen: "body", properti: "color", diharapkan: "rgb(24, 24, 27)" },
  { elemen: "body", properti: "font-size", diharapkan: "16px" },

  // .wadah: lebar maksimum 960px dengan padding dari token spasi.
  { elemen: ".wadah", properti: "max-width", diharapkan: "960px" },
  { elemen: ".wadah", properti: "padding-top", diharapkan: "24px" },

  // .badge: latar primer lunak, teks primer, bentuk pil dari token.
  { elemen: ".badge", properti: "background-color", diharapkan: "rgba(13, 148, 136, 0.1)" },
  { elemen: ".badge", properti: "color", diharapkan: "rgb(13, 148, 136)" },
  { elemen: ".badge", properti: "border-radius", diharapkan: "999px" },
  { elemen: ".badge", properti: "font-size", diharapkan: "14px" },
  { elemen: ".badge", properti: "padding-top", diharapkan: "4px" },
];

tests/themes-dan-documentation.spec.js

Unduh berkas
javascript
// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 4: Themes dan Documentation
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
//   /tests/css/proyek/component-library/themes-dan-documentation.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.

const asersi = [
  // Tema terang tetap berlaku di luar wadah data-theme.
  { elemen: "body", properti: "background-color", diharapkan: "rgb(250, 250, 250)" },
  { elemen: ".kartu-terang", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
  { elemen: ".kartu-terang", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },

  // Wadah gelap: token semantik ditimpa, latar dan garis mengikuti.
  { elemen: ".tema-sampel", properti: "background-color", diharapkan: "rgb(24, 24, 27)" },
  { elemen: ".tema-sampel", properti: "padding-top", diharapkan: "24px" },
  { elemen: ".tema-sampel", properti: "border-top-color", diharapkan: "rgb(63, 63, 70)" },

  // Komponen di dalam wadah gelap ikut berganti tanpa aturan baru.
  { elemen: ".kartu-gelap", properti: "background-color", diharapkan: "rgb(39, 39, 42)" },
  { elemen: ".teks-gelap", properti: "color", diharapkan: "rgb(161, 161, 170)" },

  // Custom property terwariskan: badge gelap membaca surface baru.
  { elemen: ".badge-gelap", properti: "--color-surface", diharapkan: "#27272a" },
  { elemen: ".badge-gelap", properti: "background-color", diharapkan: "rgba(20, 184, 166, 0.16)" },

  // Komponen dokumentasi: swatch token berukuran tetap.
  { elemen: ".swatch", properti: "width", diharapkan: "64px" },
  { elemen: ".swatch", properti: "height", diharapkan: "40px" },
  { elemen: ".swatch", properti: "border-radius", diharapkan: "6px" },

  // .contoh-kode memakai primitif zinc: tetap gelap di kedua tema.
  { elemen: ".contoh-kode", properti: "background-color", diharapkan: "rgb(24, 24, 27)" },
  { elemen: ".contoh-kode", properti: "color", diharapkan: "rgb(228, 228, 231)" },
  { elemen: ".contoh-kode", properti: "font-size", diharapkan: "14px" },
  { elemen: ".contoh-kode", properti: "padding-top", diharapkan: "12px" },
  { elemen: ".contoh-kode", properti: "border-radius", diharapkan: "10px" },
];