/* ==========================================================================
   FIEZEL — Design System v5
   Calm, minimal, intentional. Generous space, quiet motion.
   ========================================================================== */

:root{
  /* m025-115 - palet PASTEL "ceria, eksklusif, minimalis, mahal" (brief redesign OWNER v1,
     ditambah instruksi susulan: "SEMUA WARNANYA HARUS PASTEL").

     Dasar cream menggantikan seluruh dasar maroon gelap. Kuning pastel jadi aksen utama
     (CTA, progress, ikon aktif); koral pastel aksen kedua (streak, notifikasi, badge);
     coklat lembut jadi tinta dan garis - inilah yang menahan pastel supaya tidak jatuh
     jadi kartun; emas pastel HANYA untuk detail tipis, tidak pernah untuk teks.

     Aksen adalah warna BIDANG, bukan warna teks: #FFC700 di atas cream 1,4:1 dan
     #EE5D4A 3,2:1. Karena itu tiap keluarga punya satu turunan pekat yang khusus untuk
     tinta (--accent 6,5:1) dan satu turunan gelap untuk bayangan tombol. Tidak ada satu
     pun teks yang memakai warna pastelnya langsung di atas cream. */
  --cream:#FFF9EE;
  --cream-deep:#FFF3DC;
  --ink:#241A11;
  --yellow:#FFC700;
  --yellow-deep:#E6A800;
  --yellow-soft:#FFF3C4;
  /* m028 fase2 F2-16: --coral/--coral-deep/--coral-soft/--mint/--mint-soft/
     --teal-pastel/--lilac/--lilac-soft DIHAPUS. Ketiga keluarga ini dipensiunkan
     sebagai permukaan kontrol oleh DIRECTION: tinta di atasnya gagal kontras
     (#A8DCC4 1,4:1, #C9BCE4 1,8:1). Perannya diambil keluarga semantik yang punya
     turunan pekat: koral -> --bad/--bad-soft, mint -> --good/--good-soft,
     lilac -> --info/--info-soft. Tokennya dihapus PALING AKHIR di fase ini karena
     dua belas pemakaian var(--coral*) tidak punya fallback - menghapusnya lebih
     dulu berarti properti invalid dan bidang transparan, bukan warna lama. */
  --gold:#C9A24B;
  --sky-top:#FFE9B8;
  --sky-bottom:#FFF9EE;
  --scene-light:rgba(255,224,126,.42);
  --orbit-x:50%;
  --orbit-y:10%;
  --ambient-text:#241A11;
  --ambient-muted:#6E5E47;
  --chrome-bg:rgba(255,249,238,.82);
  --launcher-start:#FFF3C4;
  --launcher-end:#FFC700;
  --bg:#FFF9EE;
  --panel:#FFFFFF;
  --panel-soft:#FFF3DC;
  --line:#F0E4CF;
  --line-soft:#F7EFDF;
  --text:#241A11;
  --muted:#6E5E47;
  --muted-soft:#7E6C4B;
  --accent:#C2402C;
  --accent-strong:#A33422;
  --accent-soft:#FDE3DE;
  /* m025-113: aksen yang duduk di atas material kaca. Sejak m025-115 material tidak lagi
     dibalik oleh fase langit, jadi token ini cukup mengikuti tema - tetapi ia tetap ada
     supaya satu tempat saja yang memutuskan warna aksen di atas permukaan. */
  --accent-on-glass:var(--accent-strong);
  --black:#241A11;
  --green:#2E8B69;
  --green-soft:#E9F7F0;
  --red:#B8432D;
  --red-soft:#FDE3DE;
  --radius-lg:24px;
  --radius-md:16px;
  --radius-sm:12px;
  --radius-pill:999px;
  --shadow-sm:0 2px 10px rgba(36,26,17,.06);
  --shadow-md:0 10px 30px rgba(36,26,17,.09);
  --shadow-lg:0 24px 60px rgba(36,26,17,.15);
  --ease:cubic-bezier(.22,.8,.28,1);
  --ease-spring:cubic-bezier(.34,1.4,.4,1);
  --dur-s:.18s;
  --dur-m:.32s;
  --dur-l:.5s;
  /* Material permukaan. Kedalaman dari blur dan garis rambut, bukan dari kotak di atas
     kotak. Putihnya hangat (bukan #fff murni) supaya tidak pernah terbaca dingin. */
  --glass-thin:rgba(255,253,248,.58);
  --glass-regular:rgba(255,253,248,.72);
  --glass-thick:rgba(255,253,248,.82);--glass-solid:rgba(255,253,248,.98);
  --glass-edge:rgba(255,255,255,.90);
  --glass-blur:blur(28px) saturate(180%);
  --glass-blur-heavy:blur(40px) saturate(180%);
}

*{box-sizing:border-box}
/* m025-42: one scale, always. The viewport tag alone is ignored by iOS Safari, so the
   layout is pinned here as well and the gestures are refused in fiezel-zoom-lock.js.
   touch-action:manipulation is what removes the double-tap-to-zoom delay and action. */
html{scroll-behavior:smooth;touch-action:manipulation;-webkit-text-size-adjust:100%;text-size-adjust:100%}
html,body{touch-action:manipulation}
/* m025-43 OWNER: a long press anywhere popped the iOS selection/copy callout on top
   of the lesson. Selection is off app-wide; real text fields keep it, because a
   field you cannot select text in is broken. */
html,body,button,a,.card,section,article,div,p,span,h1,h2,h3,h4,b,strong,em,small,li{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
input,textarea,select,[contenteditable="true"]{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}
::selection{background:var(--accent);color:#fff}

body{
  margin:0;
  min-height:100vh;
  background:var(--sky-bottom);
  color:var(--ambient-text);
  font-family:-apple-system,BlinkMacSystemFont,"SF Pro Text",Inter,ui-sans-serif,"Segoe UI",sans-serif;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  transition:color 1.2s var(--ease),background 1.2s var(--ease);
}

.global-sky{
  position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none;
  background:linear-gradient(180deg,var(--sky-top) 0%,var(--sky-bottom) 100%);
  transition:background 1.2s var(--ease);
}
.sky-light{position:absolute;inset:-12%;background:radial-gradient(circle at var(--orbit-x) var(--orbit-y),var(--scene-light) 0%,transparent 42%);transition:background 1.2s var(--ease)}
.global-celestial{
  position:fixed;left:var(--orbit-x);top:var(--orbit-y);width:clamp(52px,6vw,76px);height:clamp(52px,6vw,76px);
  display:grid;place-items:center;transform:translate(-50%,-50%);transition:left 30s linear,top 30s linear,color .9s var(--ease),filter .9s var(--ease)
}
.global-celestial::before{content:"";position:absolute;inset:-160%;border-radius:50%;background:radial-gradient(circle,var(--scene-light) 0%,transparent 68%);filter:blur(8px)}
.global-celestial svg{position:relative;width:100%;height:100%;stroke-width:1.45}.global-celestial.sun{color:#fff0b3;filter:drop-shadow(0 0 14px rgba(255,222,145,.78))}.global-celestial.moon{color:#edf2ff;filter:drop-shadow(0 0 15px rgba(202,218,255,.72))}
/* Glass has to invert with the sky, or a white pane at midnight is a lamp in the face.
   Each phase carries its own material weights; every surface below reads them. */
.scene-day,.scene-dawn{--sky-top:#FFE9B8;--sky-bottom:#FFF9EE;--scene-light:rgba(255,224,126,.42)}
.scene-dusk{--sky-top:#FFD3B4;--sky-bottom:#FFF6EA;--scene-light:rgba(245,160,145,.30)}
.scene-night{--sky-top:#EFE0C4;--sky-bottom:#FFF9EE;--scene-light:rgba(217,188,126,.26)}
/* m025-115: penimpaan "kembalikan material gelap untuk fase terang" milik m025-85
   dihapus bersama sebab keberadaannya. Fase langit tidak lagi memasang satu pun token
   material, jadi tidak ada lagi yang perlu dikembalikan. */

button{
  font:inherit;
  color:var(--text);
  border:1px solid var(--line);
  background:var(--surface-solid);
  padding:13px 18px;
  border-radius:14px;
  cursor:pointer;
  transition:transform var(--dur-s) var(--ease-spring),
             box-shadow var(--dur-s) var(--ease),
             border-color var(--dur-s) var(--ease),
             background var(--dur-s) var(--ease),
             opacity var(--dur-s) var(--ease);
  -webkit-tap-highlight-color:transparent;
}
button:hover{transform:translateY(-1px);border-color:var(--surface-edge-strong);box-shadow:var(--shadow-sm)}
button:active{transform:translateY(0) scale(.97);transition-duration:.08s}
/* Disabled bukan lagi "teks yang sama, tapi pudar" (opacity .42 = 2,0:1, gagal AA).
   Yang mati adalah PERMUKAANNYA: panel-soft + tinta --text-disabled 4,6:1. */
button:disabled{background:var(--panel-soft);color:var(--text-disabled);border-color:var(--line);opacity:1;cursor:not-allowed;transform:none;box-shadow:none}
/* m028: satu cincin fokus untuk seluruh aplikasi. Cincin lama rgba(184,69,47,.32)
   menghasilkan 1,4:1 terhadap cream - terlihat kalau dicari, tidak terlihat kalau dipakai.
   --focus-ring #A67A00 = 3,4:1 terhadap cream, di atas ambang 3:1 untuk komponen non-teks. */
button:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
/* m025-63 accessibility pass. Sebelumnya hanya tombol yang punya cincin fokus, sehingga
   pengguna keyboard kehilangan jejak begitu berpindah ke tautan atau kolom isian. */
a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible,summary:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
/* Ukuran sentuh minimum ditegaskan, bukan hanya kebetulan hasil padding: satu perubahan
   ukuran huruf tidak boleh diam-diam menyusutkan sasaran sentuh di bawah 44px. */
button,.nav,input[type="url"],input[type="text"],input[type="password"],input[type="email"],input[type="number"],select{min-height:44px}
input[type="checkbox"],input[type="radio"]{min-width:24px;min-height:24px}

.app{max-width:800px;margin:auto;padding:20px 18px calc(118px + env(safe-area-inset-bottom));position:relative;z-index:2}

/* ---------- topbar ---------- */
.topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:22px;padding-top:2px}
/* m025-91: wordmark topbar kini SVG, bukan teks. Lebar menggantikan ukuran huruf, dan
   warnanya datang dari gradien di dalam SVG - bukan dari --ambient-text - sehingga ia tidak
   lagi ikut menggelap/menerang mengikuti jam seperti teks di sekitarnya. */
.brand{display:block;width:104px}
.fiezel-wordmark{display:block;width:100%;height:auto}
.version{font-size:.68rem;color:var(--muted-soft);font-variant-numeric:tabular-nums}

/* ---------- section head ---------- */
.section-head{display:flex;justify-content:space-between;gap:16px;margin:6px 0 20px}
.section-head h1{font-size:1.65rem;margin:0 0 4px;letter-spacing:-.03em;font-weight:700;color:var(--ambient-text)}
.section-head p{color:var(--ambient-muted)}.muted{color:var(--muted)}.section-head p,.muted{font-size:.86rem;line-height:1.55}

/* ---------- cards ---------- */
.card{
  background:var(--panel);
  color:var(--text);
  border:1px solid var(--line);
  border-radius:var(--radius-lg);
  padding:20px;
  margin-bottom:12px;
  box-shadow:var(--shadow-sm);
  animation:riseIn var(--dur-m) var(--ease) both;
  transition:box-shadow var(--dur-m) var(--ease),transform var(--dur-m) var(--ease);
}
.fade .card:nth-of-type(1){animation-delay:.02s}
.fade .card:nth-of-type(2){animation-delay:.07s}
.fade .card:nth-of-type(3){animation-delay:.12s}
.fade .card:nth-of-type(4){animation-delay:.17s}
.fade .card:nth-of-type(5){animation-delay:.22s}
.fade .card:nth-of-type(n+6){animation-delay:.26s}

.hero{padding:26px;background:linear-gradient(150deg,var(--surface-solid) 0%,var(--sun-soft) 130%);border-color:var(--line)}
.hero h2{font-size:1.85rem;line-height:1.12;letter-spacing:-.035em;margin:8px 0 8px;font-weight:700}
.hero p{color:var(--muted);line-height:1.6;font-size:.92rem;margin:0 0 16px}
.eyebrow{font-size:12px;letter-spacing:.1em;color:var(--info);font-weight:700;text-transform:uppercase}

.status-pill{
  display:inline-flex;align-items:center;gap:6px;margin-top:14px;
  font-size:12px;font-weight:700;color:var(--accent-strong);
  background:rgba(var(--surface-pure-rgb),.7);border:1px solid var(--surface-edge);
  padding:6px 12px;border-radius:999px;
}

.actions,.toolbar,.three{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px}
.primary{background:var(--sun);color:var(--text);border-color:var(--sun-deep)}
.primary:hover{background:var(--sun-deep);box-shadow:var(--shadow-md)}
.danger{color:var(--bad);border-color:var(--bad-soft)}
.primary.danger{background:var(--bad);color:var(--on-core);border-color:var(--bad)}

/* ---------- stats ---------- */
.stats{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:12px}
.stats>div{
  background:var(--panel);border:1px solid var(--line);border-radius:var(--radius-md);
  padding:16px;animation:riseIn var(--dur-m) var(--ease) both;
}
.stats>div:nth-child(1){animation-delay:.02s}
.stats>div:nth-child(2){animation-delay:.06s}
.stats>div:nth-child(3){animation-delay:.10s}
.stats>div:nth-child(4){animation-delay:.14s}
.stats small{display:block;color:var(--muted-soft);font-size:.66rem;text-transform:uppercase;letter-spacing:.09em;font-weight:700}
.stats strong{display:block;font-size:1.4rem;margin-top:6px;letter-spacing:-.02em}

.grid{display:grid;gap:12px}
.grid .card{margin:0}
.row{display:flex;justify-content:space-between;align-items:center;gap:12px}
.row span{color:var(--muted);font-size:.78rem}
.row b{font-weight:700}

.library{display:flex;flex-wrap:wrap;gap:9px;color:var(--ink-soft);font-size:.78rem;margin-top:12px}
.library span{background:var(--panel-soft);padding:6px 11px;border-radius:999px}

.pill,.notice{display:inline-block;border:1px solid var(--surface-edge);border-radius:999px;padding:5px 11px;color:var(--accent-strong);background:var(--accent-soft);font-size:12px;min-height:24px;font-weight:600}

/* m025-85: Peta Belajar tab switcher - keeps the 17 sections that used to be one
   long scroll grouped and reachable without turning this into a separate route. */
/* Segmented control, bukan deretan tombol lepas: kapsulnya SATU bidang --panel-soft
   dan tab-nya kehilangan garisnya sendiri, jadi yang terbaca adalah satu kontrol
   dengan satu bagian terpilih. Tab aktif = bidang tinta (resep components.css §6). */
.progress-tabs{display:flex;gap:6px;overflow-x:auto;margin:14px 0 18px;padding:4px;background:var(--panel-soft);border-radius:var(--radius-pill);-webkit-overflow-scrolling:touch}
.progress-tab{flex:0 0 auto;padding:9px 16px;border-radius:var(--radius-pill);border:0;background:transparent;color:var(--muted);font-size:.82rem;font-weight:600;min-height:36px;white-space:nowrap}
.progress-tab.active{background:var(--text);border-color:var(--text);color:var(--on-core)}

.topline{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}
.word{font-size:2.6rem;margin:6px 0;font-weight:700;letter-spacing:-.03em}
.phonetic{color:var(--muted-soft)}
.card hr{border:0;border-top:1px solid var(--line);margin:18px 0}

/* ---------- quiz ---------- */
.question{font-size:1.35rem;line-height:1.34;margin:8px 0 18px;font-weight:700;letter-spacing:-.01em}
.options{display:grid;gap:9px}
.option{
  text-align:left;background:var(--panel);border:1.5px solid var(--line);
  min-height:52px;padding:15px 16px;border-radius:var(--radius-md);
  position:relative;transition:transform var(--dur-s) var(--ease-spring),
  background var(--dur-s) var(--ease),border-color var(--dur-s) var(--ease),
  box-shadow var(--dur-s) var(--ease);
}
.option:not(:disabled):hover{background:var(--panel-soft);border-color:var(--sun-deep)}
.option.correct{border-color:var(--good-bright);background:var(--good-soft);animation:pop .32s var(--ease-spring)}
.option.wrong{border-color:var(--bad);background:var(--bad-soft);animation:shake .32s var(--ease)}
/* Mode review mematikan tombol pilihan. Resep disabled global mengubah permukaan +
   tinta - untuk pilihan jawaban itu SALAH: jawabannya masih harus dibaca. Di sini
   disabled hanya melepas interaksi, warna state benar/salah tetap. */
.option:disabled{background:var(--panel);color:var(--text);border-color:var(--line);opacity:1;cursor:default}
.option.correct:disabled{border-color:var(--good-bright);background:var(--good-soft)}
.option.wrong:disabled{border-color:var(--bad);background:var(--bad-soft)}
.feedback{
  margin-top:14px;padding:18px;border:1px solid var(--line);border-radius:18px;
  background:var(--surface-cool);line-height:1.6;font-size:.87rem;
  animation:riseIn var(--dur-m) var(--ease) both;
}
.feedback.hidden{display:none}
.feedback b{font-size:1rem}
.feedback p{margin:9px 0}
.distractor-breakdown{margin-top:6px;padding-top:6px;border-top:1px dashed var(--line)}
.distractor-breakdown p{font-size:.83rem;margin:6px 0}

.passage{font-size:.89rem;line-height:1.75;color:var(--ink-soft)}
.center{text-align:center}
.emoji{font-size:2.6rem}
.score{font-size:3.4rem;font-weight:700;color:var(--green);margin:10px 0;letter-spacing:-.03em;animation:pop .5s var(--ease-spring)}
.meter{margin:13px 0}
/* Track = --line-soft (garis, bukan bidang biru dingin #e9eef5 yang tidak ada di
   palet sama sekali). Isi = keluarga sun, gelap ke arah kanan supaya arah majunya
   terbaca tanpa membaca angkanya. */
.bar{height:8px;background:var(--line-soft);border-radius:999px;overflow:hidden;margin-top:7px}
.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--sun),var(--sun-deep));border-radius:999px;transition:width .6s var(--ease)}

/* ---------- toast ---------- */
.toast{
  position:fixed;left:50%;bottom:96px;transform:translate(-50%,16px) scale(.96);opacity:0;pointer-events:none;
  /* m028: toast dulu koral dengan tinta coklat di atasnya - 3,1:1, di bawah ambang teks,
     dan itu satu-satunya cara aplikasi mengabarkan kesalahan. Sekarang permukaan core
     dengan krem di atasnya: 14,7:1, dan sekeluarga dengan panggung splash. */
  background:var(--core);color:var(--on-core);padding:13px 20px;border-radius:var(--radius-pill);font-weight:700;font-size:.86rem;
  transition:opacity var(--dur-m) var(--ease),transform var(--dur-m) var(--ease-spring);
  z-index:80;box-shadow:0 18px 40px rgba(0,0,0,.22);max-width:88%;text-align:center
}
.toast.show{opacity:1;transform:translate(-50%,0) scale(1)}

.answer-burst{
  position:fixed;left:50%;top:clamp(92px,18vh,170px);z-index:130;pointer-events:none;
  width:min(330px,calc(100% - 32px));display:grid;justify-items:center;gap:5px;padding:20px 24px;
  border:1px solid rgba(var(--surface-pure-rgb),.7);border-radius:22px;background:rgba(var(--surface-pure-rgb),.96);
  box-shadow:0 26px 70px rgba(36,26,17,.24);opacity:0;transform:translate(-50%,-18px) scale(.84);
  transition:opacity .25s var(--ease),transform .38s var(--ease-spring);backdrop-filter:blur(16px)
}
.answer-burst.hidden{display:none}.answer-burst.show{opacity:1;transform:translate(-50%,0) scale(1)}
.answer-burst-icon{width:54px;height:54px;display:grid;place-items:center;border-radius:17px;margin-bottom:3px}.answer-burst-icon svg{width:30px;height:30px}
.answer-burst strong{font-size:1.24rem;letter-spacing:-.02em}.answer-burst small{color:var(--muted);font-size:.76rem;text-align:center}
.answer-burst.success .answer-burst-icon{color:var(--good);background:var(--good-soft)}
.answer-burst.error .answer-burst-icon{color:var(--bad);background:var(--bad-soft)}

/* ---------- bottom nav ---------- */
.bottomnav{
  position:fixed;bottom:max(12px,env(safe-area-inset-bottom));left:50%;transform:translateX(-50%);width:min(560px,calc(100% - 24px));
  padding:7px;background:rgba(var(--surface-pure-rgb),.86);
  border:1px solid rgba(239,231,232,.9);border-radius:22px;
  display:grid;grid-template-columns:repeat(5,1fr);gap:4px;z-index:40;
  box-shadow:0 16px 40px rgba(36,26,17,.10);
}
.nav{
  /* m028: lantai 12px. Label navigasi 10,4px adalah teks yang harus dibaca setiap hari;
     di bawah 12px ia berhenti terbaca sebagai kata dan hanya jadi bentuk. */
  border:0;background:transparent;padding:9px 4px;font-size:12px;font-weight:600;color:var(--muted);
  border-radius:15px;line-height:1.5;transition:color var(--dur-s) var(--ease),background var(--dur-m) var(--ease),transform var(--dur-s) var(--ease-spring)
}
.nav:hover{transform:none;box-shadow:none;border-color:transparent}
.nav.active{color:var(--black);background:var(--panel-soft);transform:translateY(-2px)}

/* ---------- animations ---------- */
.fade{animation:pageIn var(--dur-l) var(--ease)}
@keyframes pageIn{from{opacity:0;transform:translateY(14px) scale(.99)}to{opacity:1;transform:none}}
@keyframes riseIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes pop{0%{transform:scale(.94)}55%{transform:scale(1.015)}100%{transform:scale(1)}}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}

.error{margin-top:26px;padding:20px;border:1px solid #f3c3cf;background:var(--red-soft);border-radius:18px;color:var(--ink-danger)}

/* ---------- flashcards ---------- */
.flashcard{width:100%;min-height:340px;cursor:pointer;perspective:1400px;border:1px solid var(--line);border-radius:24px;background:transparent;color:inherit;outline:none;box-shadow:var(--shadow-sm)}
.flash-inner{position:relative;width:100%;min-height:340px;transition:transform .55s var(--ease-spring);transform-style:preserve-3d}
.flashcard.flipped .flash-inner{transform:rotateY(180deg)}
.flash-face{position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;border-radius:24px;padding:30px;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;background:var(--surface-solid)}
.flash-front{transform:rotateY(0deg)}
.flash-back{transform:rotateY(180deg);overflow:auto}
.flash-face .word{margin:.4rem 0}
.flash-face hr{width:100%;border:0;border-top:1px solid var(--line);margin:16px 0}
.flash-actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:16px}
.swipe-hint{text-align:center;color:var(--muted-soft);font-size:.74rem;margin:10px 0 2px}
.flashcard:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;box-shadow:none}

.three{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:14px}

/* ---------- quiz shell ---------- */
.quiz-shell{padding-bottom:20px}
.quiz-topbar{
  position:sticky;top:0;z-index:30;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;
  padding:10px 0 14px;background:rgba(var(--bg-rgb),.9);backdrop-filter:blur(14px)
}
.quiz-progress{text-align:center;font-weight:700}
.quiz-progress span{font-size:1.1rem}
.quiz-progress em{font-style:normal;color:var(--muted-soft)}
.quiz-next{justify-self:end;background:var(--sun);color:var(--text);border-color:var(--sun-deep);min-width:92px}
/* m028: keadaan nonaktif dulu memakai opacity global .42 di atas permukaan redup - hasilnya
   teks 2,4:1, tidak terbaca. Sekarang keadaan nonaktif punya warnanya sendiri (4,8:1):
   tetap jelas terbaca sebagai TIDAK BISA DIKLIK, tanpa menghilang. */
.quiz-next:disabled{background:var(--panel-soft);color:var(--text-disabled);border-color:var(--line);opacity:1}

/* m025-114: soal listening di tes penempatan. Tombolnya harus terbaca sebagai satu-satunya
   jalan ke soal - naskahnya sengaja tidak pernah dirender, jadi tanpa tombol ini murid
   hanya melihat pertanyaan tanpa bahan. */
.quiz-listen{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px}
/* m025-117: tombolnya ikut bahasa chunky milik redesign pastel - bidang koral, tinta
   coklat, bayangan pekat 4px yang memendek saat ditekan. Ia memakai koral, bukan kuning,
   supaya tidak bersaing dengan aksi utama layar; dan koral memang peran aksi kedua. */
.quiz-listen-btn{display:inline-flex;align-items:center;gap:8px;padding:11px 18px;min-height:44px;
  /* m028: koral dengan tinta coklat = 3,1:1. Tombol ini memutar audio soal - satu-satunya
     jalan menjawab soal listening - jadi ia dipindah ke permukaan tinta: krem di atas
     coklat 13,9:1, dan ia tetap TIDAK kuning sehingga tidak bersaing dengan aksi utama. */
  border:0;border-radius:var(--radius-md);background:var(--text);color:var(--on-core);
  font-weight:700;letter-spacing:-.01em;cursor:pointer;
  box-shadow:0 4px 0 var(--ink-press),0 10px 22px rgba(36,26,17,.13);
  transition:transform .12s var(--ease),box-shadow .12s var(--ease),background .2s var(--ease)}
.quiz-listen-btn:hover:not(:disabled){background:var(--ink-hover)}
.quiz-listen-btn:active:not(:disabled){
  transform:translateY(3px);box-shadow:0 1px 0 var(--ink-press),0 4px 10px rgba(36,26,17,.12)}
.quiz-listen-btn:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.quiz-listen-btn:disabled{background:var(--panel-soft);color:var(--text-disabled);opacity:1;
  cursor:progress;transform:translateY(3px);
  box-shadow:0 1px 0 var(--line)}
.quiz-listen .muted{font-size:13px}

/* ---------- level grid ---------- */
.level-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:11px}
.level-card{width:100%;display:flex;align-items:center;gap:12px;text-align:left;padding:16px;background:var(--surface-solid)}
.level-number{width:32px;height:32px;border-radius:11px;display:grid;place-items:center;background:var(--accent-soft);color:var(--accent-strong);font-weight:700}
.level-card p{margin:2px 0 0;color:var(--muted);font-size:.75rem}

/* ---------- welcome / modal overlays ---------- */
.welcome,.modal{
  /* Backdrop dulu kabut TERANG di atas layar terang (rgba(bg,.82)) - panel dialog
     tidak pernah benar-benar terangkat dari latarnya. Scrim gelap turunan --text
     memisahkan keduanya tanpa menambah satu elemen pun. */
  position:fixed;inset:0;background:var(--scrim);backdrop-filter:blur(18px);
  display:grid;place-items:center;z-index:100;opacity:0;pointer-events:none;transition:opacity var(--dur-l) var(--ease);
  padding:20px;
}
.welcome.show,.modal.show{opacity:1;pointer-events:auto}
.welcome.hidden,.modal.hidden{display:none}
.welcome-panel,.modal-panel{
  width:min(460px,100%);padding:32px 26px;border:1px solid var(--line);border-radius:var(--radius-lg);
  background:rgba(var(--surface-pure-rgb),.98);box-shadow:var(--shadow-lg);text-align:center;
  transform:translateY(16px) scale(.96);transition:transform .45s var(--ease-spring);
}
.welcome.show .welcome-panel,.modal.show .modal-panel{transform:none}
.notification-locked .app,.notification-locked .bottomnav{visibility:hidden;pointer-events:none;user-select:none}
.notification-gate{display:grid;place-items:center;opacity:1;pointer-events:auto;background:rgba(26,12,18,.82);backdrop-filter:blur(18px)}
.notification-gate.hidden{display:none}.notification-gate.show{opacity:1}
.notification-panel{box-shadow:0 28px 90px rgba(0,0,0,.28)}
.notification-requirement{display:flex;gap:10px;align-items:flex-start;margin:18px 0 14px;padding:13px 14px;border:1px solid rgba(184,69,47,.18);border-radius:14px;background:var(--accent-soft);color:var(--text);font-size:.78rem;line-height:1.5;text-align:left}
.notification-requirement svg{width:18px;flex:0 0 auto;margin-top:1px;color:var(--accent-strong)}
.notification-status{margin:10px 0 0!important;padding:10px 12px;border-radius:12px;background:var(--surface-warm);color:var(--muted)!important;font-size:.76rem!important;font-weight:700}
.notification-status.success{background:#edf8f3;color:#277f68!important}.notification-status.error{background:#fff0f2;color:#b04b5f!important}
.notification-help{font-size:.72rem!important;margin:12px 0 0!important}.notification-panel .primary[disabled]{opacity:.72;cursor:not-allowed;transform:none}
/* ---------- Gerbang akun Puter, digubah mengikuti Audit UX Bagian 3 ----------
   Bentuknya sekarang mengikuti layar Apple Sign-In: latar tenang satu warna, lambang
   merek di atas, judul besar berjarak lega, SATU tombol utama penuh lebar berbentuk
   pil, lalu keterangan kecil yang diam. Tidak ada ikon dekoratif, tidak ada kartu
   bergradien, tidak ada elemen bawaan browser yang terlihat - kelapangan yang membawa
   kesan mahal, bukan ornamen. */
.auth-locked .app,.auth-locked .bottomnav{visibility:hidden;pointer-events:none;user-select:none}
.auth-gate{z-index:150;background:var(--bg);backdrop-filter:none}
.auth-gate .auth-panel{
  width:min(400px,100%);
  padding:44px 34px 36px;
  border:1px solid var(--line);
  border-radius:26px;
  background:var(--panel);
  box-shadow:var(--shadow-lg);
  text-align:center;
}
.auth-gate .auth-mark{display:block;width:72px;height:72px;margin:0 auto 26px;border-radius:20px;object-fit:contain}
.auth-gate .auth-panel h2{
  margin:0 0 10px;
  font-family:var(--fz-heading);
  font-size:1.62rem;line-height:1.2;letter-spacing:-.03em;font-weight:700;
  color:var(--text);
}
.auth-gate .auth-panel #authGateBody{
  margin:0 auto 26px;max-width:19rem;
  color:var(--muted);font-size:.88rem;line-height:1.6;
}
/* Status dirancang sebagai komponen sendiri, bukan alert bawaan browser (Bagian 3). */
.auth-gate .auth-status{
  margin:0 0 16px;padding:10px 14px;border-radius:12px;
  background:var(--panel-soft);color:var(--muted);
  font-size:.76rem;font-weight:700;line-height:1.45;
}
.auth-gate .auth-status.success{background:var(--green-soft);color:var(--green)}
.auth-gate .auth-status.error{background:var(--red-soft);color:var(--red)}
/* Satu tombol, penuh lebar, tinggi 52px - hierarki tombol Apple: yang utama tidak
   berbagi panggung dengan apa pun. */
.auth-gate .auth-primary{
  display:flex;align-items:center;justify-content:center;gap:9px;
  width:100%;min-height:52px;padding:0 20px;
  border:0;border-radius:999px;
  background:var(--sun);color:var(--text);
  font-family:var(--fz-body);font-size:.96rem;font-weight:600;letter-spacing:-.01em;
  box-shadow:0 10px 26px rgba(36,26,17,.14);
}
.auth-gate .auth-primary:hover{background:var(--sun-deep);border-color:transparent;box-shadow:var(--shadow-md)}
.auth-gate .auth-primary svg{width:19px;height:19px}
.auth-gate .auth-primary[disabled]{background:var(--panel-soft);color:var(--text-disabled);opacity:1;cursor:not-allowed;transform:none;box-shadow:none}
.auth-gate .auth-help{margin:18px 0 0;color:var(--muted);font-size:.76rem;line-height:1.55}
.auth-gate .auth-legal{margin:14px 0 0;color:var(--muted-soft);font-size:.68rem;line-height:1.5}
@media (max-width:420px){.auth-gate .auth-panel{padding:36px 24px 30px;border-radius:22px}.auth-gate .auth-mark{width:60px;height:60px;margin-bottom:20px}}
.auth-panel .primary[disabled]{opacity:.6;cursor:not-allowed;transform:none}
.welcome-mark,.modal-mark{font-weight:700;letter-spacing:-.06em;font-size:1.02rem;color:var(--black)}
.welcome-panel h2,.modal-panel h2{font-size:1.9rem;letter-spacing:-.03em;margin:12px 0 8px;font-weight:700}
.welcome-panel p,.modal-panel p{color:var(--muted);line-height:1.6;font-size:.92rem}
.welcome-panel .primary,.modal-actions{margin-top:16px}
.modal-actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.modal-actions button{flex:1;min-width:120px}

/* ---------- FIEZEL AI ---------- */
.ai-btn{
  margin-top:14px;width:100%;
  background:linear-gradient(135deg,var(--accent-soft),var(--panel-soft));
  border-color:var(--line);color:var(--accent-strong);font-weight:700;
}
.ai-btn:hover{border-color:var(--accent);box-shadow:var(--shadow-md)}
.ai-answer{margin-top:6px;line-height:1.7;font-size:.92rem;color:var(--text);text-align:left}
.ai-answer p{margin:0 0 10px;color:var(--text)}
.ai-loading{display:flex;gap:7px;justify-content:center;margin:22px 0}
.ai-loading span{width:9px;height:9px;border-radius:50%;background:var(--accent);animation:aiBounce calc(var(--dur-l) + var(--dur-l)) var(--ease) infinite}
.ai-loading span:nth-child(2){animation-delay:var(--dur-s)}
.ai-loading span:nth-child(3){animation-delay:var(--dur-m)}
@keyframes aiBounce{0%,80%,100%{transform:translateY(0);opacity:.5}40%{transform:translateY(-7px);opacity:1}}

@media(min-width:640px){
  .app{padding-top:30px}
  .stats{grid-template-columns:repeat(4,1fr)}
}
@media(max-width:640px){
  .hero h2{font-size:1.6rem}
  .three{grid-template-columns:1fr 1fr}
  .three button:last-child{grid-column:1/-1}
  .level-grid{grid-template-columns:1fr}
  .quiz-topbar{top:-1px}
}

@media(prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* ---------- misc feature blocks (progress / diagnostics) ---------- */
.adaptive-note{margin-top:8px}
.passage{background:var(--surface-cool);border:1px solid var(--line);border-radius:18px;padding:18px;margin-bottom:14px}
.passage h3{margin:5px 0 8px;font-size:1.02rem}
.passage p{white-space:pre-wrap}
.flash-back .muted{margin-top:12px}
/* ==========================================================================
   Popup keyakinan (m025-133)
   ==========================================================================
   Percobaan ketiga, dan dua yang gagal sebelumnya layak dicatat karena keduanya salah
   dengan cara yang sama: kotak ini selalu dipindah TEMPATNYA, sementara masalahnya soal
   WAKTU. Di dasar panel umpan balik ia harus dicari dengan menggulir. Mengambang di dasar
   layar ia justru menutupi tombol Lanjut.

   Sebagai popup ia tidak perlu dicari dan tidak menghalangi apa pun - karena ia SENDIRI
   yang membawa tombol Lanjutnya, persis yang diminta OWNER.

   Ukurannya sengaja kecil dan duduk agak ke bawah: penjelasan jawaban ada di halaman di
   baliknya, dan latar gelapnya dibuat tipis supaya halaman itu tetap terlihat. Popup yang
   menutup pelajarannya sendiri akan menukar satu masalah dengan masalah lain.
   -------------------------------------------------------------------------- */
.confidence-pop{
  position:fixed;inset:0;z-index:2147481400;
  display:flex;align-items:flex-end;justify-content:center;
  padding:14px 14px calc(20px + env(safe-area-inset-bottom));
  background:var(--scrim-soft);
}
.confidence-card{
  width:min(420px,100%);
  padding:16px;border-radius:24px;
  border:1.5px solid var(--ink);background:rgba(var(--surface-pure-rgb),.98);
  box-shadow:0 3px 0 var(--ink),0 22px 50px rgba(36,26,17,.3);
}
.confidence-verdict{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:.98rem;font-weight:700;letter-spacing:-.01em}
.confidence-verdict svg{width:20px;height:20px;flex:none}
.confidence-verdict.is-ok{color:var(--good)}
.confidence-verdict.is-no{color:var(--bad)}
.confidence-q{margin:0 0 9px;font-size:.88rem;font-weight:700;color:var(--text)}

.confidence-scale{display:grid;grid-template-columns:repeat(3,1fr);gap:7px}
.confidence-scale button{
  flex-direction:column;gap:2px;min-height:62px;padding:9px 4px;
  font-size:.7rem;font-weight:700;line-height:1.25;text-align:center;border-radius:15px;
}
.confidence-scale button span{font-size:1.15rem;font-weight:700;line-height:1;font-variant-numeric:tabular-nums}
/* Tiga tingkat, tiga warna - supaya terbaca sebagai SKALA, bukan tiga tombol yang
   kebetulan bersebelahan. */
.confidence-scale button:nth-child(1){background:var(--bad-soft)}
.confidence-scale button:nth-child(2){background:var(--sun-soft)}
/* Tinta tombol ketiga dipasang EKSPLISIT. --yellow beku di kedua tema, sementara tinta
   yang diwarisi ikut berbalik jadi krem di mode gelap - krem di atas kuning. */
.confidence-scale button:nth-child(3){background:var(--sun);color:var(--text)}

.confidence-skip{
  display:block;width:100%;margin-top:10px;min-height:0;padding:6px;
  background:none;border:0;box-shadow:none;
  color:var(--muted);font-size:.78rem;font-weight:600;text-decoration:underline;
}
.confidence-skip:hover{background:none;box-shadow:none;transform:none;color:var(--text)}

.confidence-saved{
  display:flex;align-items:center;gap:6px;margin:0 0 12px;
  font-size:.86rem;font-weight:700;color:var(--good);
}
.confidence-saved svg{width:16px;height:16px}
.confidence-go{width:100%;min-height:54px;font-size:1rem;font-weight:700}

@media (prefers-reduced-motion:no-preference){
  .confidence-pop{animation:fzPopFade .2s var(--ease) both}
  .confidence-card{animation:fzPopRise .32s cubic-bezier(.3,1.12,.5,1) both}
  @keyframes fzPopFade{from{opacity:0}to{opacity:1}}
  @keyframes fzPopRise{from{opacity:0;transform:translateY(22px) scale(.97)}to{opacity:1;transform:none}}
  .confidence-pop.is-out{animation:fzPopFade .2s var(--ease) reverse both}
}
.confidence-pop.is-out{opacity:0;pointer-events:none}
.creator-credit{display:flex;align-items:center;gap:9px;margin-top:10px;color:var(--muted);font-size:.82rem}
.instagram-mark{width:22px;height:22px;border:2px solid var(--black);border-radius:7px;display:inline-grid;place-items:center;font-size:16px;line-height:1}
.grid>div>h3{margin:4px 2px 12px;font-size:1rem}
.grid hr{border:0;border-top:1px solid var(--line);margin:10px 0}
.timeline-row{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:1px solid var(--line-soft);font-size:.82rem}
.timeline-row span:last-child{color:var(--muted);text-align:right}
.diag-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:12px 0}
.diag-grid>div{padding:12px;border:1px solid var(--line);border-radius:14px;background:var(--surface-tint)}
.confusion-network{display:grid;gap:9px}
.confusion-node{display:grid;grid-template-columns:1fr auto 1fr;gap:8px;align-items:center;padding:10px;border:1px solid var(--line);border-radius:14px}
.confusion-node span:nth-child(3){text-align:right}
.confusion-node small{grid-column:1/-1;color:var(--muted)}
.creator-link{display:inline-flex;align-items:center;gap:7px;color:inherit;text-decoration:none}
.creator-link img{display:block}
@media(max-width:640px){
  .diag-grid{grid-template-columns:1fr}
  .timeline-row{align-items:flex-start;flex-direction:column}
  .timeline-row span:last-child{text-align:left}
}

/* ==========================================================================
   FIEZEL Design System v6.0
   Premium personal launcher, unified motion, tactile navigation, Creator Hub.
   ========================================================================== */

/* m025-46: this is the palette the product actually runs on - it overrides the block
   at the top of the file.
   m025-115: netralnya ikut pindah ke keluarga cream/pastel. Blok ini gampang terlewat
   justru karena ia yang menang - kalau hanya blok paling atas yang diganti, aplikasi
   tetap berjalan dengan netral marun lama sementara tokennya sudah pastel. */
:root{
  --bg:#FFF9EE;
  --panel:#FFFFFF;
  --panel-soft:#FFF3DC;
  --line:#F0E4CF;
  --line-soft:#F7EFDF;
  --text:#241A11;
  --muted:#6E5E47;
  --muted-soft:#7E6C4B;
  --accent:#C2402C;
  --accent-strong:#A33422;
  --accent-soft:#FDE3DE;
  --black:#241A11;
  --gold:#C9A24B;
  /* m025-127 wordmark topbar. Empat token ini ada karena logonya BUKAN teks: ia SVG dengan
     gradien di dalamnya, jadi ia tidak ikut --ambient-text dan tidak ikut berbalik di mode
     gelap. Sampai m025-118 itu benar - topbarnya maroon gelap dan gading di atasnya terbaca.
     Sejak dasar berubah jadi cream (m025-119/120), gading #FFFBF3 duduk di atas cream
     #FFF9EE: 1,02:1. Bukan "kurang kontras" - benar-benar tidak terlihat.

     Perannya persis peran yang brief palet berikan: coklat sebagai TINTA untuk hurufnya,
     terracotta sebagai AKSEN untuk dua balok. Tidak ada warna baru yang ditambahkan. */
  --wordmark-ink-hi:#241A11;
  --wordmark-ink-lo:#4A382A;
  --wordmark-accent-hi:#C9432F;
  --wordmark-accent-lo:#A33422;
  --green:#2E8B69;
  --green-soft:#E9F7F0;
  --red:#B8432D;
  --red-soft:#FDE3DE;
  --radius-lg:24px;
  --radius-md:16px;
  --radius-sm:12px;
  --radius-pill:999px;
  --shadow-sm:0 2px 10px rgba(36,26,17,.06);
  --shadow-md:0 10px 30px rgba(36,26,17,.09);
  --shadow-lg:0 24px 60px rgba(36,26,17,.15);
  /* ---- m028 "Warm Paper, Bright Mind" (design/redesign-v1/tokens/tokens.css) ----
     Keluarga token BARU. Yang lama TIDAK dihapus di fase ini: nilainya sudah ditukar
     di tempat, jadi seluruh layar ikut pindah tanpa satu selektor pun berubah. Keluarga
     di bawah adalah yang dipakai lapisan baru (splash, onboarding, komponen hi-fi) dan
     yang akan menggantikan alias lama di Fase 2.

     Kuning adalah warna BIDANG, bukan warna teks: --sun di atas --bg 1,5:1. Setiap
     keluarga karena itu punya turunan pekat khusus tinta (--sun-deep untuk garis,
     --info untuk teks kecil) - tidak ada teks yang memakai --sun langsung. */
  --sun:#FFC700;
  --sun-deep:#E6A800;
  --sun-press:#CC9600;
  --sun-soft:#FFF3C4;
  --sun-grad:linear-gradient(180deg,#FFDE59,#FFA500);
  /* Permukaan gelap "core": panggung splash, kartu highlight, toast. Satu keluarga saja,
     supaya ikon aplikasi, splash, dan toast terbaca sebagai satu benda. */
  --core:#1B1418;
  --core-soft:#2A2126;
  --core-line:#3A3038;
  --on-core:#FDFAF3;
  --on-core-muted:rgba(253,250,243,.68);
  --good:#1F6B4E;
  --good-bright:#2E8B69;
  --good-soft:#E9F7F0;
  --bad:#AC3E2A;
  --bad-soft:#FDE3DE;
  /* --info adalah SATU-SATUNYA kuning yang boleh jadi teks: #7A5F1B di atas cream 5,9:1. */
  --info:#7A5F1B;
  --info-soft:#FFF3C4;
  /* Cincin fokus tunggal untuk seluruh aplikasi. --gold (#C9A24B) yang dipakai sebelumnya
     hanya 1,9:1 terhadap cream - cincin yang tidak terlihat sama dengan tidak ada cincin. */
  --focus-ring:#A67A00;
  --text-disabled:#75654C;
  --ink-hover:#3A2B1C;
  --ink-press:#120C07;
  /* Fase 2: tiga token yang dipakai komponen fase ini tetapi belum ada di Fase 1.
     --bad-bright = kembaran terang --bad (nilainya sama dengan --red sekarang) untuk
     GARIS/bidang, bukan teks kecil. --scrim* = backdrop modal turunan --text; sebelum
     ini backdrop dialog memakai rgba(var(--bg-rgb),.82) alias kabut TERANG di atas
     layar terang - panelnya tidak pernah benar-benar terangkat dari latarnya. */
  --bad-bright:#B8432D;
  --scrim:rgba(36,26,17,.45);
  --scrim-soft:rgba(36,26,17,.28);
  /* m025-85 kontras: sebelum ini puluhan permukaan memaku warnanya sendiri (#fff,
     rgba(255,254,250,.9), #f6f4ed, ...) sementara TEKS di atasnya memakai var(--text).
     Di mode gelap teksnya jadi #fdf4f6 di atas putih - 1,08:1, tidak terbaca sama sekali,
     dan itulah bug "warna tulisan dan background sama" yang dilaporkan OWNER.
     Nilai terang di bawah SENGAJA sama persis dengan literal yang digantikannya, supaya
     mode terang tidak bergeser satu piksel pun; hanya kembaran gelapnya yang baru.
     --*-rgb dipakai lewat rgba(var(--x-rgb),alpha) karena banyak permukaan translusen. */
  /* m025-115: nilainya digeser ke keluarga cream/pastel. Sampai rilis ini token-token di
     bawah memang dikunci persis pada literal terang lamanya (kontrak m025-85 "mode terang
     tidak boleh bergeser"); brief redesign OWNER memang meminta pergeseran itu, jadi
     kuncinya dipindahkan ke nilai baru di contrast-test, bukan dibuang. */
  --surface-rgb:255,253,248;
  --surface-pure-rgb:255,255,255;
  --bg-rgb:255,249,238;
  --surface-solid:#ffffff;
  --surface-tint:#fffbf4;
  --surface-warm:#fdf4e6;
  --surface-cool:#f7f7f1;
  --surface-edge:#f2e2cb;
  --surface-mute:#f0e8dc;
  --surface-edge-strong:#e8d3b2;
  --ink-soft:#4E4130;
  --ink-danger:#A63A24;
  /* --glass-text/-muted/-line hanya hidup di blok .scene-* sebelum ini, jadi setiap
     layar yang lupa memasang kelas scene kehilangan warna tintanya. Diberi nilai bawaan. */
  --glass-text:#241A11;
  --glass-muted:#6E5E47;
  --glass-line:rgba(27,20,24,.08);
  /* Audit UX Bagian 5 + Roadmap #4: satu font display untuk judul, satu font teks untuk
     tubuh, dan keduanya dinaikkan ke lingkup global. Sebelum ini kedua token hanya hidup
     di dalam .fiezel-splash/.fiezel-ob, sehingga setiap dialog sistem - termasuk gerbang
     izin - jatuh ke font bawaan OS dan membocorkan kesan "campur aduk" yang ditandai
     audit. Berkas fontnya sudah ada di assets/fonts dan dimuat lewat @font-face di bawah. */
  /* m025-86: satu wajah display, satu wajah teks. Serif display dipakai HANYA di ukuran
     besar - wordmark, judul layar, judul dialog. Di ukuran kecil serif kontras-tinggi
     kehilangan keterbacaan di layar ponsel, jadi judul kecil tetap memakai sans. */
  --fz-display:'FZ Instrument Serif',Georgia,'Times New Roman',serif;
  /* m028 fase2: wajah display BULAT. DIRECTION menetapkan Fredoka untuk display &
     judul LAYAR; judul dialog/onboarding dan wordmark splash TETAP --fz-display serif
     karena koreografi pembukaan dipaku pada wajah itu (splash-choreography-test).
     Judul kartu/UI tetap Jakarta 700 - Fredoka hanya di ukuran besar, tempat
     kebulatannya terbaca sebagai kehangatan, bukan sebagai ketidakjelasan.
     Fallback menaruh Jakarta sebelum sistem supaya metriknya tetap dekat saat swap. */
  --fz-display-round:'FZ Fredoka','FZ Plus Jakarta Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --fz-heading:'FZ Plus Jakarta Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --fz-body:'FZ Plus Jakarta Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
}

/* Font merek berlaku di SELURUH aplikasi, termasuk gerbang izin, gerbang akun, modal,
   dan toast - bukan hanya di splash/onboarding seperti sebelumnya (Audit Roadmap #4). */
body{background:var(--sky-bottom);font-family:var(--fz-body)}
h1,h2,h3,h4,.welcome-mark,.modal-mark{font-family:var(--fz-heading)}
/* Ukuran display: serif, berat 400, jarak huruf sedikit dirapatkan. Kerapatan negatif pada
   ukuran besar adalah yang membedakan judul yang "disetel" dari judul yang sekadar dibesarkan. */
.section-head h1,.welcome-panel h2,.modal-panel h2,.fiezel-title{
  font-family:var(--fz-display);font-weight:400;letter-spacing:-.015em}

.app{max-width:1120px;padding:22px 24px calc(126px + env(safe-area-inset-bottom))}
button{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-weight:600}
button svg,.creator-link svg{width:17px;height:17px;flex:0 0 auto}
.wide{width:100%}

.topbar{
  position:sticky;top:0;z-index:35;margin:0 -10px 24px;padding:12px 10px;
  background:var(--chrome-bg);border-radius:0 0 18px 18px;
}
.brand-button{display:flex;align-items:center;gap:12px;border:0;background:transparent;padding:6px 2px;box-shadow:none;color:var(--ambient-text)}
.brand-button:hover{transform:none;border-color:transparent;box-shadow:none}
.brand{width:112px}.brand-edition{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--ambient-muted);font-weight:700;border-left:1px solid rgba(255,255,255,.24);padding-left:12px}
.topbar-actions{display:flex;align-items:center;gap:8px}
/* m025-113: tombol ikon duduk DI DALAM topbar, dan topbar kini memakai --chrome-bg yang
   ikut fase langit. Permukaan bertema di dalam kroma sadar-fase itulah cara lama bug
   kontras kembali: pukul 22.00 kromanya gelap, lingkaran ini tetap putih. Keduanya kini
   satu keluarga. */
.icon-button{width:42px;height:42px;padding:0;border-radius:50%;background:var(--glass-thin);color:var(--glass-text)}
.icon-button.active{color:var(--accent-strong);border-color:#cfc8f6;background:var(--accent-soft)}
.version{min-width:40px;text-align:right}

.section-kicker{display:block;font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-on-glass);font-weight:700;margin-bottom:6px}
.section-head{padding:10px 0 4px;margin-bottom:18px}.section-head h1{font-size:clamp(1.75rem,4vw,2.4rem)}
.card{background:rgba(var(--surface-rgb),.93);box-shadow:var(--shadow-sm)}
.primary{background:var(--sun);color:var(--text);border-color:var(--sun-deep)}
.primary:hover{background:var(--sun-deep);border-color:var(--sun-deep)}

/* Premium Home Launcher */
.home-page{display:grid;gap:26px}
.launcher-shell{
  position:relative;overflow:hidden;display:grid;grid-template-columns:minmax(0,1.42fr) minmax(300px,.72fr);gap:36px;
  grid-template-rows:1fr;
  min-height:500px;padding:clamp(34px,5vw,62px);border-radius:30px;color:#f8f8fb;
  background:linear-gradient(135deg,var(--launcher-start) 0%,rgba(21,26,56,.72) 56%,var(--launcher-end) 132%);
  box-shadow:0 34px 80px rgba(10,14,31,.2);
}
.launcher-shell::after{content:"";position:absolute;width:320px;height:320px;border-radius:50%;right:-170px;top:-180px;background:rgba(216,179,107,.16);filter:blur(2px);pointer-events:none}
.launcher-copy{position:relative;z-index:1;align-self:center}
.launcher-meta{display:flex;align-items:center;flex-wrap:wrap;gap:10px;color:#c8cad8;font-size:.65rem;letter-spacing:.14em;text-transform:uppercase;font-weight:700}
.celestial-status{display:inline-flex;align-items:center;gap:7px;margin-left:auto;padding:7px 10px;border:1px solid rgba(255,255,255,.14);border-radius:999px;background:rgba(255,255,255,.07);letter-spacing:0;text-transform:none;color:#faf5f6}.celestial-status svg{width:14px;height:14px}.celestial-status span{color:#cdbcc1;font-weight:600}
.live-signal{width:7px;height:7px;border-radius:50%;background:#8fd8b8;box-shadow:0 0 0 6px rgba(143,216,184,.1);animation:signalPulse 2.4s ease-in-out infinite}
.launcher-greeting{color:var(--gold);font:500 1rem Georgia,"Times New Roman",serif;font-style:italic;margin:30px 0 8px}
.launcher-copy h1{font-size:clamp(2.5rem,5.7vw,5rem);line-height:.98;letter-spacing:-.06em;margin:0;max-width:850px;font-weight:700}.launcher-copy h1.login-message{font-size:clamp(2.15rem,4.5vw,4.25rem);line-height:1.02}
.launcher-copy h1 span{color:#e8a3ad}
.launcher-lead{font-size:1rem;line-height:1.7;color:#cdbcc1;max-width:680px;margin:22px 0 0}.learner-stage{display:flex;align-items:center;gap:8px;margin:13px 0 0;color:#c0aeb3;font-size:.72rem}.learner-stage svg{width:16px;height:16px;color:#d8b36b}
.launcher-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:30px}
.launcher-actions .luxe{background:#f7f6f1;color:#241A11;border-color:#f7f6f1}
.launcher-actions .luxe:hover{background:#fff;color:#241A11;box-shadow:0 14px 34px rgba(0,0,0,.22)}
.ghost-dark{background:transparent;color:#faf5f6;border-color:rgba(255,255,255,.2)}
.ghost-dark:hover{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.34)}
.launcher-trust{display:flex;flex-wrap:wrap;gap:18px;margin-top:26px;color:#9fa3b6;font-size:.72rem}
.launcher-trust span{display:flex;align-items:center;gap:7px}.launcher-trust svg{width:15px}

.coach-preview{position:relative;z-index:1;align-self:stretch;display:flex;flex-direction:column;padding:25px;border:1px solid rgba(255,255,255,.13);background:rgba(255,255,255,.075);border-radius:22px}
.coach-head{display:flex;align-items:center;gap:11px}.coach-head>div{display:grid;gap:3px}.coach-head small{color:#c0aeb3;font-size:12px;letter-spacing:.14em}.coach-head b{font-size:.86rem}
.coach-icon{width:42px;height:42px;display:grid;place-items:center;border-radius:13px;color:#171d31;background:#d8b36b}.coach-icon svg{width:21px;height:21px}
.coach-level{display:flex;justify-content:space-between;align-items:end;margin:34px 0 22px;padding-bottom:18px;border-bottom:1px solid rgba(255,255,255,.12)}
.coach-level span{color:#afb2c4;font-size:.72rem}.coach-level strong{font:600 2.4rem Georgia,"Times New Roman",serif;color:#d9d3ff}
/* m025-99 (brief 3.7): kartu Coach kini menampilkan RINGKASAN, dan detailnya ada di balik
   tombol "Buka analisis personal" tepat di bawahnya. Pagar tinggi di sini adalah jaring
   pengaman kedua: dua kalimat pun bisa panjang, dan kartu ini tidak boleh lagi mendorong
   seluruh Home ke bawah seperti sebelum rilis ini. */
.coach-body{margin:0 0 4px}
.coach-body>p{margin:0 0 8px}
.coach-body>p:last-child{margin-bottom:0}
.coach-body strong{color:var(--gold);font-weight:700}
.coach-preview h2{font-size:1.35rem;line-height:1.25;letter-spacing:-.025em;margin:0 0 10px}.coach-preview p{color:#b7bacb;line-height:1.62;font-size:.83rem;margin:0 0 24px}
.coach-link{margin-top:auto;padding:0;justify-content:flex-start;color:#f6f5fa;background:transparent;border:0;box-shadow:none}.coach-link:hover{transform:translateX(3px);box-shadow:none;border-color:transparent}

.home-overview{display:grid;grid-template-columns:minmax(320px,.92fr) minmax(0,1.08fr);gap:12px}
.mission-panel{display:flex;align-items:center;gap:19px;padding:22px;border:1px solid var(--glass-line);background:var(--glass-thick);border-radius:20px;color:var(--glass-text)}
.mission-panel h3{margin:2px 0 4px;font-size:1.05rem}.mission-panel p{margin:0;color:var(--glass-muted);font-size:.78rem;line-height:1.55}
.mission-ring{--ring-size:76px;width:var(--ring-size);height:var(--ring-size);flex:0 0 auto;border-radius:50%;display:grid;place-items:center;background:conic-gradient(var(--sun-deep) var(--mission),var(--line-soft) 0)}
.mission-ring::before{content:"";grid-area:1/1;width:60px;height:60px;border-radius:50%;background:var(--panel)}
.mission-ring div{grid-area:1/1;z-index:1;display:flex;align-items:baseline}.mission-ring strong{font-size:1.2rem}.mission-ring span{font-size:.65rem;color:var(--muted)}
.home-stats{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--glass-line);border-radius:20px;background:var(--glass-thick);overflow:hidden;color:var(--glass-text)}
.home-stats>div{padding:22px 16px;border-right:1px solid var(--glass-line)}.home-stats>div:last-child{border:0}.home-stats small{display:block;color:var(--glass-muted);font-size:12px;text-transform:uppercase;letter-spacing:.1em}.home-stats strong{display:block;font-size:1.15rem;margin-top:8px}

.home-section-head{display:flex;align-items:end;justify-content:space-between;gap:20px;margin-top:14px}.home-section-head h2{font-size:1.65rem;margin:0;letter-spacing:-.035em}.text-button{border:0;background:transparent;padding:6px;color:var(--accent-strong);box-shadow:none}.text-button:hover{box-shadow:none;border-color:transparent;transform:translateX(2px)}
.learning-launcher{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.launch-card{position:relative;min-height:220px;padding:24px;display:grid;grid-template-columns:1fr auto;grid-template-rows:auto 1fr;text-align:left;align-items:start;justify-content:stretch;background:var(--panel);border-color:var(--line);overflow:hidden}
.launch-card>span:nth-child(2){grid-column:1/-1;align-self:end;display:grid;gap:6px}.launch-card>svg{grid-column:2;grid-row:1;width:18px;color:var(--muted)}
.launch-icon{width:46px;height:46px;display:grid;place-items:center;border-radius:14px;background:var(--accent-soft);color:var(--accent-strong)}.launch-icon svg{width:22px;height:22px}
.launch-card small{color:var(--muted);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase}.launch-card b{font-size:1.3rem;letter-spacing:-.025em}.launch-card em{font-style:normal;font-weight:500;color:var(--muted);font-size:.78rem;line-height:1.5}
.launch-card:hover{transform:translateY(-5px);box-shadow:var(--shadow-md)}
.grammar-launch .launch-icon{background:var(--sun-soft);color:var(--info)}.reading-launch .launch-icon{background:var(--good-soft);color:var(--good)}.skills-launch .launch-icon{background:var(--info-soft);color:var(--info)}
.skills-page{display:grid;gap:18px}.voice-setup-card{display:flex;align-items:center;justify-content:space-between;gap:22px;padding:22px;border:1px solid var(--line);border-radius:20px;background:rgba(var(--surface-rgb),.93);color:var(--text)}.voice-setup-copy{min-width:0;flex:1}.voice-setup-card h2{margin:0 0 7px;font-size:1.15rem}.voice-setup-card p{max-width:720px;margin:0;color:var(--muted);font-size:.8rem;line-height:1.55}.voice-setup-actions{display:flex;gap:10px;align-items:center;flex:0 0 auto}.voice-setup-card button{flex:0 0 auto}.neural-voice-choice{display:grid;gap:5px;margin-top:14px;max-width:360px}.neural-voice-choice span{font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase}.neural-voice-choice select{width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--surface-solid);color:var(--text);font:inherit}.neural-voice-choice small{color:var(--muted);font-size:.72rem;line-height:1.4}.skills-loading{padding:24px}
.privacy-strip{display:flex;justify-content:space-between;align-items:center;gap:18px;padding:20px 22px;border:1px solid var(--line);border-radius:20px;background:rgba(var(--surface-rgb),.9);color:var(--text)}
.privacy-strip>div{display:flex;align-items:center;gap:13px}.privacy-strip b{font-size:.86rem}.privacy-strip p{margin:3px 0 0;color:var(--muted);font-size:.74rem}.privacy-icon{width:40px;height:40px;display:grid;place-items:center;border-radius:13px;color:var(--accent-strong);background:var(--accent-soft)}

/* Controls, reports, result states */
.settings-list{display:grid;margin:22px 0;text-align:left;border-top:1px solid var(--line)}
.setting-row{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;padding:15px 0;border-bottom:1px solid var(--line);cursor:pointer}
.setting-icon{width:38px;height:38px;display:grid;place-items:center;border-radius:12px;background:var(--panel-soft);color:var(--accent-strong)}
.setting-row span:nth-child(2){display:grid;gap:3px}.setting-row small{color:var(--glass-muted);font-size:.7rem;line-height:1.4}
/* Centang bawaan browser digambar PUTIH di atas accent-color. --sun gagal di situ
   (putih di atas kuning 1,4:1); tinta memberi 10:1+ tanpa menggambar apa pun. */
.setting-row input,.consent-row input{accent-color:var(--text);width:20px;height:20px}
.report-settings{margin:4px 0 18px;padding:18px;text-align:left;background:var(--surface-warm);border:1px solid var(--line);border-radius:18px}.report-settings .row{align-items:start}.report-settings .row p{margin:3px 0 0}
.endpoint-label{display:grid;gap:7px;margin:16px 0 12px;font-size:.72rem;font-weight:700;color:var(--muted)}
.setup-link{display:inline-flex;align-items:center;gap:8px;margin-top:14px;color:var(--accent-strong);font-size:.74rem;font-weight:700;text-decoration:none}.setup-link:hover{text-decoration:underline}.setup-link svg{width:16px;height:16px}
.endpoint-label input{width:100%;min-height:48px;padding:13px 14px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--panel);font:inherit;color:var(--text)}
.endpoint-label input:focus{outline:2px solid var(--focus-ring);outline-offset:2px;border-color:var(--focus-ring)}
.consent-row{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;font-size:.72rem;line-height:1.5;color:var(--muted);cursor:pointer}
.report-state{font-size:.7rem!important;margin:13px 0 0!important;padding-top:11px;border-top:1px solid var(--line)}
.report-preview{text-align:left;display:grid;gap:0;margin:18px 0;padding:15px 18px;background:var(--surface-warm);border:1px solid var(--line);border-radius:16px}.report-preview p{margin:5px 0;font-size:.8rem}
.memory-tip,.ai-disclosure{display:flex;align-items:flex-start;gap:9px}.memory-tip svg,.ai-disclosure svg{width:17px;flex:0 0 auto;margin-top:2px;color:var(--accent-strong)}
.result-stage{padding-top:7vh}.result-card{max-width:620px;margin:0 auto}.result-icon{width:62px;height:62px;display:grid;place-items:center;margin:0 auto 15px;border-radius:18px;color:#765824;background:#f4e7ca}.result-icon svg{width:29px;height:29px}

.welcome-icon{width:54px;height:54px;display:grid;place-items:center;margin:0 auto 16px;border-radius:17px;background:var(--accent-soft);color:var(--accent-strong)}.welcome-icon svg{width:25px;height:25px}
.welcome-mark,.modal-mark{font-size:.65rem;letter-spacing:.16em;color:var(--accent-strong)}
/* Audit UX Bagian 5: warna panel diambil dari token, bukan dipaku. Nilai lamanya
   rgba(255,254,250,.98) - putih hangat - membuat SETIAP modal dan gerbang tetap terang
   di mode gelap, sehingga teksnya nyaris hilang. */
.welcome-panel,.modal-panel{width:min(520px,100%);border-color:var(--line);background:var(--panel);color:var(--text)}
.modal-panel{max-height:min(760px,88vh);overflow:auto}

.bottomnav{width:min(620px,calc(100% - 24px));padding:7px;border-color:rgba(223,221,214,.82);background:rgba(var(--surface-rgb),.88);box-shadow:0 20px 50px rgba(17,23,42,.13);color:var(--text)}
.nav{display:flex;flex-direction:column;gap:3px;min-height:54px}.nav svg{width:18px;height:18px}.nav.active{color:var(--text);background:var(--sun-soft)}
.topline button,.toolbar button,.flash-actions button,.quiz-topbar button{display:inline-flex;align-items:center;gap:7px}
.feedback{background:var(--panel);color:var(--text)}
/* Aksen kiri 4px dipasang lewat box-shadow inset, BUKAN border-left: border akan
   menggeser padding dan membuat teks banner melompat saat state berubah. */
.feedback.feedback-success{border-color:var(--line);box-shadow:inset 4px 0 0 var(--good)}
.feedback.feedback-error{border-color:var(--line);box-shadow:inset 4px 0 0 var(--bad)}
.feedback-title{display:flex;align-items:center;gap:9px}.feedback-title svg{width:21px;height:21px}.feedback-success .feedback-title{color:var(--good)}.feedback-error .feedback-title{color:var(--bad)}
.grammar-grid .card{display:grid;gap:10px}.lesson-card-foot{display:flex;align-items:center;justify-content:space-between;gap:12px}.lesson-card-foot>span{font-size:.72rem;color:var(--muted)}
.lesson-title{font-size:1.55rem;margin:8px 0 10px}.grammar-lesson-card>p{line-height:1.7}
.lesson-example{margin:20px 0;padding:18px;border:1px solid var(--line);border-radius:17px;background:var(--surface-warm)}.lesson-example>span{font-size:.63rem;letter-spacing:.13em;text-transform:uppercase;color:var(--accent-strong);font-weight:700}.lesson-example h3{margin:7px 0 8px;font-size:1rem;line-height:1.5}.lesson-example p{margin:0;color:var(--muted);font-size:.82rem;line-height:1.55}
.practice-contract{display:flex;align-items:center;justify-content:space-between;gap:24px;margin:14px 0;padding:22px;border:1px solid var(--line);border-radius:20px;background:rgba(var(--surface-rgb),.9);color:var(--text)}.practice-contract h3{margin:0 0 5px}.practice-contract p{margin:0;max-width:600px;color:var(--muted);font-size:.8rem;line-height:1.55}.practice-contract button{flex:0 0 auto}

@keyframes signalPulse{0%,100%{opacity:.7;transform:scale(.92)}50%{opacity:1;transform:scale(1.08)}}
.reduce-motion *{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}

@media(min-width:900px){.topbar{padding-top:14px}.section-head{padding-top:22px}}
@media(max-width:860px){
  .launcher-shell{grid-template-columns:1fr;grid-template-rows:auto auto;min-height:0}.coach-preview{min-height:290px}
  .home-overview{grid-template-columns:1fr}.learning-launcher{grid-template-columns:1fr 1fr}
}
@media(max-width:640px){
  .app{padding:12px 14px calc(116px + env(safe-area-inset-bottom))}.topbar{margin:0 -2px 16px;padding:9px 2px}.brand-edition{display:none}.version{display:none}
  .icon-button{width:39px;height:39px}.launcher-shell{padding:24px 18px 30px;border-radius:24px;gap:24px}.celestial-status{width:100%;margin-left:17px;justify-content:flex-start}.launcher-copy h1{font-size:2.65rem}.launcher-copy h1.login-message{font-size:2.25rem}.launcher-lead{font-size:.88rem}.launcher-actions{display:grid}.launcher-actions button{width:100%}.launcher-trust{gap:10px}
  .coach-preview{padding:20px}.home-stats{grid-template-columns:1fr 1fr}.home-stats>div:nth-child(2){border-right:0}.home-stats>div:nth-child(-n+2){border-bottom:1px solid var(--line)}
  /* m025-98 (brief redesign 3.7). Hero diukur 966px di 375x812 - lebih tinggi dari satu
     layar penuh, untuk satu sapaan. Yang dipotong di sini RUANG dan pengulangan, bukan kata:
     brief 3.1 secara eksplisit mempertahankan gaya bahasa Gen Z dan emoji sebagai identitas
     suara FIEZEL, jadi tidak satu kalimat pun diformalkan atau dibuang.

     - Narasi langit ("Matahari mendekati tenggelam") disembunyikan di ponsel saja; teksnya
       tetap hidup di atribut title dan tetap tampil di layar lebar. Ia membuat baris meta
       membungkus jadi dua baris untuk keterangan yang tidak membantu keputusan belajar.
     - Baris "kelas 1 SMA · Semester 1 · Tahun Ajaran 2026/2027" adalah data administratif
       yang tidak pernah berubah; ia tidak menolong murid memutuskan apa pun hari itu.
     - Judul 2,65rem menghasilkan tiga baris setinggi 184px di layar 375px. Diturunkan
       secukupnya supaya tetap terbaca sebagai judul, bukan sebagai paragraf besar.
     - Brief 3.5: satu CTA primer per layar. Tombol kedua dijadikan gaya teks, bukan tombol
       penuh kedua yang bersaing dengan yang utama. */
  #celestialDetail{display:none}
  .learner-stage{display:none}
  .launcher-copy h1{font-size:1.95rem;line-height:1.06}
  .launcher-greeting{margin:20px 0 6px}
  .launcher-actions{gap:8px}
  .launcher-actions .ghost-dark{min-height:40px;padding:8px 12px;border:0;background:transparent;text-decoration:underline;text-underline-offset:3px}
  .mission-panel{align-items:flex-start}
  /* m025-98 (brief redesign 3.7, OWNER: "terlalu panjang untuk scroll sampai bawah").
     Enam kartu modul dulu diruntuhkan menjadi SATU kolom di ponsel. Diukur di 375x812:
     blok itu sendirian setinggi 976px - hampir 1,2 layar - padahal isi tiap kartu cuma tiga
     kata ("1.765 KATA / Vocabulary"). Satu kolom membuatnya terbaca sebagai daftar panjang,
     bukan sebagai pilihan. Dua kolom memotongnya jadi sekitar setengah tanpa menghilangkan
     satu pun informasi, dan itulah bentuk yang dipakai aplikasi sekelas Spotify/Duolingo.
     min-height diturunkan karena kartu dua kolom tidak perlu setinggi kartu selebar layar. */
  .learning-launcher{grid-template-columns:1fr 1fr;gap:10px}.launch-card{min-height:118px}
  .voice-setup-card{align-items:stretch;flex-direction:column}.voice-setup-actions{width:100%;display:grid;grid-template-columns:1fr}.voice-setup-card button{width:100%}
  .home-section-head{align-items:flex-start;flex-direction:column}.privacy-strip{align-items:flex-start;flex-direction:column}.privacy-strip>button{width:100%}
  .bottomnav{bottom:max(8px,env(safe-area-inset-bottom));width:calc(100% - 16px)}.nav{font-size:12px;padding:8px 2px}
  .welcome-panel,.modal-panel{padding:26px 20px;border-radius:var(--radius-lg)}.modal{padding:12px}.setting-row{grid-template-columns:auto 1fr auto}.practice-contract{align-items:stretch;flex-direction:column}.practice-contract button{width:100%}.lesson-card-foot{align-items:flex-start;flex-direction:column}.lesson-card-foot button{width:100%}
}

/* m025-30 neural voice rate control */
.neural-voice-choice input[type="range"]{width:100%;accent-color:var(--accent,#C2402C);height:28px}
.neural-voice-choice input[type="range"]:disabled{opacity:.5}

/* m025-32 Indonesian optional voice block */
.indonesian-voice-block{margin-top:14px;padding-top:14px;border-top:1px solid var(--line,#F0E4CF)}
.indonesian-voice-block p{margin:.35rem 0 0;color:var(--muted,#6E5E47);line-height:1.5}

/* m025-33 FIEZEL Classroom */
.classroom-page{display:grid;gap:14px}
.classroom-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.classroom-cat{display:grid;gap:4px;justify-items:start;text-align:left;padding:16px;border-radius:18px;border:1px solid var(--line,#F0E4CF);background:var(--panel,#fff);color:var(--text,#241A11);min-height:88px}
.classroom-cat small{color:var(--muted,#6E5E47)}
.classroom-board{padding:18px;border-radius:20px;background:var(--panel,#fff);color:var(--text,#241A11);border:1px solid var(--line,#F0E4CF)}
.classroom-board h2{margin:.2rem 0 .5rem}
.classroom-formula{font:600 1.05rem/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;padding:10px 12px;border-radius:12px;background:var(--panel-soft,#f6eef0)}
.classroom-board ul{margin:.6rem 0 0;padding-left:1.1rem;line-height:1.6}
.classroom-subtitle-card{padding:16px;border-radius:20px;background:var(--panel,#fff);color:var(--text,#241A11);border:1px solid var(--line,#F0E4CF)}
.classroom-en{font-weight:600;line-height:1.5;margin:.3rem 0}
.classroom-id{color:var(--accent,#C2402C);font-weight:600;line-height:1.5;margin:.2rem 0;min-height:1.4em}
.classroom-options{display:grid;gap:9px}
.classroom-option{text-align:left;padding:14px;border-radius:14px;min-height:48px}
.classroom-option.is-correct{border-color:var(--good-bright);background:var(--good-soft)}
.classroom-option.is-wrong{border-color:var(--bad);background:var(--bad-soft)}
.classroom-actions{display:flex;flex-wrap:wrap;gap:9px}
.classroom-actions button{min-height:46px;padding:0 16px;border-radius:14px}

/* m025-43 mandatory one-batch neural voice download — stays until it finishes */
.voice-bundle-sheet{position:fixed;inset:0;z-index:95;display:grid;place-items:center;padding:16px;background:linear-gradient(160deg,rgba(7,13,29,.95),rgba(45,37,86,.95));backdrop-filter:blur(10px)}
body.voice-bundle-locked{overflow:hidden}
body.voice-bundle-locked .bottomnav,body.voice-bundle-locked .app-header{pointer-events:none;opacity:.3}
.voice-bundle-panel{width:min(520px,100%);display:grid;gap:10px;padding:20px;border-radius:24px;background:var(--panel,#fff);color:var(--text,#241A11);border:1px solid var(--line,#F0E4CF);box-shadow:0 24px 60px rgba(7,13,29,.28)}
.voice-bundle-mark{font:700 11px/1.4 -apple-system,system-ui,sans-serif;letter-spacing:.12em;color:var(--accent,#C2402C)}
.voice-bundle-panel h2{margin:0}
.voice-bundle-panel p{margin:0;color:var(--muted,#6E5E47);line-height:1.55}
.voice-bundle-track{height:8px;border-radius:999px;background:var(--line-soft,var(--panel-soft));overflow:hidden}
.voice-bundle-track span{display:block;height:100%;width:0;border-radius:999px;background:var(--sun-deep);transition:width .3s ease}
.voice-bundle-progress{font-size:.92rem}
.voice-bundle-actions{display:flex;gap:9px;justify-content:flex-end;flex-wrap:wrap}
.voice-bundle-actions button{min-height:48px;padding:0 18px;border-radius:14px}
.voice-bundle-pill{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(84px + env(safe-area-inset-bottom,0));z-index:60;padding:9px 16px;border-radius:999px;background:var(--panel,#fff);color:var(--text,#241A11);border:1px solid var(--line,#F0E4CF);box-shadow:0 10px 30px rgba(7,13,29,.18);font:600 .86rem/1.3 -apple-system,system-ui,sans-serif}
@media (prefers-reduced-motion:reduce){.voice-bundle-track span{transition:none}}

/* m025-42 mandatory daily target lock */
.daily-lock{position:fixed;inset:0;z-index:90;display:grid;place-items:center;padding:18px;background:linear-gradient(160deg,rgba(7,13,29,.94),rgba(45,37,86,.94));backdrop-filter:blur(10px)}
.daily-lock-panel{width:min(460px,100%);display:grid;gap:12px;padding:24px;border-radius:26px;background:var(--panel,#fff);color:var(--text,#241A11);text-align:center;box-shadow:0 30px 70px rgba(7,13,29,.4)}
.daily-lock-mark{font:700 11px/1.4 -apple-system,system-ui,sans-serif;letter-spacing:.12em;color:var(--accent,#C2402C)}
.daily-lock-panel h2{margin:0}
.daily-lock-panel p{margin:0;color:var(--muted,#6E5E47);line-height:1.55}
.daily-lock-track{height:10px;border-radius:999px;background:var(--line-soft,var(--panel-soft));overflow:hidden}
.daily-lock-track span{display:block;height:100%;border-radius:999px;background:var(--sun-deep);transition:width .35s ease}
.daily-lock-count{font-weight:700;color:var(--text,#241A11)}
.daily-lock-panel .wide{width:100%;min-height:52px;border-radius:16px}
.daily-lock-note{font-size:.86rem}
/* While the lock is armed every escape route inside the app is inert, including the
   bottom navigation and the header controls. */
body.daily-locked .bottomnav,body.daily-locked .app-header,body.daily-locked .icon-button{pointer-events:none;opacity:.35}
body.daily-locked{overflow:hidden}
@media (prefers-reduced-motion:reduce){.daily-lock-track span{transition:none}}

/* m025-44 FIEZEL Library: shelf, reader, audiobook, tap-to-translate */
.library-page{display:grid;gap:14px}
.library-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:11px}
.library-card{display:grid;grid-template-columns:56px 1fr;gap:12px;align-items:start;text-align:left;padding:15px;border-radius:20px;border:1px solid var(--line,#F0E4CF);background:var(--panel,#fff);color:var(--text,#241A11);border-left:4px solid var(--book-accent,#C2402C)}
.library-cover{font-size:2rem;line-height:1}
.library-meta{display:grid;gap:3px}
.library-meta b{font-size:1.02rem}
.library-meta small{color:var(--muted,#6E5E47)}
.library-meta em{color:var(--muted,#6E5E47);font-style:normal;line-height:1.45}
.library-badge{justify-self:start;margin-top:3px;padding:2px 8px;border-radius:999px;background:var(--panel-soft,#f6eef0);color:var(--muted,#6E5E47);font:600 10px/1.6 -apple-system,system-ui,sans-serif;letter-spacing:.04em}
/* --book-accent (aksen per buku dari JS) tetap dihormati; hanya fallback-nya pindah. */
.library-progress{display:block;height:5px;margin-top:7px;border-radius:999px;background:var(--line-soft,var(--panel-soft));overflow:hidden}
.library-progress span{display:block;height:100%;background:var(--book-accent,var(--sun-deep))}
.library-reader{padding-bottom:190px}
.library-reader-head{display:flex;gap:12px;align-items:flex-start}
.library-back{min-height:44px;padding:0 14px;border-radius:12px}
.library-note{margin:0;padding:10px 12px;border-radius:12px;background:var(--panel-soft,#f6eef0);color:var(--muted,#6E5E47);font-size:.88rem;line-height:1.5}
.library-text{display:grid;gap:2px}
.library-chapter{margin:16px 0 6px;font-size:1.05rem}
.library-sentence{display:block;width:100%;text-align:left;padding:7px 10px;border:none;border-radius:10px;background:transparent;color:var(--text,#241A11);font:500 1.06rem/1.72 -apple-system,system-ui,sans-serif}
.library-sentence[data-active]{background:var(--panel-soft,#f6eef0);box-shadow:inset 3px 0 0 var(--accent,#C2402C)}
/* m025-45: the translation floats in the middle of the screen. The book stays visible
   behind it and a tap outside dismisses it - a reader, not a modal. */
.library-translation-layer{position:fixed;inset:0;z-index:78;display:grid;place-items:center;padding:20px;background:rgba(7,13,29,.28);backdrop-filter:blur(2px)}
.library-translation-card{width:min(460px,100%);display:grid;gap:7px;padding:18px 18px 14px;border-radius:22px;background:var(--panel,#fff);border:1px solid var(--line,#F0E4CF);box-shadow:0 26px 60px rgba(7,13,29,.32)}
.library-translation-mark{font:700 10px/1.4 -apple-system,system-ui,sans-serif;letter-spacing:.12em;color:var(--accent,#C2402C)}
.library-translation-en{margin:0;font-weight:600;line-height:1.5}
.library-translation-id{margin:0;color:var(--accent,#C2402C);font-weight:600;line-height:1.5}
.library-translation-actions{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
#libraryCloseOne{margin-left:auto;width:44px;padding:0}
.library-translation-actions button{min-height:42px;padding:0 13px;border-radius:12px}
.library-dock{position:fixed;left:0;right:0;bottom:calc(64px + env(safe-area-inset-bottom,0));z-index:40;display:grid;gap:7px;padding:11px 14px;background:var(--chrome-bg,rgba(250,247,247,.94));backdrop-filter:blur(12px);border-top:1px solid var(--line,#F0E4CF)}
.library-progress-line{height:5px;border-radius:999px;background:var(--line-soft,var(--panel-soft));overflow:hidden}
.library-progress-line span{display:block;height:100%;background:var(--sun-deep);transition:width .25s ease}
.library-status{margin:0;font-size:.84rem;color:var(--muted,#6E5E47)}
.library-controls{display:flex;gap:8px;align-items:center}
.library-controls button{min-height:48px;padding:0 14px;border-radius:14px}
.library-controls .primary{flex:1}
.library-ask-sheet{position:fixed;inset:0;z-index:80;display:grid;place-items:center;padding:16px;background:rgba(7,13,29,.5)}
.library-ask-panel{width:min(480px,100%);display:grid;gap:9px;padding:20px;border-radius:22px;background:var(--panel,#fff);color:var(--text,#241A11)}
.library-ask-mark{font:700 11px/1.4 -apple-system,system-ui,sans-serif;letter-spacing:.12em;color:var(--accent,#C2402C)}
.library-ask-panel h2{margin:0}
.library-ask-quote{margin:0;padding:9px 11px;border-radius:12px;background:var(--panel-soft,#f6eef0);line-height:1.5}
.library-ask-panel textarea{width:100%;padding:11px;border-radius:13px;border:1px solid var(--line,#F0E4CF);font:inherit;resize:vertical}
.library-ask-actions{display:flex;gap:8px;justify-content:flex-end}
.library-ask-actions button{min-height:46px;padding:0 16px;border-radius:13px}
.library-ask-answer{margin:0;line-height:1.55;color:var(--accent,#C2402C);font-weight:600}
.library-ask-answer:empty{display:none}
@media (max-width:620px){.library-sentence{font-size:1.02rem}}
@media (prefers-reduced-motion:reduce){.library-progress-line span{transition:none}}


/* ==========================================================================
   m025-46 — Liquid Glass surfaces
   Depth from blur and a hairline, never from boxes stacked on boxes. Hierarchy
   from the type ramp, never from capitals. Every hit target clears 44px.
   Pinned selectors elsewhere in this file are untouched on purpose.
   ========================================================================== */

.card,.launcher-shell,.coach-preview,.launch-card,.mission-panel,.home-stats>div{
  background:var(--glass-thick);
  border:.5px solid var(--glass-edge);
  color:var(--glass-text);
  box-shadow:0 1px 1px rgba(36,26,17,.03),0 8px 24px rgba(36,26,17,.07);
}
.card{border-radius:22px;padding:18px}
.card p.muted,.launch-card small,.coach-preview p{color:var(--glass-muted)}

/* Large title. This is what replaces the capitals the screens used to shout with. */
.section-head h1{font-size:clamp(28px,7vw,34px);line-height:1.18;font-weight:700;letter-spacing:-.6px;margin:0}
.section-head p{font-size:15px;line-height:20px;color:var(--ambient-muted);margin:.25rem 0 0}
.section-head{margin-bottom:18px}

/* One primary action per screen, and it is unmistakable. */
button.primary,.primary.wide,.primary.luxe{
  min-height:52px;border-radius:26px;background:var(--accent);color:#fff;border:0;
  font-size:17px;font-weight:600;letter-spacing:-.2px;
  box-shadow:0 8px 22px rgba(184,69,47,.30);
}
button.primary:hover,.primary.luxe:hover{background:var(--sun-deep);color:var(--text)}

.launcher-shell{border-radius:26px}
.coach-preview{border-radius:22px}
.launch-card{border-radius:20px;min-height:84px}
.launch-card b{font-size:15px;line-height:20px;font-weight:600;letter-spacing:-.2px}
.launch-card small{font-size:13px;line-height:17px}

/* m025-98 (brief redesign 3.7): pembungkus expand/collapse untuk blok yang tidak perlu
   dibuka bersamaan. Dipakai di Home untuk peta kemampuan dan pemilih tujuan belajar.
   Target sentuhnya 44px penuh, dan panahnya berputar supaya keadaannya terbaca tanpa
   perlu membaca label. */
.home-fold{border:1px solid var(--glass-line);border-radius:18px;background:var(--glass-thick);color:var(--glass-text);margin:12px 0 0;overflow:hidden}
.home-fold>summary{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:44px;padding:11px 16px;cursor:pointer;list-style:none;font-size:.82rem;font-weight:700;color:var(--glass-text)}
.home-fold>summary::-webkit-details-marker{display:none}
.home-fold>summary svg{width:17px;height:17px;flex:0 0 auto;color:var(--glass-muted);transition:transform .2s var(--ease)}
.home-fold[open]>summary svg{transform:rotate(180deg)}
.home-fold[open]>summary{border-bottom:1px solid var(--glass-line)}
.home-fold>.journey-skills,.home-fold>.journey-goal{margin:0;padding:14px 16px 16px;border:0;background:transparent}

/* m025-101 — tur pengenalan (coach marks). OWNER: "anggaplah ada user baru... ga ngerti cara
   pake, seharusnya ada tutorial seperti apps terkenal".

   Sorotannya dibuat dengan SATU box-shadow raksasa, bukan empat panel peredup: satu elemen,
   satu lapis cat, dan lubangnya selalu pas mengikuti kotak targetnya berapa pun ukurannya.
   Lubang itu pointer-events:none supaya ia tidak pernah menelan sentuhan - lapisan induknya
   yang menangkapnya, dan sentuhan di mana pun memajukan tur. */
/* Baris Pengaturan yang berupa AKSI, bukan sakelar. Bentuknya sengaja sama persis dengan
   .setting-row supaya daftarnya tetap terbaca satu irama, hanya penutupnya panah alih-alih
   kotak centang. m025-88 mencatat perkenalan tidak bisa diputar ulang sama sekali; ini
   jalannya. */
.setting-row-action{width:100%;text-align:left;border:0;background:transparent;font:inherit;cursor:pointer}
.setting-row-action>svg:last-child{width:17px;height:17px;color:var(--muted);justify-self:end}

.fz-tour{position:fixed;inset:0;z-index:2147481800;color:var(--glass-text,#fff)}
.fz-tour-hole{position:fixed;border-radius:18px;pointer-events:none;
  box-shadow:0 0 0 9999px rgba(10,5,8,.78),0 0 0 2px rgba(255,255,255,.55) inset;
  transition:top .26s var(--ease,ease),left .26s var(--ease,ease),width .26s var(--ease,ease),height .26s var(--ease,ease)}
.fz-tour-card{position:fixed;left:16px;right:16px;padding:20px 20px 16px;border-radius:22px;
  background:var(--glass-solid,#fff);color:var(--text,#241A11);box-shadow:0 24px 70px rgba(0,0,0,.34);
  animation:fz-tour-in .28s cubic-bezier(.22,.8,.28,1) both}
.fz-tour-card.is-top{top:max(22px,env(safe-area-inset-top))}
.fz-tour-card.is-bottom{bottom:calc(104px + env(safe-area-inset-bottom))}
@keyframes fz-tour-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.fz-tour-card h2{margin:8px 0 6px;font-size:1.12rem;line-height:1.25;letter-spacing:-.02em}
.fz-tour-card p{margin:0;font-size:.86rem;line-height:1.6;color:var(--muted,#6E5E47)}
.fz-tour-dots{display:flex;gap:6px}
.fz-tour-dot{width:6px;height:6px;border-radius:50%;background:var(--line,#e9dfe1)}
.fz-tour-dot.is-active{background:var(--accent,#C2402C);width:18px;border-radius:3px}
.fz-tour-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px}
.fz-tour-skip{min-height:44px;padding:10px 14px;border:0;background:transparent;color:var(--muted,#6E5E47);font:inherit;font-size:.82rem;font-weight:700;cursor:pointer}
.fz-tour-next{min-height:44px;padding:11px 22px;border:0;border-radius:14px;background:var(--accent,#C2402C);color:#fff;font:inherit;font-size:.86rem;font-weight:700;cursor:pointer}
/* Kurangi-gerak: sorotannya tetap ada, hanya perpindahannya yang tidak dianimasikan. */
.fz-tour-still .fz-tour-hole{transition:none}
.fz-tour-still .fz-tour-card{animation:none}

/* Tab bar mengapung sebagai satu kapsul.

   m025-93 (brief redesign Bab 2, bug kritis #2): OWNER melaporkan "bottom navigation bar
   menimpa konten saat scroll - teks/angka terpotong di belakang nav pill". Ini BUKAN soal
   padding: ruang bawah .app sudah 112px + safe-area, sementara pill hanya memakan 73px.
   Yang salah adalah pill-nya sendiri - diukur di peramban pada m025-91:

       background:      rgba(255, 255, 255, 0.74)
       backdrop-filter: none

   m025-81 mencabut backdrop-filter dari chrome demi baterai, tetapi TRANSPARANSINYA
   ditinggal. Token --glass-thick dirancang untuk kaca buram; tanpa blur ia hanya panel
   bening, jadi 26% dari apa pun yang lewat di bawahnya menembus ke atas dan angka yang
   sedang bergulir terbaca samar di balik pill.

   Blur TIDAK dikembalikan - keputusan baterai m025-81 tetap berlaku. Yang dipakai adalah
   pola yang sama dengan Spotify/Apple Music: konten diredupkan SEBELUM sampai ke tab bar
   lewat satu lapisan gradien statis (lihat .nav-scrim), dan pill-nya sendiri dibuat cukup
   pekat sehingga tidak pernah bisa dibaca tembus. Keduanya nol biaya render. */
.bottomnav{
  background:var(--glass-solid);
  border:.5px solid var(--glass-edge);border-radius:30px;padding:6px;
  box-shadow:0 1px 1px rgba(36,26,17,.05),0 14px 34px rgba(36,26,17,.14);
}
/* Peredup di dasar layar. pointer-events:none supaya ia tidak pernah menelan sentuhan, dan
   ia duduk DI BAWAH pill (z-index 39 lawan 40) supaya tab tetap tajam di atasnya. */
.nav-scrim{
  position:fixed;left:0;right:0;bottom:0;z-index:39;pointer-events:none;
  height:calc(96px + env(safe-area-inset-bottom));
  background:linear-gradient(to top,var(--bg) 34%,rgba(0,0,0,0));
}
@media (prefers-reduced-transparency:reduce){.nav-scrim{background:var(--bg)}}
.nav{min-height:44px;color:var(--glass-muted);border-radius:24px}
.nav.active{color:var(--accent-on-glass);background:transparent;transform:none;font-weight:600}

/* Sheets sit on the heavier material, because they take the whole screen. */
.modal-panel,.welcome-panel{
  background:var(--glass-thick);
  -webkit-backdrop-filter:var(--glass-blur-heavy);backdrop-filter:var(--glass-blur-heavy);
  border:.5px solid var(--glass-edge);border-radius:34px;color:var(--glass-text);
  box-shadow:0 1px 2px rgba(36,26,17,.06),0 -8px 60px rgba(36,26,17,.18);
}

/* The sky is a clock, not wallpaper: it stays, but it stops competing with the text. */
.sky-light{opacity:.72}
.global-celestial{opacity:.9}

/* --------------------------------------------------------------------------
   m025-46 fix: text on glass must follow the material, not the light theme.
   The mission panel and the stat strip used to be near-opaque cream cards with
   dark type. Turning them into glass made them follow the sky, but their labels
   still came from the light-theme tokens, so at night they sank into their own
   background. Caught by rendering the page, not by any assertion.
   -------------------------------------------------------------------------- */
.card,.launcher-shell,.coach-preview,.launch-card,.mission-panel,.home-stats,.home-stats>div{color:var(--glass-text)}
.card h1,.card h2,.card h3,.card b,.card strong,
.mission-panel h3,.home-stats strong,.launch-card b{color:var(--glass-text)}
.card p.muted,.card .muted,.mission-panel p,.home-stats small,
.launch-card small,.coach-preview p,.coach-preview small{color:var(--glass-muted)}

/* Headings sitting straight on the sky take the ambient colour, which already
   tracks the phase - otherwise they are dark type on a dark sky after sunset. */
.section-head h1,.home-section-head h2,.home-section-head h3{color:var(--ambient-text)}
.section-head p{color:var(--ambient-muted)}

/* The stat labels were the last capitals left on Home. */
.home-stats small,.stats small{text-transform:none;letter-spacing:.01em;font-size:.7rem}

/* R2 Personal Learning Journey. Memakai token yang sama dengan home-overview supaya panel ini
   terbaca sebagai bagian dari Home, bukan tempelan. */
.journey-week{color:var(--ambient-muted);font-size:.7rem;letter-spacing:.04em}
.journey-panel{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:14px}
.journey-mission,.journey-today,.journey-goal{padding:22px;border:1px solid var(--glass-line);border-radius:20px;background:var(--glass-thick);color:var(--glass-text)}
.journey-mission small,.journey-today small,.journey-goal small{display:block;color:var(--glass-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.1em}
.journey-mission h3{margin:8px 0 6px;font-size:1.05rem;text-transform:capitalize}
.journey-target{margin:6px 0 0;font-size:.78rem;color:var(--glass-text)}
.journey-why,.journey-note{margin:8px 0 0;color:var(--glass-muted);font-size:.74rem;line-height:1.55}
.journey-blocks{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:8px}
.journey-block{display:grid;gap:2px;padding:10px 12px;border:1px solid var(--glass-line);border-radius:14px}
.journey-block b{font-size:.8rem}.journey-block span{color:var(--glass-muted);font-size:.72rem;line-height:1.5}
.journey-block-review{border-color:var(--accent-on-glass)}
.journey-recovery{margin:8px 0 0;font-size:.74rem;color:var(--accent-on-glass)}
.journey-today button{margin-top:12px;width:100%}
.journey-skills{display:grid;grid-template-columns:repeat(5,1fr);border:1px solid var(--glass-line);border-radius:20px;background:var(--glass-thick);color:var(--glass-text);overflow:hidden;margin-bottom:14px}
.journey-skill{padding:16px 12px;border-right:1px solid var(--glass-line);display:grid;gap:6px}
.journey-skill:last-child{border-right:0}
.journey-skill b{font-size:.78rem}.journey-skill span{color:var(--muted);font-size:.72rem}
.journey-skill.is-unmeasured span{font-style:italic}
.journey-goal-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.journey-goal-chip{padding:8px 12px;border:1px solid var(--line);border-radius:999px;background:transparent;color:var(--text);font-size:12px;min-height:36px}
/* Chip terpilih = BIDANG kuning + tinta gelap, bukan garis+teks aksen: satu-satunya
   penanda "terpilih" sebelum ini adalah warna garis 1px - hampir tak terlihat. */
.journey-goal-chip.is-active{background:var(--sun);border-color:var(--sun-deep);color:var(--text);font-weight:600}
@media(max-width:760px){.journey-panel{grid-template-columns:1fr}.journey-skills{grid-template-columns:repeat(2,1fr)}.journey-skill{border-bottom:1px solid var(--line)}}
.journey-skill small{color:var(--muted);font-size:.66rem;letter-spacing:.01em}
.readiness-block{margin-bottom:14px}
.readiness-block h4{margin:0 0 8px;font-size:.86rem}
.readiness-met{color:var(--accent)}
.readiness-unknown,.readiness-not_met{color:var(--muted)}
.backup-settings .backup-actions{margin-top:10px}
.backup-settings #backupPreview:empty{display:none}


/* ========================================================================================
   FIEZEL brand: Percik + splash + onboarding
   Sumber warna dan tipografi: FIEZEL_Complete_Design_Specification.pdf, bagian 2 dan 15.
   Token di bawah SENGAJA dinamai --fz-* dan dilingkupi ke elemen `.fiezel-*` saja - ini
   BUKAN skema warna aplikasi (yang tetap --accent:#C2402C dkk di :root atas). Menyamakan
   keduanya berarti mengecat ulang puluhan layar lain yang tidak diminta pada redesign ini;
   splash dan onboarding adalah lapisan tersendiri sehingga aman dilingkupi sendiri.
   ======================================================================================== */

@font-face{font-family:'FZ Instrument Serif';font-style:normal;font-weight:400;font-display:swap;
  src:url('./assets/fonts/InstrumentSerif-400.woff2') format('woff2')}
@font-face{font-family:'FZ Plus Jakarta Sans';font-style:normal;font-weight:400;font-display:swap;
  src:url('./assets/fonts/PlusJakartaSans-400.woff2') format('woff2')}
@font-face{font-family:'FZ Plus Jakarta Sans';font-style:normal;font-weight:500;font-display:swap;
  src:url('./assets/fonts/PlusJakartaSans-500.woff2') format('woff2')}
@font-face{font-family:'FZ Plus Jakarta Sans';font-style:normal;font-weight:600;font-display:swap;
  src:url('./assets/fonts/PlusJakartaSans-600.woff2') format('woff2')}
@font-face{font-family:'FZ Plus Jakarta Sans';font-style:normal;font-weight:700;font-display:swap;
  src:url('./assets/fonts/PlusJakartaSans-700.woff2') format('woff2')}
/* FZ Fredoka - wajah display bulat brand, di-self-host (29 KB, sudah ter-subset:
   217 codepoint, latin dasar lengkap). Ia VARIABLE font dengan axis wght 300-700,
   jadi satu deklarasi sudah menutup seluruh rentang beratnya - tidak seperti
   PlusJakartaSans yang butuh empat berkas statis. */
@font-face{font-family:'FZ Fredoka';font-style:normal;font-weight:300 700;font-display:swap;
  src:url('./assets/fonts/Fredoka-var.woff2') format('woff2')}

.fiezel-splash,.fiezel-ob{
  /* m028 "Warm Paper, Bright Mind". Peran token TIDAK berubah - hanya nilainya, plus
     empat token baru untuk peran yang dulu dipaksa dipikul --fz-accent sendirian:
     bidang aksi (--fz-sun-grad), bidang terpilih (--fz-sun-soft), tinta kecil di atas
     krem (--fz-info), dan panggung gelap (--fz-core). Kuning adalah warna BIDANG:
     #FFC700 di atas krem hanya 1,5:1, jadi tidak satu pun teks memakainya. */
  --fz-bg:#FFF9EE; --fz-paper:#FFFFFF; --fz-ink:#241A11; --fz-ink-muted:#6E5E47;
  --fz-accent:#241A11; --fz-accent-deep:#120C07; --fz-gold:#E6A800; --fz-soft:#FFF3C4;
  --fz-line:#F0E4CF;
  --fz-sun:#FFC700; --fz-sun-soft:#FFF3C4; --fz-sun-press:#CC9600;
  --fz-sun-grad:linear-gradient(180deg,#FFDE59,#FFA500);
  --fz-info:#7A5F1B; --fz-core:#1B1418; --fz-core-soft:#2A2126; --fz-on-core:#FDFAF3;
  --fz-display:'FZ Instrument Serif',Georgia,'Times New Roman',serif;
  --fz-heading:'FZ Plus Jakarta Sans',-apple-system,'Segoe UI',sans-serif;
  --fz-body:'FZ Plus Jakarta Sans',-apple-system,'Segoe UI',sans-serif;
}


/* Star/Charm Twinkle (bagian 14): scale .85->1.08, rotate +-6deg, opacity .75->1, 2.2s. */
@keyframes fzm-twinkle{0%,100%{transform:scale(.85) rotate(-6deg);opacity:.75}50%{transform:scale(1.08) rotate(6deg);opacity:1}}
.fiezel-star{display:inline-block;animation:fzm-twinkle 2.2s ease-in-out infinite}

/* ---------- Lapisan penuh layar (splash dan onboarding) ----------
   Versi sebelumnya menaruh kartu kecil terapung di tengah layar kosong - OWNER menandainya
   "tidak penuh layar, terlalu kecil". Perbaikannya: latar krem menutupi SELURUH viewport,
   maskotnya besar di area atas, dan lembar konten (--fz-paper) menempel di tepi bawah layar
   selebar penuh dengan sudut atas membulat - pola "bottom sheet" yang dipakai onboarding
   mobile modern, dan CTA-nya selalu terjangkau ibu jari tanpa harus scroll ke tengah. */
.fiezel-splash,.fiezel-ob{
  position:fixed;inset:0;z-index:2147482000;display:flex;flex-direction:column;
  background:var(--fz-bg);font-family:var(--fz-body);color:var(--fz-ink);
  padding-top:max(18px,env(safe-area-inset-top));
  animation:fzm-page-in .4s cubic-bezier(.22,.61,.36,1) both;
}
/* m028: kepala onboarding kini bidang gelap yang menempel ke tepi atas, jadi padding
   aman-area dipindah KE DALAM band itu - kalau tidak, ada garis krem tipis di atas bidang
   gelap yang terbaca sebagai kesalahan render. Lapisannya juga boleh digulir: langkah
   pemilihan tujuan lebih tinggi dari 844px begitu enam chip level muncul, dan sebelum ini
   kelebihannya terpotong tanpa jalan keluar. */
.fiezel-ob{z-index:2147481900;padding-top:0;overflow-y:auto;overscroll-behavior:contain}
.fiezel-ob-reveal{padding-top:max(26px,calc(env(safe-area-inset-top) + 10px))}
.fiezel-splash[hidden]{display:none}
.fiezel-splash.is-leaving,.fiezel-ob.is-leaving{animation:fzm-page-out .3s ease-in both}
/* Page In/Out (bagian 14): fade + slide, 400ms masuk / 300ms keluar. */
@keyframes fzm-page-in{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:none}}
@keyframes fzm-page-out{from{opacity:1;transform:none}to{opacity:0;transform:translateX(-16px)}}

.fiezel-topbar{display:flex;align-items:center;justify-content:space-between;
  padding:4px 16px;min-height:40px}

/* ---------- m028: reveal gelap di kepala onboarding ----------
   Splash tutup di panggung gelap, lalu aplikasi terang. Sebelum ini peralihannya adalah
   potongan keras: gelap penuh langsung jadi krem penuh. Band ini yang menjembatani -
   bidang core yang sama dengan splash, mengecil jadi kepala layar, membawa wordmark yang
   baru saja tersusun di splash. Ia dekorasi murni: tidak ada aksi di dalamnya. */
.fiezel-ob-reveal{
  position:relative;overflow:hidden;flex:0 0 auto;margin:-1px 0 0;
  background:radial-gradient(120% 130% at 50% 0%,var(--fz-core-soft) 0%,var(--fz-core) 62%);
  border-radius:0 0 var(--radius-lg) var(--radius-lg);
  padding:26px 20px 20px;text-align:center;color:var(--fz-on-core);
}
.fiezel-ob-reveal::before{
  content:"";position:absolute;left:50%;top:36%;width:min(70vw,300px);height:170px;
  transform:translate(-50%,-50%);border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(255,199,0,.26),rgba(255,199,0,0));
}
.fiezel-ob-reveal .fiezel-wordmark{position:relative;width:min(46vw,178px);margin:0 auto;display:block}
.fiezel-ob-word{position:relative;margin:0;font-family:var(--fz-heading);font-weight:700;
  font-size:1.8rem;letter-spacing:.02em;color:var(--fz-on-core)}
.fiezel-ob-tag{position:relative;margin:10px 0 0;font-size:12px;font-weight:700;
  letter-spacing:.32em;text-indent:.32em;text-transform:uppercase;color:var(--fz-sun)}

/* ---------- m028: stepper enam langkah ----------
   Perkenalan lama hanya memberi tahu di mana murid berada lewat titik-titik kecil di dalam
   carousel - dan hanya di satu langkah. Sekarang posisinya selalu terbaca: nomor langkah,
   nama langkah, dan enam segmen. Jumlah langkah dan urutannya TIDAK berubah. */
.fiezel-stepper{padding:16px 16px 4px;flex:0 0 auto}
.fiezel-stepper-eyebrow{display:block;font-size:12px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--fz-info)}
.fiezel-stepper-names{display:block;margin-top:3px;font-size:13px;font-weight:600;
  line-height:1.4;color:var(--fz-ink-muted)}
.fiezel-stepper-names b{color:var(--fz-ink);font-weight:700}
.fiezel-segments{display:grid;grid-template-columns:repeat(6,1fr);gap:5px;margin-top:10px}
.fiezel-segments i{height:6px;border-radius:var(--radius-pill);background:var(--fz-line)}
.fiezel-segments i.is-done{background:var(--fz-sun-grad)}
/* Back selalu ada dari langkah 1+, Skip selalu ada - keduanya ukuran sentuh penuh
   walau tampilannya ringan, karena ini SATU-SATUNYA jalan keluar dari lapisan penuh layar. */
.fiezel-back,.fiezel-skip{min-height:44px;min-width:44px;display:inline-flex;align-items:center;
  gap:4px;background:none;border:0;color:var(--fz-ink-muted);font-family:var(--fz-body);
  font-size:13px;font-weight:600;padding:0 6px}
.fiezel-topbar.is-bare{min-height:0;padding:0;height:6px}
.fiezel-back[hidden],.fiezel-skip[hidden]{visibility:hidden}
.fiezel-skip{text-decoration:underline;margin-left:auto}

.fiezel-stage{flex:0 0 auto;display:flex;flex-direction:column;align-items:stretch;
  min-height:0;padding:12px 16px 0;text-align:left}
/* m028-maskot: wajah 64px di SAMPING gelembung diganti maskot besar DI ATAS gelembung.
   Susunan kolom dipilih karena aritmetikanya: pada 390px lebar isi hanya 358px, dan
   maskot 132px + gelembung 270px tidak muat berdampingan tanpa memaksa gelembungnya
   menyusut jadi dua kata per baris. Menumpuknya juga yang menjaga aturan DIRECTION -
   maskot tidak pernah berada di atas kolom nama atau tombol, ia berada DI ATASNYA dalam
   aliran normal, tanpa position:absolute sama sekali. */
.fiezel-stage-art{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;
  gap:8px;min-height:64px;width:100%}
.fiezel-stage-art img{max-height:38vh;width:auto}

/* ---------- m028-maskot: MASKOT PAW di kepala tiap panel perkenalan ----------
   Lambang Lucide di dalam kartu 64px (m025-80) dilepas: ia menunggu pustaka yang dimuat
   `defer` dan karena itu bisa lahir sebagai kotak kosong, dan sebuah lambang yang gagal
   tampil lebih buruk daripada tidak ada lambang. Penggantinya bukan gambar baru melainkan
   maskot yang SUDAH ada di produk (<fiezel-mascot>, features/mascot) - satu sumber bentuk,
   satu sistem gerak, kini juga di layar pertama yang dilihat murid.

   Ukurannya dijepit clamp: 132px pada 390px, 152px pada layar lebar. Keduanya di dalam
   rentang yang diminta (120-160px), dan tidak satu pun bergantung pada tinggi viewport -
   maskot yang tumbuh mengikuti vh adalah maskot yang menelan CTA di layar pendek. */
.fiezel-ob-mascot{
  /* Nilai bawaan bila JS tidak mengirimnya. Angka dari JS menjadi BATAS ATAS, bukan ukuran
     mati: pada 390px yang menang tetap 34vw (=132px), jadi satu angka tidak bisa membuat
     layar kecil kebanjiran maskot. */
  --fz-ob-paw:148px;
  width:clamp(120px,34vw,var(--fz-ob-paw));
  aspect-ratio:320/300;
  flex:0 0 auto;
  display:grid;place-items:center;
  /* Tidak ada bidang, tidak ada cincin, tidak ada bayangan: maskotnya sendiri sudah
     membawa bayangan tanahnya di dalam SVG, dan piringan di belakangnya hanya membuat
     badan kuning duduk di atas kuning. */
  background:none;border:0;box-shadow:none;
  pointer-events:none;
}
/* Komponen memaku .fz-mascot ke 200px; di sini lebarnya milik wadah. Warna TIDAK
   disentuh - tidak satu pun fill/stroke maskot ditimpa dari berkas ini. */
.fiezel-ob-mascot .fiezel-ob-paw{width:100%;height:100%}
/* Micro-entrance saat langkah berganti: satu scale settle 240ms dengan pegas yang sama
   dipakai seluruh aplikasi. Sekali per langkah, bukan gerak yang berulang - maskot yang
   melompat tiap kali layar dicat ulang terbaca hiperaktif, bukan hidup. */
.fiezel-ob-mascot.is-entering{animation:fzm-ob-paw-in 240ms var(--ease-spring) both}
@keyframes fzm-ob-paw-in{
  from{transform:scale(.88) translateY(8px);opacity:.55}
  to{transform:none;opacity:1}
}
/* Cadangan bila custom element tidak terdaftar: ikon paw, tetap satu bentuk yang sama. */
.fiezel-ob-paw-fallback{display:grid;place-items:center;width:64%;height:64%;color:var(--fz-ink)}
.fiezel-ob-paw-fallback svg{width:100%;height:100%}

/* Lambang kecil di dalam kartu (SVG inline, tanpa pustaka - lihat GLYPHS di
   features/onboarding/fiezel-onboarding.js). */
.fiezel-glyph{width:20px;height:20px;flex:0 0 auto}
.fiezel-back .fiezel-glyph{width:18px;height:18px}
.fiezel-carousel-arrow .fiezel-glyph{width:22px;height:22px}
/* Gelembung sapaan. Kalimatnya berbeda tiap langkah, jadi murid tidak merasa sedang
   diwawancarai formulir - ada yang menemani. */
.fiezel-greet-bubble{
  position:relative;margin:0;background:var(--fz-paper);border:1.5px solid var(--fz-line);
  border-radius:var(--radius-md);
  /* Sudut yang "dipotong" pindah ke ATAS: gelembung sekarang duduk di bawah maskot, jadi
     ekornya harus menunjuk ke atas - ke wajah yang sedang bicara. */
  border-top-left-radius:4px;
  padding:10px 14px;box-shadow:var(--shadow-sm);
  font-size:14px;font-weight:500;line-height:1.45;color:var(--fz-ink);max-width:320px;
  /* Gelembung ikut di tengah bersama maskot: pada layar lebar gelembung yang menempel ke
     tepi kiri sementara maskotnya di tengah terbaca seperti dua elemen yang tidak saling
     bicara. Teksnya tetap rata kiri karena ini kalimat, bukan judul. */
  align-self:center;text-align:left;
}
@media (max-height:700px){.fiezel-stepper{padding-top:10px}.fiezel-ob-reveal{padding:18px 20px 14px}}

/* m028: lembar bawah selebar layar diganti kartu. Bottom sheet dipilih dulu supaya CTA
   terjangkau ibu jari - itu masih benar, dan tetap dijaga: kartu ini yang terakhir dalam
   kolom, jadi tombolnya tetap duduk di bawah. Yang hilang cuma dua sudut yang menempel ke
   tepi layar, dan bersama itu kesan "dialog sistem" yang tidak pernah dimaksudkan. */
.fiezel-sheet{position:relative;flex:0 0 auto;width:auto;background:var(--fz-paper);
  border-radius:var(--radius-lg);
  border:1px solid var(--fz-line);
  box-shadow:var(--shadow-md);
  margin:14px 16px max(16px,env(safe-area-inset-bottom));
  padding:22px 20px 20px;
  display:flex;flex-direction:column;align-items:stretch;gap:10px;text-align:left}

.fiezel-badge{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
  background:var(--fz-sun);color:var(--fz-ink);font-family:var(--fz-heading);font-weight:700;font-size:13px}
.fiezel-title{margin:0 0 2px;font-family:var(--fz-heading);font-weight:600;font-size:1.38rem;
  line-height:1.22;color:var(--fz-ink)}
.fiezel-body{margin:0;font-size:15px;line-height:1.55;color:var(--fz-ink-muted);max-width:24rem}
.fiezel-note{margin:0;font-size:13px;line-height:1.5;color:var(--fz-ink-muted);max-width:24rem}

/* Component Styling Guidelines (bagian 2): Primary/Secondary/Ghost. */
.fiezel-btn{min-height:44px;font-family:var(--fz-body);font-weight:700;font-size:16px;
  border-radius:var(--radius-md);padding:15px 20px;width:100%;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  transition:transform .12s ease-out,box-shadow .12s ease-out}
/* Aksi utama memakai bidang sun, bukan tinta: satu-satunya kuning penuh di layar adalah
   apa yang harus disentuh berikutnya. Tulisannya tinta di atas kuning (10,4:1) - bukan
   putih di atas kuning, yang cuma 1,9:1 dan itulah kesalahan paling sering pada tombol
   kuning di mana pun. */
.fiezel-btn-primary{background:var(--fz-sun-grad);color:var(--fz-ink);border:0;
  box-shadow:0 3px 0 var(--fz-sun-press),var(--shadow-sm)}
.fiezel-btn-primary:active{transform:translateY(2px);box-shadow:0 1px 0 var(--fz-sun-press)}
.fiezel-btn-secondary{background:var(--fz-ink);color:var(--fz-on-core);border:0;
  box-shadow:var(--shadow-sm)}
.fiezel-btn-secondary:active{transform:translateY(2px)}
.fiezel-btn-ghost{background:transparent;color:var(--fz-ink-muted);border:0;box-shadow:none;
  font-size:14px;font-weight:600;width:100%}
/* Nonaktif punya warnanya sendiri, bukan opacity .4 yang menyeret teks ke 2,3:1. Tombol
   yang belum bisa ditekan tetap harus BISA DIBACA - itu yang menjelaskan apa syaratnya. */
.fiezel-btn[disabled]{background:var(--fz-soft);color:var(--text-disabled);box-shadow:none;
  transform:none;pointer-events:none}

/* m025-117 Step 1: kolom nama murid. Tinggi sentuh 48px (di atas ambang 44px yang dijaga
   gate a11y), font 16px supaya iOS TIDAK memperbesar halaman saat kolom mendapat fokus -
   zoom itu menggeser seluruh lapisan perkenalan dan terbaca sebagai layar yang melompat. */
.fiezel-field{display:flex;flex-direction:column;align-items:flex-start;gap:8px;
  width:100%;text-align:left}
.fiezel-field>span{font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  font-weight:700;color:var(--fz-info)}
.fiezel-field input{width:100%;min-height:52px;font-size:16px;font-weight:600;font-family:var(--fz-body);
  color:var(--fz-ink);background:var(--fz-bg);border:1.5px solid var(--fz-line);border-radius:var(--radius-md);
  padding:12px 16px;transition:border-color .14s ease-out,box-shadow .14s ease-out}
.fiezel-field input::placeholder{color:var(--fz-ink-muted);font-weight:500;opacity:1}
.fiezel-field input:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.fiezel-field input:focus{border-color:var(--fz-gold);
  box-shadow:0 0 0 3px rgba(230,168,0,.22)}
/* Step 1 tidak punya tombol "Lewati" (langkah wajib). Penahan ini menjaga tombol "Kembali"
   tetap di kolom kiri, supaya kepala layarnya tidak bergeser antar-langkah. */
.fiezel-skip-spacer{display:inline-block;min-width:44px;min-height:44px}

.fiezel-dots{display:flex;gap:6px;margin-top:2px}
.fiezel-dot{width:7px;height:7px;border-radius:50%;background:var(--fz-line)}
.fiezel-dot.is-active{background:var(--fz-sun-press)}

/* ---------- Splash (Step 0) ---------- */
.fiezel-splash-body{flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:14px;padding:24px;text-align:center}
.fiezel-splash-word{font-family:var(--fz-heading);font-weight:700;font-size:2.6rem;
  letter-spacing:.01em;color:var(--fz-accent);margin:0;display:flex;align-items:center;gap:8px}
.fiezel-splash-tag{font-family:var(--fz-body);font-size:.72rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fz-ink-muted);margin:0}
.fiezel-splash-bubble{position:relative;max-width:20rem;background:#fff;border:1px solid var(--fz-line);
  border-radius:16px;padding:12px 16px;color:var(--fz-ink);font-size:.86rem;line-height:1.5;
  box-shadow:0 4px 14px rgba(74,17,25,.12)}
.fiezel-splash-bubble::after{content:"";position:absolute;left:50%;bottom:-9px;width:16px;height:16px;
  transform:translateX(-50%) rotate(45deg);background:#fff;border-right:1px solid var(--fz-line);
  border-bottom:1px solid var(--fz-line)}

/* ==========================================================================
   Sapaan pembuka bermerek (m025-80 OWNER)
   Maskot dilepas dari layar ini; yang tampil hanya logo yang dianimasikan di atas
   bidang gelap - bidang yang sama dengan ikon aplikasi, jadi ikon di home screen dan
   layar pertama terbaca sebagai satu benda.
   Sekuensnya sengaja disamakan dengan nada pembuka di fiezel-splash.js: huruf F masuk
   pada nada pertama (0ms), dua batang emas naik pada nada kedua (150ms), wordmark
   menyusul setelah keduanya berdiri. Semuanya selesai di ~1,3 detik, jauh sebelum splash
   menutup diri di 2,6 detik.
   ========================================================================== */
.fiezel-splash-dark{background:#1B1418;padding-top:0}
.fiezel-splash-brand{
  background:radial-gradient(circle at 30% 18%,#2A2126 0%,#1B1418 55%,#120C0F 100%);
  position:relative;overflow:hidden;
  /* m025-91 OWNER: "tulisan fiezel itu diletakkan di bawah lagi seperti duolingo".
     Baris pertama menyerap seluruh sisa tinggi, jadi tanda terpusat di area atas-tengah;
     wordmark dan tagline menempel ke bawah lewat padding, bukan lewat angka mati - itu
     sebabnya susunannya tetap benar dari layar pendek sampai tablet. */
  display:grid;grid-template-rows:1fr auto auto;justify-items:center;align-items:center;
  gap:0;padding:24px 24px 17vh;
}
/* Cahaya emas di belakang logo, berdenyut pelan supaya layar tidak terasa beku. */
@keyframes fz-splash-halo{
  0%,100%{opacity:.22;transform:translate(-50%,-50%) scale(1)}
  50%{opacity:.42;transform:translate(-50%,-50%) scale(1.12)}
}
.fiezel-splash-brand::before{
  content:"";position:absolute;left:50%;top:38%;width:min(78vw,440px);aspect-ratio:1;
  border-radius:50%;pointer-events:none;z-index:0;
  background:radial-gradient(circle,rgba(255,199,0,.34) 0%,rgba(255,199,0,0) 68%);
  animation:fz-splash-halo 3.4s ease-in-out infinite;
}
.fiezel-splash-brand>*{position:relative;z-index:1}
/* inline-grid supaya lebar kotak ini persis selebar logo - kilau di bawah memakai inset:0,
   dan kalau kotaknya selebar layar sapuannya ikut melebar ke seluruh layar. */
.fiezel-logo-stage{display:inline-grid;place-items:center;overflow:hidden}
.fiezel-logo{width:min(46vw,190px);height:auto;display:block;overflow:visible}

/* Huruf F: tiga batang yang masing-masing tumbuh dari titik jangkarnya, bukan sekadar
   muncul - batang tegak memanjang ke bawah, dua lengan memanjang ke kanan. */
@keyframes fz-logo-stem{from{opacity:0;transform:scaleY(0)}to{opacity:1;transform:scaleY(1)}}
@keyframes fz-logo-arm{from{opacity:0;transform:scaleX(0)}to{opacity:1;transform:scaleX(1)}}
/* Batang emas naik seperti gelombang suara yang bereaksi pada nada. */
@keyframes fz-logo-bar{
  0%{opacity:0;transform:scaleY(.08)}
  70%{opacity:1;transform:scaleY(1.035)}
  100%{opacity:1;transform:scaleY(1)}
}
.fiezel-logo .fz-f,.fiezel-logo .fz-bar{transform-box:fill-box}
/* m025-82: jeda di bawah TIDAK boleh diubah tanpa mengubah MOTIF di
   features/audio/fiezel-ui-sfx.js juga - keduanya satu koreografi.
   Motif berbunyi di 0 / 105 / 210 ms, dan setiap ketukan visual mendarat di nadanya:
     nada 1 (F4, 0ms)   -> batang tegak huruf F tumbuh
     nada 2 (A4, 105ms) -> dua lengan huruf F memanjang
     nada 3 (D5, 210ms) -> dua batang emas naik; inilah gelombang suara yang bereaksi
   Sebelum perbaikan ini batang emas baru bergerak di 520/620 ms - melodinya sudah habis
   sebelum bagian yang menggambarkan bunyi itu sempat bergerak sama sekali. */
.fiezel-logo .fz-f1{transform-origin:top center;animation:fz-logo-stem .7s cubic-bezier(.22,.8,.28,1) var(--fz-b1,0ms) both}
.fiezel-logo .fz-f2{transform-origin:left center;animation:fz-logo-arm .56s cubic-bezier(.22,.8,.28,1) var(--fz-b2,190ms) both}
.fiezel-logo .fz-f3{transform-origin:left center;animation:fz-logo-arm .56s cubic-bezier(.22,.8,.28,1) var(--fz-b3,285ms) both}
.fiezel-logo .fz-bar1{transform-origin:center bottom;animation:fz-logo-bar .76s cubic-bezier(.2,.9,.3,1) var(--fz-b4,430ms) both}
.fiezel-logo .fz-bar2{transform-origin:center bottom;animation:fz-logo-bar .76s cubic-bezier(.2,.9,.3,1) var(--fz-b5,530ms) both}

/* Kilau emas menyapu logo sekali, tepat setelah kedua batang berdiri. */
@keyframes fz-logo-sheen{from{transform:translateX(-130%)}to{transform:translateX(130%)}}
.fiezel-logo-stage{position:relative}
.fiezel-logo-stage::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(74deg,transparent 38%,rgba(255,222,89,.30) 50%,transparent 62%);
  animation:fz-logo-sheen 1.2s cubic-bezier(.3,.7,.3,1) var(--fz-b6,820ms) both;
}

@keyframes fz-splash-rise{from{opacity:0;transform:translateY(13px)}to{opacity:1;transform:none}}
@keyframes fz-splash-settle{
  from{opacity:0;transform:translateY(15px) scaleX(1.045)}
  to{opacity:1;transform:none}
}
.fiezel-splash-brand .fiezel-splash-word{
  width:min(52vw,238px);margin:0 auto;display:block;
  animation:fz-splash-settle .82s cubic-bezier(.22,.8,.28,1) var(--fz-b7,1060ms) both;
}
.fiezel-splash-brand .fiezel-splash-tag{
  font-family:var(--fz-body);font-size:12px;letter-spacing:.30em;
  text-transform:uppercase;color:#FFC700;margin:14px 0 0;
  animation:fz-splash-rise .82s cubic-bezier(.22,.8,.28,1) var(--fz-b8,1360ms) both;
}
/* Kurangi-gerak: seluruh sekuens dimatikan, logo langsung utuh dan diam. */
/* Kurangi-gerak dulu berarti animation:none - dan hasilnya seluruh sapaan pembuka lenyap:
   logo langsung utuh, tidak ada yang tersusun, tidak ada yang mendarat. OWNER melaporkannya
   sebagai "animasinya terlalu cepat dan singkat", dan memang begitulah rasanya ketika tidak
   ada animasi sama sekali.
   Kurangi-gerak meminta lebih sedikit GERAKAN, bukan lebih sedikit pengalaman. Jadi
   perpindahan, penskalaan, dan sapuan dibuang - yang tersisa muncul dengan memudar, pada
   KETUKAN YANG SAMA. Susunannya tetap terbaca, tanpa satu piksel pun yang bergerak. */
@keyframes fz-fade-in{from{opacity:0}to{opacity:1}}
.fiezel-splash-still .fiezel-logo .fz-f,.fiezel-splash-still .fiezel-logo .fz-bar{
  transform:none!important;animation-name:fz-fade-in!important}
.fiezel-splash-still .fiezel-splash-word{
  transform:none!important;animation-name:fz-fade-in!important}
.fiezel-splash-still .fiezel-splash-tag{transform:none!important;animation-name:fz-fade-in!important}
/* Denyut halo dan sapuan kilau memang gerakan tanpa isi - keduanya tetap dimatikan. */
.fiezel-splash-still .fiezel-splash-brand::before,
.fiezel-splash-still .fiezel-logo-stage::after{animation:none}
.fiezel-splash-still .fiezel-logo-stage::after{opacity:0}

/* ---------- Feature Carousel (Step 1) ---------- */
.fiezel-carousel-track{display:flex;flex-direction:column;gap:8px;width:100%;text-align:left}
.fiezel-carousel-item{display:flex;align-items:center;gap:10px;background:var(--fz-bg);
  border:1px solid var(--fz-line);border-radius:var(--radius-sm);padding:11px 13px;font-size:14px;font-weight:600}
.fiezel-carousel-item i,.fiezel-carousel-item .fiezel-glyph{flex:0 0 auto;color:var(--fz-gold)}
.fiezel-carousel-arrows{display:flex;align-items:center;gap:14px;justify-content:center}
/* padding:0 + width tetap: tanpa itu padding 13px/18px dari aturan `button` dasar membuat
   tombol "bulat" ini melebar jadi lonjong, dan border-radius:50% mengikuti bentuk kotaknya. */
.fiezel-carousel-arrow{width:44px;height:44px;min-height:44px;min-width:44px;padding:0;
  border-radius:50%;background:var(--fz-sun-soft);
  color:var(--fz-ink);border:1.5px solid var(--fz-line);display:grid;place-items:center}
.fiezel-carousel-arrow[disabled]{background:var(--fz-bg);color:#75654C;opacity:1}

/* ---------- Goal Selection (Step 2) ---------- */
.fiezel-goal-grid{display:flex;flex-direction:column;gap:8px;width:100%}
/* Card Selection (bagian 14): border->gold, bg->soft, scale 1->1.035->1, 300-400ms. */
/* align-items dipaksa flex-start: aturan dasar `button{display:inline-flex;align-items:center}`
   di kepala berkas ini menang atas text-align, jadi tanpa baris ini judul dan penjelasan
   kartu tujuan tetap rata tengah walau kartunya jelas-jelas daftar pilihan. */
.fiezel-goal-card{display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;
  gap:3px;text-align:left;width:100%;
  border:1.5px solid var(--fz-line);border-radius:var(--radius-sm);padding:12px 14px;background:var(--fz-paper);
  transition:transform .32s cubic-bezier(.34,1.56,.64,1),border-color .3s,background .3s}
.fiezel-goal-card b{font-family:var(--fz-heading);font-weight:700;font-size:14px;color:var(--fz-ink)}
.fiezel-goal-card span{font-size:13px;color:var(--fz-ink-muted);line-height:1.45}
/* Keadaan terpilih ditandai DUA hal - garis tinta dan bidang kuning lembut - supaya ia
   tetap terbaca oleh mata yang tidak membedakan kuning dari krem. */
.fiezel-goal-card.is-selected{border:2px solid var(--fz-ink);background:var(--fz-sun-soft);
  transform:scale(1.02)}
.fiezel-level-row{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-start;width:100%}
.fiezel-level-chip{min-height:44px;padding:0 16px;border-radius:var(--radius-pill);border:1.5px solid var(--fz-line);
  background:var(--fz-paper);color:var(--fz-ink);font-family:var(--fz-body);font-weight:700;font-size:13px}
.fiezel-level-chip.is-selected{border:1.5px solid var(--fz-ink);background:var(--fz-ink);color:var(--fz-on-core)}

/* ---------- Summary (Step 5) ---------- */
.fiezel-summary-card{width:100%;background:var(--fz-bg);border:1px solid var(--fz-line);
  border-radius:var(--radius-sm);padding:14px;display:flex;flex-direction:column;gap:8px;text-align:left}
.fiezel-summary-row{display:flex;justify-content:space-between;gap:10px;font-size:14px}
.fiezel-summary-row b{color:var(--fz-ink)}
.fiezel-summary-row span{color:var(--fz-ink-muted);text-align:right}

/* Confetti kecil, CSS murni, berhenti di bawah kurangi-gerak lewat blok global di atas. */
.fiezel-confetti{position:absolute;inset:0;pointer-events:none;overflow:hidden;border-radius:inherit}
.fiezel-confetti i{position:absolute;top:-10px;width:6px;height:6px;border-radius:1px;
  background:var(--fz-sun);animation:fzm-confetti 1.6s ease-in both}
.fiezel-confetti i:nth-child(2n){background:var(--fz-gold)}
.fiezel-confetti i:nth-child(3n){background:var(--fz-paper);border:1px solid var(--fz-gold)}
@keyframes fzm-confetti{to{transform:translateY(120px) rotate(220deg);opacity:0}}

/* ---------- Kurangi-gerak: splash dan onboarding tunduk pada blok global juga,
   ditambah override lokal untuk memastikan lambaian/kedip-setara berhenti total. ---------- */
.fiezel-splash-still .fiezel-star,.fiezel-ob-still .fiezel-star{animation:none}
/* m028-maskot: kurangi-gerak berarti maskot tampil sebagai POSE STATIS dari state yang
   SAMA - bukan maskot yang hilang, dan bukan maskot yang tetap bernapas. Kelas st-<state>
   yang menentukan pose sudah dipasang di markup, jadi mematikan animasinya tidak mengubah
   arti satu langkah pun. Dua jalan masuk dijaga sekaligus: preferensi sistem (lapisan
   dapat .fiezel-ob-still dari JS) dan preferensi aplikasi (.reduce-motion di <body>). */
.fiezel-ob-still .fiezel-ob-mascot,
.fiezel-ob-still .fiezel-ob-mascot *,
body.reduce-motion .fiezel-ob-mascot,
body.reduce-motion .fiezel-ob-mascot *{animation:none!important;transition:none!important}
@media (prefers-reduced-motion:reduce){
  .fiezel-ob-mascot,.fiezel-ob-mascot *{animation:none!important;transition:none!important}
}

/* ========== SKELETON LOADING STATES (Polished, Premium Feel) ========== */
/* Shimmer animation: Creates the premium "loading" feel like Spotify/Duolingo */
@keyframes shimmer {
  0% { background-position: -1000px 0; }
  100% { background-position: 1000px 0; }
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

.skeleton {
  /* Kilaunya dulu panel<->panel-soft: dua bidang yang hampir sama, di ATAS panel.
     Skeleton yang tidak terlihat berkedip sama dengan tidak ada skeleton. */
  background: linear-gradient(90deg, var(--line-soft) 25%, var(--panel-soft) 50%, var(--line-soft) 75%);
  background-size: 1000px 100%;
  animation: shimmer 2s infinite;
  border-radius: var(--radius-md);
  height: 16px;
}

/* Skeleton card (useful for lists/grids) */
.skeleton-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 20px;
  margin-bottom: 12px;
}

.skeleton-card .skeleton { margin-bottom: 12px; }
.skeleton-card .skeleton:last-child { margin-bottom: 0; }

/* Skeleton variants for different sizes */
.skeleton-text { height: 16px; }
.skeleton-title { height: 24px; margin-bottom: 8px; }
.skeleton-subtitle { height: 14px; width: 60%; margin-bottom: 16px; }
.skeleton-avatar { width: 48px; height: 48px; border-radius: 50%; display: inline-block; }
.skeleton-line { height: 12px; margin-bottom: 8px; }
.skeleton-line:last-child { margin-bottom: 0; }

/* Skeleton grid (for grid layouts) */
.skeleton-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.skeleton-grid .skeleton-card {
  padding: 16px;
  margin-bottom: 0;
}

/* Loading state wrapper */
.loading-state {
  opacity: 0.7;
  pointer-events: none;
}

/* Prevent FOUC (Flash Of Unstyled Content) */
[data-loading="true"] { visibility: hidden; }
[data-loading="false"] { visibility: visible; }

/* ========== EMPTY STATES (Friendly, Encouraging) ========== */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px 20px;
  text-align: center;
  min-height: 300px;
  /* Garis PUTUS-PUTUS: satu-satunya penanda bahwa yang kosong itu memang tempat
     yang belum terisi, bukan kartu yang gagal dimuat. */
  background: var(--panel-soft);
  border-radius: var(--radius-lg);
  border: 1.5px dashed var(--line);
  margin: 20px 0;
}

.empty-state-icon {
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
  margin-bottom: 16px;
  font-size: 2.5rem;
}

.empty-state-icon svg {
  width: 100%;
  height: 100%;
  color: var(--accent-soft);
  opacity: 0.8;
}

.empty-state h2 {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 8px;
  letter-spacing: -0.02em;
}

.empty-state p {
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.6;
  margin: 0 0 20px;
  max-width: 280px;
}

.empty-state .primary {
  margin-top: 8px;
}

/* Variant: minimal empty state (for small containers) */
.empty-state-minimal {
  padding: 24px 16px;
  min-height: auto;
  background: transparent;
  border: 1px dashed var(--line-soft);
}

.empty-state-minimal h2 {
  font-size: 1.1rem;
  margin-bottom: 4px;
}

.empty-state-minimal p {
  font-size: 0.8rem;
}

/* Variant: inline empty message (for grid cells) */
.empty-inline {
  padding: 12px;
  color: var(--muted);
  font-size: 0.8rem;
  text-align: center;
  background: var(--panel-soft);
  border-radius: var(--radius-md);
}

/* Progress indicator during load */
.loading-progress {
  height: 2px;
  background: var(--line-soft);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 12px;
}

.loading-progress::after {
  content: "";
  display: block;
  height: 100%;
  width: 30%;
  background: linear-gradient(90deg, transparent, var(--sun), transparent);
  animation: shimmer 1.5s infinite;
}

/* ========== MICRO-ANIMATIONS FOR TRANSITIONS & INTERACTIONS ========== */
/* Page view transitions */
::view-transition-old(root) {
  animation: pageOut 0.4s var(--ease) forwards;
}

::view-transition-new(root) {
  animation: pageIn 0.4s var(--ease) forwards;
}

@keyframes pageOut {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes pageIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Card entrance animation */
@keyframes cardSlideIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card.animate-in {
  animation: cardSlideIn 0.35s var(--ease) both;
}

/* Staggered card animations */
.cards-container .card:nth-child(1) { animation-delay: 0.05s; }
.cards-container .card:nth-child(2) { animation-delay: 0.1s; }
.cards-container .card:nth-child(3) { animation-delay: 0.15s; }
.cards-container .card:nth-child(n+4) { animation-delay: 0.2s; }

/* Modal/Dialog entrance */
@keyframes modalAppear {
  from {
    opacity: 0;
    transform: translateY(20px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.modal {
  animation: modalAppear 0.3s var(--ease-spring) both;
}

/* Button press animation (tactile feedback) */
@keyframes buttonPress {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(0.97); }
}

button:active {
  animation: buttonPress 0.1s ease-out;
}

/* Fade in for content reveal */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.content-reveal {
  animation: fadeIn 0.35s var(--ease);
}

/* Bounce for success states */
@keyframes successBounce {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

.success-state {
  animation: successBounce 0.4s var(--ease-spring);
}

/* Shake for error states */
@keyframes errorShake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

.error-state {
  animation: errorShake 0.3s ease;
}

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


/* m025-92 subtitle Indonesia di bawah suara Inggris.
   Setelah suara Indonesia dihapus, baris ini adalah satu-satunya jalur pemahaman
   bahasa ibu, jadi keterbacaannya diperlakukan sebagai isi - bukan hiasan: latar
   pekat sendiri supaya kontras tidak bergantung pada apa pun yang ada di belakangnya,
   dan lebar dibatasi supaya matanya tidak menyeberangi layar tiap baris. */
.fiezel-subtitle{
  position:fixed;
  left:50%;
  transform:translateX(-50%);
  /* Di atas bilah navigasi bawah, dan menghormati area aman iOS. */
  bottom:calc(88px + env(safe-area-inset-bottom,0px));
  z-index:70;
  max-width:min(680px,calc(100vw - 32px));
  padding:10px 16px;
  border-radius:12px;
  background:rgba(20,16,18,.88);
  color:#fdf6f5;
  font-size:clamp(15px,4vw,18px);
  line-height:1.45;
  text-align:center;
  text-wrap:balance;
  pointer-events:none;
  box-shadow:0 6px 24px rgba(0,0,0,.28);
}
.fiezel-subtitle[hidden]{display:none}

/* Pergantian baris dihaluskan, tetapi hanya bagi yang tidak meminta gerak dikurangi. */
@media (prefers-reduced-motion:no-preference){
  .fiezel-subtitle{transition:opacity .18s ease}
}


/* m025-106 Tanya FIEZEL.

   Token di sini WAJIB token yang benar-benar ada di berkas ini. m025-105 memakai
   var(--card,#fff) - dan --card tidak pernah ada, jadi nilainya selalu jatuh ke putih
   keras sementara warna teksnya ikut halaman. Di mode gelap hasilnya teks terang di atas
   putih: kotaknya terlihat, ketikannya tidak. Yang benar adalah --panel dan --text, sama
   seperti .endpoint-label input yang sudah lama dipakai. */
.fiezel-ask-mark{height:18px;width:auto;display:block}

/* Tombolnya menumpuk tanda dan label, jadi ia tidak lagi sebangun dengan icon-button
   lain di topbar dan ukurannya diatur sendiri. */
.ask-button{display:flex;flex-direction:column;align-items:center;gap:2px;line-height:1;
  padding:4px 6px;height:auto;width:auto}
/* m025-107: OWNER melaporkan labelnya terlalu besar. Ukurannya sudah 9px, jadi yang
   membuatnya mendominasi bukan tinggi hurufnya melainkan BOBOTNYA: kapital tebal dengan
   jarak huruf melebar membuat "TANYA FIEZEL?" selebar ~60px di atas tombol 42px, sehingga
   ia melebar keluar tombolnya sendiri.

   Permintaan harfiahnya - 10x lebih kecil, yaitu 0,9px - tidak akan terlihat sama sekali.
   Yang diambil karena itu maksudnya: label yang mengecil sampai batas masih terbaca, dan
   tidak lagi bersaing dengan baloknya. Kapital, tebal, dan jarak huruf dicabut; ketiganya
   itulah yang menyumbang lebar, bukan tinggi hurufnya. */
.ask-button .ask-label{font-size:12px;font-weight:500;letter-spacing:0;
  color:var(--muted);white-space:nowrap;opacity:.75}

.ask-box{display:flex;gap:8px;align-items:center;margin:4px 0 16px}
.ask-box input{flex:1;min-width:0;min-height:48px;padding:12px 14px;border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--panel);color:var(--text);font:inherit;outline:none}
.ask-box input::placeholder{color:var(--muted)}
/* outline dimatikan di atas demi sudut membulat, jadi penanda fokusnya WAJIB ada di
   sini: tanpa ini pengguna keyboard kehilangan jejak posisinya sama sekali. */
.ask-box input:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;border-color:var(--focus-ring)}
.ask-box button{flex-shrink:0;padding:12px 16px;border-radius:14px}
.ask-answer{padding:16px;margin-bottom:16px}
/* Jawaban model datang sebagai satu blok teks; tanpa ini baris barunya hilang dan
   penjelasan enam kalimat terbaca sebagai satu paragraf padat. */
.ask-answer p{white-space:pre-wrap}
.ask-related-title{font-size:13px;text-transform:uppercase;letter-spacing:.06em;
  opacity:.6;margin:0 0 8px}

/* Materi terkait. Gaya ini sempat HILANG saat style.css ditulis ulang di milestone lain
   dan tidak ada yang menyadarinya, karena tombolnya tetap berfungsi - hanya tampil
   telanjang. Tes sekarang menjaga token warnanya. */
.search-hit{display:flex;justify-content:space-between;align-items:center;gap:12px;
  width:100%;text-align:left;padding:14px;margin-bottom:8px;border:1px solid var(--line);
  border-radius:12px;background:var(--panel);color:var(--text);font:inherit;cursor:pointer}
.search-hit-title{font-weight:600;text-transform:capitalize}
.search-hit-view{font-size:12px;opacity:.6;text-transform:uppercase;letter-spacing:.06em;flex-shrink:0}

/* ==========================================================================
   m025-113 - Home minimalis dan eksklusif (brief redesign 4)

   OWNER: "dari atas sampai bawah masih berantakan sekali ui atau ux nya" lalu
   "buatkan dengan kesan minimalis dan eksklusif".

   Yang diukur sebelum menulis satu baris pun, di 375x812:
   - Home setinggi 2.791px. Tiga koma empat layar penuh untuk satu menu utama.
   - 12 kotak bergaris di dalamnya, termasuk kotak DI DALAM kotak (kartu Coach di dalam
     hero, empat kotak statistik di sebelah kotak misi).
   - Empat ajakan aksi bersaing di layar pertama, dua di antaranya memanggil fungsi yang
     sama persis (askCoachAI).
   - Tiga keluarga warna: marun merek, biru sisa palet v6, dan emas.
   - Satu bug kontras 1,05:1 pada seluruh kartu modul. Sudah diperbaiki di sumbernya
     (tutor-v3.css) - catatannya ada di sana.

   Prinsip lapisan ini, dan hanya ini:
   1. Satu material per bidang. Kedalaman datang dari garis rambut dan jarak, bukan dari
      kotak yang ditumpuk di atas kotak.
   2. Satu aksi utama per bidang.
   3. Satu wajah display (serif merek) untuk yang besar - judul, level, angka statistik -
      dan sans untuk sisanya. Huruf kapital hanya untuk label mikro.
   4. Tidak ada informasi yang dibuang. Yang dipotong adalah RUANG dan PENGULANGAN.
   ========================================================================== */

/* 1. Tanah halaman ikut fase langit juga di TEMA TERANG.
   m025-85 sudah meredam langit untuk tema gelap supaya halaman tidak menjadi lumpur.
   Kebalikannya tidak pernah ditangani: pukul 22.00 di tema terang, gradien langit gelap
   dipasang pada opasitas .58 di atas --ui-bg terang, jadi tanahnya berhenti di abu-abu
   ungu tengah - terlalu gelap untuk tinta gelap, terlalu terang untuk tinta terang, dan
   .scene-night sudah memasang tinta ambient TERANG di atasnya (sekitar 4,6:1). Karena
   materialnya memang sudah sepakat menggelap saat malam (kontrak m025-85), tanahnya yang
   dibuat ikut - bukan tintanya yang dibalik. */
/* m025-115: aturan "langit malam menjadi tanah" milik m025-113 dicabut. Ia ada karena
   material ikut menggelap saat malam; sejak brief pastel, material tidak pernah menggelap
   lagi di tema terang, jadi menggelapkan tanahnya justru membalik kontras. */

/* Tautan teks duduk langsung di atas tanah itu, jadi ia ikut fase yang sama. */
.text-button{color:var(--accent-on-glass);font-weight:600}

/* 2. Hero. Gradiennya dulu memuat satu stop BIRU (#151a38) di tengah dua marun; itulah
   yang membuat hero terbaca lumpur, bukan marun. Dua stop, satu keluarga. */


.launcher-meta{font-size:.6rem;letter-spacing:.18em}
/* Sapaan tidak lagi Georgia miring emas di sebelah judul serif: dua wajah display
   bertengkar di satu blok. Sapaan turun jadi label kecil, judulnya yang bicara. */
.launcher-greeting{font-family:var(--fz-body);font-style:normal;font-weight:600;font-size:.82rem;letter-spacing:.02em;margin:24px 0 10px}
.launcher-copy h1.login-message{font-family:var(--fz-display);font-weight:400;letter-spacing:-.01em;line-height:1.08}
/* Nama murid dulu satu baris raksasa merah muda di atas judul, memakan sepertiga hero.
   Ia tetap ada - sebagai sapaan mikro, tempat yang memang pantas untuknya. */
.launcher-copy h1.login-message span{display:block;font-family:var(--fz-body);font-size:.32em;font-weight:700;letter-spacing:.16em;text-transform:uppercase;margin:0 0 10px}
.launcher-copy h1.login-message br{display:none}


/* Kartu Coach berhenti menjadi kotak di dalam kotak; ia menjadi bagian bawah hero yang
   dipisahkan satu garis rambut. */
.coach-preview{padding:20px 0 0;border:0;border-radius:0;background:transparent}
.coach-icon{width:36px;height:36px;border-radius:12px}
.coach-icon svg{width:18px;height:18px}
.coach-head small{letter-spacing:.16em}
.coach-level{margin:18px 0 14px;padding-bottom:14px}
.coach-level span{font-size:.62rem;letter-spacing:.16em;text-transform:uppercase}
.coach-level strong{font:400 2.1rem var(--fz-display);letter-spacing:-.01em}
.coach-preview h2{font-family:var(--fz-display);font-weight:400;font-size:1.2rem;letter-spacing:-.01em}
.coach-preview p{font-size:.82rem}
.coach-link{font-size:.82rem;font-weight:700}

/* 3. Ringkasan hari ini: SATU bidang, bukan lima kotak.
   Selektor sengaja diturunkan lewat .home-overview supaya deklarasi latar milik
   .mission-panel dan .home-stats sendiri tetap utuh - contrast-test membaca deklarasi itu
   sebagai sumber kebenaran untuk mengukur pasangan tinta/latarnya. */
.home-overview{gap:0;border:1px solid var(--glass-line);border-radius:20px;background:var(--glass-thick);color:var(--glass-text);overflow:hidden;box-shadow:0 1px 1px rgba(36,26,17,.03),0 8px 24px rgba(36,26,17,.06)}
.home-overview .mission-panel,.home-overview .home-stats{border:0;border-radius:0;background:transparent;box-shadow:none}
.home-overview .mission-panel{border-bottom:1px solid var(--glass-line)}
.mission-panel h3{font-family:var(--fz-body);font-size:.95rem;font-weight:600;letter-spacing:-.01em}
.mission-ring{--ring-size:60px;background:conic-gradient(var(--sun-deep) var(--mission),var(--glass-line) 0)}
.mission-ring::before{width:46px;height:46px;background:var(--glass-solid)}
.mission-ring strong{font-size:1rem}
.mission-ring span{font-size:.6rem;color:var(--glass-muted)}
.home-stats strong{font:400 1.6rem var(--fz-display);letter-spacing:-.01em;margin-top:2px}
.home-stats small{text-transform:none;letter-spacing:.01em;font-size:.7rem}

/* 4. Perjalanan belajar: dua panel menjadi satu bidang dengan satu garis pemisah, dan
   blok rencana berhenti menjadi kotak-kotak kecil di dalam kotak. */
.journey-panel{grid-template-columns:1fr;gap:0;margin:0;border:1px solid var(--glass-line);border-radius:20px;background:var(--glass-thick);color:var(--glass-text);overflow:hidden;box-shadow:0 1px 1px rgba(36,26,17,.03),0 8px 24px rgba(36,26,17,.06)}
.journey-panel .journey-mission,.journey-panel .journey-today{border:0;border-radius:0;background:transparent;box-shadow:none}
.journey-panel .journey-mission{border-bottom:1px solid var(--glass-line)}
.journey-mission small,.journey-today small{font-size:.6rem;letter-spacing:.16em}
.journey-mission h3{font:400 1.2rem var(--fz-display);letter-spacing:-.01em;margin:8px 0 6px}
.journey-blocks{gap:4px}
.journey-panel .journey-block{border:0;border-left:2px solid var(--glass-line);border-radius:0;padding:5px 0 5px 12px}
.journey-panel .journey-block-review{border-left-color:var(--accent-on-glass)}
.journey-skills{margin:0}
.home-fold{margin:0}
.home-fold>summary{font-weight:600}

/* 5. Kepala bagian: satu bentuk untuk semuanya - judul serif, tautan tenang di kanan. */
.home-section-head{margin:18px 0 0;align-items:baseline}
.home-section-head h2{font:400 1.35rem var(--fz-display);letter-spacing:-.01em}

/* 6. Kartu modul. Judulnya yang dibaca lebih dulu, angkanya menyusul - dulu terbalik,
   dan itu membuat enam kartu terbaca sebagai enam angka tanpa nama. */
.learning-launcher{gap:10px}
.launch-card{padding:16px}
.launch-card>span:nth-child(2){display:flex;flex-direction:column-reverse;gap:3px}
.launch-card b{font-family:var(--fz-body);font-weight:600;letter-spacing:-.01em}
.launch-card small{text-transform:none;letter-spacing:.01em;font-size:12px}
.launch-card>svg{opacity:.4;width:15px}
.launch-icon{width:38px;height:38px;border-radius:12px}
.launch-icon svg{width:19px;height:19px}

/* 7. Ponsel: satu irama jarak, satu kolom untuk yang panjang, dua kolom untuk yang pendek. */
@media(max-width:640px){
  .home-page{gap:14px}
  .launcher-shell{padding:22px 18px 24px;gap:18px;border-radius:22px}
  .launcher-greeting{margin:18px 0 8px;font-size:.78rem}
  .launcher-copy h1.login-message{font-size:1.72rem}
  .launcher-lead{font-size:.84rem;line-height:1.6;margin:12px 0 0}
  .launcher-actions{margin-top:20px}
  .coach-preview{padding:18px 0 0}
  .coach-level{margin:14px 0 12px}
  .coach-level strong{font-size:1.8rem}
  .coach-preview h2{font-size:1.08rem}
  .home-overview .mission-panel{padding:16px;gap:14px}
  .home-overview .home-stats>div{padding:13px 16px}
  .home-stats strong{font-size:1.35rem}
  .journey-panel .journey-mission,.journey-panel .journey-today{padding:16px}
  /* Kepala bagian tetap SATU baris di ponsel: judul dan tautannya sejajar dasar huruf.
     Menumpuknya menambah 44px tinggi per bagian tanpa menambah satu informasi pun. */
  .home-section-head{flex-direction:row;align-items:baseline;gap:12px;margin:16px 0 0}
  .home-section-head h2{font-size:1.2rem}
  .home-section-head .text-button{padding:6px 0;font-size:.76rem;white-space:nowrap}
  .launch-card{min-height:100px;padding:14px}
  .launch-icon{width:34px;height:34px;border-radius:11px}
}

/* 8. Aksi utama di atas material malam. Gradien marun gelap milik lapisan v6
   (#4a1a26 -> #241016) sah di siang hari, tetapi di atas kaca malam ia menjadi kotak
   gelap di atas kotak gelap: teksnya terbaca, tombolnya tidak. Malam hari aksi utama
   memakai bidang gading yang sama dengan tombol hero - satu-satunya bidang terang di
   layar, dan karena itu tidak pernah salah dikenali sebagai aksi utama. */
/* m025-115: aturan "aksi utama jadi gading saat malam" dicabut. Ia ada karena material
   ikut menggelap saat malam; sekarang aksi utama selalu bidang kuning pastel dengan
   tinta coklat, di jam berapa pun. */

/* Jam langit adalah keterangan, bukan bidang: ia berhenti memakan satu baris penuh. */
@media(max-width:640px){
  .celestial-status{width:auto;margin-left:0;padding:5px 10px}
  .launcher-meta{gap:8px}
}
/* Tombol utama di dalam hero selalu gading, siang maupun malam: hero-nya memang selalu
   marun gelap, jadi gradien marun milik lapisan v6 (yang menang spesifisitas atas
   .launcher-actions .luxe sejak v6 dipasang se-aplikasi) membuatnya gelap di atas gelap.
   Ini mengembalikan maksud aslinya, bukan menambah gaya baru. */

/* ==========================================================================
   m025-115 - Komponen pastel: ceria, eksklusif, minimalis, mahal
   Brief: FIEZEL_Instruksi_Redesign_UIUX.pdf (OWNER, v1) + susulan "semua warnanya
   harus pastel".

   Empat kata itu saling menegangkan, dan ketegangannya diselesaikan begini:
   - CERIA datang dari BIDANG: cream, kuning pastel, koral pastel, mint.
   - MAHAL datang dari TINTA DAN GARIS: coklat lembut, emas tipis, satu garis rambut,
     jarak yang longgar. Bukan dari warna gelap.
   - MINIMALIS dijaga dengan disiplin lama: satu aksi utama per bidang, satu material
     per bidang, tidak ada kotak di dalam kotak.
   - EKSKLUSIF datang dari yang paling murah dan paling terasa: ikon buatan sendiri,
     tombol yang benar-benar bisa "ditekan", dan tipografi serif untuk yang besar.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tombol chunky. Tombol pill putih rata diganti seluruhnya.
   Bayangan bawahnya PEKAT dan tidak buram - itulah yang membuat tombol terbaca
   punya tebal, dan kenapa menekannya terasa seperti menekan sesuatu: tombol turun
   3px dan bayangannya ikut memendek, persis seperti benda yang ditekan.
   -------------------------------------------------------------------------- */
button.primary,.primary.wide,.primary.luxe,html.fiezel-ui-v6 body .primary{
  background:var(--sun);color:var(--text);border:0;border-radius:18px;
  font-weight:700;letter-spacing:-.01em;
  box-shadow:0 4px 0 var(--sun-deep),0 10px 22px rgba(36,26,17,.13);
  transition:transform .12s var(--ease),box-shadow .12s var(--ease),background .2s var(--ease);
}
/* Hover MENGGELAP, bukan menerang: #FFE896 lebih terang dari --sun sehingga tombol
   terasa "menghilang" saat disentuh. Resep components.css §1: sun -> sun-deep. */
button.primary:hover,.primary.luxe:hover,html.fiezel-ui-v6 body .primary:hover{background:var(--sun-deep);color:var(--text)}
button.primary:active,.primary.luxe:active,html.fiezel-ui-v6 body .primary:active{
  transform:translateY(3px);box-shadow:0 1px 0 var(--sun-deep),0 4px 10px rgba(36,26,17,.12)}
/* .primary.is-coral DIHAPUS di F2-16: grep pada app.js + index.html memberi NOL
   pemakaian. Ia sudah mati sebelum rebrand ini; menyimpan selector mati berarti
   fase berikutnya harus menebak apakah ia masih dipakai. Aksi kedua sekarang punya
   resep sendiri di components.css (varian tinta) dan akan dipasang saat markup
   memerlukannya. */

/* Tombol biasa ikut punya tebal, hanya lebih tenang. */
html.fiezel-ui-v6 body button:not(.primary):not(.nav):not(.icon-button):not(.text-button):not(.coach-link):not(.fz-coach-bubble):not(.launch-card):not(.skill-card){
  border:1.5px solid var(--surface-edge);border-radius:16px;
  box-shadow:0 3px 0 var(--surface-edge);
  transition:transform .12s var(--ease),box-shadow .12s var(--ease);
}
html.fiezel-ui-v6 body button:not(.primary):not(.nav):not(.icon-button):not(.text-button):not(.coach-link):not(.fz-coach-bubble):not(.launch-card):not(.skill-card):active{
  transform:translateY(2px);box-shadow:0 1px 0 var(--surface-edge)}

/* --------------------------------------------------------------------------
   2. Hero. Dasar maroon gelap diganti total oleh gradien kuning pastel, dan
   seluruh tintanya ikut berbalik menjadi coklat - kalau tidak, hero cerah dengan
   tinta terang adalah bug kontras yang sama yang baru diperbaiki di m025-113.
   -------------------------------------------------------------------------- */
.launcher-shell{
  background:linear-gradient(155deg,var(--launcher-start) 0%,var(--launcher-end) 118%);
  color:var(--ink);
  border:1px solid rgba(217,188,126,.45);
  box-shadow:0 18px 44px rgba(36,26,17,.14);
}
/* Matahari sudut: satu lingkaran krem, bukan kabut emas yang tidak terbaca. */
.launcher-shell::after{
  width:210px;height:210px;right:-70px;top:-90px;
  background:radial-gradient(circle,rgba(255,255,255,.85) 0%,rgba(255,255,255,0) 70%);filter:none}
.launcher-meta{color:var(--ink);opacity:.62;font-size:.6rem;letter-spacing:.18em}
.launcher-greeting{color:var(--accent-strong);opacity:.9}
.launcher-copy h1.login-message{color:var(--ink)}
.launcher-copy h1.login-message span{color:var(--ink);opacity:.55}
.launcher-lead{color:var(--ink);opacity:.78}
.celestial-status{border:1px solid rgba(36,26,17,.14);background:rgba(255,255,255,.55);color:var(--ink)}
.celestial-status span{color:var(--ink);opacity:.7}
.live-signal{background:var(--green);box-shadow:0 0 0 5px rgba(46,139,105,.16)}

/* Kartu Coach di dalam hero tetap tanpa bingkai, hanya garis rambut - hanya
   warnanya yang ikut berbalik. */
.coach-preview{border-top:1px solid rgba(36,26,17,.14)}
.coach-icon{background:rgba(255,255,255,.7);color:var(--accent-strong);border:1px solid rgba(217,188,126,.6)}
.coach-head small{color:var(--ink);opacity:.6}
.coach-head b{color:var(--ink)}
.coach-level{border-bottom:1px solid rgba(36,26,17,.12)}
.coach-level span{color:var(--ink);opacity:.6}
.coach-level strong{color:var(--ink)}
.coach-preview h2{color:var(--ink)}
.coach-preview p{color:var(--ink);opacity:.78}
.coach-link{color:var(--accent-strong)}

/* --------------------------------------------------------------------------
   3. Ikon duotone buatan sendiri (features/ui/fiezel-icons.js).
   Ini titik ungkit termurah dari "template" ke "eksklusif", persis seperti yang
   ditulis brief: garis coklat + isian pastel, sudut membulat, satu keluarga.
   -------------------------------------------------------------------------- */
.fz-i{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;line-height:0}
.fz-i svg{width:100%;height:100%;display:block}
.fz-i .fz-fill{fill:var(--fz-i-fill,var(--yellow));transition:fill .2s var(--ease)}
.fz-i .fz-line{fill:none;stroke:var(--fz-i-line,var(--ink));stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.nav .fz-i{width:24px;height:24px}
.launch-icon .fz-i,.skill-card .fz-i{width:24px;height:24px}

/* --------------------------------------------------------------------------
   4. Tab bar. Tab aktif jadi kapsul kuning pastel, bukan hanya teks berwarna.
   -------------------------------------------------------------------------- */
.bottomnav{border:1px solid var(--surface-edge);box-shadow:0 2px 0 var(--surface-edge),0 16px 36px rgba(36,26,17,.16)}
.nav{color:var(--muted);font-weight:600}
.nav .fz-i{--fz-i-fill:var(--surface-mute);--fz-i-line:var(--muted)}
.nav.active{color:var(--text);background:var(--sun-soft);font-weight:700}
.nav.active .fz-i{--fz-i-fill:var(--sun);--fz-i-line:var(--text)}

/* --------------------------------------------------------------------------
   5. Home hub: empat skill inti tes sebagai pusat gravitasi baru.
   Tidak ada yang dihapus - kartu modul lama tetap ada di bawahnya, hanya tidak
   lagi menjadi hal pertama yang dilihat.
   -------------------------------------------------------------------------- */
.skill-hub{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.skill-card{
  position:relative;display:grid;gap:10px;padding:16px;text-align:left;align-content:start;
  min-height:132px;border-radius:22px;border:1.5px solid var(--skill-line,var(--surface-edge));
  background:var(--skill-bg,var(--panel-soft));color:var(--ink);
  box-shadow:0 4px 0 var(--skill-line,var(--surface-edge)),0 12px 26px rgba(36,26,17,.10);
  transition:transform .14s var(--ease),box-shadow .14s var(--ease);
}
.skill-card:active{transform:translateY(3px);box-shadow:0 1px 0 var(--skill-line,var(--surface-edge)),0 6px 14px rgba(36,26,17,.10)}
.skill-card .fz-i{--fz-i-fill:var(--skill-ink,var(--yellow));--fz-i-line:var(--ink)}
.skill-card-top{display:flex;align-items:center;justify-content:space-between;gap:10px}
.skill-card b{font-size:1rem;font-weight:700;letter-spacing:-.01em}
.skill-card small{display:block;color:var(--ink);opacity:.66;font-size:.72rem;line-height:1.45}
.skill-badge{font-size:.6rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ink);opacity:.55}
/* Cincin progres: satu conic-gradient, tanpa satu pun elemen tambahan. */
.skill-ring{
  width:38px;height:38px;border-radius:50%;display:grid;place-items:center;flex:0 0 auto;
  background:conic-gradient(var(--skill-ink,var(--yellow)) var(--ring,0%),rgba(36,26,17,.10) 0);
}
.skill-ring::before{content:"";grid-area:1/1;width:28px;height:28px;border-radius:50%;background:var(--skill-bg,var(--panel-soft))}
.skill-ring b{grid-area:1/1;z-index:1;font-size:.62rem;font-weight:700;color:var(--ink)}
.skill-listening{--skill-bg:#FFF3C4;--skill-line:#F3E0AE;--skill-ink:#FFC700}
/* --skill-ink adalah warna ANGKA di tengah cincin. Tiga dari empat nilai lamanya
   pastel: #A8DCC4 mengukur 1,4:1 dan #C9BCE4 1,8:1 terhadap bidangnya - angkanya
   memang tidak terbaca, bukan kurang terbaca. Sekarang tiap keterampilan memakai
   turunan pekat keluarganya. Writing masuk keluarga INFO (kuning tua): lilac tidak
   punya turunan pekat di sistem baru, dan --sun-deep 5,9:1 di atas info-soft.
   --skill-line dibiarkan literal: ia garis lokal, bukan token brief. */
.skill-speaking{--skill-bg:var(--bad-soft);--skill-line:#F6D3C9;--skill-ink:var(--bad-bright)}
.skill-reading{--skill-bg:var(--good-soft);--skill-line:#CDE9DD;--skill-ink:var(--good-bright)}
.skill-writing{--skill-bg:var(--info-soft);--skill-line:#F3E0AE;--skill-ink:var(--sun-deep)}

/* --------------------------------------------------------------------------
   6. Kartu modul lama ikut keluarga yang sama, hanya lebih tenang: ia bukan lagi
   pusat perhatian, tetapi tetap satu ketukan.
   -------------------------------------------------------------------------- */
.launch-icon{background:var(--yellow-soft);color:var(--accent-strong);border:1px solid var(--surface-edge)}
.grammar-launch .launch-icon{background:var(--sun-soft)}
.reading-launch .launch-icon{background:var(--good-soft)}
.skills-launch .launch-icon{background:var(--info-soft)}
.launch-card{border:1.5px solid var(--surface-edge);box-shadow:0 3px 0 var(--surface-edge),0 10px 22px rgba(36,26,17,.08)}
.launch-card:active{transform:translateY(2px);box-shadow:0 1px 0 var(--surface-edge)}

/* --------------------------------------------------------------------------
   7. FIEZEL sebagai pembimbing: gelembung mengambang yang hadir di semua halaman.
   Ia BUKAN panel laporan lagi. Napasnya pelan supaya terbaca hidup, dan berhenti
   sepenuhnya kalau perangkat minta kurangi-gerak.
   -------------------------------------------------------------------------- */
.fz-coach-bubble{
  position:fixed;right:16px;bottom:calc(104px + env(safe-area-inset-bottom));z-index:41;
  width:58px;height:58px;padding:0;border-radius:50%;border:2px solid var(--ink);
  background:var(--yellow);color:var(--ink);cursor:pointer;
  box-shadow:0 4px 0 var(--yellow-deep),0 14px 30px rgba(36,26,17,.24);
  display:grid;place-items:center;
  transition:transform .16s var(--ease-spring),box-shadow .16s var(--ease);
}
.fz-coach-bubble:active{transform:translateY(3px) scale(.97);box-shadow:0 1px 0 var(--yellow-deep),0 6px 16px rgba(36,26,17,.2)}
.fz-coach-bubble .fz-coach-face{width:30px;height:30px}
.fz-coach-bubble .fz-coach-pulse{
  position:absolute;inset:-6px;border-radius:50%;border:2px solid var(--yellow);
  opacity:0;animation:fzCoachBreath 3.4s var(--ease) infinite}
@keyframes fzCoachBreath{0%{transform:scale(.94);opacity:.55}70%{transform:scale(1.16);opacity:0}100%{opacity:0}}
.fz-coach-dot{
  position:absolute;top:-3px;right:-3px;width:20px;height:20px;border-radius:50%;
  background:var(--bad);border:2px solid var(--bg);
  display:grid;place-items:center;font-size:12px;font-weight:700;color:var(--on-core)}
.fz-coach-bubble[hidden]{display:none}

/* Sapaan singkat yang muncul sendiri di samping gelembung. Ia menghilang sendiri;
   tidak ada tombol tutup, karena menutup sesuatu yang menyapa itu pekerjaan. */
.fz-coach-peek{
  position:fixed;right:84px;bottom:calc(116px + env(safe-area-inset-bottom));z-index:41;
  max-width:min(230px,62vw);padding:10px 13px;border-radius:16px 16px 4px 16px;
  border:1.5px solid var(--surface-edge);background:var(--glass-solid);color:var(--text);
  font-size:.78rem;line-height:1.45;box-shadow:0 10px 26px rgba(36,26,17,.16);
  animation:fzCoachPeek .34s var(--ease-spring) both}
@keyframes fzCoachPeek{from{opacity:0;transform:translateY(6px) scale(.96)}to{opacity:1;transform:none}}
.fz-coach-peek[hidden]{display:none}

.fz-coach-sheet{
  position:fixed;inset:0;z-index:2147481500;display:flex;align-items:flex-end;justify-content:center;
  padding:12px;background:var(--scrim-soft);animation:fzCoachFade .2s var(--ease) both}
.fz-coach-sheet[hidden]{display:none}
@keyframes fzCoachFade{from{opacity:0}to{opacity:1}}
.fz-coach-panel{
  width:min(560px,100%);max-height:min(78vh,640px);display:flex;flex-direction:column;
  padding:16px 16px calc(14px + env(safe-area-inset-bottom));border-radius:26px;
  border:1.5px solid var(--surface-edge);background:var(--glass-solid);color:var(--text);
  box-shadow:0 -6px 60px rgba(36,26,17,.24);animation:fzCoachRise .28s var(--ease-spring) both}
@keyframes fzCoachRise{from{transform:translateY(24px);opacity:0}to{transform:none;opacity:1}}
.fz-coach-head{display:flex;align-items:center;gap:10px;padding-bottom:12px;border-bottom:1px solid var(--line)}
.fz-coach-head b{font-size:.95rem}
.fz-coach-head small{display:block;color:var(--muted);font-size:.68rem}
.fz-coach-avatar{width:38px;height:38px;border-radius:50%;background:var(--yellow);border:2px solid var(--ink);display:grid;place-items:center}
.fz-coach-avatar .fz-coach-face{width:22px;height:22px}
.fz-coach-close{margin-left:auto;width:38px;height:38px;border-radius:50%;display:grid;place-items:center;border:1.5px solid var(--surface-edge);background:transparent;color:var(--text);cursor:pointer}
.fz-coach-log{flex:1;overflow-y:auto;display:grid;gap:10px;padding:14px 2px;align-content:start}
.fz-coach-msg{max-width:88%;padding:10px 13px;font-size:.84rem;line-height:1.55;border-radius:16px}
.fz-coach-msg.is-coach{justify-self:start;border-radius:16px 16px 16px 4px;background:var(--yellow-soft);border:1px solid var(--surface-edge)}
.fz-coach-msg.is-user{justify-self:end;border-radius:16px 16px 4px 16px;background:var(--panel-soft);border:1px solid var(--surface-edge)}
.fz-coach-msg p{margin:0 0 6px}.fz-coach-msg p:last-child{margin:0}
.fz-coach-chips{display:flex;flex-wrap:wrap;gap:7px;padding:2px 0 10px}
.fz-coach-chip{
  min-height:36px;padding:7px 12px;border-radius:999px;font-size:.76rem;font-weight:600;cursor:pointer;
  border:1.5px solid var(--surface-edge);background:var(--panel-soft);color:var(--text)}
.fz-coach-chip:active{transform:translateY(1px)}
.fz-coach-form{display:flex;gap:8px;align-items:flex-end}
.fz-coach-form textarea{
  flex:1;min-height:44px;max-height:110px;padding:11px 13px;border-radius:16px;resize:none;
  border:1.5px solid var(--surface-edge);background:var(--panel);color:var(--text);font:inherit;font-size:.86rem}
.fz-coach-send{width:46px;height:46px;flex:0 0 auto;border-radius:16px;border:0;background:var(--yellow);color:var(--ink);
  box-shadow:0 3px 0 var(--yellow-deep);display:grid;place-items:center;cursor:pointer}
.fz-coach-send:active{transform:translateY(2px);box-shadow:0 1px 0 var(--yellow-deep)}
body.fz-coach-open{overflow:hidden}

/* --------------------------------------------------------------------------
   8. Micro-interaction saat sesuatu SELESAI. Kecil, sekali, lalu hilang.
   -------------------------------------------------------------------------- */
.fz-pop{animation:fzPop .5s var(--ease-spring) both}
@keyframes fzPop{0%{transform:scale(.7);opacity:0}60%{transform:scale(1.08)}100%{transform:none;opacity:1}}
.fz-confetti{position:fixed;inset:0;pointer-events:none;z-index:2147481400;overflow:hidden}
.fz-confetti i{--fz-fall:1.5s;position:absolute;top:-12px;width:8px;height:12px;border-radius:2px;opacity:.95;animation:fzFall var(--fz-fall) linear forwards}
@keyframes fzFall{to{transform:translateY(105vh) rotate(540deg);opacity:.2}}
@media (prefers-reduced-motion:reduce){
  .fz-coach-bubble .fz-coach-pulse,.fz-pop,.fz-confetti i{animation:none}
  .fz-coach-peek,.fz-coach-panel{animation:none}
}
body.reduce-motion .fz-coach-bubble .fz-coach-pulse,body.reduce-motion .fz-confetti i{animation:none}

/* --------------------------------------------------------------------------
   9. Halaman skill baru (Listening, Speaking, Writing) memakai pola yang sama
   dengan Reading/Grammar supaya tidak ada pola baru yang harus dipelajari.
   -------------------------------------------------------------------------- */
.skill-page-hero{
  display:grid;gap:8px;padding:18px;border-radius:22px;margin-bottom:14px;
  border:1.5px solid var(--skill-line,var(--surface-edge));background:var(--skill-bg,var(--panel-soft));color:var(--ink)}
.skill-page-hero .skill-badge{opacity:.6}
.skill-page-hero h1{margin:0;font-size:1.5rem;letter-spacing:-.02em}
.skill-page-hero p{margin:0;font-size:.84rem;line-height:1.6;color:var(--ink);opacity:.76}
.writing-prompt{display:grid;gap:10px}
.writing-prompt textarea{
  width:100%;min-height:150px;padding:14px;border-radius:18px;resize:vertical;font:inherit;font-size:.9rem;line-height:1.6;
  border:1.5px solid var(--surface-edge);background:var(--panel);color:var(--text)}
.writing-meta{display:flex;justify-content:space-between;gap:10px;font-size:.74rem;color:var(--muted)}
.writing-feedback{display:grid;gap:8px}
.writing-feedback .card{background:var(--yellow-soft)}

/* Badge runtun: satu-satunya tempat koral menjadi bidang penuh di Home (brief bagian 5 -
   "badge streak yang terasa didapat"). Ikon api ikut ukuran teksnya, bukan sebaliknya. */
.home-stats .streak-badge{
  display:inline-flex;align-items:center;gap:6px;margin-top:4px;padding:4px 10px 4px 7px;
  border-radius:999px;background:var(--sun-soft);border:1.5px solid var(--sun-deep);
  font-size:1rem;line-height:1.2}
.home-stats .streak-badge .fz-i{width:17px;height:17px;--fz-i-fill:var(--sun);--fz-i-line:var(--ink)}

/* m025-118 giliran bicara tutor.
   Sengaja BUKAN memakai gaya .feedback: keduanya berbeda peran dan tidak boleh terlihat
   sama. Kotak feedback membuka jawaban; giliran tutor justru sering menahannya, dan murid
   harus bisa membedakan "ini petunjuk, soalnya masih terbuka" dari "ini jawabannya". */
/* Petunjuk BUKAN kesalahan. Aksen marun membuat setiap giliran tutor terbaca sebagai
   peringatan; keluarga info (kuning tua) menandainya sebagai bantuan. */
.tutor-turn{margin-top:14px;padding:14px 16px;border-radius:16px;
  background:var(--panel-soft);border:1px solid var(--line);
  border-left:3px solid var(--info)}
.tutor-turn.hidden{display:none}
.tutor-turn-head{display:flex;align-items:center;gap:8px;margin-bottom:8px;
  font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.tutor-turn-face{display:grid;place-items:center;width:24px;height:24px;border-radius:50%;
  background:var(--sun);color:var(--text)}
.tutor-turn-face svg{width:14px;height:14px}
.tutor-turn-say{margin:0;font-size:.94rem;line-height:1.6;color:var(--ink)}
.tutor-turn-ask{margin:8px 0 0;font-size:.94rem;line-height:1.6;font-weight:600;
  color:var(--info)}
.tutor-turn-actions{margin-top:12px}
/* Tinggi sentuh 44px, sama dengan seluruh kontrol lain - tombol ini justru ditekan oleh
   murid yang sedang bingung, jadi ia tidak boleh jadi target yang sulit dikenai. */
.tutor-stuck{min-height:44px;padding:10px 16px;border-radius:12px;font-size:.86rem;
  background:transparent;border:1px solid var(--line);color:var(--muted)}
.tutor-stuck:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.tutor-report{display:flex;align-items:center;justify-content:center;gap:8px;margin:10px 0 0;
  font-size:.9rem;line-height:1.55;color:var(--ink)}
.tutor-report svg{width:16px;height:16px;flex:0 0 auto}

/* m025-126 - kartu konsep (tindakan 
eteach) dan tawaran berhenti (reathe).
   Bidangnya memakai --surface-tint (punya pasangan gelap) dengan tinta yang diwarisi,
   sama seperti .tutor-turn - jadi gerbang bidang pastel m025-117 tetap terpenuhi dan
   kartunya ikut berbalik dengan benar di mode gelap. */
.tutor-card{display:grid;gap:12px}
.tutor-card-head{display:flex;align-items:center;gap:10px}
.tutor-card-head small{display:block;font-size:.62rem;letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.tutor-card-head b{font-size:1.05rem;letter-spacing:-.01em}
.tutor-card-why{margin:0;padding:10px 12px;border-radius:12px;font-size:.86rem;line-height:1.55;
  background:var(--panel-soft);border-left:3px solid var(--info)}
.tutor-card-rule{margin:0;font-size:.98rem;line-height:1.6;font-weight:600}
.tutor-card-cue{display:flex;align-items:flex-start;gap:8px;margin:0;font-size:.88rem;line-height:1.55;color:var(--muted)}
.tutor-card-cue svg{width:16px;height:16px;flex:0 0 auto;margin-top:2px}
.quiz-teach-flag{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
/* Dua jalan keluar berdampingan, dan yang "berhenti" justru jadi tombol utamanya:
   pada titik ini FIEZEL memang sedang menyarankan berhenti, bukan sekadar mengizinkan. */
.tutor-breathe{display:flex;flex-wrap:wrap;gap:8px}
.tutor-breathe .primary{min-height:44px;padding:10px 18px;font-size:.88rem}
/* ==========================================================================
   PAW — gerak per halaman (m025-128)
   ==========================================================================
   OWNER memilih arah 02, lalu meminta dua hal: "animasinya buatkan lebih eksklusif lagi,
   dan authentic" dan "animasinya berubah tergantung user masuk ke menu bagian apa".

   APA YANG MEMBUAT GERAK TERASA MURAH, dan karena itu dihindari di seluruh blok ini:
   amplitudo besar, durasi pendek, easing bawaan, dan gerak yang mengulang persis sejak
   milidetik pertama. Semua itu menarik perhatian ke DIRINYA. Yang dipakai di sini
   kebalikannya - amplitudo di bawah 1,6 px, durasi 2,6-5,2 detik, easing yang ditulis
   sendiri, dan satu gerak masuk sekali-jalan tiap kali halaman berganti supaya loop-nya
   tidak pernah tertangkap sebagai loop.

   APA YANG MEMBUATNYA OTENTIK, bukan sekadar berbeda-beda. Tiap halaman mendapat gerak
   yang menggambarkan PEKERJAAN di halaman itu, bukan gerak acak yang kebetulan tidak sama:
   kosakata mengumpulkan, grammar menelusuri satu pola, membaca mengikuti satu baris,
   listening berjalan sebagai gelombang, speaking mendorong keluar dari tengah. Tes justru
   nyaris diam - saat murid sedang diukur, maskot yang bergerak adalah gangguan.

   SATU LAPIS YANG SELALU HIDUP: napas 5,2 detik pada seluruh marka. Gerak per halaman
   ditumpuk DI ATASNYA lewat elemen yang berbeda (balok, bukan grup), jadi keduanya tidak
   pernah saling menimpa transform.
   -------------------------------------------------------------------------- */

.fz-i .fz-paw-bar,.fz-i .fz-paw-pad{fill:var(--fz-i-line,var(--ink));stroke:none}

/* Tiap balok berputar/bergeser dari ALASNYA sendiri, bukan dari pusat kanvas. Tanpa
   fill-box, transform-origin dihitung terhadap viewBox dan keempat balok bergerak seperti
   satu papan - persis yang membuat animasi SVG terlihat kaku. */
.fz-paw-bar{transform-box:fill-box;transform-origin:50% 100%}
.fz-paw{transform-box:view-box;transform-origin:12px 13px}

@media (prefers-reduced-motion:no-preference){

  /* Lapis dasar: napas. Selalu hidup, di semua halaman, pada GRUP-nya. */
  .fz-coach-bubble .fz-paw,.fz-coach-avatar .fz-paw{
    animation:fzPawBreath 5.2s cubic-bezier(.37,0,.24,1) infinite;
  }
  @keyframes fzPawBreath{0%,100%{transform:scale(1)}50%{transform:scale(1.035)}}

  /* Gerak masuk sekali-jalan saat halaman berganti. Inilah yang membuat perpindahan
     terasa disusun, bukan ditukar: marka mengendap sekali sebelum karakter barunya
     mengambil alih. */
  .fz-coach-bubble.is-paw-shift .fz-paw{
    animation:fzPawSettle .62s cubic-bezier(.34,1.12,.52,1) 1;
  }
  @keyframes fzPawSettle{
    0%{transform:scale(.9) rotate(-5deg)}
    55%{transform:scale(1.05) rotate(1.5deg)}
    100%{transform:scale(1) rotate(0)}
  }
  .fz-coach-bubble.is-paw-shift .fz-paw-bar{animation:none}

  /* ---- home / ask / search: mengendap bergiliran, tidak menuntut apa pun ---- */
  [data-fz-scene="home"] .fz-paw-bar{animation:fzPawIdle 4.6s cubic-bezier(.37,0,.24,1) infinite}
  [data-fz-scene="home"] .fz-paw-bar:nth-child(2){animation-delay:.22s}
  [data-fz-scene="home"] .fz-paw-bar:nth-child(3){animation-delay:.44s}
  [data-fz-scene="home"] .fz-paw-bar:nth-child(4){animation-delay:.66s}
  @keyframes fzPawIdle{0%,72%,100%{transform:scaleY(1)}36%{transform:scaleY(1.07)}}

  /* ---- vocab: mengumpulkan. Balok naik satu per satu lalu DITAHAN sebentar,
          seperti koin yang dikumpulkan - bukan bolak-balik. ---- */
  [data-fz-scene="vocab"] .fz-paw-bar{animation:fzPawCollect 4.2s cubic-bezier(.32,1.06,.6,1) infinite}
  [data-fz-scene="vocab"] .fz-paw-bar:nth-child(2){animation-delay:.3s}
  [data-fz-scene="vocab"] .fz-paw-bar:nth-child(3){animation-delay:.6s}
  [data-fz-scene="vocab"] .fz-paw-bar:nth-child(4){animation-delay:.9s}
  @keyframes fzPawCollect{
    0%{transform:translateY(1.4px) scaleY(.9)}
    18%,74%{transform:translateY(0) scaleY(1)}
    100%{transform:translateY(1.4px) scaleY(.9)}
  }

  /* ---- grammar: satu pola dulu. Tepat SATU balok meninggi pada satu waktu, berjalan
          dari kiri ke kanan - kalimat yang diucapkan halaman ini sendiri. ---- */
  [data-fz-scene="grammar"] .fz-paw-bar{animation:fzPawPattern 4.8s cubic-bezier(.4,0,.2,1) infinite}
  [data-fz-scene="grammar"] .fz-paw-bar:nth-child(2){animation-delay:1.2s}
  [data-fz-scene="grammar"] .fz-paw-bar:nth-child(3){animation-delay:2.4s}
  [data-fz-scene="grammar"] .fz-paw-bar:nth-child(4){animation-delay:3.6s}
  @keyframes fzPawPattern{
    0%,50%,100%{transform:scaleY(1);opacity:.72}
    22%{transform:scaleY(1.16);opacity:1}
  }

  /* ---- reading / library / classroom: mengikuti satu baris. Sapuan pekat berjalan
          kiri ke kanan, seperti jari yang menuntun bacaan. ---- */
  [data-fz-scene="reading"] .fz-paw-bar{animation:fzPawLine 3.8s cubic-bezier(.45,0,.25,1) infinite}
  [data-fz-scene="reading"] .fz-paw-bar:nth-child(2){animation-delay:.26s}
  [data-fz-scene="reading"] .fz-paw-bar:nth-child(3){animation-delay:.52s}
  [data-fz-scene="reading"] .fz-paw-bar:nth-child(4){animation-delay:.78s}
  @keyframes fzPawLine{0%,58%,100%{opacity:.55}22%{opacity:1}}

  /* ---- listening: gelombang berjalan. Di sinilah bacaan "equalizer" yang tadinya
          risiko justru menjadi keuntungan - halaman ini memang tentang bunyi. ---- */
  [data-fz-scene="listening"] .fz-paw-bar{animation:fzPawWave 2.6s cubic-bezier(.37,0,.24,1) infinite}
  [data-fz-scene="listening"] .fz-paw-bar:nth-child(2){animation-delay:.17s}
  [data-fz-scene="listening"] .fz-paw-bar:nth-child(3){animation-delay:.34s}
  [data-fz-scene="listening"] .fz-paw-bar:nth-child(4){animation-delay:.51s}
  @keyframes fzPawWave{0%,100%{transform:scaleY(1)}50%{transform:scaleY(1.22)}}

  /* ---- speaking: mendorong keluar dari tengah. Dua balok tengah lebih dulu, lalu
          dua balok tepi menyusul - suara yang keluar, bukan yang masuk. ---- */
  [data-fz-scene="speaking"] .fz-paw-bar{animation:fzPawProject 3.1s cubic-bezier(.3,1.1,.6,1) infinite;animation-delay:.28s}
  [data-fz-scene="speaking"] .fz-paw-bar:nth-child(2),
  [data-fz-scene="speaking"] .fz-paw-bar:nth-child(3){animation-delay:0s}
  @keyframes fzPawProject{
    0%,64%,100%{transform:scaleY(1) translateY(0)}
    30%{transform:scaleY(1.14) translateY(-.9px)}
  }

  /* ---- writing: satu goresan. Marka miring sedikit dan balok tertinggi turun -
          gerak tangan yang menekan pena, bukan denyut. ---- */
  [data-fz-scene="writing"] .fz-paw-bar:nth-child(3){animation:fzPawStroke 4.4s cubic-bezier(.4,0,.2,1) infinite}
  @keyframes fzPawStroke{
    0%,70%,100%{transform:scaleY(1) rotate(0)}
    26%{transform:scaleY(.82) rotate(-4deg)}
    44%{transform:scaleY(1.04) rotate(2deg)}
  }

  /* ---- progress: naik jadi tangga, lalu ditahan lama. Halaman ini tentang hasil yang
          menumpuk, jadi geraknya berakhir di posisi tinggi - bukan kembali ke nol. ---- */
  [data-fz-scene="progress"] .fz-paw-bar{animation:fzPawClimb 5s cubic-bezier(.32,1.06,.6,1) infinite}
  [data-fz-scene="progress"] .fz-paw-bar:nth-child(2){animation-delay:.24s}
  [data-fz-scene="progress"] .fz-paw-bar:nth-child(3){animation-delay:.48s}
  [data-fz-scene="progress"] .fz-paw-bar:nth-child(4){animation-delay:.72s}
  @keyframes fzPawClimb{
    0%{transform:scaleY(.86)}
    16%,82%{transform:scaleY(1.1)}
    100%{transform:scaleY(.86)}
  }

  /* ---- test / skills: nyaris diam.
          Ini keputusan, bukan kelalaian. Saat murid sedang diukur, maskot yang bergerak
          adalah gangguan - jadi yang tersisa hanya napas pada grupnya, dan baloknya
          benar-benar diam. Halaman inilah yang membuktikan sistem geraknya punya
          pendapat, bukan sekadar punya variasi. ---- */
  [data-fz-scene="test"] .fz-paw-bar{animation:none}
}

/* Gerak mati sepenuhnya bila murid memintanya. Marka tetap utuh dan terbaca; tidak ada
   satu pun state yang HANYA bisa dibedakan lewat gerak - lihat titik notifikasi. */
@media (prefers-reduced-motion:reduce){
  .fz-paw,.fz-paw-bar{animation:none !important}
}

/* ==========================================================================
   PAW — kelahiran: partikel meledak, lalu MEMBENTUK marka (m025-129)
   ==========================================================================
   OWNER: "untuk pawnya harusnya ada animasi jangan motion aja, seperti effect particle
   burst, kemudian dari partikel itu terbentuk pawnya baru di lanjutkan oleh motion."

   URUTANNYA, dan kenapa dibagi begini:
     0,00-0,26s  dua belas partikel melesat KELUAR dari titiknya sendiri
     0,26-0,74s  partikel kembali dan mengunci di tempat asalnya
     0,52-0,86s  marka muncul dari balik partikel, sedikit membesar lalu mengendap
     0,74-0,92s  partikel padam
     0,92s ->    gerak per halaman mengambil alih, tanpa jeda

   KUNCINYA ADA DI ARAH ANIMASI, dan ini bagian yang gampang dibuat salah. Partikel di
   sini TIDAK lahir acak lalu mencari tempatnya - cx/cy tiap partikel sudah berdiri
   tepat di simpul bentuk PAW (ujung tiap balok, enam titik keliling bantalan), dan yang
   dianimasikan adalah perjalanan MENJAUH lalu KEMBALI ke nol. Arah sebaliknya - dua
   belas titik acak yang harus dituntun ke posisi akhirnya - akan meleset satu-dua piksel
   pada tiap partikel dan hasilnya terbaca sebagai kotoran, bukan pembentukan.

   Tumpang tindih 0,52-0,74s juga disengaja: marka mulai muncul SEBELUM partikelnya padam,
   jadi mata membaca "partikel menjadi marka", bukan "partikel hilang, lalu marka datang".
   Dua kejadian yang tidak bertumpuk terbaca sebagai dua kejadian.
   -------------------------------------------------------------------------- */

.fz-paw-spark{
  fill:var(--fz-i-line,var(--ink));
  transform-box:fill-box;transform-origin:50% 50%;
  opacity:0;
}
.fz-paw-sparks{pointer-events:none}

@media (prefers-reduced-motion:no-preference){
  .is-paw-born .fz-paw-spark{
    animation:fzPawSpark .92s cubic-bezier(.22,.68,.28,1) var(--sd,0s) 1 both;
  }
  @keyframes fzPawSpark{
    0%   {transform:translate(0,0) scale(.2);opacity:0}
    12%  {opacity:1}
    28%  {transform:translate(var(--sx,0px),var(--sy,-6px)) scale(1);opacity:1}
    74%  {transform:translate(0,0) scale(.85);opacity:1}
    100% {transform:translate(0,0) scale(.3);opacity:0}
  }

  /* Marka menyusul, dan gerak per halaman ditahan sampai ia selesai mengendap -
     kalau tidak, napas 5,2 detik akan bertabrakan dengan transform kelahirannya. */
  .is-paw-born .fz-paw{
    animation:fzPawForm .92s cubic-bezier(.3,1.08,.5,1) 1 both;
  }
  .is-paw-born .fz-paw-bar{animation:none}
  @keyframes fzPawForm{
    0%,52%{transform:scale(.62);opacity:0}
    72%   {transform:scale(1.07);opacity:1}
    100%  {transform:scale(1);opacity:1}
  }
}

/* Tanpa gerak: tidak ada kelahiran sama sekali, marka langsung utuh dan partikelnya
   tidak pernah terlihat. Bukan versi yang lebih cepat - versi yang memang diam. */
@media (prefers-reduced-motion:reduce){
  .fz-paw-spark{display:none}
}

/* ==========================================================================
   Tab bar — berat, bukan garis tipis (m025-129)
   ==========================================================================
   OWNER: "icon taskbarnya terlalu jadul kurang modern dan eye catching."

   Ikonnya sendiri sudah digambar ulang di fiezel-icons.js - bidang jadi bentuk utamanya,
   garis tinggal menegaskan tepi. Yang tersisa di sini adalah wadahnya, dan wadahnya punya
   masalah yang sama: tab aktif hanya berubah warna latar. Perubahan warna adalah sinyal
   TERLEMAH yang dimiliki antarmuka - ia tidak punya berat, tidak punya gerak, dan pada
   layar terang nyaris tidak terbaca sama sekali.

   Tab aktif kini mendapat tiga hal sekaligus: ia NAIK, ia punya bayangan padat 2 px
   seperti tombol chunky di seluruh aplikasi, dan ikonnya MEMANTUL sekali saat dipilih.
   Ketiganya bahasa yang sudah dipakai FIEZEL - tidak ada kosakata visual baru yang
   diperkenalkan hanya untuk tab bar.
   -------------------------------------------------------------------------- */

.nav .fz-i{width:26px;height:26px}
.nav .fz-i .fz-line{stroke-width:2}

html.fiezel-ui-v6 .nav{
  gap:5px;border-radius:17px;
  transition:transform .18s var(--ease-spring),background .16s var(--ease),color .16s var(--ease),box-shadow .16s var(--ease);
}
html.fiezel-ui-v6 .nav.active{
  transform:translateY(-3px);
  box-shadow:0 2px 0 var(--sun-deep);
}
/* Titik di bawah label. Penanda kedua yang tidak bergantung pada warna sama sekali -
   satu-satunya bagian dari state aktif yang tetap terbaca oleh mata yang sulit
   membedakan kuning pastel dari cream. */
html.fiezel-ui-v6 .nav.active::after{
  content:"";width:5px;height:5px;border-radius:50%;background:var(--ink);
  margin-top:-1px;
}

@media (prefers-reduced-motion:no-preference){
  html.fiezel-ui-v6 .nav.active .fz-i{animation:fzNavPop .42s cubic-bezier(.3,1.32,.5,1) 1}
  @keyframes fzNavPop{
    0%{transform:scale(.84) translateY(2px)}
    58%{transform:scale(1.12) translateY(-1px)}
    100%{transform:scale(1) translateY(0)}
  }
}

/* ==========================================================================
   Home — kepingan angka menggantikan sapaan serif (m025-129)
   ==========================================================================
   Pita ini menempati baris yang dulu diisi sapaan serif miring. Empat kepingan, dan
   keempatnya angka yang BISA NAIK - itu syaratnya, bukan lencana yang menempel pada
   angka mati.

   Runtun mendapat koral karena ia satu-satunya yang bisa HILANG; cincin harian memakai
   conic-gradient sehingga kemajuannya terbaca sebagai bentuk, bukan sebagai persen yang
   harus dibaca. Sisanya tetap cream supaya keramaiannya tidak pindah tempat saja.
   -------------------------------------------------------------------------- */
.hero-stats{display:flex;flex-wrap:wrap;gap:8px;margin:26px 0 14px}
.hero-stat{
  display:flex;flex-direction:column;gap:1px;
  padding:8px 13px;border-radius:15px;
  background:rgba(var(--surface-pure-rgb),.96);border:1.5px solid var(--ink);
  box-shadow:0 2px 0 var(--ink);
  color:var(--ink);
}
.hero-stat b{
  display:flex;align-items:center;gap:5px;
  font-size:1.02rem;font-weight:700;line-height:1.15;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;
}
.hero-stat small{font-size:.6rem;letter-spacing:.12em;text-transform:uppercase;font-weight:700;color:var(--muted)}
.hero-stat svg{width:15px;height:15px}
.hero-stat.is-streak{background:var(--sun-soft)}
/* Ikon kecil butuh >=3:1. --sun-deep hanya 1,9:1 di atas sun-soft, jadi tintanya --info. */
.hero-stat.is-streak svg{color:var(--info)}
.hero-stat.is-level{background:var(--sun)}

/* Cincin harian. Sudut conic dihitung dari --v (0-100), jadi satu variabel saja yang
   berpindah dari data ke bentuk - tidak ada perhitungan derajat yang tersebar di JS. */
.hero-ring{
  width:15px;height:15px;border-radius:50%;flex:none;
  background:conic-gradient(var(--ink) calc(var(--v,0) * 1%),rgba(36,26,17,.16) 0);
  -webkit-mask:radial-gradient(circle,transparent 46%,#000 47%);
  mask:radial-gradient(circle,transparent 46%,#000 47%);
}

/* Paragraf yang tersisa dijaga tetap PENDEK, bukan dihapus. Isinya masih berguna; yang
   tidak berguna adalah membiarkannya tumbuh jadi dinding. Batas baris memotong pada
   ukuran layar mana pun, termasuk yang belum ada saat ini ditulis. */
.launcher-lead{
  margin-top:14px;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  line-clamp:2;overflow:hidden;
}
.coach-body{
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;
  line-clamp:4;overflow:hidden;
}

@media (max-width:620px){
  .hero-stats{gap:7px;margin:20px 0 12px}
  .hero-stat{padding:7px 11px}
  .hero-stat b{font-size:.94rem}
}

/* ==========================================================================
   Home berhenti terbaca sebagai artikel (m025-131)
   ==========================================================================
   OWNER, sambil menunjukkan layarnya: "masih terlihat seperti bacaan article."

   m025-130 sudah mengganti sapaan serif miring dengan kepingan angka, dan itu benar tapi
   TIDAK CUKUP - karena tepat di bawahnya masih berdiri elemen yang jauh lebih besar:
   judul Instrument Serif dua baris setinggi ~2,5rem, lalu paragraf pengantar di bawahnya,
   lalu kartu Coach berisi paragraf lagi. Kepingan angka kalah telak melawan tiga blok itu.

   Tiga hal yang membuat sebuah layar terbaca sebagai ARTIKEL, dan ketiganya ada di sini:
     - huruf SERIF berukuran display sebagai elemen terbesar di layar;
     - PARAGRAF mengalir - kalimat yang dibaca berurutan, bukan dipindai;
     - tidak ada BATAS antar-blok, sehingga semuanya terbaca sebagai satu kolom bacaan.

   Ketiganya dibalik:
     - judul serif jadi satu baris sans pendek; yang terbesar di layar kini TOMBOL;
     - paragraf pengantar dan paragraf Coach dihapus, bukan diperpendek. Panel Coach
       tinggal satu kalimat, persis yang OWNER tulis di papan edit;
     - strip Coach jadi kartu tersendiri dengan tepi dan bayangan padat, jadi mata
       membacanya sebagai TOMBOL BESAR, bukan sebagai alinea berikutnya.
   -------------------------------------------------------------------------- */

/* Sapaan tinggal satu baris. Sans, bukan serif; ukuran teks, bukan ukuran judul. */
.hero-line{
  font-family:var(--fz-body);font-size:1rem;line-height:1.5;font-weight:600;
  letter-spacing:-.01em;color:var(--ink);margin:2px 0 16px;max-width:38ch;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;
}
.hero-line span{font-weight:700}

/* Strip Coach: satu kalimat, satu tombol besar, satu tautan kecil. */
.coach-strip{
  display:grid;grid-template-columns:auto 1fr;gap:12px 13px;align-items:center;
  padding:15px;border-radius:22px;
  background:rgba(var(--surface-pure-rgb),.94);
  border:1.5px solid var(--ink);box-shadow:0 3px 0 var(--ink);
}
.coach-strip-face{
  width:42px;height:42px;border-radius:50%;
  background:var(--yellow);border:2px solid var(--ink);
  display:grid;place-items:center;--fz-i-line:var(--ink);
}
.coach-strip-face svg{width:24px;height:24px}
.coach-strip-say{min-width:0}
.coach-strip-say small{
  display:block;font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;
  font-weight:700;color:var(--muted);margin-bottom:2px;
}
.coach-strip-say b{
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;
  font-size:1.02rem;line-height:1.35;font-weight:700;letter-spacing:-.015em;color:var(--ink);
}
/* Tombolnya melintasi dua kolom: di layar ponsel inilah elemen terbesar di Home, dan
   memang harus begitu - yang paling besar di layar seharusnya yang paling ingin ditekan. */
.coach-strip-go{grid-column:1/-1;width:100%;min-height:52px;font-size:1rem;font-weight:700}
.coach-strip-more{
  grid-column:1/-1;justify-self:center;
  /* Hit area 101x22 sebelum ini - di bawah 44px minimum DIRECTION #6. Padding-nya
     yang tumbuh, bukan tekstunya, jadi tata letak Home tidak bergeser. */
  background:none;border:0;box-shadow:none;padding:10px 14px;min-height:44px;
  color:var(--accent);font-size:.78rem;font-weight:700;
}
.coach-strip-more:hover{background:none;box-shadow:none;transform:none}
.coach-strip-more svg{width:14px;height:14px}

/* Panel peluncur berhenti jadi dua kolom yang tinggi; ia kini setumpuk blok pendek. */
html.fiezel-ui-v6 .launcher-shell{
  grid-template-columns:1fr;grid-template-rows:auto;min-height:0;gap:16px;
  padding:clamp(16px,4vw,22px);
}
@media (min-width:900px){
  html.fiezel-ui-v6 .launcher-shell{grid-template-columns:minmax(0,1fr) minmax(280px,.7fr);align-items:center}
  .coach-strip-go{grid-column:1/-1}
}

/* ==========================================================================
   Logo topbar lahir seperti PAW (m025-131)
   ==========================================================================
   OWNER: "untuk logo fiezel di topbar buatkan animasi persis seperti animasi PAW."

   Persis, dan itu bukan sekadar meniru tampilannya: enam belas partikel di sini juga
   sudah berdiri di simpul HURUFNYA - ujung batang F, siku E, dua ujung Z, dua balok
   aksen - dan yang dianimasikan tetap perjalanan MENJAUH lalu KEMBALI. Alasannya sama
   seperti di PAW: partikel yang lahir acak lalu dituntun ke posisinya akan meleset dan
   terbaca sebagai kotoran, bukan sebagai huruf yang terbentuk.

   Satu perbedaan yang disengaja: durasinya 1 detik, bukan 0,92 detik. Wordmark jauh
   lebih lebar daripada marka PAW, jadi partikelnya menempuh jarak lebih jauh; memakai
   durasi yang sama akan membuatnya terlihat terburu-buru justru pada elemen yang paling
   ingin terlihat tenang.

   Jalannya SEKALI saja saat aplikasi dibuka - keputusan OWNER di papan edit: "Sekali saja
   waktu aplikasi pertama dibuka. Tidak diulang tiap pindah menu - biar tetap terasa
   spesial, bukan jadi kedipan."
   -------------------------------------------------------------------------- */

.fzw-spark{
  fill:var(--wordmark-ink-hi);
  transform-box:fill-box;transform-origin:50% 50%;
  opacity:0;
}
.fzw-mark{transform-box:view-box;transform-origin:500px 130px}

@media (prefers-reduced-motion:no-preference){
  .is-mark-born .fzw-spark{animation:fzwSpark 1s cubic-bezier(.22,.68,.28,1) var(--sd,0s) 1 both}
  @keyframes fzwSpark{
    0%{transform:translate(0,0) scale(.15);opacity:0}
    12%{opacity:1}
    30%{transform:translate(var(--sx,0px),var(--sy,-40px)) scale(1);opacity:1}
    76%{transform:translate(0,0) scale(.9);opacity:1}
    100%{transform:translate(0,0) scale(.25);opacity:0}
  }
  .is-mark-born .fzw-mark{animation:fzwForm 1s cubic-bezier(.3,1.06,.5,1) 1 both}
  @keyframes fzwForm{
    0%,54%{transform:scale(.72);opacity:0}
    74%{transform:scale(1.04);opacity:1}
    100%{transform:scale(1);opacity:1}
  }
}
@media (prefers-reduced-motion:reduce){
  .fzw-spark{display:none}
}

/* Global learner-level contract */
.active-level-control,.home-level-context{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line,#eadfce);border-radius:14px;background:var(--panel,#fff);color:var(--ink,#241a11);cursor:pointer;box-shadow:none}
.active-level-control{flex:0 0 auto;flex-direction:column;align-items:flex-start;padding:10px 13px;min-width:118px;text-align:left}
.active-level-control span,.active-level-control small{font-size:.66rem;color:var(--muted,#746958);line-height:1.1}
.active-level-control strong{font-size:1rem;line-height:1.1;color:var(--accent,#c2402c)}
.active-level-control:hover,.home-level-context:hover{border-color:var(--accent,#c2402c);box-shadow:0 4px 14px rgba(67,43,25,.08);transform:translateY(-1px)}
.home-level-context{padding:4px 9px;font-size:.68rem;font-weight:700;white-space:nowrap}
.level-picker-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px;margin:18px 0}
.level-picker-card{display:grid;gap:5px;min-height:88px;padding:13px;text-align:left;border:1px solid var(--line,#eadfce);border-radius:16px;background:var(--panel,#fff);color:var(--ink,#241a11);cursor:pointer}
.level-picker-card strong{font-size:1.15rem;color:var(--accent,#c2402c)}
.level-picker-card span{font-size:.72rem;line-height:1.35;color:var(--muted,#746958)}
.level-picker-card.is-active{border-color:var(--accent,#c2402c);background:color-mix(in srgb,var(--accent,#c2402c) 8%,var(--panel,#fff));box-shadow:0 0 0 2px color-mix(in srgb,var(--accent,#c2402c) 16%,transparent)}
.level-source-note,.level-scope-note,.grammar-level-note{display:flex;flex-wrap:wrap;gap:5px 10px;align-items:baseline;padding:12px 14px;margin:0 0 16px;border-radius:15px;background:var(--panel-soft,#f8f1e7);color:var(--ink,#241a11);font-size:.83rem}
.level-source-note{display:block;margin-top:10px}
.level-source-note b{color:var(--accent,#c2402c)}
.level-scope-note span,.grammar-level-note span,.grammar-level-note small{color:var(--muted,#746958)}
.grammar-level-note{display:grid;gap:4px}
.grammar-level-note b{color:var(--accent,#c2402c)}
.skill-level-note{margin-top:10px;font-size:.82rem;color:var(--muted,#746958)}
.skill-level-note b{color:var(--accent,#c2402c)}
@media(max-width:620px){
  .section-head{align-items:flex-start;flex-direction:column}
  .section-head .active-level-control{align-self:stretch;flex-direction:row;align-items:center;justify-content:space-between}
  .level-picker-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .home-level-context{font-size:.62rem}
}
/* m025-137: lesson yang prasyaratnya belum tuntas. Kartunya sengaja tetap terbaca -
   murid perlu melihat apa yang menunggunya di depan, bukan menemukan daftar yang kosong. */
.card.lesson-locked{opacity:.72}
/* warna sudah datang dari resep button:disabled; opacity dilepas supaya tidak dobel-pudar */
.card.lesson-locked .lesson-card-foot button[disabled]{cursor:not-allowed;opacity:1}
.lesson-lock-note{display:flex;gap:7px;align-items:flex-start;margin:8px 0 0;font-size:.78rem;line-height:1.4;color:var(--muted,#746958)}
.lesson-lock-note i{flex:none;width:14px;height:14px;margin-top:2px}
/* m025-138: kontrak ujian dan rubrik Writing. Batas kata sengaja dibuat menonjol -
   di IELTS, tulisan di bawah batas kena penalti sebelum isinya sempat dinilai. */
.writing-exam{display:grid;gap:3px;margin:0 0 10px;padding:11px 13px;border-radius:14px;background:var(--panel-soft,#f8f1e7);font-size:.8rem}
.writing-exam b{color:var(--accent,#c2402c)}
.writing-exam span{font-weight:600}
.writing-exam small{color:var(--muted,#746958);line-height:1.4}
.writing-focus{margin:6px 0 0;font-size:.78rem;color:var(--muted,#746958)}
.writing-rubric ul,.writing-checklist{display:grid;gap:8px;margin:10px 0 0;padding:0;list-style:none}
.writing-rubric li{display:grid;gap:2px;font-size:.8rem}
.writing-rubric li span{color:var(--muted,#746958)}
.writing-checklist li{display:grid;gap:2px;padding:9px 11px;border-radius:12px;border-left:3px solid var(--line,#eadfce);background:var(--panel-soft,#f8f1e7);font-size:.79rem}
.writing-checklist li span{color:var(--muted,#746958);line-height:1.45}
.writing-check.is-ok{border-left-color:#3f8f5f}
.writing-check.is-perhatikan{border-left-color:var(--accent,#c2402c)}
.writing-check.is-ai{border-left-color:#7a6cc4}
/* m025-139: jalur Reading berformat ujian. Kontraknya (panjang, jumlah soal, waktu)
   ditaruh di muka karena itulah yang membedakannya dari bacaan latihan biasa. */
.reading-exam{display:grid;gap:11px;margin:0 0 16px}
.reading-exam-set{display:grid;gap:4px;padding:12px 13px;border-radius:14px;background:var(--panel-soft,#f8f1e7)}
.reading-exam-set span{font-size:.75rem;font-weight:600;color:var(--accent,#c2402c)}
.reading-exam-set small{font-size:.74rem;line-height:1.45;color:var(--muted,#746958)}
.reading-exam-set button{justify-self:start;margin-top:5px}


/* ==========================================================================
   FASE 2 — komponen BARU dari design/redesign-v1/components (§9 hint, §10 audio,
   §13 field). Belum ada markup yang memanggilnya; resepnya ditulis di sini supaya
   layar Fase 3 tidak menulis ulang tiga kali dengan tiga nilai berbeda.
   ========================================================================== */
/* §9 panel petunjuk bertahap — nomor langkah, bukan paragraf jawaban */
.hintpanel{background:var(--panel);border:1.5px solid var(--line);border-radius:var(--radius-md);
  padding:14px 16px;display:grid;gap:10px}
.hint-step{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--text)}
.hint-step .hint-num{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;
  font-size:12px;font-weight:700;background:var(--panel-soft);color:var(--muted);
  border:1.5px solid var(--line)}
.hint-step.is-done .hint-num{background:var(--sun-soft);border-color:var(--sun);color:var(--text)}
.hint-step.is-current .hint-num{background:var(--text);border-color:var(--text);color:var(--on-core)}
.hint-step.is-locked{color:var(--muted)}
.hint-step.is-locked .hint-num{background:var(--panel-soft);color:var(--muted)}

/* §10 pemutar audio + equalizer */
.audioplayer{display:flex;align-items:center;gap:12px;background:var(--panel);
  border:1.5px solid var(--line);border-radius:var(--radius-lg);padding:12px 16px}
.eq{display:flex;align-items:flex-end;gap:3px;height:22px}
.eq i{width:4px;border-radius:2px;background:var(--sun);height:100%;
  animation:eq .9s var(--ease) infinite alternate}
.eq i:nth-child(2){animation-delay:.15s}
.eq i:nth-child(3){animation-delay:.3s}
.eq i:nth-child(4){animation-delay:.45s}
@keyframes eq{from{transform:scaleY(.55)}to{transform:scaleY(1)}}
@media (prefers-reduced-motion:reduce){.eq i{animation:none;transform:scaleY(.8)}}

/* §13 field — tinggi 48px, cincin fokus satu resep, state error/success by teks+warna */
.field{display:grid;gap:6px}
.field label{font-size:12px;font-weight:600;color:var(--muted)}
.field input,.field textarea,.field select{min-height:48px;padding:12px 14px;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);background:var(--panel);
  color:var(--text);font:inherit}
.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{
  outline:2px solid var(--focus-ring);outline-offset:2px;border-color:var(--focus-ring)}
.field.is-error input{border-color:var(--bad)}
.field.is-error .field-msg{color:var(--bad);font-size:12px}
.field.is-success input{border-color:var(--good)}
.field.is-success .field-msg{color:var(--good);font-size:12px}
.field input:disabled{background:var(--panel-soft);color:var(--text-disabled)}


/* ==========================================================================
   FASE 2 F2-15 — LANTAI 12px. DIRECTION Tipografi: "tak ada teks <12px".
   Blok ini APPEND dan keyed-by-selector, bukan tiga puluh suntingan tersebar:
   satu tempat untuk dibaca, satu tempat untuk dicabut. Pelanggar terverifikasi
   berkisar .6rem-.74rem (9,6-11,8px); tidak ada satu pun yang MENGECIL karena
   blok ini - yang terbesar sebelumnya 11,84px.
   ========================================================================== */
.version,
.stats small,.home-stats small,
.auth-legal,
.confidence-scale button,
.launcher-meta,
.mission-ring span,
.launch-card small,
.welcome-mark,.modal-mark,
.lesson-example>span,.lesson-card-foot>span,
.skill-badge,.skill-ring b,
.fz-coach-head small,
.tutor-turn-head,.tutor-card-head small,
.hero-stat small,
.coach-strip-say small,
.active-level-control span,.home-level-context,
.swipe-hint,
.setting-row small,
.endpoint-label,.setup-link,.consent-row,
.journey-week,.journey-week small,.journey-day small,.journey-skill small,
.journey-mission small,.journey-today small,.journey-goal small,
.journey-why,.journey-note,.journey-block span,.journey-skill span,.journey-recovery,
.fiezel-splash-tag,
.coach-level span{
  font-size:12px;
}
/* Dua pelanggar memaku ukurannya dengan !important, jadi lantainya harus sama keras. */
.notification-help,.report-state{font-size:12px!important}
/* Label huruf besar yang membesar: tracking dirapatkan supaya tidak memaksa baris kedua. */
.launcher-meta,.skill-badge,.tutor-turn-head{letter-spacing:.08em}
.fiezel-splash-tag{letter-spacing:.11em}

/* ==========================================================================
   FASE 2 F2-14 — ikon state toast. Dua nilai di bawah adalah SATU-SATUNYA
   literal baru fase ini (asal: design/redesign-v1/components). Keduanya tinta
   di atas permukaan --core yang gelap, jadi mereka memang harus terang dan
   TIDAK boleh memakai --good/--bad (keduanya gelap, 1,3:1 di atas core).
   Ganti ke var() bila Fase 3 menambahkan --good-on-core/--bad-on-core.
   ========================================================================== */
.toast.is-good .toast-icon{color:#7ED9AE}
.toast.is-bad .toast-icon{color:#F0907B}

/* ==========================================================================
   FASE 2 F2-13 — .toggle (components.css §14). Belum ada markup pemanggil;
   settings di-reskin di Fase 3. Track 52x32, knob 25px, is-on = tinta + knob sun.
   ========================================================================== */
.toggle{position:relative;width:52px;height:32px;border-radius:var(--radius-pill);
  background:var(--line);border:0;cursor:pointer;transition:background var(--dur-s) var(--ease)}
.toggle::after{content:"";position:absolute;top:3.5px;left:4px;width:25px;height:25px;
  border-radius:50%;background:var(--panel);box-shadow:0 1px 3px rgba(36,26,17,.25);
  transition:transform var(--dur-s) var(--ease)}
.toggle.is-on{background:var(--text)}
.toggle.is-on::after{background:var(--sun);transform:translateX(19px)}
.toggle:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}

/* ==========================================================================
   FASE 2 — wajah display bulat pada TEKS DISPLAY BESAR (DIRECTION Tipografi).

   DEVIASI SADAR, dan ini batas yang dipilih dengan sengaja. Aturan display
   eksisting menyatukan .section-head h1 dengan .welcome-panel h2/.modal-panel h2/
   .fiezel-title dalam SATU selector, dan aturan itu dipaku oleh
   splash-choreography-test: wordmark + judul dialog harus tetap Instrument Serif
   berat 400. Memecah selector itu supaya .section-head h1 bisa pindah ke Fredoka
   berarti membongkar kontrak koreografi untuk keuntungan kosmetik di satu judul.
   Jadi judul-seksi tetap serif, dan Fredoka dipasang pada dua permukaan display
   yang TIDAK ikut aturan itu dan BENAR-BENAR ADA di markup: kata besar kartu
   kosakata (.word, 2,6rem) dan judul lesson grammar (.lesson-title, 1,55rem).
   Keduanya diperiksa di app.js, bukan diasumsikan - .hero h2 dan .empty-state h2
   sempat masuk daftar ini lalu dikeluarkan karena TIDAK ADA elemennya: .hero cuma
   punya turunan -line/-ring/-stat, dan .empty-state punya CSS tanpa pemanggil.
   Di dua ukuran itu kebulatan Fredoka terbaca sebagai kehangatan; di ukuran UI
   ia hanya jadi kabur.
   ========================================================================== */
.word,
.lesson-title{
  font-family:var(--fz-display-round);
  font-weight:600;
  letter-spacing:-.01em;
/* ==========================================================================
   ===== FASE3 =====
   Blok terpisah di akhir berkas, dengan sengaja. Fase 2 sedang mengedit blok
   atas (palet :root, tombol, .option, nav bawah, kartu). Seluruh tambahan
   Fase 3 tinggal di bawah marker ini supaya dua rangkaian patch tidak pernah
   bertengkar atas baris yang sama; urutan cascade juga menguntungkan kita —
   restyle di sini menang tanpa perlu !important.
   ========================================================================== */
:root{
  /* Fase 2 sudah memasang keluarga --sun/--core/--good/--bad/--focus-ring di
     blok :root kedua. Yang belum ada hanya cincin fokus DI ATAS permukaan core:
     --focus-ring #A67A00 cuma 1,9:1 di atas --core #1B1418, jadi fokus di dalam
     panel gelap butuh kuningnya sendiri (#FFC700 = 11,4:1 di atas --core). */
  --focus-ring-on-core:#FFC700;
}

/* ---------- §9.2 toast: ikon + sejajar ----------
   Warna toast (permukaan --core, tinta --on-core) sudah dipasang Fase 2 di blok
   atas; yang ditambahkan di sini hanya tata letaknya supaya ikon dan teks duduk
   satu baris, dan teks panjang membungkus rata kiri alih-alih rata tengah. */
.toast{display:flex;align-items:center;gap:8px;text-align:left}
.toast .toast-mark{flex:0 0 auto;color:var(--sun)}

/* ---------- §1/§9.1 panel ANALYZING ----------
   Permukaan gelap yang sengaja: ia satu-satunya bidang di layar kuis yang bukan
   kertas, jadi murid tahu yang sedang bicara adalah mesinnya. Tinta --on-core di
   atas --core = 14,7:1; ukuran terkecil .core-eyebrow 12px (.75rem). */
.core-panel{position:relative;overflow:hidden;background:var(--core);border-radius:var(--radius-lg);padding:18px;color:var(--on-core)}
.core-panel .neural{position:absolute;inset:0;width:100%;height:100%;opacity:.5;pointer-events:none;color:var(--sun)}
.core-panel>div{position:relative}
.core-eyebrow{font-size:.75rem;font-weight:700;letter-spacing:.18em;color:var(--sun)}
.core-title{margin-top:6px;font-size:1rem;font-weight:700;color:var(--on-core)}
.core-sub{margin-top:5px;font-size:.82rem;line-height:1.5;color:var(--on-core-muted)}
.core-bar{position:relative;margin-top:14px;height:5px;border-radius:99px;background:rgba(253,250,243,.22);overflow:hidden}
.core-bar i{position:absolute;inset:0 auto 0 0;width:46%;border-radius:99px;background:linear-gradient(90deg,var(--sun),var(--sun-deep))}
.core-bar::after{content:"";position:absolute;inset:0 auto 0 0;width:18%;border-radius:99px;background:rgba(253,250,243,.35);animation:coreScan 1.6s var(--ease) infinite}
@keyframes coreScan{from{left:-18%}to{left:100%}}
.core-panel :focus-visible{outline:2px solid var(--focus-ring-on-core);outline-offset:2px}
.core-analyzing{margin:12px 0}
/* Sapuan pemindai adalah satu-satunya gerak di panel ini, jadi ia yang dimatikan -
   panelnya sendiri tetap tampil supaya sebab-akibatnya tidak hilang. */
@media (prefers-reduced-motion:reduce){.core-bar::after{animation:none;display:none}}

/* ---------- §8/§9.3 aturan dock maskot ----------
   Gelembung pembimbing tetap tinggal di <body> dan tetap bisa diketuk di mana pun
   (kontrak m025-115). Yang berubah hanya di dua panggung latihan: sapaan otomatis
   dibungkam supaya tidak ada balon yang menutup soal, gelembungnya mengecil dan
   turun keluar dari kolom konten, dan elemen interaktif terakhir diberi ruang
   napas supaya selalu bisa digulir lepas dari bayangan gelembung.
   Z-index tidak diubah: .fz-coach-sheet dan #confidencePop tetap menang. */
body.fz-stage-quiz .fz-coach-peek,
body.fz-stage-sl .fz-coach-peek,
body.fz-stage-map .fz-coach-peek{display:none}
body.fz-stage-quiz .fz-coach-bubble,
body.fz-stage-sl .fz-coach-bubble,
body.fz-stage-map .fz-coach-bubble{width:46px;height:46px;bottom:calc(88px + env(safe-area-inset-bottom))}
body.fz-stage-quiz .fz-coach-bubble .fz-coach-face,
body.fz-stage-sl .fz-coach-bubble .fz-coach-face,
body.fz-stage-map .fz-coach-bubble .fz-coach-face{width:24px;height:24px}
/* Ruang bawah supaya kartu terakhir Peta Belajar bisa lewat di atas pita dok. */
body.fz-stage-map .app{padding-bottom:104px}
body.fz-stage-quiz .quiz-shell{padding-bottom:96px}

/* ---------- §2 kuis: benar / salah / pijakan ----------
   Banner benar-salah, kartu sebab, dan tip ingatan SUDAH ada 1:1 di reveal(); yang
   kurang cuma dua hal yang bisa dibaca dalam sekejap: mana jawaban yang benar, dan
   mana yang tadi dipilih. Keduanya dipasang sebagai pseudo-element - nol perubahan
   pada answer()/reveal(), jadi tidak ada kontrak markup yang bergeser. */
.option.correct::after,
.option.wrong::after{
  display:block;width:fit-content;margin-top:9px;padding:3px 9px;border-radius:999px;
  font-size:.75rem;font-weight:700;letter-spacing:.08em
}
/* Tag ditaruh DI BAWAH teks pilihan, bukan mengambang di sudut: pilihan jawaban bisa
   dua baris pada layar sempit, dan tag mengambang akan menabraknya. */
.option.correct::after{content:"BENAR";background:var(--good);color:var(--on-core)}
.option.wrong::after{content:"PILIHANMU";background:var(--bad);color:var(--on-core)}

/* Rincian pengecoh dulu selalu terbentang. Pada soal empat pilihan itu empat paragraf
   tambahan tepat di bawah kesimpulan yang justru paling penting dibaca; sekarang ia
   terlipat dan dibuka kalau memang mau dibandingkan. */
.acc{margin-top:10px;border-top:1px dashed var(--line);padding-top:8px}
.acc>summary{cursor:pointer;font-size:.8rem;font-weight:700;color:var(--muted);list-style:none}
.acc>summary::-webkit-details-marker{display:none}
.acc>summary::after{content:"\2304";margin-left:6px;font-weight:700}
.acc[open]>summary::after{content:"\2303"}
.acc>summary:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;border-radius:6px}
.acc .distractor-breakdown{margin-top:2px;border-top:0;padding-top:0}

/* Tombol Lanjut yang terkunci: Fase 2 sudah membuat tintanya terbaca (4,8:1). Yang
   ditambahkan di sini adalah SEBABNYA - gembok, supaya "belum bisa" tidak perlu
   ditebak dari warna. Digambar lewat CSS mask agar markup draw() tetap utuh. */
.quiz-next:disabled::before{
  content:"";width:13px;height:13px;flex:0 0 auto;background:currentColor;
  -webkit-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E") center/contain no-repeat
}

/* Kartu ajar-ulang dan pijakan: aksennya lepas dari marun kontrol dan pindah ke
   keluarga sun, sekeluarga dengan panel FIEZEL. Nama kelas tidak ada yang berubah -
   tutor-reteach-card-test.js dan tutor-classroom-regression-test.js memeriksa
   strukturnya, dan struktur itu memang tidak boleh bergeser. */
.tutor-turn,.tutor-card-why{border-left-color:var(--sun-deep)}
.tutor-card-why{background:var(--sun-soft)}
/* Wajah tutor dulu bidang --accent dengan tinta --accent-on-glass di atasnya: dua
   turunan marun yang sama, 1,3:1 - ikon topi wisudanya praktis tidak ada. Sekarang
   bidang sun dengan tinta ink, 11,4:1. */
.tutor-turn-face{background:var(--sun);color:var(--text)}
/* Penanda "Jeda mengajar" jadi bidang, bukan teks abu di antara teks abu lain: ia
   satu-satunya keterangan bahwa layar ini BUKAN soal. --info di atas --sun-soft 5,9:1. */
.quiz-teach-flag{padding:4px 10px;border-radius:999px;font-size:.75rem;background:var(--sun-soft);color:var(--info)}

/* ---------- §4 flashcard: chip level + "Kelas kata" ----------
   indonesianPartOfSpeech() sudah menerjemahkan kuncinya sejak lama, jadi ini bukan
   perbaikan kebocoran kunci mentah - ini soal keterbacaan. "A2 · Kata benda" sebagai
   satu baris eyebrow abu tidak memberi tahu bahwa yang kedua adalah KELAS KATA;
   dua chip dengan labelnya sendiri memberi tahu. */
.chips-row{display:flex;gap:7px;flex-wrap:wrap;justify-content:center}
.chip{display:inline-flex;align-items:center;min-height:24px;padding:3px 10px;border-radius:999px;font-size:.75rem;font-weight:600}
.chip-level{background:var(--sun-soft);color:var(--text);border:1px solid var(--sun-deep)}
.chip-cat{background:var(--panel-soft);border:1px solid var(--line);color:var(--muted)}
.chip-cat b{color:var(--text);font-weight:700}

/* ---------- §5 peta belajar satu kartu + panel NEXT SESSION ---------- */
.map-rows{display:grid;gap:13px}
.map-row{display:grid;grid-template-columns:22px 84px 1fr 40px;align-items:center;gap:10px}
.map-row .mi{width:22px;height:22px;display:grid;place-items:center;border-radius:7px;background:var(--sun-soft);color:var(--text)}
.map-row .mi svg{width:14px;height:14px}
.map-row .mn{font-weight:700;font-size:.86rem}
.map-row .bar{margin-top:0}
.map-row .mp{text-align:right;font-weight:800;font-size:.84rem;font-variant-numeric:tabular-nums}
/* Keterangan bukti pindah ke baris kedua di kolom batang: pada layar sempit ia tidak
   pernah ikut menyempitkan batangnya sendiri. */
.map-row .me{grid-column:3/5;font-size:.75rem;color:var(--muted);line-height:1.4}
.map-note{display:flex;align-items:center;gap:9px;margin:14px 0 0;font-size:.79rem;line-height:1.5;color:var(--muted)}
.map-note .coach-strip-face{flex:0 0 auto;width:28px;height:28px}

.next-session{margin-bottom:2px}
.core-actions{display:flex;flex-wrap:wrap;gap:9px;margin-top:14px}
.core-cta,.core-ghost{min-height:44px;padding:10px 18px;border-radius:var(--radius-md);font-weight:700;font-size:.86rem;cursor:pointer}
/* Bidang kuning dengan tinta ink di atasnya (11,4:1). Kuning tidak pernah jadi warna
   TEKS di sistem ini; di sini ia bidang, dan itu memang perannya. */
.core-cta{background:linear-gradient(135deg,var(--sun),var(--sun-deep));color:var(--text);border:1.5px solid var(--sun-deep)}
.core-ghost{background:var(--core-soft);border:1.5px solid var(--core-line);color:var(--on-core)}
.core-cta:focus-visible,.core-ghost:focus-visible{outline:2px solid var(--focus-ring-on-core);outline-offset:2px}

/* ---------- §6 layar selesai ----------
   Skor berhenti berwarna hijau: hijau adalah warna BENAR di sistem ini (banner, opsi),
   dan memakainya untuk skor 34% berarti mengucapkan "bagus" pada sesi yang justru perlu
   diulang. Angkanya jadi tinta biasa; yang merayakan adalah piala, maskot, dan bunyinya. */
.result-card .score{color:var(--text)}
.ring-row{display:flex;align-items:center;justify-content:center;gap:14px}
.ring-row .coach-strip-face{flex:0 0 auto;width:52px;height:52px}
.result-actions{display:grid;gap:9px;margin-top:4px}
.result-actions .ghost{min-height:44px;background:transparent;border:1.5px solid var(--line);color:var(--muted)}

/* ---------- §7 pengaturan: sakelar + ikon ----------
   CSS-ONLY, nol JS. Sakelarnya digambar DI ATAS checkbox natif, jadi seluruh id
   (#settingReminders, #settingHaptics, #settingFeedbackSounds, #settingMotion),
   handler #settingsSave, label, dan role bawaan tetap utuh - pembaca layar tetap
   mendapat checkbox sungguhan, bukan div ber-aria. */
.setting-row{min-height:44px}
.setting-row input[type=checkbox]{
  appearance:none;-webkit-appearance:none;position:relative;
  width:50px;height:30px;flex:0 0 auto;border-radius:99px;
  background:var(--line);border:1.5px solid var(--line);cursor:pointer;
  transition:background var(--dur-s) var(--ease),border-color var(--dur-s) var(--ease)
}
.setting-row input[type=checkbox]::after{
  content:"";position:absolute;top:2px;left:2px;width:23px;height:23px;border-radius:50%;
  background:var(--panel);box-shadow:0 1px 4px rgba(36,26,17,.25);
  transition:transform var(--dur-s) var(--ease-spring)
}
.setting-row input[type=checkbox]:checked{background:var(--text);border-color:var(--text)}
.setting-row input[type=checkbox]:checked::after{transform:translateX(20px);background:var(--sun)}
.setting-row input[type=checkbox]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.setting-row input[type=checkbox]:disabled{background:var(--panel-soft);border-color:var(--line);cursor:not-allowed}
.setting-row input[type=checkbox]:disabled::after{background:var(--line-soft);box-shadow:none}
/* Audit #4 lagi: baris yang tidak bisa diubah tetap TERBACA, tinta yang berubah -
   bukan opacity. Tanpa dukungan :has() teks tetap warna normal, jadi kegagalan
   fitur ini bukan regresi keterbacaan. */
.setting-row:has(input:disabled) b,
.setting-row:has(input:disabled) small{color:var(--muted)}
/* Ikon baris pindah ke keluarga sun: marun --accent-strong di dalam kotak kecil
   membuat setiap baris pengaturan terbaca seperti peringatan. */
.setting-icon{background:var(--sun-soft);color:var(--text);border-radius:10px}
