/* ==========================================================================
   TUTOORIA — 02. BASE
   Reset modern, dasar tipografi, primitif layout, utilitas.
   ========================================================================== */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  font-size: var(--root-size);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--space-l));
  tab-size: 2;
}

body {
  min-height: 100svh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  font-weight: var(--weight-body);
  line-height: var(--leading-prose);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }

/* [hidden] harus menang atas display dari komponen (mis. .tutor-card{display:flex})
   — dipakai oleh penyaring tutor dan pesan status formulir. */
[hidden] { display: none !important; }

::selection { background: var(--selection-bg); color: var(--selection-fg); }

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-xs);
}
:focus:not(:focus-visible) { outline: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Tipografi ----------
   Judul memakai Farro (bobot terberat 700), teks memakai Hanken Grotesk. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  text-wrap: balance;
}

/* Ukuran datang dari peran di tokens.css (--text-h1 … --text-h4), bukan
   dari --step-* langsung. Kelas .display/.h1–.h4 memberi gaya yang sama
   pada elemen apa pun — pakai bila level semantik dan ukuran visual
   berbeda (mis. <h2> yang tampil sebesar judul kartu). */
h1, .h1 { font-size: var(--text-h1); }
h2, .h2 { font-size: var(--text-h2); }
h3, .h3 { font-size: var(--text-h3); line-height: var(--leading-snug); }
h4, .h4 { font-size: var(--text-h4); line-height: var(--leading-snug); }

.display, .h1, .h2, .h3, .h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}
.display, .h1, .h2 { line-height: var(--leading-tight); }
/* Hero beranda saja — satu per situs. */
.display { font-size: var(--text-display); }

/* Paragraf pembuka di bawah judul halaman atau hero. */
.lead {
  max-inline-size: 52ch;
  font-size: var(--text-lead);
  line-height: var(--leading-normal);
  color: var(--fg);
}

/* Label kecil berhuruf kapital — judul kolom menu & footer, label daftar
   info, jenis kartu, kepala tabel. SATU gaya untuk semuanya; dulu ada
   tujuh salinan dengan nama berbeda. Bukan "eyebrow" di atas judul seksi
   (dilarang) — ia melabeli kelompok isi, bukan menghias judul. */
.overline {
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  line-height: var(--leading-snug);
  text-transform: uppercase;
  color: var(--fg-muted);
}
/* Versi berwarna penuh, untuk label yang jadi bagian utama kartu. */
.overline--strong { color: var(--fg); }

p { text-wrap: pretty; }

a {
  color: inherit;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 0.22em;
  text-decoration-thickness: from-font;
  transition: text-decoration-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
/* Ungu gagal kontras sebagai warna teks di atas putih (2.21:1), jadi hover
   tidak mengubah warna huruf — hanya menebalkan garis bawahnya. */
a:hover {
  text-decoration-color: var(--line-strong);
  text-decoration-thickness: 2px;
}

strong, b { font-weight: var(--weight-semibold); }

code {
  padding: 0.1em 0.35em;
  border-radius: var(--radius-xs);
  background: color-mix(in oklab, var(--fg) 6%, transparent);
  font-family: var(--font-mono);
  font-size: 0.86em;
}

.tabular { font-variant-numeric: tabular-nums; }

/* ---------- Primitif layout ----------
   .container dan .container--fluid kini jatuh di tepi yang sama (lihat
   --container di tokens.css), sehingga logo header, judul hero, dan isi
   seksi mana pun sejajar di semua lebar layar. .container--fluid tetap
   dipertahankan untuk elemen yang memang harus selalu selebar viewport
   walau --container suatu saat dibatasi lagi. */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--wide { max-width: var(--container-wide); }
/* Selebar viewport; jarak tepi tetap dijaga oleh --gutter. */
.container--fluid { max-width: none; }
.container--text { max-width: var(--container-text); }

.section { padding-block: var(--space-3xl); }
.section--tight { padding-block: var(--space-2xl); }
.section--sunken { background: var(--bg-sunken); }

/* ---------- Permukaan hitam ----------
   SATU definisi untuk semua bidang hitam: seksi, footer, sidebar
   aplikasi, dan kartu (.card.surface-invert). Yang dibalik adalah TOKEN,
   bukan warna tiap elemen — jadi komponen apa pun yang ditaruh di dalamnya
   (kartu, garis, teks redup, bar progres, cincin fokus) otomatis ikut
   benar tanpa aturan tambahan. Di atas hitam ungu boleh jadi teks/garis. */
.surface-invert,
.section--invert,
.site-footer,
.app-sidebar {
  --bg-raised: var(--clr-black);
  --bg-sunken: color-mix(in oklab, var(--clr-white) 8%, var(--clr-black));
  --fg: var(--clr-white);
  --fg-muted: color-mix(in oklab, var(--clr-white) 66%, transparent);
  --fg-subtle: color-mix(in oklab, var(--clr-white) 45%, transparent);
  --line: color-mix(in oklab, var(--clr-white) 20%, transparent);
  --line-strong: var(--clr-white);
  --progress-track: color-mix(in oklab, var(--clr-white) 18%, transparent);
  --focus-color: var(--clr-purple);
  background: var(--bg-invert);
  color: var(--fg);
}

/* ---------- ROW & COL — sistem kolom 12 ----------
   Semua tata letak berkolom memakai sistem ini, bukan grid buatan tiap
   komponen. Mobile-first: tanpa kelas, setiap kolom selebar penuh; kelas
   berawalan breakpoint berlaku MULAI lebar itu ke atas.

     sm 30rem · md 48rem · lg 64rem · xl 80rem · 2xl 90rem

   Tiga cara memakai .row:

   1. Lebar kolom sendiri-sendiri — .col-{n}, .col-{bp}-{n} (n = 1–12),
      geser dengan .offset-{bp}-{n} = lewati n kolom (mulai di kolom n+1).
      Offset + lebar tidak boleh lebih dari 12: .col-5.offset-7 pas sampai
      tepi kanan; .col-6.offset-7 membuat kolom ke-13 diam-diam dan semua
      kolom di baris itu menyempit.
        <div class="row">
          <div class="col-lg-7">…</div>
          <div class="col-lg-4 offset-lg-8">…</div>
        </div>

   2. Kolom sama lebar — .row-cols-{n}, .row-cols-{bp}-{n} (n = 1–6) di
      .row-nya; anak tidak perlu kelas. Untuk deretan kartu setara.
        <div class="row row-cols-2 row-cols-md-3 row-cols-lg-4">…</div>

   3. Mengalir — .row--auto (-s / -l): jumlah kolom mengikuti ruang,
      minimal --col-min-*. Untuk katalog yang jumlah kartunya berubah.

   Pengubah: .row--gap-{s|m|l|xl|2xl} (jarak), .row--rail (rel geser
   mendatar di bawah lg), .row--center / --start / --end (perataan
   vertikal), .col-full (selebar baris di dalam row-cols/row--auto).
   Jarak baris dan kolom bisa ditimpa terpisah lewat --row-gap/--col-gap.

   PENTING — jangan besarkan jarak KOLOM pada .row 12 kolom. Jaraknya
   dihitung 11 kali: --col-gap 3.5rem sudah 616px, lebih lebar dari layar
   ponsel, dan halaman meluber ke samping. Jarak lebar antar-area dibuat
   dengan offset (satu kolom kosong), mis. .col-md-6 + .col-md-5.offset-md-7.
   Pengubah .row--gap-* hanya untuk row-cols-* dan row--auto (≤ 6 kolom). */
.row {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  gap: var(--row-gap, var(--grid-gap)) var(--col-gap, var(--grid-gap));
}
.row > * { grid-column: auto / span var(--grid-columns); min-inline-size: 0; }

.col-1 { grid-column-end: span 1; }
.col-2 { grid-column-end: span 2; }
.col-3 { grid-column-end: span 3; }
.col-4 { grid-column-end: span 4; }
.col-5 { grid-column-end: span 5; }
.col-6 { grid-column-end: span 6; }
.col-7 { grid-column-end: span 7; }
.col-8 { grid-column-end: span 8; }
.col-9 { grid-column-end: span 9; }
.col-10 { grid-column-end: span 10; }
.col-11 { grid-column-end: span 11; }
.col-12 { grid-column-end: span 12; }
.offset-0 { grid-column-start: auto; }
.offset-1 { grid-column-start: 2; }
.offset-2 { grid-column-start: 3; }
.offset-3 { grid-column-start: 4; }
.offset-4 { grid-column-start: 5; }
.offset-5 { grid-column-start: 6; }
.offset-6 { grid-column-start: 7; }
.offset-7 { grid-column-start: 8; }
.offset-8 { grid-column-start: 9; }
.offset-9 { grid-column-start: 10; }
.offset-10 { grid-column-start: 11; }
.offset-11 { grid-column-start: 12; }
.row-cols-1 { grid-template-columns: minmax(0, 1fr); }
.row-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.row-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.row-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.row-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.row-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

@media (min-width: 30rem) {   /* sm — ponsel besar */
  .col-sm-1 { grid-column-end: span 1; }
  .col-sm-2 { grid-column-end: span 2; }
  .col-sm-3 { grid-column-end: span 3; }
  .col-sm-4 { grid-column-end: span 4; }
  .col-sm-5 { grid-column-end: span 5; }
  .col-sm-6 { grid-column-end: span 6; }
  .col-sm-7 { grid-column-end: span 7; }
  .col-sm-8 { grid-column-end: span 8; }
  .col-sm-9 { grid-column-end: span 9; }
  .col-sm-10 { grid-column-end: span 10; }
  .col-sm-11 { grid-column-end: span 11; }
  .col-sm-12 { grid-column-end: span 12; }
  .offset-sm-0 { grid-column-start: auto; }
  .offset-sm-1 { grid-column-start: 2; }
  .offset-sm-2 { grid-column-start: 3; }
  .offset-sm-3 { grid-column-start: 4; }
  .offset-sm-4 { grid-column-start: 5; }
  .offset-sm-5 { grid-column-start: 6; }
  .offset-sm-6 { grid-column-start: 7; }
  .offset-sm-7 { grid-column-start: 8; }
  .offset-sm-8 { grid-column-start: 9; }
  .offset-sm-9 { grid-column-start: 10; }
  .offset-sm-10 { grid-column-start: 11; }
  .offset-sm-11 { grid-column-start: 12; }
  .row-cols-sm-1 { grid-template-columns: minmax(0, 1fr); }
  .row-cols-sm-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .row-cols-sm-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .row-cols-sm-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .row-cols-sm-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .row-cols-sm-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (min-width: 48rem) {   /* md — tablet */
  .col-md-1 { grid-column-end: span 1; }
  .col-md-2 { grid-column-end: span 2; }
  .col-md-3 { grid-column-end: span 3; }
  .col-md-4 { grid-column-end: span 4; }
  .col-md-5 { grid-column-end: span 5; }
  .col-md-6 { grid-column-end: span 6; }
  .col-md-7 { grid-column-end: span 7; }
  .col-md-8 { grid-column-end: span 8; }
  .col-md-9 { grid-column-end: span 9; }
  .col-md-10 { grid-column-end: span 10; }
  .col-md-11 { grid-column-end: span 11; }
  .col-md-12 { grid-column-end: span 12; }
  .offset-md-0 { grid-column-start: auto; }
  .offset-md-1 { grid-column-start: 2; }
  .offset-md-2 { grid-column-start: 3; }
  .offset-md-3 { grid-column-start: 4; }
  .offset-md-4 { grid-column-start: 5; }
  .offset-md-5 { grid-column-start: 6; }
  .offset-md-6 { grid-column-start: 7; }
  .offset-md-7 { grid-column-start: 8; }
  .offset-md-8 { grid-column-start: 9; }
  .offset-md-9 { grid-column-start: 10; }
  .offset-md-10 { grid-column-start: 11; }
  .offset-md-11 { grid-column-start: 12; }
  .row-cols-md-1 { grid-template-columns: minmax(0, 1fr); }
  .row-cols-md-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .row-cols-md-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .row-cols-md-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .row-cols-md-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .row-cols-md-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (min-width: 64rem) {   /* lg — laptop */
  .col-lg-1 { grid-column-end: span 1; }
  .col-lg-2 { grid-column-end: span 2; }
  .col-lg-3 { grid-column-end: span 3; }
  .col-lg-4 { grid-column-end: span 4; }
  .col-lg-5 { grid-column-end: span 5; }
  .col-lg-6 { grid-column-end: span 6; }
  .col-lg-7 { grid-column-end: span 7; }
  .col-lg-8 { grid-column-end: span 8; }
  .col-lg-9 { grid-column-end: span 9; }
  .col-lg-10 { grid-column-end: span 10; }
  .col-lg-11 { grid-column-end: span 11; }
  .col-lg-12 { grid-column-end: span 12; }
  .offset-lg-0 { grid-column-start: auto; }
  .offset-lg-1 { grid-column-start: 2; }
  .offset-lg-2 { grid-column-start: 3; }
  .offset-lg-3 { grid-column-start: 4; }
  .offset-lg-4 { grid-column-start: 5; }
  .offset-lg-5 { grid-column-start: 6; }
  .offset-lg-6 { grid-column-start: 7; }
  .offset-lg-7 { grid-column-start: 8; }
  .offset-lg-8 { grid-column-start: 9; }
  .offset-lg-9 { grid-column-start: 10; }
  .offset-lg-10 { grid-column-start: 11; }
  .offset-lg-11 { grid-column-start: 12; }
  .row-cols-lg-1 { grid-template-columns: minmax(0, 1fr); }
  .row-cols-lg-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .row-cols-lg-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .row-cols-lg-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .row-cols-lg-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .row-cols-lg-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (min-width: 80rem) {   /* xl — desktop */
  .col-xl-1 { grid-column-end: span 1; }
  .col-xl-2 { grid-column-end: span 2; }
  .col-xl-3 { grid-column-end: span 3; }
  .col-xl-4 { grid-column-end: span 4; }
  .col-xl-5 { grid-column-end: span 5; }
  .col-xl-6 { grid-column-end: span 6; }
  .col-xl-7 { grid-column-end: span 7; }
  .col-xl-8 { grid-column-end: span 8; }
  .col-xl-9 { grid-column-end: span 9; }
  .col-xl-10 { grid-column-end: span 10; }
  .col-xl-11 { grid-column-end: span 11; }
  .col-xl-12 { grid-column-end: span 12; }
  .offset-xl-0 { grid-column-start: auto; }
  .offset-xl-1 { grid-column-start: 2; }
  .offset-xl-2 { grid-column-start: 3; }
  .offset-xl-3 { grid-column-start: 4; }
  .offset-xl-4 { grid-column-start: 5; }
  .offset-xl-5 { grid-column-start: 6; }
  .offset-xl-6 { grid-column-start: 7; }
  .offset-xl-7 { grid-column-start: 8; }
  .offset-xl-8 { grid-column-start: 9; }
  .offset-xl-9 { grid-column-start: 10; }
  .offset-xl-10 { grid-column-start: 11; }
  .offset-xl-11 { grid-column-start: 12; }
  .row-cols-xl-1 { grid-template-columns: minmax(0, 1fr); }
  .row-cols-xl-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .row-cols-xl-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .row-cols-xl-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .row-cols-xl-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .row-cols-xl-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (min-width: 90rem) {   /* 2xl — desktop besar */
  .col-2xl-1 { grid-column-end: span 1; }
  .col-2xl-2 { grid-column-end: span 2; }
  .col-2xl-3 { grid-column-end: span 3; }
  .col-2xl-4 { grid-column-end: span 4; }
  .col-2xl-5 { grid-column-end: span 5; }
  .col-2xl-6 { grid-column-end: span 6; }
  .col-2xl-7 { grid-column-end: span 7; }
  .col-2xl-8 { grid-column-end: span 8; }
  .col-2xl-9 { grid-column-end: span 9; }
  .col-2xl-10 { grid-column-end: span 10; }
  .col-2xl-11 { grid-column-end: span 11; }
  .col-2xl-12 { grid-column-end: span 12; }
  .offset-2xl-0 { grid-column-start: auto; }
  .offset-2xl-1 { grid-column-start: 2; }
  .offset-2xl-2 { grid-column-start: 3; }
  .offset-2xl-3 { grid-column-start: 4; }
  .offset-2xl-4 { grid-column-start: 5; }
  .offset-2xl-5 { grid-column-start: 6; }
  .offset-2xl-6 { grid-column-start: 7; }
  .offset-2xl-7 { grid-column-start: 8; }
  .offset-2xl-8 { grid-column-start: 9; }
  .offset-2xl-9 { grid-column-start: 10; }
  .offset-2xl-10 { grid-column-start: 11; }
  .offset-2xl-11 { grid-column-start: 12; }
  .row-cols-2xl-1 { grid-template-columns: minmax(0, 1fr); }
  .row-cols-2xl-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .row-cols-2xl-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .row-cols-2xl-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .row-cols-2xl-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .row-cols-2xl-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}


/* Kolom sama lebar & mengalir: anak mengisi satu sel. Spesifisitas dua
   kelas sengaja, supaya menang atas .row > * di atas. */
.row[class*="row-cols-"] > *,
.row:is(.row--auto, .row--auto-s, .row--auto-l) > * { grid-column: auto; }
.row > .col-full { grid-column: 1 / -1; }

.row--auto,
.row--auto-s,
.row--auto-l {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--col-min)), 1fr));
}
.row--auto   { --col-min: var(--col-min-m); }
.row--auto-s { --col-min: var(--col-min-s); }
.row--auto-l { --col-min: var(--col-min-l); }

.row--gap-s   { --row-gap: var(--space-s);   --col-gap: var(--space-s); }
.row--gap-m   { --row-gap: var(--space-m);   --col-gap: var(--space-m); }
.row--gap-l   { --row-gap: var(--space-l);   --col-gap: var(--space-l); }
.row--gap-xl  { --row-gap: var(--space-xl);  --col-gap: var(--space-xl); }
.row--gap-2xl { --row-gap: var(--space-2xl); --col-gap: var(--space-2xl); }

.row--start  { align-items: start; }
.row--center { align-items: center; }
.row--end    { align-items: end; }

/* Rel geser: di bawah lg baris menjadi satu lajur mendatar (scroll-snap)
   yang dibentangkan sampai tepi layar — kartu yang terpotong di tepi
   LAYAR terbaca "masih bisa digeser", terpotong di garis gutter terbaca
   rusak. Mulai lg kolomnya kembali mengikuti row-cols-*. */
@media (max-width: 63.99rem) {
  .row.row--rail {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: min(72%, 17rem);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    scroll-padding-inline: var(--gutter);
  }
  .row--rail::-webkit-scrollbar { display: none; }
  .row--rail > * { scroll-snap-align: start; }
}

.stack > * + * { margin-block-start: var(--flow, var(--space-s)); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster-gap, var(--space-s));
}

.prose { max-width: var(--measure); }
.prose > * + * { margin-block-start: var(--space-s); }

/* ---------- Utilitas ---------- */
.visually-hidden:not(:focus):not(:active) {
  position: absolute;
  width: 1px; height: 1px;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* Radio/checkbox yang tampilannya digantikan chip atau kartu opsi.
   Beda dengan .visually-hidden: TETAP tersembunyi saat difokus — .visually-
   hidden sengaja muncul kembali saat fokus (untuk skip-link), sehingga radio
   bawaan ikut tampil begitu diklik. Cincin fokus dipindah ke pembungkusnya
   lewat :has(:focus-visible). */
.sr-control {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: 0;
  opacity: 0;
  clip-path: inset(50%);
  overflow: hidden;
  pointer-events: none;
}

.skip-link {
  position: absolute;
  inset-inline-start: var(--space-s);
  inset-block-start: var(--space-s);
  z-index: var(--z-overlay);
  padding: var(--space-2xs) var(--space-s);
  background: var(--clr-black);
  color: var(--clr-white);
  border-radius: var(--radius-m);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--dur-base) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

.text-muted  { color: var(--fg-muted); }
.text-center { text-align: center; }

.rule {
  border: 0;
  border-block-start: var(--border-hair) solid var(--line);
  margin-block: var(--space-xl);
}

/* ---------- Scroll reveal (progressive enhancement) ---------- */
[data-reveal] { opacity: 1; }
.js [data-reveal] {
  opacity: 0;
  transform: translateY(1.75rem);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}
/* Hasil penyaringan muncul seketika. Durasi 900ms cocok untuk animasi
   masuk saat menggulir, tapi terasa lambat sebagai respons klik. */
.js [data-reveal].is-instant { transition-duration: 0s; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; }
}
