Landing page adalah halaman yang tugasnya satu: mengubah kunjungan pertama menjadi tindakan — memesan, mendaftar, atau menghubungi. Pada proyek ini kita membangun landing page untuk kedai kopi fiktif bernama Kopi Senja, lengkap dengan navigation bar yang menempel saat digulir, hero dua kolom, baris keunggulan, grid menu unggulan, pita ajakan bertindak, dan footer. Proyek ini satu tingkat lebih besar daripada Proyek: Website Portofolio
: di sini kita menambahkan navigasi responsif tanpa JavaScript serta lapisan animasi yang menghormati preferensi gerak pengguna. Empat bagian berurutan memperluas satu file styles/landing.css, dan setiap bagian ditutup halaman uji otomatis.
Tujuan Proyek #
Target yang kita capai di akhir bagian keempat:
- Fondasi visual: token warna hangat, skala spasi, radius, dan komponen tombol serta badge yang dikonsumsi lewat
var(). - Hero flexbox dua kolom (basis 55% dan 45%) dengan judul fluid
clamp()dan kotak gambaraspect-ratio. - Baris keunggulan berbasis
flex: 1dan grid menurepeat(3, 1fr)yang runtuh menjadi satu kolom di layar kecil. - Navigation
position: stickydengan latar semi transparan danbackdrop-filter, plus hamburger yang membuka menu memakai:checked— tanpa satu baris JavaScript pun. - Polish:
transitionpada tombol dan kartu,@keyframespada badge,scroll-behavior: smooth, dan pembungkusprefers-reduced-motion.
Lebih penting dari daftar itu: kita berlatih menahan diri. Animasi pada landing page seharusnya mengarahkan perhatian, bukan memenuhi layar.
Prasyarat #
Proyek ini memakai konsep dari beberapa Section sebelumnya tanpa mengulang teorinya:
- Token dan warna: Custom Properties serta Color Syntax .
- Flexbox: Flex Container dan Items , Flex Grow, Shrink, dan Basis , serta Gap .
- Grid: Grid Container dan Items dan Repeat dan Minmax .
- Navigasi dan posisi: Sticky Positioning , Media Queries , dan Breakpoints .
- Animasi: Transition Properties , Keyframe Animations , dan Prefers Reduced Motion .
Struktur Folder Proyek #
Struktur berikut adalah kondisi akhir setelah empat bagian selesai:
landing-page-responsif/
├── index.html markup halaman utuh
├── styles/
│ └── landing.css satu file CSS utuh yang berkembang
├── assets/
│ ├── gelas-kopi.svg ilustrasi gelas kopi untuk hero
│ ├── menu-kopi-susu.svg gambar kartu menu "Kopi Susu Senja"
│ ├── menu-americano.svg gambar kartu menu "Americano Dingin"
│ └── menu-croissant.svg gambar kartu menu "Croissant Mentega"
├── tests/
│ ├── visual-foundation.spec.js
│ ├── flexbox-dan-grid.spec.js
│ ├── responsive-navigation.spec.js
│ └── animations-dan-polish.spec.js
└── bagian/
├── visual-foundation/
├── flexbox-dan-grid/
├── responsive-navigation/
└── animations-dan-polish/Sama seperti dua proyek sebelumnya, styles/landing.css adalah satu file yang di-update di tiap bagian, bukan diganti. Komentar penanda Bagian N di dalam file menandai asal setiap kelompok aturan; Bagian 4 menambahkan baris transition dan animation pada aturan yang sudah ada, bukan menduplikasi selector.
Daftar Bagian #
| Bagian | Fokus |
|---|---|
| Bagian 1: Visual Foundation | Token warna hangat, reset, wadah 1120px, tombol, dan badge |
| Bagian 2: Flexbox dan Grid | Hero flex 55/45, keunggulan flex: 1, grid menu tiga kolom |
| Bagian 3: Responsive Navigation | Navigation sticky, hamburger :checked, breakpoint 899px |
| Bagian 4: Animations dan Polish | Transition, keyframes denyut, pita CTA, reduced motion |
Menjalankan Halaman Uji Otomatis #
Setiap bagian memiliki halaman uji mandiri di bawah /tests/css/proyek/landing-page-responsif/<topic>.html, misalnya uji Bagian 1
. Elemen probe di dalamnya membawa atribut data-expected berisi JSON pasangan properti dan nilai computed; harness membuka halaman di headless Chromium dan membandingkan hasil getComputedStyle() dengan nilai tersebut.
Jalankan seluruh uji proyek ini dengan satu perintah:
node scripts/css-test/run_tests.mjs --filter landing-page-responsifRingkasan asersi per bagian juga tersedia sebagai tests/<topic>.spec.js yang dapat dibaca dan diunduh melalui bagian Berkas Sumber. Untuk pemeriksaan manual, buka halaman uji di browser, tekan F12, lalu bandingkan panel Computed dengan tabel asersi di akhir setiap bagian.
Bangun fondasi visual landing page dengan token warna hangat, skala spasi, reset ringkas, wadah 1120px, serta komponen tombol dan badge.
Buka → # Bagian 2: Flexbox dan GridSusun hero flexbox dua kolom dengan judul fluid, baris keunggulan flex: 1, dan grid menu tiga kolom yang rata.
Buka → # Bagian 3: Responsive NavigationTempelkan navigation bar sticky dengan backdrop-filter, lalu bangun hamburger yang membuka menu memakai :checked tanpa JavaScript.
Buka → # Bagian 4: Animations dan PolishHaluskan landing page dengan transition tombol dan kartu, keyframes denyut pada badge, pita CTA berbayangan, serta pembungkus prefers-reduced-motion.
Buka →Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
styles/landing.css
Unduh berkas/* =========================================================
Proyek: Landing Page Responsif — styles/landing.css
File utuh proyek yang berkembang mengikuti empat bagian:
Bagian 1 (Visual Foundation), Bagian 2 (Flexbox dan Grid),
Bagian 3 (Responsive Navigation), Bagian 4 (Animations dan
Polish). Komentar "Bagian N" menandai kelompok aturan yang
dibahas pada setiap bagian.
========================================================= */
/* Bagian 1: Visual Foundation ----------------------------- */
:root {
/* Warna semantik — brand kedai Kopi Senja */
--warna-primer: #c2410c;
--warna-primer-tua: #9a3412;
--warna-latar: #fffbeb;
--warna-permukaan: #ffffff;
--warna-teks: #292524;
--warna-teks-lembut: #57534e;
--warna-teks-balik: #ffffff;
--warna-garis: #e7e5e4;
/* Skala spasi */
--spasi-1: 4px;
--spasi-2: 8px;
--spasi-3: 12px;
--spasi-4: 16px;
--spasi-6: 24px;
--spasi-8: 32px;
--spasi-12: 48px;
--spasi-16: 64px;
/* Bentuk */
--radius-sedang: 12px;
--radius-besar: 16px;
--radius-penuh: 999px;
/* Tipografi */
--font-utama: system-ui, sans-serif;
--teks-dasar: 16px;
--teks-lg: 20px;
}
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-utama);
font-size: var(--teks-dasar);
line-height: 1.6;
color: var(--warna-teks);
background-color: var(--warna-latar);
}
.wadah {
max-width: 1120px;
margin: 0 auto;
padding: 0 var(--spasi-6);
}
.tombol {
display: inline-block;
padding: var(--spasi-3) var(--spasi-4);
border-radius: var(--radius-sedang);
font-size: var(--teks-dasar);
font-weight: 500;
text-decoration: none;
/* Bagian 4: menambah baris transition di bawah ini */
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.tombol-primer {
background-color: var(--warna-primer);
color: var(--warna-teks-balik);
}
.tombol-kedua {
background-color: var(--warna-permukaan);
color: var(--warna-primer);
border: 1px solid var(--warna-primer);
}
.badge {
display: inline-block;
padding: var(--spasi-1) var(--spasi-3);
border-radius: var(--radius-penuh);
background-color: rgb(194 65 12 / 10%);
color: var(--warna-primer-tua);
font-size: 14px;
font-weight: 600;
/* Bagian 4: menambah baris animation di bawah ini */
animation: denyut 2s ease-in-out infinite;
}
.judul-bagian {
font-size: 28px;
font-weight: 700;
}
.deskripsi-bagian {
margin-top: var(--spasi-2);
max-width: 560px;
color: var(--warna-teks-lembut);
}
/* Bagian 2: Flexbox dan Grid ------------------------------ */
.hero {
display: flex;
align-items: center;
gap: var(--spasi-12);
padding: var(--spasi-16) 0;
}
.hero-teks {
flex: 1 1 55%;
}
.hero-gambar {
flex: 1 1 45%;
display: flex;
}
.gambar-hero {
width: 100%;
aspect-ratio: 4 / 3;
border-radius: var(--radius-besar);
object-fit: cover;
}
.judul-hero {
font-size: clamp(32px, 16px + 3vw, 52px);
line-height: 1.15;
}
.teks-aksen {
color: var(--warna-primer);
}
.deskripsi-hero {
margin-top: var(--spasi-4);
font-size: 18px;
color: var(--warna-teks-lembut);
}
.hero-aksi {
display: flex;
gap: var(--spasi-4);
margin-top: var(--spasi-6);
}
.keunggulan {
display: flex;
gap: var(--spasi-6);
}
.keunggulan-item {
flex: 1;
padding: var(--spasi-6);
background-color: var(--warna-permukaan);
border: 1px solid var(--warna-garis);
border-radius: var(--radius-sedang);
}
.keunggulan-judul {
font-size: 18px;
font-weight: 600;
}
.keunggulan-isi {
margin-top: var(--spasi-2);
font-size: 14px;
color: var(--warna-teks-lembut);
}
.grid-menu {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--spasi-6);
margin-top: var(--spasi-8);
}
.kartu-menu {
display: flex;
flex-direction: column;
background-color: var(--warna-permukaan);
border: 1px solid var(--warna-garis);
border-radius: var(--radius-sedang);
overflow: hidden;
/* Bagian 4: menambah baris transition di bawah ini */
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.gambar-menu {
width: 100%;
aspect-ratio: 3 / 2;
object-fit: cover;
}
.kartu-menu-isi {
display: grid;
gap: var(--spasi-2);
padding: var(--spasi-6);
}
.kartu-menu-nama {
font-size: var(--teks-lg);
font-weight: 600;
}
.kartu-menu-harga {
color: var(--warna-primer);
font-weight: 600;
}
.kartu-menu-deskripsi {
font-size: 14px;
color: var(--warna-teks-lembut);
}
/* Bagian 3: Responsive Navigation ------------------------- */
.navigasi {
position: sticky;
top: 0;
z-index: 20;
background-color: rgb(255 251 235 / 90%);
backdrop-filter: blur(8px);
border-bottom: 1px solid var(--warna-garis);
}
.navigasi-isi {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spasi-6);
height: 64px;
}
.logo {
font-size: var(--teks-lg);
font-weight: 700;
color: var(--warna-teks);
text-decoration: none;
}
.navigasi-menu {
display: flex;
gap: var(--spasi-6);
list-style: none;
}
.navigasi-tautan {
color: var(--warna-teks-lembut);
font-weight: 500;
text-decoration: none;
}
.navigasi-tautan:hover {
color: var(--warna-primer);
}
.navigasi-tautan:focus-visible {
outline: 2px solid var(--warna-primer);
outline-offset: 2px;
}
/* Checkbox hamburger disembunyikan secara visual, tetap
bisa di-fokus dan dibaca screen reader */
.menu-toggle {
position: absolute;
width: 1px;
height: 1px;
opacity: 0;
}
.tombol-menu {
display: none;
padding: var(--spasi-2) var(--spasi-4);
border: 1px solid var(--warna-garis);
border-radius: var(--radius-sedang);
background-color: var(--warna-permukaan);
font-size: 14px;
font-weight: 500;
cursor: pointer;
}
/* Fokus keyboard dari checkbox yang tersembunyi ditunjukkan
pada label hamburger di sebelahnya */
.menu-toggle:focus-visible + .tombol-menu {
outline: 2px solid var(--warna-primer);
outline-offset: 2px;
}
@media (max-width: 899px) {
.hero {
flex-direction: column;
align-items: flex-start;
}
.hero-gambar {
width: 100%;
}
.keunggulan {
flex-direction: column;
}
.grid-menu {
grid-template-columns: 1fr;
}
.tombol-menu {
display: inline-flex;
}
.navigasi-menu {
display: none;
position: absolute;
top: 64px;
left: 0;
right: 0;
flex-direction: column;
gap: var(--spasi-1);
padding: var(--spasi-4) var(--spasi-6);
background-color: var(--warna-permukaan);
border-bottom: 1px solid var(--warna-garis);
}
/* Panel menu terbuka tanpa JavaScript memakai :checked */
.menu-toggle:checked ~ .navigasi-menu {
display: flex;
}
}
/* Bagian 4: Animations dan Polish ------------------------- */
@keyframes denyut {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.06);
opacity: 0.85;
}
}
.tombol-primer:hover {
transform: translateY(-2px);
box-shadow: 0 8px 16px rgb(154 52 18 / 25%);
}
.tombol-kedua:hover {
transform: translateY(-2px);
background-color: rgb(194 65 12 / 8%);
}
.kartu-menu:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgb(41 37 36 / 12%);
}
.pita-cta {
margin-top: var(--spasi-16);
padding: var(--spasi-12) var(--spasi-8);
background-color: var(--warna-primer);
color: var(--warna-teks-balik);
text-align: center;
border-radius: var(--radius-besar);
box-shadow: 0 12px 24px rgb(154 52 18 / 25%);
}
.pita-cta-judul {
font-size: 24px;
font-weight: 700;
}
.pita-cta-isi {
margin-top: var(--spasi-2);
}
.kaki {
display: flex;
justify-content: space-between;
gap: var(--spasi-4);
margin-top: var(--spasi-16);
padding: var(--spasi-8) 0;
border-top: 1px solid var(--warna-garis);
font-size: 14px;
color: var(--warna-teks-lembut);
}
html {
scroll-behavior: smooth;
}
/* Pengguna yang mengaktifkan reduce motion menerima halaman
tanpa animasi: keyframes dan transition dimatikan */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
.badge {
animation: none;
}
.tombol,
.kartu-menu {
transition: none;
}
}
tests/animations-dan-polish.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Landing Page Responsif
// Bagian 4: Animations dan Polish
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji (viewport 1280x720):
// /tests/css/proyek/landing-page-responsif/animations-dan-polish.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// Guliran antarbagian bergerak halus lewat scroll-behavior.
{ elemen: "html", properti: "scroll-behavior", diharapkan: "smooth" },
// Tombol bertransisi pada properti transform dan box-shadow.
{ elemen: ".tombol-primer", properti: "transition-property", diharapkan: "transform, box-shadow" },
{ elemen: ".tombol-primer", properti: "transition-duration", diharapkan: "0.2s, 0.2s" },
// Kartu menu bertransisi dengan nilai yang sama seperti tombol.
{ elemen: ".kartu-menu", properti: "transition-property", diharapkan: "transform, box-shadow" },
{ elemen: ".kartu-menu", properti: "transition-duration", diharapkan: "0.2s, 0.2s" },
// Badge berdenyut: keyframes denyut, 2 detik, tanpa henti.
{ elemen: ".badge", properti: "animation-name", diharapkan: "denyut" },
{ elemen: ".badge", properti: "animation-duration", diharapkan: "2s" },
{ elemen: ".badge", properti: "animation-timing-function", diharapkan: "ease-in-out" },
{ elemen: ".badge", properti: "animation-iteration-count", diharapkan: "infinite" },
// Pita CTA berlatar primer dengan bayangan kehangatan primer-tua.
{ elemen: ".pita-cta", properti: "background-color", diharapkan: "rgb(194, 65, 12)" },
{ elemen: ".pita-cta", properti: "color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".pita-cta", properti: "border-radius", diharapkan: "16px" },
{ elemen: ".pita-cta", properti: "text-align", diharapkan: "center" },
{ elemen: ".pita-cta", properti: "box-shadow", diharapkan: "rgba(154, 52, 18, 0.25) 0px 12px 24px 0px" },
// Judul pita CTA 24px dengan bobot 700.
{ elemen: ".pita-cta-judul", properti: "font-size", diharapkan: "24px" },
{ elemen: ".pita-cta-judul", properti: "font-weight", diharapkan: "700" },
// Footer dua sisi: flex dengan ruas terpisah dan garis atas.
{ elemen: ".kaki", properti: "display", diharapkan: "flex" },
{ elemen: ".kaki", properti: "justify-content", diharapkan: "space-between" },
{ elemen: ".kaki", properti: "border-top-width", diharapkan: "1px" },
];
tests/flexbox-dan-grid.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Landing Page Responsif
// Bagian 2: Flexbox dan Grid
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji (viewport 1280x720):
// /tests/css/proyek/landing-page-responsif/flexbox-dan-grid.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// Hero adalah flex container dengan item terpusat vertikal.
{ elemen: ".hero", properti: "display", diharapkan: "flex" },
{ elemen: ".hero", properti: "align-items", diharapkan: "center" },
{ elemen: ".hero", properti: "gap", diharapkan: "48px" },
// Teks hero: basis 55% yang menyusut menjadi 563.2px akibat gap.
{ elemen: ".hero-teks", properti: "flex-grow", diharapkan: "1" },
{ elemen: ".hero-teks", properti: "flex-shrink", diharapkan: "1" },
{ elemen: ".hero-teks", properti: "flex-basis", diharapkan: "55%" },
{ elemen: ".hero-teks", properti: "width", diharapkan: "563.2px" },
// Gambar hero: basis 45%, lebar akhir 460.8px.
{ elemen: ".hero-gambar", properti: "flex-basis", diharapkan: "45%" },
{ elemen: ".hero-gambar", properti: "width", diharapkan: "460.8px" },
// Kotak gambar menjaga rasio 4:3 sehingga tingginya 345.6px.
{ elemen: ".gambar-hero", properti: "aspect-ratio", diharapkan: "4 / 3" },
{ elemen: ".gambar-hero", properti: "height", diharapkan: "345.6px" },
{ elemen: ".gambar-hero", properti: "border-radius", diharapkan: "16px" },
// Judul hero fluid mencapai batas atas clamp 52px pada 1280px.
{ elemen: ".judul-hero", properti: "font-size", diharapkan: "52px" },
{ elemen: ".judul-hero", properti: "line-height", diharapkan: "59.8px" },
// Baris tombol aksi adalah flex dengan gap 16px.
{ elemen: ".hero-aksi", properti: "display", diharapkan: "flex" },
{ elemen: ".hero-aksi", properti: "gap", diharapkan: "16px" },
// Item keunggulan memakai flex: 1 = grow 1, shrink 1, basis 0%.
{ elemen: ".keunggulan-item", properti: "flex-grow", diharapkan: "1" },
{ elemen: ".keunggulan-item", properti: "flex-shrink", diharapkan: "1" },
{ elemen: ".keunggulan-item", properti: "flex-basis", diharapkan: "0%" },
// Grid menu tiga kolom sama lebar dengan gap 24px.
{ elemen: ".grid-menu", properti: "display", diharapkan: "grid" },
{ elemen: ".grid-menu", properti: "gap", diharapkan: "24px" },
{ elemen: ".grid-menu", properti: "grid-template-columns", diharapkan: "341.328px 341.328px 341.344px" },
// Kartu menu berlatar permukaan putih dengan radius 12px.
{ elemen: ".kartu-menu", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".kartu-menu", properti: "border-radius", diharapkan: "12px" },
{ elemen: ".kartu-menu", properti: "display", diharapkan: "flex" },
];
tests/responsive-navigation.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Landing Page Responsif
// Bagian 3: Responsive Navigation
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji (viewport 1280x720):
// /tests/css/proyek/landing-page-responsif/responsive-navigation.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// Navigation menempel di atas: sticky dengan jarak 0 dari tepi.
{ elemen: ".navigasi", properti: "position", diharapkan: "sticky" },
{ elemen: ".navigasi", properti: "top", diharapkan: "0px" },
{ elemen: ".navigasi", properti: "z-index", diharapkan: "20" },
// Latar krem semi transparan 90% dengan efek blur di belakangnya.
{ elemen: ".navigasi", properti: "background-color", diharapkan: "rgba(255, 251, 235, 0.9)" },
{ elemen: ".navigasi", properti: "backdrop-filter", diharapkan: "blur(8px)" },
// Baris navigasi setinggi 64px dengan ruas logo dan menu terpisah.
{ elemen: ".navigasi-isi", properti: "height", diharapkan: "64px" },
{ elemen: ".navigasi-isi", properti: "justify-content", diharapkan: "space-between" },
{ elemen: ".navigasi-isi", properti: "gap", diharapkan: "24px" },
{ elemen: ".navigasi-isi", properti: "display", diharapkan: "flex" },
// Logo memakai ukuran 20px dengan bobot 700.
{ elemen: ".logo", properti: "font-size", diharapkan: "20px" },
{ elemen: ".logo", properti: "font-weight", diharapkan: "700" },
// Menu tersusun horizontal dengan jarak antartautan 24px.
{ elemen: ".navigasi-menu", properti: "display", diharapkan: "flex" },
{ elemen: ".navigasi-menu", properti: "gap", diharapkan: "24px" },
// Tautan memakai warna teks lembut tanpa garis bawah.
{ elemen: ".navigasi-tautan", properti: "color", diharapkan: "rgb(87, 83, 78)" },
{ elemen: ".navigasi-tautan", properti: "font-weight", diharapkan: "500" },
{ elemen: ".navigasi-tautan", properti: "text-decoration-line", diharapkan: "none" },
// Checkbox hamburger disembunyikan secara visual.
{ elemen: ".menu-toggle", properti: "position", diharapkan: "absolute" },
{ elemen: ".menu-toggle", properti: "opacity", diharapkan: "0" },
{ elemen: ".menu-toggle", properti: "width", diharapkan: "1px" },
// Tombol hamburger hanya tampil pada breakpoint 899px ke bawah.
{ elemen: ".tombol-menu", properti: "display", diharapkan: "none" },
];
tests/visual-foundation.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Landing Page Responsif
// Bagian 1: Visual Foundation
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji (viewport 1280x720):
// /tests/css/proyek/landing-page-responsif/visual-foundation.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// body mengonsumsi token: latar krem hangat dan teks stone-800.
{ elemen: "body", properti: "font-size", diharapkan: "16px" },
{ elemen: "body", properti: "line-height", diharapkan: "25.6px" },
{ elemen: "body", properti: "color", diharapkan: "rgb(41, 37, 36)" },
{ elemen: "body", properti: "background-color", diharapkan: "rgb(255, 251, 235)" },
// Wadah konten dibatasi 1120px dan terpusat di viewport 1280px.
{ elemen: ".wadah", properti: "max-width", diharapkan: "1120px" },
{ elemen: ".wadah", properti: "margin-left", diharapkan: "80px" },
// Judul bagian memakai ukuran 28px dengan bobot 700.
{ elemen: ".judul-bagian", properti: "font-size", diharapkan: "28px" },
{ elemen: ".judul-bagian", properti: "font-weight", diharapkan: "700" },
// Deskripsi bagian memakai warna teks lembut dan lebar terbatas.
{ elemen: ".deskripsi-bagian", properti: "color", diharapkan: "rgb(87, 83, 78)" },
{ elemen: ".deskripsi-bagian", properti: "max-width", diharapkan: "560px" },
// Tombol primer: latar oranye terbakar, teks putih, padding dari token.
{ elemen: ".tombol-primer", properti: "background-color", diharapkan: "rgb(194, 65, 12)" },
{ elemen: ".tombol-primer", properti: "color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".tombol-primer", properti: "padding-top", diharapkan: "12px" },
{ elemen: ".tombol-primer", properti: "padding-left", diharapkan: "16px" },
{ elemen: ".tombol-primer", properti: "border-radius", diharapkan: "12px" },
// Tombol kedua: permukaan putih dengan teks dan border primer.
{ elemen: ".tombol-kedua", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".tombol-kedua", properti: "color", diharapkan: "rgb(194, 65, 12)" },
{ elemen: ".tombol-kedua", properti: "border-top-color", diharapkan: "rgb(194, 65, 12)" },
// Badge memakai warna primer dengan alpha 10% dan radius penuh.
{ elemen: ".badge", properti: "background-color", diharapkan: "rgba(194, 65, 12, 0.1)" },
{ elemen: ".badge", properti: "color", diharapkan: "rgb(154, 52, 18)" },
{ elemen: ".badge", properti: "border-radius", diharapkan: "999px" },
{ elemen: ".badge", properti: "font-size", diharapkan: "14px" },
];