/* ============================================================
   JazLearnThai - "Duo-Play" design system
   Thesis: a game you want to open daily. Bright navy + tassel-yellow,
   chunky rounded geometry, and tactile 3D press-down buttons.

   Signature: every interactive surface has a solid darker bottom edge
   that collapses as the surface presses down (:active), so the whole UI
   feels physically pressable. Correct answers bounce the mascot; wrong
   answers shake it. All motion respects prefers-reduced-motion.

   Layout goal: the full learning loop (prompt + 4 options) and the answer
   feedback fit the first fold on a phone. Mobile-first density.
   ============================================================ */

:root {
  /* --- brand palette --- */
  --navy:        #2E2C8B;   /* structure, text, hero */
  --navy-deep:   #23215F;   /* button 3D edges, deep shadow */
  --navy-soft:   #EEEEFB;   /* tinted fills on light */
  --yellow:      #FFE100;   /* primary action + XP */
  --yellow-deep: #E0B500;   /* yellow 3D edge */
  --green:       #3FD07A;   /* correct */
  --green-deep:  #29A65E;
  --green-soft:  #E4F9ED;
  --red:         #FF5468;   /* wrong */
  --red-deep:    #D63A4D;
  --red-soft:    #FFE7EA;
  --pink:        #F5A9BC;   /* hearts / lives */
  --sky:         #8ECAE6;   /* progress / audio accent */
  --sky-deep:    #5AA9CC;   /* sky 3D edge (pronunciation button) */
  --gold:        #F2C037;

  /* podium metals (ranking) */
  --silver:      #DCDBEA; --silver-2: #B9B7D2; --silver-edge: #9E9CBE;
  --bronze:      #EBB88C; --bronze-2: #CE924F; --bronze-edge: #A96C34;

  --canvas:      #FFFDF5;   /* warm off-white page */
  --canvas-2:    #FFF7E0;
  --surface:     #FFFFFF;
  --surface-2:   #F7F7FC;

  --ink:         #2E2C8B;   /* primary text = navy */
  --ink-2:       #4A4880;
  --ink-soft:    #7C7AA6;
  --ink-faint:   #A9A7C6;
  --line:        #E7E6F5;

  /* chunky radii */
  --r-xl: 28px;
  --r-lg: 22px;
  --r-md: 16px;
  --r-sm: 12px;

  /* soft lift shadows (distinct from the hard 3D press edges) */
  --lift-sm: 0 3px 10px -4px rgba(46,44,139,.18);
  --lift-md: 0 14px 30px -14px rgba(46,44,139,.30);
  --lift-lg: 0 28px 60px -26px rgba(46,44,139,.40);

  --font-display: "Baloo 2", "Nunito", ui-rounded, system-ui, sans-serif;
  --font-body: "Nunito", ui-rounded, system-ui, "Segoe UI", sans-serif;

  /* Thai learning surface: looped, beginner-friendly face (huruf berkepala). */
  --font-thai: "Sarabun", "IBM Plex Sans Thai", sans-serif;

  --safe-b: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; }
html, body { margin: 0; }
[hidden] { display: none !important; }
.svg-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

body {
  font-family: var(--font-body);
  color: var(--ink);
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
  /* soft dotted "confetti" texture over a warm canvas */
  background-color: var(--canvas);
  background-image:
    radial-gradient(circle at 1px 1px, rgba(46,44,139,.055) 1.4px, transparent 0),
    radial-gradient(760px 480px at 90% -10%, rgba(255,225,0,.16), transparent 60%),
    radial-gradient(700px 520px at -8% 110%, rgba(142,202,230,.18), transparent 60%);
  background-size: 22px 22px, auto, auto;
  background-attachment: fixed;
}

/* ---------- Welcome intro ---------- */
body.welcome-active { overflow: hidden; }
.welcome {
  position: fixed; inset: 0; z-index: 1000;
  display: grid; place-items: center;
  min-height: 100dvh;
  padding: max(28px, env(safe-area-inset-top)) 24px max(28px, env(safe-area-inset-bottom));
  overflow: hidden;
  background-color: var(--canvas);
  background-image:
    radial-gradient(circle at 1px 1px, rgba(46,44,139,.055) 1.4px, transparent 0),
    radial-gradient(circle at 50% 47%, rgba(255,225,0,.16) 0, rgba(255,225,0,.055) 22%, transparent 48%),
    radial-gradient(760px 480px at 90% -10%, rgba(255,225,0,.16), transparent 60%),
    radial-gradient(700px 520px at -8% 110%, rgba(142,202,230,.18), transparent 60%);
  background-size: 22px 22px, auto, auto, auto;
  background-attachment: fixed;
  opacity: 1;
  transition: opacity .16s .24s ease, visibility .4s ease;
}
.welcome::before,
.welcome::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  border-radius: 50%; pointer-events: none;
  background: var(--yellow); opacity: .7;
  animation: welcome-dot 1.8s ease-in-out infinite;
}
.welcome::before { width: 9px; height: 9px; margin: -204px 0 0 -246px; }
.welcome::after {
  width: 6px; height: 6px; margin: 190px -268px 0 0;
  background: var(--sky); animation-delay: -.7s;
}
.welcome.is-leaving { opacity: 0; visibility: hidden; pointer-events: none; }
.welcome.is-leaving .welcome-inner { animation: none; }
.welcome.is-leaving .welcome-logo-wrap,
.welcome.is-leaving .welcome-greeting,
.welcome.is-leaving .welcome-progress {
  animation: welcome-elements-out .22s ease both;
}
.welcome.is-leaving .welcome-letter {
  animation: welcome-letter-out .2s ease both;
}
.welcome.is-leaving .welcome-orbit {
  animation: welcome-fade-out .16s ease both;
}
.welcome.is-leaving .welcome-mascot {
  animation: welcome-mascot-out .28s cubic-bezier(.4,0,.8,.25) both;
}
.welcome.is-leaving .welcome-halo {
  animation: welcome-halo-out .4s cubic-bezier(.4,0,.6,1) both;
}
.welcome-inner {
  position: relative; width: min(84vw, 380px);
  display: flex; flex-direction: column; align-items: center;
  animation: welcome-in .62s cubic-bezier(.2,.9,.25,1) both;
}
.welcome-logo-wrap {
  width: min(54vw, 216px); overflow: hidden;
  animation: welcome-logo-reveal .56s .12s cubic-bezier(.25,.8,.25,1) both;
}
.welcome-logo { display: block; width: 100%; height: auto; }
.welcome-mascot-wrap {
  position: relative; width: clamp(150px, 38vw, 182px); aspect-ratio: 1;
  margin-top: 24px; display: grid; place-items: center;
}
.welcome-halo {
  position: absolute; z-index: 0; width: 82%; height: 82%; border-radius: 50%;
  background:
    radial-gradient(circle at 38% 32%, #FFF39A 0, var(--yellow) 40%, #F7CA00 100%);
  box-shadow: 0 12px 34px rgba(224,181,0,.24);
  transform: scale(.4); opacity: 0;
  animation:
    welcome-halo .55s .38s cubic-bezier(.2,.9,.25,1) both,
    welcome-halo-breathe 1.3s 1.05s ease-in-out infinite;
}
.welcome-halo::after {
  content: ""; position: absolute; inset: 8px; border-radius: inherit;
  border: 2px solid rgba(255,255,255,.72);
}
.welcome-orbit {
  position: absolute; z-index: 0; inset: -8%; border-radius: 50%;
  border: 1.5px dashed rgba(46,44,139,.18);
  opacity: 0;
  animation:
    welcome-orbit-in .45s .58s ease both,
    welcome-orbit-spin 7s 1.04s linear infinite;
}
.welcome-letter {
  position: absolute; z-index: 3; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 10px;
  font-family: var(--font-thai); font-size: 1rem; font-weight: 700;
  color: var(--navy); background: var(--surface);
  border: 1.5px solid var(--line);
  box-shadow: 0 5px 14px rgba(46,44,139,.13);
  opacity: 0;
  animation: welcome-letter-pop .48s cubic-bezier(.2,1.35,.3,1) both;
}
.welcome-letter-a { --letter-rotate: -9deg; left: -18px; top: 19%; animation-delay: .67s; }
.welcome-letter-b { --letter-rotate: 8deg; right: -20px; top: 12%; animation-delay: .75s; }
.welcome-letter-c { --letter-rotate: 7deg; left: -10px; bottom: 3%; animation-delay: .83s; }
.welcome-letter-d { --letter-rotate: -7deg; right: -16px; bottom: 7%; animation-delay: .91s; }
.welcome-sparks { position: absolute; z-index: 2; inset: 50%; pointer-events: none; }
.welcome-sparks span {
  --spark-distance: -103px;
  position: absolute; left: -2px; top: -5px;
  width: 4px; height: 11px; border-radius: 999px;
  background: var(--navy); opacity: 0;
  transform-origin: 2px 5px;
  animation: welcome-spark .58s .68s cubic-bezier(.2,.7,.2,1) both;
}
.welcome-sparks span:nth-child(1) { --spark-angle: 0deg; }
.welcome-sparks span:nth-child(2) { --spark-angle: 45deg; --spark-distance: -110px; background: var(--sky); animation-delay: .72s; }
.welcome-sparks span:nth-child(3) { --spark-angle: 90deg; background: var(--yellow-deep); animation-delay: .7s; }
.welcome-sparks span:nth-child(4) { --spark-angle: 135deg; --spark-distance: -110px; background: var(--pink); animation-delay: .75s; }
.welcome-sparks span:nth-child(5) { --spark-angle: 180deg; animation-delay: .71s; }
.welcome-sparks span:nth-child(6) { --spark-angle: 225deg; --spark-distance: -110px; background: var(--sky); animation-delay: .76s; }
.welcome-sparks span:nth-child(7) { --spark-angle: 270deg; background: var(--yellow-deep); animation-delay: .73s; }
.welcome-sparks span:nth-child(8) { --spark-angle: 315deg; --spark-distance: -110px; background: var(--pink); animation-delay: .77s; }
.welcome-mascot {
  position: relative; z-index: 1; display: block;
  width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 12px 15px rgba(35,33,95,.18));
  transform-origin: 50% 90%;
  animation:
    welcome-mascot-in .72s .3s cubic-bezier(.2,1.15,.3,1) both,
    welcome-mascot-float 1.2s 1.08s ease-in-out infinite;
}
.welcome-greeting {
  margin: 8px 0 13px;
  font-family: var(--font-thai); font-size: clamp(.9rem, 2.6vw, 1.02rem);
  font-weight: 600; letter-spacing: .03em; color: var(--ink-soft);
  animation: welcome-copy .4s .96s ease both;
}
.welcome-progress {
  position: relative; width: 54px; height: 4px; overflow: hidden; border-radius: 999px;
  background: var(--navy-soft);
  animation: welcome-copy .4s 1.05s ease both;
}
.welcome-progress span {
  display: block; width: 100%; height: 100%; border-radius: inherit;
  background: var(--navy);
  transform: translateX(-100%);
  animation: welcome-progress 1.12s 1.1s cubic-bezier(.55,0,.25,1) both;
}
.welcome-progress::after {
  content: ""; position: absolute; inset: 0 auto 0 -14px; width: 12px;
  background: rgba(255,255,255,.72); transform: skewX(-20deg);
  animation: welcome-progress-shine .72s 1.38s ease-in-out both;
}

/* ================= 3D PRESS BUTTONS (the signature) ================= */
/* A solid darker bottom edge (box-shadow, not blur) that collapses while
   the surface translates down on press. Reused across every control. */
.btn-primary, .opt, .btn-ghost {
  --edge: var(--navy-deep);
  --lift: 5px;
  border: 0; cursor: pointer;
  transition: transform .06s ease, box-shadow .06s ease, background .14s ease, border-color .14s ease;
}
.btn-primary:active:not(:disabled),
.opt:active:not(:disabled),
.btn-ghost:active {
  transform: translateY(var(--lift));
  box-shadow: 0 0 0 0 var(--edge) !important;
}
:focus-visible { outline: 3px solid var(--sky); outline-offset: 3px; }

/* ---------- App shell ---------- */
.app {
  position: relative; z-index: 1;
  max-width: 560px; margin: 0 auto;
  height: 100dvh;             /* fixed frame so a practice session fits the page */
  padding: 16px 16px 0;       /* tabbar rides the bottom in-flow; no reservation */
  display: flex; flex-direction: column; gap: 13px;
  /* opacity-only entrance: never leaves a lingering transform, so the pinned
     Lanjut button stays viewport-relative on phones. */
  animation: fade .45s ease both;
}

/* ---------- Practice bar ---------- */
/* Back + title hard left, the practice controls hard right, one row: the title
   ellipses rather than wrapping the controls onto a second line. */
.brand { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* Practice header controls: cara-baca ก/Aa pill (always visible) sitting beside
   a "..." menu that holds the practice direction. */
.play-controls { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }

/* Romanization segmented pill; echoes the direction control's pill language. */
.roman-toggle {
  display: inline-flex; align-items: stretch; background: var(--surface);
  border: 2px solid var(--line); border-radius: 999px; padding: 3px; gap: 2px;
  box-shadow: var(--lift-sm); flex: 0 0 auto;
}
.roman-toggle button {
  border: 0; background: transparent; color: var(--ink-soft); cursor: pointer;
  font-family: var(--font-display); font-weight: 800; line-height: 1;
  min-width: 36px; padding: 8px 10px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .16s ease, color .16s ease, box-shadow .16s ease;
}
.roman-toggle .th { font-family: var(--font-thai); font-size: 1.02rem; }
.roman-toggle .aa { font-size: .84rem; letter-spacing: .3px; }
.roman-toggle button:hover { color: var(--navy); }
.roman-toggle button[aria-pressed="true"] {
  color: var(--navy); background: var(--yellow); box-shadow: 0 3px 0 0 var(--yellow-deep);
}

/* Direction overflow menu. */
.dir-menu { position: relative; flex: 0 0 auto; }
.dir-menu-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 999px; box-shadow: var(--lift-sm);
  background: var(--surface); border: 2px solid var(--line); color: var(--ink-soft);
  cursor: pointer; transition: color .16s ease, border-color .16s ease;
}
.dir-menu-btn svg { width: 20px; height: 20px; }
.dir-menu-btn:hover, .dir-menu-btn[aria-expanded="true"] { color: var(--navy); border-color: #DEDDF6; }
.dir-menu-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 40;
  display: flex; flex-direction: column; gap: 4px; min-width: 168px;
  background: var(--surface); border: 2px solid var(--line);
  border-radius: var(--r-md); padding: 8px; box-shadow: var(--lift-md);
}
.dir-menu-title { font-size: .64rem; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft); padding: 2px 6px 4px; }
.dir-menu-pop button {
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
  font-family: var(--font-display); font-size: .84rem; font-weight: 700;
  text-align: left; white-space: nowrap; padding: 9px 10px; border-radius: var(--r-sm);
  transition: background .12s ease, color .12s ease;
}
.dir-menu-pop button:hover { background: var(--navy-soft); color: var(--navy); }
.dir-menu-pop button.active {
  color: var(--navy); background: var(--yellow); box-shadow: 0 2px 0 0 var(--yellow-deep);
}

/* ---------- Profile: "Kartu Pemain" — gold lai-thai (kranok) collectible card ---------- */
.k-eyebrow { display: flex; align-items: center; justify-content: center; gap: 9px; margin: 0; }
.ey-pill { font-size: .7rem; font-weight: 800; letter-spacing: .16em; color: var(--navy);
  background: var(--navy-soft); padding: 5px 12px; border-radius: 999px; }
.ey-note { font-size: .75rem; font-weight: 700; color: var(--ink-faint); }

.kartu {
  --px: 50%; --py: 50%;
  flex-shrink: 0; margin: 2px auto 0; width: 100%; max-width: 340px; border-radius: 29px;
}
/* Tilt only where initCardTilt() actually runs. A permanent 3D layer (perspective
   + will-change) makes iOS Safari rasterize the whole card once and upscale it,
   so every glyph, icon and the mascot go soft on phones. */
@media (hover: hover) and (pointer: fine) {
  .kartu {
    --rx: 0deg; --ry: 0deg;
    transform: perspective(760px) rotateX(var(--rx)) rotateY(var(--ry));
    transition: transform .5s cubic-bezier(.2,.8,.2,1); will-change: transform;
  }
}
/* gold-leaf rim (Thai temple gilding) */
.k-frame { position: relative; padding: 3px; border-radius: 29px;
  background: linear-gradient(135deg,#FFF3B0 0%,#F4C64A 24%,#C9992E 44%,#FBE38A 62%,#B8860B 82%,#F4C64A 100%);
  box-shadow: 0 4px 0 0 var(--navy-deep), 0 22px 44px -14px rgba(35,33,95,.55); }
.k-face { position: relative; overflow: hidden; border-radius: 26px; padding: 16px 17px 14px;
  background:
    radial-gradient(rgba(244,198,74,.07) 1px, transparent 1.7px) 0 0/18px 18px,
    radial-gradient(130% 100% at 22% 0%, #3B39A6 0%, var(--navy) 46%, #1F1D57 100%);
  box-shadow: inset 0 0 0 1px rgba(212,175,55,.28), inset 0 2px 10px rgba(0,0,0,.30); }
/* gold sheen that shifts with tilt/pointer */
.k-foil { position: absolute; inset: 0; z-index: 1; pointer-events: none; mix-blend-mode: screen; opacity: .6;
  background:
    radial-gradient(150px 150px at var(--px) var(--py), rgba(255,240,190,.5), transparent 62%),
    repeating-linear-gradient(103deg, rgba(255,235,150,.10) 0 12%, rgba(255,255,255,.16) 12% 19%, rgba(201,153,46,.10) 19% 32%);
  background-size: auto, 240% 240%;
  background-position: 0 0, calc(var(--px) - 20%) calc(var(--py) - 20%); }
/* gold lai-thai ornament: double hairline frame + flame-scroll corners */
.k-thai { position: absolute; inset: 8px; z-index: 2; pointer-events: none; border-radius: 20px;
  border: 1.5px solid rgba(244,198,74,.55); box-shadow: inset 0 0 0 4px rgba(244,198,74,.16); }
.k-corner { position: absolute; width: 40px; height: 40px; z-index: 2; pointer-events: none;
  color: #F4C64A; }
.k-corner svg { width: 100%; height: 100%; display: block; }
.k-corner.tl { top: 5px; left: 5px; }
.k-corner.tr { top: 5px; right: 5px; transform: scaleX(-1); }
.k-corner.bl { bottom: 5px; left: 5px; transform: scaleY(-1); }
.k-corner.br { bottom: 5px; right: 5px; transform: scale(-1,-1); }
.k-content { position: relative; z-index: 3; }
.k-ribbon { display: flex; align-items: center; justify-content: space-between; padding: 0 28px; color: rgba(255,255,255,.72); }
.k-mark { display: flex; align-items: center; gap: 6px; font-weight: 900; font-size: .68rem; letter-spacing: .16em; }
.k-mark .el { font-size: .85rem; filter: saturate(0) brightness(1.6); opacity: .9; }
.k-rarity { display: flex; align-items: center; gap: 5px; font-family: "Sarabun", var(--font-body);
  font-weight: 700; font-size: .72rem; letter-spacing: .03em; color: #1F1D57;
  background: linear-gradient(120deg,#FFF0A8,#FFE100 55%,#E0B500); padding: 3px 11px; border-radius: 999px;
  box-shadow: 0 2px 0 0 rgba(0,0,0,.22), inset 0 1px 0 rgba(255,255,255,.6); }
.k-portrait { position: relative; width: 150px; height: 150px; margin: 6px auto 2px; }
.k-portrait svg { transform: rotate(-90deg); overflow: visible; }
.k-ring-track { fill: none; stroke: rgba(255,255,255,.16); stroke-width: 11; }
.k-ring-prog { fill: none; stroke: url(#kGrad); stroke-width: 11; stroke-linecap: round;
  stroke-dasharray: 414.69; stroke-dashoffset: 414.69;
  filter: drop-shadow(0 2px 5px rgba(63,208,122,.55)); transition: stroke-dashoffset 1s cubic-bezier(.4,0,.2,1); }
.k-disc { position: absolute; inset: 15px; border-radius: 50%; overflow: hidden;
  background: radial-gradient(circle at 50% 34%, #fff, var(--canvas-2));
  display: flex; align-items: flex-end; justify-content: center;
  box-shadow: inset 0 0 0 4px rgba(255,255,255,.9), 0 8px 18px rgba(0,0,0,.35); }
.k-disc img { width: 116%; margin-bottom: -5px; filter: drop-shadow(0 5px 5px rgba(35,33,95,.28)); }
.k-lv { position: absolute; left: 50%; bottom: -6px; transform: translateX(-50%);
  font-family: var(--font-display); font-weight: 800; font-size: .82rem; color: var(--navy);
  background: var(--yellow); padding: 4px 14px; border-radius: 999px; border: 3px solid #fff;
  box-shadow: 0 4px 0 0 var(--yellow-deep); z-index: 4; white-space: nowrap; }
.k-name { text-align: center; margin-top: 14px; font-family: var(--font-display); font-weight: 800;
  font-size: 1.9rem; line-height: 1; color: #fff; text-shadow: 0 2px 0 rgba(0,0,0,.18); }
.k-title { text-align: center; margin-top: 5px; font-weight: 900; font-size: .72rem; letter-spacing: .12em;
  text-transform: uppercase; color: #FFE79A; }
.k-title .dot { color: rgba(255,255,255,.4); margin: 0 6px; }
.k-title .lv { color: #fff; }
.k-stats { display: flex; gap: 8px; margin-top: 14px; }
.k-badge { flex: 1; text-align: center; padding: 9px 4px 8px; border-radius: 12px;
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.12); border-top: 3px solid rgba(255,255,255,.2);
  box-shadow: inset 0 -1px 0 rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.08); }
.k-badge.s { border-top-color: #FF8A1E; }
.k-badge.a { border-top-color: var(--green); }
.k-badge.x { border-top-color: var(--yellow); }
.k-badge .n { display: flex; align-items: center; justify-content: center; gap: 3px; min-height: 1.5em; font-family: var(--font-display); font-weight: 800; font-size: 1.25rem; color: #fff; line-height: 1; }
.k-badge .n .em { font-size: .95rem; }
.k-badge .l { display: block; margin-top: 4px; font-size: .56rem; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; color: rgba(255,255,255,.62); }
.k-serial { display: flex; align-items: center; justify-content: space-between; margin-top: 13px; padding: 11px 26px 0;
  border-top: 1px solid rgba(255,255,255,.12); font-weight: 900; font-size: .6rem; letter-spacing: .16em; color: rgba(255,255,255,.5); }
.k-serial .mid { letter-spacing: .4em; color: rgba(255,255,255,.28); }

/* Profile account actions - grouped "Akun" card (rows split by a divider) */
.account-sec { margin: 20px 0 16px; }
.account-sec .sec-label { margin-bottom: 10px; }

.account-card { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 4px 0 0 var(--line); overflow: hidden; }

.account-row { display: flex; align-items: center; gap: 14px; width: 100%; min-height: 56px;
  padding: 14px 16px; background: transparent; border: 0; text-align: left; cursor: pointer;
  color: var(--navy); font-family: var(--font-display);
  transition: background-color .14s ease, box-shadow .06s ease; }
.account-row + .account-row { border-top: 2px solid var(--line); }
.account-row:hover { background: var(--navy-soft); }
.account-row:active { background: var(--surface-2); box-shadow: inset 0 3px 6px rgba(46,44,139,.10); }
.account-row:focus-visible { outline: 3px solid var(--navy); outline-offset: -3px; background: var(--navy-soft); }

.row-ico { flex: none; width: 34px; height: 34px; border-radius: var(--r-sm); display: grid; place-items: center;
  background: var(--navy-soft); color: var(--navy); }
.row-ico svg { width: 20px; height: 20px; display: block; }
.row-label { flex: 1 1 auto; font-size: .98rem; font-weight: 700; color: var(--navy); line-height: 1.1; }
.row-chev { flex: none; color: var(--ink-faint); display: grid; place-items: center; transition: transform .12s ease; }
.row-chev svg { width: 18px; height: 18px; display: block; }
.account-row:hover .row-chev { transform: translateX(2px); color: var(--ink-soft); }

.account-row.is-exit .row-ico { background: var(--red-soft); color: var(--red-deep); }
.account-row.is-exit .row-label { color: var(--red-deep); }
.account-row.is-exit .row-chev { color: var(--red); }
.account-row.is-exit:hover { background: var(--red-soft); }
.account-row.is-exit:focus-visible { outline-color: var(--red-deep); background: var(--red-soft); }

@media (prefers-reduced-motion: reduce) { .account-row, .row-chev { transition: none; } }

/* Settings toggle row (profile) */
.setting-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  padding: 12px 14px; margin: 8px 0 0; cursor: pointer; }
.setting-text { font-family: var(--font-display); font-size: .86rem; font-weight: 700; color: var(--navy); }
.setting-switch { appearance: none; -webkit-appearance: none; flex: none; position: relative;
  width: 42px; height: 24px; border-radius: 999px; background: var(--line); cursor: pointer; transition: background .15s ease; }
.setting-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px;
  border-radius: 50%; background: #fff; transition: transform .15s ease; }
.setting-switch:checked { background: var(--green, var(--navy)); }
.setting-switch:checked::after { transform: translateX(18px); }
body.hide-roman .prompt-roman, body.hide-roman .opt-roman { display: none; }

/* quiet section labels */
.sec-label { font-size: .68rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-soft); margin: 0 2px; }

/* XP-to-next-level card */
.xpcard { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 4px 0 0 var(--line); padding: 15px 16px 16px; }
.xp-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 9px; }
.xp-head .g { font-family: var(--font-display); font-weight: 800; font-size: .95rem; }
.xp-head .g b { color: var(--green-deep); }
.xp-head .pct { font-weight: 900; font-size: .78rem; color: var(--ink-soft); }
.xp-track { height: 16px; background: var(--navy-soft); border-radius: 999px; overflow: hidden; border: 2px solid var(--line); }
.xp-fill { height: 100%; width: 0; border-radius: 999px; background: linear-gradient(90deg,var(--green),var(--green-deep));
  box-shadow: inset 0 2px 0 rgba(255,255,255,.4); transition: width 1s cubic-bezier(.4,0,.2,1); }
.xp-cap { margin-top: 8px; font-size: .8rem; font-weight: 800; color: var(--ink-soft); }
.xp-cap b { color: var(--navy); }

/* Gelar (titles) open button + full board in the sheet */
.titles-open { display: flex; align-items: center; gap: 10px; width: 100%; margin: 12px 0;
  background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 4px 0 0 var(--line); padding: 13px 15px; cursor: pointer;
  font-family: var(--font-display); color: var(--navy); text-align: left; }
.titles-open:active { transform: translateY(2px); box-shadow: 0 2px 0 0 var(--line); }
.titles-open .to-ic { flex: none; font-size: 1.3rem; }
.titles-open img.to-ic { display: block; width: 30px; height: 30px; margin: -8px 2px -8px -1px; object-fit: contain; }
.titles-open .to-txt { flex: 1 1 auto; font-weight: 800; font-size: .95rem; }
.titles-open .to-txt b { color: var(--green-deep); }
.titles-open .to-cta { font-weight: 800; font-size: .82rem; color: var(--ink-soft); }

.titles-board { display: flex; flex-direction: column; gap: 18px; }
.tl-track { display: flex; flex-direction: column; gap: 8px; }
.tl-head { display: flex; align-items: baseline; justify-content: space-between; }
.tl-label { font-family: var(--font-display); font-weight: 800; font-size: .95rem; color: var(--navy); }
.tl-count { font-weight: 900; font-size: .75rem; color: var(--ink-soft); }
.tl-tiers { display: flex; flex-direction: column; gap: 6px; }
.tl-tier { display: flex; align-items: center; gap: 10px; padding: 9px 12px; width: 100%;
  background: var(--surface-2); border: 2px solid var(--line); border-radius: var(--r-md); opacity: .72; }
button.tl-tier { font: inherit; text-align: left; cursor: pointer; }
button.tl-tier:active { transform: translateY(1px); }
button.tl-tier .tl-req { color: var(--green-deep); } /* "Pakai" reads as an action */
.tl-tier.on { opacity: 1; background: var(--green-soft); border-color: #BFEBCF; }
.tl-tier.cur { background: var(--yellow); border-color: var(--yellow-deep); box-shadow: 0 3px 0 0 var(--yellow-deep); }
.tl-mark { flex: none; width: 20px; text-align: center; font-weight: 900; color: var(--ink-faint); }
.tl-tier.on .tl-mark { color: var(--green-deep); }
.tl-tier.cur .tl-mark { color: var(--navy); }
.tl-name { flex: 1 1 auto; font-family: var(--font-display); font-weight: 800; font-size: .9rem; color: var(--navy); }
.tl-req { flex: none; font-size: .72rem; font-weight: 800; color: var(--ink-soft); text-align: right; }
.tl-tier.cur .tl-req { color: var(--navy); }

/* Statistik strip */
.strip { display: grid; grid-template-columns: repeat(4,1fr); gap: 8px; }
.strip .stat { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md); box-shadow: 0 4px 0 0 var(--line);
  padding: 12px 4px 10px; text-align: center; min-height: 70px; display: flex; flex-direction: column; justify-content: center; gap: 5px; }
.strip .stat .n { font-family: var(--font-display); font-weight: 800; font-size: 1.35rem; line-height: 1; font-variant-numeric: tabular-nums; }
.strip .stat .l { font-size: .55rem; font-weight: 900; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-faint); line-height: 1.2; }
.strip .stat.due .n { color: var(--navy); }
.strip .stat.master .n { color: var(--ink-faint); }
.strip .stat.ok .n { color: var(--green-deep); }
.strip .stat.bad .n { color: var(--red-deep); }

/* enrollment chip */
.member { display: flex; align-items: center; gap: 8px; background: var(--surface); border: 2px solid var(--line);
  border-radius: 999px; box-shadow: 0 3px 0 0 var(--line); padding: 8px 14px; font-size: .78rem; font-weight: 800; color: var(--ink-soft); }
.member .em { font-size: .95rem; }
.member b { color: var(--navy); }

@media (prefers-reduced-motion: reduce) {
  .kartu { transform: none; }
  .k-ring-prog, .xp-fill { transition: none; }
}

/* ---------- Login ---------- */
.login {
  position: fixed; inset: 0; z-index: 40; padding: 24px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(700px 560px at 50% 32%, rgba(142,202,230,.22), transparent 72%);
  animation: fade .25s ease both;
}
/* Signature: the Thai letters you're about to learn, drifting behind the card. */
.login-scene { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.login-scene span {
  position: absolute; left: var(--x); top: var(--y);
  font-family: var(--font-thai); font-weight: 700; line-height: 1;
  font-size: calc(5.5rem * var(--s, 1));
  color: var(--navy); opacity: .06;
  transform: translate(-50%, -50%);
  animation: drift 9s ease-in-out infinite; animation-delay: var(--d, 0s);
  will-change: transform;
}
.login-scene span:nth-child(even) { color: var(--yellow-deep); opacity: .12; }

.login-card {
  position: relative; z-index: 1; width: 100%; max-width: 400px;
  background: var(--surface); border: 3px solid var(--navy);
  border-radius: var(--r-xl); overflow: hidden;
  box-shadow: 0 14px 0 0 var(--navy-deep), var(--lift-lg);
  animation: pop .45s cubic-bezier(.2,.9,.3,1) both;
}
/* Navy hero cap: white wordmark on a dotted field, mascot straddling the seam. */
.login-cap {
  position: relative; text-align: center; padding: 22px 24px 74px;
  background:
    radial-gradient(circle at 1.5px 1.5px, rgba(255,255,255,.16) 1.4px, transparent 0) 0 0 / 17px 17px,
    linear-gradient(158deg, #3A38A8 0%, var(--navy) 58%, var(--navy-deep) 100%);
}
.login-logo { width: 150px; max-width: 66%; height: auto; display: block; margin: 0 auto; }
/* White coin behind the mascot so its navy mortarboard reads against the navy
   cap instead of blending in. Sits low on the cap so it clears the wordmark. */
.login-cap::after {
  content: ""; position: absolute; left: 50%; margin-left: -53px; bottom: -46px;
  width: 106px; height: 106px; border-radius: 50%;
  background: var(--surface); border: 3px solid var(--navy);
  box-shadow: var(--lift-md); z-index: 1;
}
.login-mascot {
  position: absolute; left: 50%; margin-left: -43px; bottom: -38px;
  width: 86px; height: auto; z-index: 2;
  filter: drop-shadow(0 5px 7px rgba(35,33,95,.20));
  animation: bob 3s ease-in-out infinite;
}
.login-body { padding: 56px 26px 26px; text-align: center; }
.login-hi {
  display: inline-block; font-family: var(--font-thai); font-weight: 700; font-size: .95rem;
  color: var(--navy); background: var(--yellow); border-radius: 999px;
  padding: 5px 15px; box-shadow: 0 3px 0 0 var(--yellow-deep); margin-bottom: 12px;
}
.login-title { font-family: var(--font-display); font-weight: 800; font-size: 1.55rem; margin: 0 0 8px; color: var(--navy); }
.login-sub { color: var(--ink-soft); font-size: .92rem; line-height: 1.5; margin: 0 0 20px; font-weight: 600; }

.login-field { position: relative; margin-bottom: 14px; }
.login-field-icon {
  position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; color: var(--ink-faint); pointer-events: none;
  transition: color .15s ease;
}
.login-field:focus-within .login-field-icon { color: var(--navy); }
.login-input {
  width: 100%; border: 2.5px solid var(--line); background: var(--surface-2);
  border-radius: var(--r-md); padding: 14px 16px 14px 44px;
  font-family: var(--font-body); font-size: 1rem; font-weight: 700; color: var(--navy);
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.login-input::placeholder { color: var(--ink-faint); font-weight: 600; }
.login-input:focus { outline: 0; border-color: var(--navy); background: var(--surface); box-shadow: 0 0 0 4px var(--navy-soft); }
.login-submit .login-arrow { font-weight: 900; transition: transform .16s ease; }
.login-submit:hover:not(:disabled) .login-arrow { transform: translateX(3px); }
.login-google {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin: 12px 0 0; padding: 14px 18px; border-radius: 14px;
  border: 2px solid var(--navy-soft); background: var(--surface); color: var(--navy);
  font-weight: 800; text-align: center; text-decoration: none;
  transition: background .15s ease, border-color .15s ease;
}
.login-google-icon { width: 20px; height: 20px; flex: none; }
.login-google:hover { background: var(--navy-soft); border-color: var(--navy); }
.login-error { color: var(--red-deep); font-size: .86rem; line-height: 1.45; margin: 14px 0 0; font-weight: 700; }
.login-note { color: var(--ink-faint); font-size: .82rem; margin: 18px 0 0; font-weight: 600; }
.login-note-link { border: 0; background: transparent; padding: 0; font: inherit; font-weight: 800;
  color: var(--navy); text-decoration: underline; cursor: pointer; }
.register-form { display: flex; flex-direction: column; gap: 10px; }
.login-forgot { display: block; margin: 12px auto 0; border: 0; background: transparent;
  color: var(--ink-soft); font-family: var(--font-display); font-weight: 800; font-size: .84rem;
  cursor: pointer; text-decoration: underline; }
.login-forgot:hover { color: var(--navy); }

/* Set-password + forgot-password modals: a compact card reusing .overlay. */
.pw-card {
  background: var(--surface); border: 3px solid var(--navy); border-radius: var(--r-xl);
  padding: 26px 24px 20px; max-width: 380px; width: 100%; margin: auto; text-align: center;
  box-shadow: 0 12px 0 0 var(--navy-deep), var(--lift-lg);
  animation: pop .4s cubic-bezier(.2,.9,.3,1) both;
}
.pw-title { font-family: var(--font-display); font-weight: 800; font-size: 1.35rem; color: var(--navy); margin: 0 0 6px; }
.pw-sub { color: var(--ink-soft); font-size: .9rem; line-height: 1.5; font-weight: 600; margin: 0 0 18px; }
.pw-input {
  width: 100%; padding: 14px 16px; border: 2px solid var(--line); border-radius: 14px;
  font-family: inherit; font-size: 1rem; font-weight: 700; color: var(--ink); background: var(--surface-2);
}
.pw-input::placeholder { color: var(--ink-faint); font-weight: 600; }
.pw-input:focus { outline: 0; border-color: var(--navy); background: var(--surface); box-shadow: 0 0 0 4px var(--navy-soft); }
.pw-card .btn-primary { width: 100%; margin-top: 16px; }
.pw-error { color: var(--red-deep); font-size: .85rem; line-height: 1.4; margin: 12px 0 0; font-weight: 700; }
.pw-error.ok { color: var(--green-deep); }
.pw-skip { display: block; margin: 14px auto 0; border: 0; background: transparent;
  color: var(--ink-soft); font-family: var(--font-display); font-weight: 800; font-size: .86rem; cursor: pointer; }
.pw-skip:hover { color: var(--navy); }

/* ---------- Card ---------- */
/* Question flashcard: sizes to its content (mascot + meta + prompt) and sits at
   the top of the practice frame; the answers fill the space below it. */
.card {
  position: relative;
  background: var(--surface);
  border: 3px solid var(--navy);
  border-radius: var(--r-xl);
  padding: 24px 20px 28px;
  box-shadow: 0 10px 0 0 var(--navy-deep), var(--lift-md);
  display: flex; flex-direction: column; gap: 14px;
  flex: 0 0 auto;
  min-height: 215px;   /* a bigger box, so the question sits with room to breathe */
  margin-bottom: 22px; /* separation between the question card and the answers */
}
/* Scrollable answer area below the question card: options before answering,
   reveal + example after. It fills the remaining frame and centers the options
   so 4 choices don't look sparse; `safe` falls back to top-align (scrollable)
   when the review is tall. Overflow lives here so option press-shadows survive. */
.answer-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 14px;
  justify-content: safe center;
  padding: 2px 2px 6px; /* room for the option 3D bottom edges */
}
.answer-scroll .options { gap: 12px; }
.card.dealt { animation: deal .42s cubic-bezier(.2,.8,.2,1) both; }

/* Mascot peeks over the top-right corner and reacts to the answer. The card
   is offset by the peek height so the mascot clears the practice bar. */
.question-card { margin-top: 42px; }
.mascot { position: absolute; top: -46px; right: 10px; width: 88px; height: 92px; pointer-events: none; z-index: 2; }
.mascot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 8px 10px rgba(46,44,139,.20)); }
.mascot .m-idle { animation: bob 3s ease-in-out infinite; }
.mascot .m-correct, .mascot .m-wrong { opacity: 0; transform: scale(.7); }
body.correct-answer .mascot .m-idle,
body.wrong-answer   .mascot .m-idle { opacity: 0; }
body.correct-answer .mascot .m-correct { opacity: 1; transform: scale(1); animation: pop-bounce .5s cubic-bezier(.2,1.3,.4,1) both; }
body.wrong-answer   .mascot .m-wrong   { opacity: 1; transform: scale(1); animation: mascot-shake .45s ease both; }

.card-meta { display: flex; align-items: center; justify-content: space-between; padding-right: 74px; }
.level { display: inline-flex; align-items: center; gap: 8px; }
.level-label { font-size: .62rem; text-transform: uppercase; letter-spacing: .7px; color: var(--ink-faint); font-weight: 800; }
.pips { display: inline-flex; gap: 5px; }
.pip { width: 9px; height: 9px; border-radius: 50%; background: var(--line); transition: background .2s ease, transform .2s ease; }
.pip.on { background: var(--yellow); box-shadow: 0 1px 0 var(--yellow-deep); transform: scale(1.1); }
.pip.on.mastered { background: var(--green); box-shadow: 0 1px 0 var(--green-deep); }
.dir-pill {
  font-size: .72rem; font-weight: 800; color: var(--navy);
  background: var(--navy-soft); border: 2px solid #DEDDF6;
  padding: 4px 11px; border-radius: 999px;
}

/* Fill the card body and center the question, so there's even margin between
   the text and the box edges as the box grows. */
.prompt-wrap { text-align: center; padding: 8px 4px; flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; }
.prompt-tag { display: inline-block; font-size: .76rem; color: var(--ink-soft); font-weight: 800; margin-bottom: 8px; letter-spacing: .3px; }
.prompt {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.75rem; line-height: 1.25; color: var(--navy); word-break: break-word;
}
.prompt.is-thai { font-family: var(--font-thai); font-size: 2.8rem; font-weight: 700; letter-spacing: .5px; }
.prompt-roman { font-family: var(--font-body); color: var(--green-deep); font-weight: 800; font-size: 1.05rem; margin-top: 6px; }

/* ---------- Options (3D press tiles) ---------- */
.options { display: grid; gap: 11px; }
.opt {
  position: relative; text-align: left;
  background: var(--surface); border: 2.5px solid var(--line);
  color: var(--navy);
  font-family: var(--font-body); font-size: 1.04rem; font-weight: 700;
  padding: 13px 14px 13px 50px; border-radius: var(--r-md);
  box-shadow: 0 4px 0 0 var(--line);
  animation: rise .32s ease both;
}
.opt.is-thai { font-family: var(--font-thai); font-size: 1.35rem; font-weight: 600; }
.opt-roman { display: block; font-family: var(--font-body); font-size: .8rem; font-weight: 700; color: var(--ink-soft); margin-top: 2px; }
.opt .badge {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
  background: var(--surface-2); border: 2px solid var(--line); color: var(--ink-soft);
  font-family: var(--font-display); font-size: .82rem; font-weight: 800;
}
.opt:hover:not(:disabled) { border-color: var(--navy); box-shadow: 0 4px 0 0 var(--navy); transform: translateY(-1px); }
.opt:hover:not(:disabled) .badge { border-color: var(--navy); color: var(--navy); }
.opt:disabled { cursor: default; }
.opt.correct { background: var(--green-soft); border-color: var(--green); color: var(--green-deep); box-shadow: 0 4px 0 0 var(--green-deep); }
.opt.correct .badge { background: var(--green); border-color: var(--green); color: #fff; }
.opt.wrong { background: var(--red-soft); border-color: var(--red); color: var(--red-deep); box-shadow: 0 4px 0 0 var(--red-deep); animation: shake .4s ease; }
/* Save failed (e.g. server hiccup): shake the tapped tile; the card re-arms. */
.opt.shake-err { animation: shake .4s ease; }
.opt.wrong .badge { background: var(--red); border-color: var(--red); color: #fff; }

/* After answering, the two un-picked distractors collapse to reclaim the fold. */
.opt.gone {
  padding-top: 0; padding-bottom: 0; margin: 0;
  max-height: 0; min-height: 0; opacity: 0; border-width: 0; box-shadow: none;
  pointer-events: none; overflow: hidden;
  transition: max-height .28s ease, opacity .2s ease, padding .28s ease;
}

/* ---------- Card matching (two columns of tap tiles) ---------- */
/* Fill the practice frame like .answer-scroll does, so a short round (few pairs)
   spreads down the screen instead of clustering at the top. */
.match { display: flex; flex-direction: column; gap: 12px; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.match-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.match-head .prompt-tag { margin-bottom: 0; }
/* Row-major fill: each row is [prompt, answer]; align-items:stretch (grid
   default) makes both cells take the row's height, so the taller Thai+roman
   tile sets the height its meaning counterpart matches. The grid grows to fill
   the board and align-content spreads the rows evenly (top, between, bottom), so
   fewer pairs -> more breathing room rather than a gap at the bottom. */
.match-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; flex: 1 1 auto; align-content: space-evenly; }
.mtile {
  min-height: 62px; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--surface); border: 2.5px solid var(--line); color: var(--navy);
  font-family: var(--font-body); font-size: .98rem; font-weight: 700; line-height: 1.25;
  padding: 10px 8px; border-radius: var(--r-md);
  box-shadow: 0 4px 0 0 var(--line);
  animation: rise .32s ease both;
}
.mtile.is-thai { font-family: var(--font-thai); font-size: 1.25rem; font-weight: 600; }
.mtile:hover:not(.matched) { border-color: var(--navy); box-shadow: 0 4px 0 0 var(--navy); transform: translateY(-1px); }
.mtile.sel { background: var(--navy-soft); border-color: var(--navy); box-shadow: 0 4px 0 0 var(--navy-deep); }
.mtile.miss { background: var(--red-soft); border-color: var(--red); color: var(--red-deep); animation: shake .4s ease; }
/* A matched pair stays in place (the grid must not reflow under a finger) but
   goes quiet, so only the unsolved tiles read as tappable. */
.mtile.matched {
  background: var(--green-soft); border-color: var(--green); color: var(--green-deep);
  box-shadow: none; opacity: .45; pointer-events: none;
  transition: opacity .3s ease, background .2s ease;
}

/* ---------- Reveal + example ---------- */
.afterthought { display: flex; flex-direction: column; gap: 11px; animation: rise .34s ease both; }
.reveal {
  background: var(--canvas-2); border: 2px solid var(--yellow); border-radius: var(--r-md);
  padding: 13px 15px; line-height: 1.45;
}
.reveal .r-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.reveal .r-thai { font-family: var(--font-thai); font-size: 1.5rem; font-weight: 700; color: var(--navy); }
.reveal .r-roman { color: var(--green-deep); font-weight: 800; font-size: 1rem; }
.reveal .r-tone { color: var(--ink-faint); font-size: .82rem; font-weight: 700; }
.reveal .r-meaning { font-weight: 800; margin-top: 3px; color: var(--navy); }

.example {
  background: var(--surface-2); border: 2px solid var(--line); border-radius: var(--r-md);
  padding: 13px 15px;
}
.example .ex-label { font-size: .64rem; text-transform: uppercase; letter-spacing: .8px; color: var(--sky); font-weight: 800; margin-bottom: 8px; }
.example .ex-thai { font-family: var(--font-thai); font-size: 1.4rem; font-weight: 600; line-height: 1.4; color: var(--navy); }
.example .ex-roman { color: var(--green-deep); font-weight: 800; font-size: .94rem; margin-top: 4px; }
.example .ex-meaning { color: var(--ink-soft); font-style: italic; font-size: .94rem; margin-top: 3px; font-weight: 600; }

/* Tap the Thai word to hear it (Chirp 3 HD audio). The word itself is the
   control: a dotted sky underline plus a small speaker glyph signal it, and the
   word turns green while playing. Sky = the audio accent. */
.tap-word {
  cursor: pointer;
  text-decoration: underline dotted var(--sky-deep);
  text-underline-offset: 7px;
  text-decoration-thickness: 2px;
  -webkit-tap-highlight-color: transparent;
  transition: color .15s, text-decoration-color .15s, transform .06s;
  /* Masked SVG speaker recolours cleanly with state (unlike an emoji glyph). */
  --spk-ico: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M4%209h4l5-4v14l-5-4H4z'/%3E%3Cpath%20d='M16%208.5a4%204%200%20010%207M18.5%206a7.5%207.5%200%20010%2012'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'/%3E%3C/svg%3E");
}
.tap-word::after {
  content: ""; display: inline-block; width: .5em; height: .5em;
  margin-left: .18em; vertical-align: .42em;
  background-color: var(--sky-deep);
  -webkit-mask: var(--spk-ico) center/contain no-repeat;
          mask: var(--spk-ico) center/contain no-repeat;
  transition: background-color .15s;
}
.tap-word:active { transform: translateY(1px); }
.tap-word.playing { color: var(--green-deep); text-decoration-color: var(--green); }
.tap-word.playing::after { background-color: var(--green-deep); }

/* Question prompt: keep the WORD centered and float the speaker glyph just to
   its right, so the icon never shifts the word off-center. */
.prompt.tap-word { display: inline-block; align-self: center; position: relative; max-width: 100%; }
.prompt.tap-word::after {
  position: absolute; left: 100%; top: 50%; transform: translateY(-50%);
  margin-left: .22em; width: .5em; height: .5em; vertical-align: baseline;
}
@media (prefers-reduced-motion: reduce) {
  .tap-word, .tap-word::after { transition: none; }
  .tap-word:active { transform: none; }
}

.bd-toggle {
  margin-top: 11px; width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  border: 2px dashed var(--line); background: transparent; cursor: pointer;
  font-family: var(--font-display); font-size: .82rem; font-weight: 800; color: var(--navy);
  padding: 9px 12px; border-radius: var(--r-sm); transition: background .15s ease, border-color .15s ease;
}
.bd-toggle:hover { background: var(--surface); border-color: var(--navy); }
.bd-toggle .chev { transition: transform .2s ease; font-size: .7rem; }
.bd-toggle.open .chev { transform: rotate(180deg); }
.breakdown { margin-top: 11px; border-top: 2px dashed var(--line); padding-top: 11px; display: flex; flex-direction: column; gap: 8px; }
.breakdown.collapsed { display: none; }
.bd-row { display: grid; grid-template-columns: minmax(54px,auto) minmax(78px,auto) 1fr; gap: 12px; align-items: baseline; font-size: .92rem; }
.bd-thai { font-family: var(--font-thai); font-weight: 600; color: var(--navy); }
.bd-roman { color: var(--green-deep); font-weight: 700; }
.bd-arti { color: var(--ink-soft); font-weight: 600; }

/* ---------- Primary + ghost buttons ---------- */
.card-actions { display: flex; flex: 0 0 auto; }
/* Once answered, Lanjut owns the bottom band; drop the pre-answer footer/hint. */
body.answered .footer-row, body.answered .hint { display: none; }
.btn-primary {
  width: 100%;
  font-family: var(--font-display); font-size: 1.08rem; font-weight: 800; color: var(--navy);
  padding: 15px; border-radius: var(--r-md);
  background: var(--yellow);
  box-shadow: 0 5px 0 0 var(--yellow-deep);
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  letter-spacing: .2px;
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.03); }
.btn-primary:disabled { opacity: .55; cursor: default; }
.kbd { font-family: var(--font-body); font-size: .72rem; font-weight: 800; background: rgba(46,44,139,.14); color: var(--navy); border-radius: 6px; padding: 2px 7px; }

.footer-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

.btn-ghost {
  --edge: #D8D7EE; --lift: 4px;
  border: 2px solid var(--line); background: var(--surface); color: var(--ink-soft);
  font-family: var(--font-display); font-size: .84rem; font-weight: 800;
  padding: 10px 18px; border-radius: 999px; box-shadow: 0 4px 0 0 #E4E3F2;
}
.btn-ghost:hover { border-color: var(--red); color: var(--red-deep); box-shadow: 0 4px 0 0 var(--red); }
.hint { font-size: .78rem; color: var(--ink-faint); text-align: center; margin: -2px 0 0; font-weight: 600; }

/* ---------- Home landing (quick-start + class picker) ---------- */
/* Practice is a full-height flex frame: header + question stay fixed, the card
   flexes to fill, and Lanjut sits at the bottom, so the layout is identical
   between the question and the answer-review (only the scroll area's content
   swaps). */
.home-practice:not([hidden]) {
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; gap: 11px;
}
.home-start:not([hidden]) {
  display: flex; flex-direction: column; gap: 13px; animation: fade .25s ease both;
  flex: 1 1 auto; min-height: 0; overflow-y: auto; /* scroll the class list, not the page */
}

/* Top bar: greeting + two real stat chips (mastered / due). */
.hub-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 2px 2px 0; }
.hub-hi small { display: block; font-size: .78rem; font-weight: 800; color: var(--ink-soft); }
.hub-hi b { font-family: var(--font-display); font-weight: 800; font-size: 1.35rem; line-height: 1.1; color: var(--navy); }
.hub-hi b span { color: var(--green-deep); }
.hub-chips { display: flex; gap: 8px; flex: 0 0 auto; }
.gchip {
  display: flex; align-items: center; gap: 5px;
  border: 2px solid var(--line); border-radius: 999px;
  padding: 6px 12px 6px 9px; font-family: var(--font-display); font-weight: 800; font-size: .9rem;
}
.gchip .ic { width: 19px; height: 19px; display: block; flex: 0 0 auto; }
.gchip .profile-trophy-icon {
  width: 20px;
  height: 20px;
  display: block;
  flex: 0 0 auto;
  margin-left: -1px;
  object-fit: contain;
}
.gchip b { min-width: 3ch; text-align: center; font-variant-numeric: tabular-nums; }
.gchip .ic path, .gchip .ic rect { stroke: var(--navy); stroke-width: 2; stroke-linejoin: round; }
.gchip.mastered { background: #F1EEFF; border-color: #CFC7FF; box-shadow: 0 3px 0 0 #CFC7FF; }
.gchip.mastered b { color: #5948C8; }
.gchip.due { background: var(--red-soft); border-color: #FBD4D9; box-shadow: 0 3px 0 0 #FBD4D9; }
.gchip.due b { color: var(--red-deep); }
.gchip.streak { background: #FFF3E0; border-color: #FFE0B2; box-shadow: 0 3px 0 0 #FFE0B2; }
.gchip.streak b { color: #E8710A; }

/* Profile streak flame icon: reused in the player card plate and activity headline. */
.profile-fire-icon {
  width: 1.05em;
  height: 1.05em;
  display: inline-block;
  vertical-align: -.25em;
  flex: 0 0 auto;
}
.k-badge .n .profile-fire-icon { width: 1.08em; height: 1.08em; vertical-align: -.3em; }
.k-badge .n .k-acc-icon { width: 1.08em; height: 1.08em; vertical-align: -.3em; }
.k-badge .n .k-xp-icon { width: 1.08em; height: 1.08em; vertical-align: -.3em; }
.cal-head .profile-fire-icon { width: 1.38em; height: 1.38em; vertical-align: -.43em; margin-right: 3px; }
.gchip.streak .profile-fire-icon { width: 20px; height: 20px; margin: -2px 0 -3px -1px; }

/* Profile streak heatmap: current run headline + 10-week activity grid. */
/* Activity heatmap (matches the Kartu Pemain mockup): week-major intensity grid */
.cal { background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 4px 0 0 var(--line); padding: 15px 16px 14px; }
.cal-head { display: flex; align-items: center; font-weight: 800; font-size: .85rem; color: var(--ink-soft); margin-bottom: 11px; }
.cal-head b { font-family: var(--font-display); font-size: 1.25rem; color: #E8710A; margin: 0 5px; }
.cal-head .rec { margin-left: auto; font-size: .72rem; font-weight: 900; color: var(--ink-faint); }
.cal-head .rec b { font-family: var(--font-body); font-size: .72rem; color: #E8710A; margin: 0 3px; }
.cal-grid { display: grid; grid-template-rows: repeat(7, 13px); grid-auto-flow: column; gap: 5px; justify-content: start; }
.cal .cell { width: 13px; height: 13px; border-radius: 4px; background: var(--navy-soft); }
.cal .cell.lv1 { background: #FFDCA8; }
.cal .cell.lv2 { background: #FF8A1E; }
.cal .cell.lv3 { background: #E8710A; }
.cal .cell.today { outline: 2px solid var(--navy); outline-offset: 1px; }
.cal-legend { display: flex; align-items: center; gap: 5px; margin-top: 12px; font-size: .66rem; font-weight: 800; color: var(--ink-faint); }
.lg-cell { width: 11px; height: 11px; border-radius: 3px; }

/* Aktivitas: heatmap left, flame gauge right */
.cal-body { display: flex; gap: 18px; align-items: stretch; }
.cal-left { flex: 0 0 auto; }
.cal-right { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center;
  border-left: 2px solid var(--line); padding-left: 16px; min-width: 0; }

.gauge {
  --gauge-size: 176px;
  position: relative;
  width: var(--gauge-size);
  height: var(--gauge-size);
  display: grid;
  place-items: center;
  isolation: isolate;
}
.gauge::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 52%, rgba(255,215,148,.66) 0 41%, rgba(255,239,207,.62) 58%, rgba(255,255,255,.9) 73%),
    #fff;
  border: max(8px, calc(var(--gauge-size) * .06)) solid #ECECFF;
  box-shadow: inset 0 -10px 24px rgba(255,178,77,.12), 0 12px 28px -20px rgba(46,44,139,.45);
  z-index: -2;
  animation: streakBadgeBreathe 4.8s ease-in-out infinite;
}
.gauge::after {
  content: "";
  position: absolute;
  inset: 13%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 58%, rgba(255,152,42,.28), transparent 66%);
  filter: blur(4px);
  z-index: -1;
  animation: streakGlowPulse 3.6s ease-in-out infinite;
}
.g-ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; opacity: 0; pointer-events: none; }
.g-track { fill: none; stroke: var(--navy-soft); stroke-width: 12; }
.g-prog { fill: none; stroke: url(#streakRingGrad); stroke-width: 12; stroke-linecap: round;
  filter: drop-shadow(0 2px 4px rgba(232,113,10,.4)); transition: stroke-dashoffset 1.1s cubic-bezier(.4,0,.2,1); }
.g-rec { fill: none; stroke: var(--navy); stroke-width: 14; stroke-linecap: butt; }

.flame-svg {
  width: 74%;
  height: auto;
  overflow: visible;
  filter: drop-shadow(0 8px 10px rgba(205,78,0,.20));
}
.flame-svg path {
  transform-box: fill-box;
  transform-origin: 50% 100%;
}
.flame-outer-mark {
  animation: streakOuterFlame 3.4s ease-in-out infinite;
}
.flame-inner-mark {
  animation: streakInnerFlame 2.25s ease-in-out infinite;
}
.flame-coal-mark {
  animation: streakCoalFlame 2.9s ease-in-out infinite;
}
.g-num {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 52px;
  fill: #6B2400;
  letter-spacing: 0;
  text-anchor: middle;
  dominant-baseline: central;
  paint-order: stroke fill;
  stroke: rgba(255,179,71,.18);
  stroke-width: 2px;
}

.g-unit { margin-top: 4px; font-family: var(--font-display); font-weight: 800; font-size: .8rem; color: var(--ink-soft); }
.g-rec-cap { margin-top: 6px; font-size: .68rem; font-weight: 900; letter-spacing: .02em; color: var(--ink-faint); text-align: center; }
.g-rec-cap b { font-family: var(--font-body); color: #E8710A; margin: 0 2px; }
.g-rec-cap.is-best { color: #E8710A; }

@keyframes streakBadgeBreathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.025); }
}
@keyframes streakGlowPulse {
  0%, 100% { opacity: .72; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.08); }
}
@keyframes streakOuterFlame {
  0%, 100% { transform: scaleY(1) skewX(0deg); }
  24% { transform: scaleY(1.018) skewX(-.8deg); }
  52% { transform: scaleY(.99) skewX(.7deg); }
  78% { transform: scaleY(1.014) skewX(-.35deg); }
}
@keyframes streakInnerFlame {
  0%, 100% { transform: scaleX(1) scaleY(1) translateY(0); }
  34% { transform: scaleX(.96) scaleY(1.07) translateY(-3px); }
  68% { transform: scaleX(1.04) scaleY(.98) translateY(1px); }
}
@keyframes streakCoalFlame {
  0%, 100% { transform: scaleX(1) translateY(0); opacity: .96; }
  50% { transform: scaleX(1.08) translateY(-1px); opacity: 1; }
}

@media (max-width: 440px) {
  /* keep heatmap + gauge on one row; shrink both to fit a narrow phone */
  .cal-body { gap: 10px; align-items: center; }
  .cal-left { min-width: 0; }
  .cal-grid { grid-template-rows: repeat(7, 11px); gap: 4px; }
  .cal .cell { width: 11px; height: 11px; }
  .cal-legend { gap: 4px; font-size: .58rem; flex-wrap: wrap; }
  .cal-right { padding-left: 10px; }
  .gauge { --gauge-size: 118px; }
}

/* Hero: XP level-ring with the mascot inside it, the signature element. */
.hub-hero { text-align: center; padding: 2px 0 0; animation: pop .5s cubic-bezier(.2,.9,.3,1.1) both; }
.ringwrap { position: relative; width: 186px; height: 186px; margin: 0 auto; }
.ringwrap svg { transform: rotate(-90deg); overflow: visible; width: 100%; height: 100%; }
.ring-track { fill: none; stroke: var(--navy-soft); stroke-width: 14; }
.ring-prog {
  fill: none; stroke: url(#ringGrad); stroke-width: 14; stroke-linecap: round;
  stroke-dasharray: 597; stroke-dashoffset: 597; /* JS sets offset from real XP */
  filter: drop-shadow(0 2px 4px rgba(63,208,122,.45));
  transition: stroke-dashoffset 1.1s cubic-bezier(.4,0,.2,1);
}
.avatar-disc {
  position: absolute; inset: 22px; border-radius: 50%; overflow: hidden;
  background: radial-gradient(circle at 50% 35%, #fff, var(--canvas-2));
  display: flex; align-items: flex-end; justify-content: center;
  box-shadow: inset 0 0 0 5px #fff, 0 8px 22px rgba(46,44,139,.18);
}
.avatar-disc img { width: 116%; margin-bottom: -6px; filter: drop-shadow(0 6px 6px rgba(46,44,139,.15)); }
.lv-badge {
  position: absolute; top: -6px; left: 50%; transform: translateX(-50%); z-index: 3;
  font-family: var(--font-display); font-weight: 800; font-size: .9rem; color: var(--navy);
  background: var(--yellow); border: 3px solid #fff; border-radius: 999px;
  padding: 4px 14px; box-shadow: 0 5px 0 0 var(--yellow-deep);
}
.xp-line { font-family: var(--font-display); font-weight: 800; font-size: 1.25rem; margin-top: 8px; color: var(--navy); }
.xp-line b { color: var(--green-deep); }
.xp-sub { font-size: .84rem; font-weight: 800; color: var(--ink-soft); margin-top: 1px; }
.xp-sub em { font-style: normal; color: var(--navy); background: var(--yellow); padding: 1px 7px; border-radius: 8px; }

/* Primary CTA: one big "Main sekarang", the signature 3D press. */
.quickstart {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
  background: var(--yellow); border: 0; border-radius: var(--r-lg); color: var(--navy);
  font-family: var(--font-display); font-weight: 800; font-size: 1.2rem; padding: 16px;
  cursor: pointer; box-shadow: 0 6px 0 0 var(--yellow-deep), var(--lift-md);
  transition: transform .08s ease, box-shadow .08s ease, filter .15s ease;
}
.quickstart:hover { filter: brightness(1.03); }
.quickstart:active { transform: translateY(5px); box-shadow: 0 1px 0 0 var(--yellow-deep); }
.qs-play { font-size: .8rem; }
.qs-due {
  font-family: var(--font-display); font-weight: 800; font-size: .78rem;
  background: var(--navy); color: #fff; border-radius: 999px; padding: 4px 11px;
}

.class-head { display: flex; align-items: baseline; justify-content: space-between; margin: 6px 2px 0; }
.class-head-title { font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; color: var(--navy); }
/* Subtle "browse other open classes" action; unobtrusive next to the title. */
.class-more {
  border: 0; background: transparent; cursor: pointer;
  font-family: var(--font-display); font-weight: 800; font-size: .8rem;
  color: var(--ink-soft); padding: 4px 9px; border-radius: 999px;
  transition: color .14s ease, background .14s ease;
}
.class-more:hover { color: var(--navy); background: var(--navy-soft); }
.class-more:active { transform: translateY(1px); }

/* One section per Kelas: a heading over its own shelf. */
.class-groups { display: flex; flex-direction: column; gap: 4px; }
.class-group-title { font-family: var(--font-display); font-weight: 800; font-size: .9rem; color: var(--navy); margin: 8px 2px 0; }

/* Classes as a horizontal shelf of tappable "stage" cards. */
.class-list {
  display: flex; gap: 11px; overflow-x: auto; overflow-y: hidden;
  padding: 4px 2px 10px; scroll-snap-type: x proximity;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.class-list::-webkit-scrollbar { display: none; }
.stage {
  scroll-snap-align: start; flex: 0 0 auto; width: 156px; text-align: left; cursor: pointer;
  position: relative;
  background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  box-shadow: 0 4px 0 0 var(--line); padding: 13px 13px 14px;
  transition: transform .08s ease, box-shadow .08s ease, border-color .15s ease;
  animation: rise .4s cubic-bezier(.2,.9,.3,1) both; animation-delay: calc(var(--i, 0) * 55ms);
}
.stage:hover { border-color: var(--navy); }
.stage:active { transform: translateY(4px); box-shadow: 0 0 0 0 var(--line); }
.stage:focus-visible { outline: 3px solid var(--sky); outline-offset: 2px; }
.stage.complete { background: #F1EEFF; border-color: #CFC7FF; box-shadow: 0 4px 0 0 #CFC7FF; }
.stage-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 9px; }
.stage-flag {
  display: block;
  width: 30px;
  height: 30px;
  margin: -5px 0;
  object-fit: contain;
}
.stage-trophy {
  display: block;
  width: 30px;
  height: 30px;
  margin: -8px -4px -5px 0;
  object-fit: contain;
}
.stage-pill {
  font-family: var(--font-display); font-weight: 800; font-size: .74rem;
  padding: 3px 9px; border-radius: 999px; min-width: 22px; text-align: center;
}
.stage-pill.hot { background: var(--red-soft); color: var(--red-deep); }
.stage-pill.done { background: #E5DFFF; color: #5948C8; }
.stage-date { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1rem; color: var(--navy); line-height: 1.15; }
.stage-sub { display: block; font-size: .72rem; font-weight: 700; color: var(--ink-faint); margin: 3px 0 10px; }
.mini { display: block; height: 8px; background: var(--navy-soft); border-radius: 999px; overflow: hidden; }
.mini i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--green), var(--green-deep)); }
.stage.complete .mini { background: #E1DCFF; }
.stage.complete .mini i { background: linear-gradient(90deg, #8D7AF2, #5948C8); }
.stage-status { display: block; margin-top: 9px; font-family: var(--font-display); font-weight: 800; font-size: .74rem; color: var(--yellow-deep); }
.stage-status.ok { color: #5948C8; }

.class-empty { width: 100%; text-align: center; color: var(--ink-faint); font-weight: 600; font-size: .88rem; padding: 16px 0; }

/* ================= "Belum ikut kelas?" invite + open-class sheet =================
   Shown in place of the class shelf when a learner has no practiceable vocab.
   openClassWidget() mounts the card; the sheet below is the generic openSheet(). */
.invite {
  display: flex; gap: 12px; align-items: center; text-align: left;
  background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 5px 0 0 var(--line); padding: 15px 14px; margin: 4px 2px 8px;
  animation: rise .4s cubic-bezier(.2,.9,.3,1) both;
}
.invite img { width: 60px; height: 60px; object-fit: contain; flex: 0 0 auto; }
.invite-body { min-width: 0; }
.invite-body h3 { font-family: var(--font-display); font-weight: 800; font-size: 1.02rem; margin: 0 0 3px; color: var(--navy); }
.invite-body p { font-size: .82rem; line-height: 1.4; color: var(--ink-soft); margin: 0 0 11px; font-weight: 600; }
.invite-cta {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer; border: 0;
  font-family: var(--font-display); font-weight: 800; font-size: .9rem;
  background: var(--yellow); color: var(--navy); border-radius: 14px; padding: 10px 16px;
  box-shadow: 0 5px 0 0 var(--yellow-deep); transition: transform .08s ease, box-shadow .08s ease;
}
.invite-cta:active { transform: translateY(5px); box-shadow: 0 0 0 0 var(--yellow-deep); }

/* Generic bottom sheet (openSheet/closeSheet): one reusable element on <body>. */
.sheet-root { position: fixed; inset: 0; z-index: 1000; pointer-events: none; }
.sheet-root.open { pointer-events: auto; }
.sheet-scrim { position: absolute; inset: 0; background: rgba(35,33,95,.42); opacity: 0; transition: opacity .28s ease; }
.sheet-root.open .sheet-scrim { opacity: 1; }
.sheet-panel {
  position: absolute; left: 0; right: 0; bottom: 0; margin: 0 auto; max-width: 560px;
  background: var(--surface); border-radius: 26px 26px 0 0; max-height: 86dvh; overflow-y: auto;
  box-shadow: 0 -18px 40px -20px rgba(46,44,139,.5);
  padding: 8px 16px calc(18px + var(--safe-b));
  transform: translateY(102%); transition: transform .34s cubic-bezier(.2,.9,.3,1);
}
.sheet-root.open .sheet-panel { transform: translateY(0); }
.sheet-grab { display: block; width: 44px; height: 5px; border: 0; padding: 0; border-radius: 999px; background: var(--line); margin: 8px auto 14px; cursor: pointer; }
/* Explicit close, sticky so it stays reachable while a long sheet scrolls. */
.sheet-x { position: sticky; top: 6px; float: right; z-index: 3; display: grid; place-items: center;
  width: 34px; height: 34px; border: 0; padding: 0 0 3px; border-radius: 50%; cursor: pointer;
  background: var(--surface-2); color: var(--ink-soft); font-size: 1.5rem; line-height: 1; font-weight: 700;
  box-shadow: 0 2px 8px rgba(46,44,139,.18); }
.sheet-x:active { transform: scale(.92); }
.sheet-title { font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; margin: 0 0 3px; color: var(--navy); }
.sheet-sub { font-size: .82rem; color: var(--ink-soft); font-weight: 600; margin: 0 0 14px; }

.oc-list { display: flex; flex-direction: column; }
.oc-row { display: flex; align-items: center; gap: 12px; padding: 13px 0; border-top: 1px solid var(--line); }
.oc-row:first-child { border-top: 0; }
.oc-body { flex: 1 1 auto; min-width: 0; }
.oc-name { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 4px;
  font-family: var(--font-display); font-weight: 800; font-size: .95rem; color: var(--navy); }
.oc-badge { font-family: var(--font-display); font-weight: 800; font-size: .62rem; letter-spacing: .03em;
  text-transform: uppercase; padding: 3px 8px; border-radius: 999px; }
.oc-badge.t-private { background: var(--navy-soft); color: var(--navy); }
.oc-badge.t-semi { background: #E3F1F8; color: var(--sky-deep); }
.oc-badge.t-group { background: #FDEAF0; color: #C25378; }
.oc-badge.t-other { background: var(--surface-2); color: var(--ink-soft); }
.oc-sched { font-size: .78rem; font-weight: 700; color: var(--ink-soft); }
.oc-teacher { font-size: .76rem; font-weight: 700; color: var(--ink-faint); margin-top: 2px; }
.oc-join {
  flex: 0 0 auto; text-decoration: none; font-family: var(--font-display); font-weight: 800; font-size: .84rem;
  background: var(--yellow); color: var(--navy); border-radius: 12px; padding: 9px 15px;
  box-shadow: 0 4px 0 0 var(--yellow-deep); transition: transform .08s ease, box-shadow .08s ease;
}
.oc-join:active { transform: translateY(4px); box-shadow: 0 0 0 0 var(--yellow-deep); }

@media (prefers-reduced-motion: reduce) {
  .sheet-scrim, .sheet-panel, .invite { transition: none; animation: none; }
}

/* Practice header: back to the landing + which slice you're drilling. */
.practice-head { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1 1 auto; }
.back-btn {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 12px;
  border: 2px solid var(--line); background: var(--surface); color: var(--ink-soft);
  display: grid; place-items: center; cursor: pointer;
  box-shadow: var(--lift-sm); transition: all .15s ease;
}
.back-btn:hover { border-color: var(--navy); color: var(--navy); }
.back-btn svg { width: 20px; height: 20px; }
.practice-title {
  font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; color: var(--navy);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- Done state ---------- */
#done { text-align: center; background: var(--surface); border: 3px solid var(--navy); border-radius: var(--r-xl); padding: 30px 26px 34px; box-shadow: 0 10px 0 0 var(--navy-deep), var(--lift-md); }
.done-mascot { width: 128px; height: auto; margin: 0 auto 6px; display: block; animation: bob 3s ease-in-out infinite; }
.done h2 { font-family: var(--font-display); font-weight: 800; margin: 0 0 8px; color: var(--navy); }
.done p { color: var(--ink-soft); margin: 0; line-height: 1.5; font-weight: 600; }

/* ---------- Summary overlay ---------- */
.overlay {
  position: fixed; inset: 0; z-index: 50; padding: 64px 20px 20px;
  display: flex; align-items: center; justify-content: center;
  overflow-y: auto;
  animation: fade .25s ease both;
}
/* Scrim is its own layer behind the card, like .sheet-scrim. A backdrop-filter
   on the ancestor makes iOS Safari blur the modal's own text along with the
   backdrop; a sibling layer frosts the background only. */
.overlay::before {
  content: ""; position: fixed; inset: 0; z-index: -1;
  background: rgba(35,33,95,.55); backdrop-filter: blur(7px);
}
.summary-card {
  position: relative; background: var(--surface); border: 3px solid var(--navy);
  border-radius: var(--r-xl); padding: 30px 24px 24px; max-width: 460px; width: 100%;
  box-shadow: 0 12px 0 0 var(--navy-deep), var(--lift-lg); text-align: center;
  animation: pop .4s cubic-bezier(.2,.9,.3,1) both; margin: auto;
}
.summary-mascot { width: 96px; height: auto; display: block; margin: -74px auto 2px; filter: drop-shadow(0 10px 14px rgba(46,44,139,.22)); }
.summary-close { position: absolute; top: 12px; right: 14px; border: 0; background: var(--surface-2); width: 32px; height: 32px; border-radius: 50%; font-size: 1.3rem; line-height: 1; color: var(--ink-soft); cursor: pointer; }
.summary-close:hover { color: var(--navy); background: var(--navy-soft); }
.summary-kicker { font-size: .72rem; text-transform: uppercase; letter-spacing: 1px; color: var(--sky); font-weight: 800; }

.ring-wrap { position: relative; width: 132px; height: 132px; margin: 14px auto 16px; }
.ring { width: 132px; height: 132px; transform: rotate(-90deg); }
.ring-bg { fill: none; stroke: var(--line); stroke-width: 12; }
.ring-fg { fill: none; stroke: var(--green); stroke-width: 12; stroke-linecap: round; stroke-dasharray: 327; stroke-dashoffset: 327; transition: stroke-dashoffset .9s cubic-bezier(.2,.8,.2,1); }
.ring-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ring-num { font-family: var(--font-display); font-weight: 800; font-size: 2.1rem; color: var(--navy); line-height: 1; }
.ring-lbl { font-size: .68rem; text-transform: uppercase; letter-spacing: .6px; color: var(--ink-faint); margin-top: 3px; font-weight: 800; }

.summary-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 9px; margin-bottom: 18px; }
.sstat { background: var(--surface-2); border: 2px solid var(--line); border-radius: var(--r-md); padding: 12px 4px; }
.sstat .num { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1.4rem; line-height: 1; color: var(--navy); }
.sstat.ok .num { color: var(--green-deep); }
.sstat.bad .num { color: var(--red-deep); }
.sstat.streak .num { color: var(--gold); }
.sstat .lbl { display: block; font-size: .58rem; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .4px; margin-top: 5px; font-weight: 800; }

.summary-miss { margin-bottom: 18px; text-align: left; }
.summary-miss h3 { font-size: .74rem; color: var(--red-deep); text-transform: uppercase; letter-spacing: .6px; margin: 0 0 9px; font-weight: 800; }
.summary-miss ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; max-height: 210px; overflow-y: auto; }
.summary-miss li { background: var(--red-soft); border: 2px solid #FBD4D9; border-radius: var(--r-sm); padding: 10px 13px; font-size: .94rem; font-weight: 600; }
.summary-miss li .m-thai { font-family: var(--font-thai); font-weight: 700; color: var(--navy); }
.summary-miss li .m-roman { color: var(--green-deep); font-weight: 700; }
.summary-miss li .m-arti { color: var(--ink-soft); }
.summary-miss .clean { background: var(--green-soft); border-color: #BFE9CF; color: var(--green-deep); padding: 12px 14px; border-radius: var(--r-sm); font-weight: 800; }

/* ---------- Views + bottom menu ---------- */
.view { display: flex; flex-direction: column; gap: 13px; }
/* The active view fills the space under the brand bar. Ranking/Profile scroll
   internally when long; Home has no view-level overflow so the practice card's
   3D shadow is never clipped (the answers scroll via .answer-scroll instead). */
.view:not([hidden]) { flex: 1 1 auto; min-height: 0; }
#viewRanking:not([hidden]), #viewProfile:not([hidden]) { overflow-y: auto; }
/* Profile stacks a few standalone cards; give them more air. The ranking
   profile peek clones those same cards into the sheet, so it takes its rhythm
   from this one rule instead of a second set of margins to keep in sync. */
#viewProfile, .profile-peek { display: flex; flex-direction: column; gap: 14px; }
.view-title { font-family: var(--font-display); font-weight: 800; color: var(--navy); font-size: 1.5rem; margin: 4px 0 0; text-align: center; }
.view-sub { color: var(--ink-soft); font-weight: 600; font-size: .9rem; line-height: 1.5; text-align: center; margin: 0 4px 6px; }

/* Practice is full-screen: hide the bottom menu and give its reserved space
   back to the practice frame (Lanjut then pins to the very bottom). */
body.practicing .tabbar { display: none; }
body.practicing .app { padding-bottom: calc(14px + var(--safe-b)); }

.tabbar {
  /* In-flow last child of the 100dvh .app column (not position:fixed): a fixed
     bar anchors to iOS Safari's layout viewport, which disagrees with dvh when
     the toolbar is dragged and strands the bar above the real bottom. Riding the
     dvh column keeps it glued to the visible bottom. The negative inline margin
     cancels .app's side padding so the bar stays edge-to-edge (matched per
     breakpoint below). */
  flex: none; margin: 0 -16px;
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px;
  background: var(--surface); border-top: 2px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: 0 -10px 28px -16px rgba(46,44,139,.35);
  padding: 8px 10px calc(8px + var(--safe-b));
}
.tabbar button {
  border: 0; background: transparent; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  font-family: var(--font-display); font-weight: 800; font-size: .68rem;
  color: var(--ink-faint); padding: 7px 4px; border-radius: var(--r-sm);
  transition: color .15s ease, background .15s ease;
}
/* .tabbar button sets display:flex, which would otherwise override the hidden
   attribute on the admin-only Beranda tab; re-hide it explicitly. */
.tabbar button[hidden] { display: none; }
.tabbar button svg { width: 23px; height: 23px; }
.tabbar button:hover { color: var(--navy); }
.tabbar button.active { color: var(--navy); background: var(--navy-soft); }

/* ---------- Ranking: "Papan Juara" ---------- */
/* Top 3 rise onto a 3D podium with confetti; ranks 4+ are a static list; a
   sticky self-summary bar keeps the viewer's own standing in view. Selectors
   are scoped to #viewRanking because the podium/list reuse short, generic
   class names (row, stage, xp, lv, nm) that also appear elsewhere. */
.rank-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.rank-tt small { display: block; font-size: .72rem; font-weight: 900; color: var(--ink-soft); letter-spacing: .5px; text-transform: uppercase; }
.rank-tt b { font-family: var(--font-display); font-weight: 800; font-size: 1.6rem; line-height: 1.05; }
.rank-reset {
  flex: none; display: flex; align-items: center; gap: 6px; background: var(--surface);
  border-radius: 999px; padding: 7px 12px; font-weight: 900; font-size: .72rem; color: var(--navy);
  border: 2px solid var(--line); box-shadow: 0 3px 0 0 var(--line); line-height: 1.1; max-width: 132px;
}
.rank-reset .em { font-size: .95rem; line-height: 1; }
.rank-reset b { color: var(--red-deep); }
.rank-lead { font-size: .8rem; font-weight: 700; color: var(--ink-soft); line-height: 1.45; margin: -6px 2px 0; }

/* Period toggle: yellow 3D segmented pill (reuses the existing #rankTabs). */
.rank-tabs { display: flex; gap: 6px; background: var(--navy-soft); border: 2px solid var(--line); border-radius: 999px; padding: 5px; }
.rank-tab {
  flex: 1; border: none; background: transparent; cursor: pointer;
  font-family: var(--font-display); font-weight: 800; font-size: .88rem; color: var(--ink-soft);
  border-radius: 999px; padding: 9px 4px 10px; transition: transform .06s ease;
}
.rank-tab.is-on { color: var(--navy); background: var(--yellow); box-shadow: 0 3px 0 0 var(--yellow-deep); }
.rank-tab.is-on:active { transform: translateY(3px); box-shadow: 0 0 0 0 var(--yellow-deep); }

/* ---- Podium stage: the top three feel like a medal ceremony ---- */
.rank-stage {
  /* flex-shrink:0 is load-bearing: overflow:hidden gives a flex item min-height:0,
     so inside the fixed-height scrolling view the stage would otherwise be
     squished to its padding and clip the podium. */
  position: relative; flex: none; padding: 16px 10px 0; border-radius: var(--r-xl); overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% -8%, rgba(255,225,0,.30), transparent 60%),
    linear-gradient(180deg, var(--navy) 0%, var(--navy-deep) 100%);
  box-shadow: 0 8px 0 0 #17153f, inset 0 1px 0 rgba(255,255,255,.12);
}
.rank-stage .stage-title {
  position: relative; z-index: 3; text-align: center; color: #fff;
  font-family: var(--font-display); font-weight: 800; font-size: .82rem; letter-spacing: .5px;
  text-transform: uppercase; opacity: .92; margin-bottom: 2px;
}
/* falling confetti behind the podium */
.rank-stage .rain { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden; }
.rank-stage .rain i { position: absolute; top: -14px; width: 8px; height: 12px; border-radius: 2px; opacity: .9; animation: rankFall linear infinite; }
@keyframes rankFall {
  0% { transform: translateY(-14px) rotate(0deg); opacity: 0; }
  10% { opacity: .95; }
  100% { transform: translateY(320px) rotate(420deg); opacity: .15; }
}
.rank-stage .podium { position: relative; z-index: 2; display: flex; align-items: flex-end; justify-content: center; gap: 8px; padding-top: 6px; }
.rank-stage .p-col { flex: 1; max-width: 118px; display: flex; flex-direction: column; align-items: center; }
.rank-stage .crown { font-size: 1.6rem; line-height: 1; filter: drop-shadow(0 3px 3px rgba(0,0,0,.25)); animation: bob 2.6s ease-in-out infinite; }
.rank-stage .p-mascot { position: relative; display: grid; place-items: center; filter: drop-shadow(0 6px 8px rgba(0,0,0,.28)); }
.rank-stage .p-mascot img { width: 100%; display: block; }
.rank-stage .p1 .p-mascot { width: 92px; }
.rank-stage .p1 .p-mascot img { animation: bob 3s ease-in-out infinite; }
.rank-stage .p2 .p-mascot { width: 70px; margin-bottom: 2px; }
.rank-stage .p3 .p-mascot { width: 66px; margin-bottom: 2px; }
/* sparkles around the champion */
.rank-stage .spark { position: absolute; font-size: .85rem; opacity: 0; animation: rankTwinkle 2.4s ease-in-out infinite; }
.rank-stage .spark.s1 { top: 2px; left: -6px; animation-delay: 0s; }
.rank-stage .spark.s2 { top: 14px; right: -8px; animation-delay: .8s; font-size: .7rem; }
.rank-stage .spark.s3 { bottom: 8px; left: -4px; animation-delay: 1.5s; font-size: .62rem; }
@keyframes rankTwinkle { 0%, 100% { opacity: 0; transform: scale(.6); } 50% { opacity: 1; transform: scale(1); } }
.rank-stage .p-badge {
  margin-top: -8px; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800; font-size: 1rem; color: var(--navy-deep);
  border: 3px solid #fff; position: relative; z-index: 3;
}
.rank-stage .p1 .p-badge { background: radial-gradient(circle at 38% 30%, #FFF0B0, var(--gold) 55%, var(--yellow-deep)); box-shadow: 0 3px 0 0 var(--yellow-deep); width: 40px; height: 40px; font-size: 1.15rem; }
.rank-stage .p2 .p-badge { background: radial-gradient(circle at 38% 30%, #fff, var(--silver) 50%, var(--silver-2)); box-shadow: 0 3px 0 0 var(--silver-edge); }
.rank-stage .p3 .p-badge { background: radial-gradient(circle at 38% 30%, #FCE2C8, var(--bronze) 50%, var(--bronze-2)); box-shadow: 0 3px 0 0 var(--bronze-edge); }
.rank-stage .p-name { color: #fff; font-family: var(--font-display); font-weight: 800; font-size: .95rem; line-height: 1.1; margin-top: 6px; text-align: center; white-space: nowrap; display: flex; align-items: center; gap: 5px; justify-content: center; max-width: 100%; }
.rank-stage .p1 .p-name { font-size: 1.05rem; }
.rank-stage .p-name .kamu { flex: none; font-family: var(--font-body); font-size: .56rem; font-weight: 900; letter-spacing: .4px; text-transform: uppercase; color: var(--navy-deep); background: var(--yellow); padding: 1px 6px; border-radius: 999px; }
.rank-stage .p-xp { color: var(--yellow); font-weight: 900; font-size: .82rem; font-variant-numeric: tabular-nums; margin-top: 1px; }
.rank-stage .p-meta { display: flex; gap: 5px; margin: 5px 0 8px; }
.rank-stage .p-tag { font-size: .62rem; font-weight: 900; color: #fff; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.28); border-radius: 999px; padding: 2px 7px; line-height: 1.2; }
/* the physical steps */
.rank-stage .p-step { width: 100%; border-radius: 14px 14px 0 0; display: grid; place-items: start center; padding-top: 8px; font-family: var(--font-display); font-weight: 800; color: rgba(0,0,0,.32); font-size: 1.6rem; position: relative; }
.rank-stage .p-step::after { content: ""; position: absolute; top: 8px; left: 12px; right: 12px; height: 3px; border-radius: 3px; background: rgba(255,255,255,.35); }
.rank-stage .p1 .p-step { height: 104px; background: linear-gradient(180deg,#FFE99A,var(--gold)); box-shadow: inset 0 -10px 0 rgba(224,181,0,.55), 0 0 0 3px rgba(255,255,255,.10); }
.rank-stage .p2 .p-step { height: 74px; background: linear-gradient(180deg,#F1F0F8,var(--silver-2)); box-shadow: inset 0 -10px 0 rgba(120,118,150,.45); }
.rank-stage .p3 .p-step { height: 58px; background: linear-gradient(180deg,#F4D9BF,var(--bronze-2)); box-shadow: inset 0 -10px 0 rgba(120,80,40,.40); }

/* ---- List heading + rows (ranks 4+) ---- */
.rank-listhead { display: flex; align-items: center; gap: 9px; margin-top: 4px; }
.rank-listhead h2 { font-family: var(--font-display); font-weight: 800; font-size: 1rem; }
.rank-listhead .rule { flex: 1; height: 2px; background: var(--line); border-radius: 2px; }
.rank-listhead .cnt { font-family: var(--font-display); font-weight: 800; font-size: .72rem; color: var(--ink-soft); background: var(--navy-soft); padding: 2px 10px; border-radius: 999px; }
.rank-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
#viewRanking .row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--surface); border: 2px solid var(--line); border-radius: var(--r-md);
  box-shadow: 0 3px 0 0 var(--line); padding: 11px 14px 11px 11px;
}
/* Board entries open that learner's profile peek in the shared sheet. */
#viewRanking [data-slug] { cursor: pointer; }
#viewRanking .row[data-slug]:active { transform: translateY(2px); box-shadow: 0 1px 0 0 var(--line); }
.sheet-body .titles-open:disabled { cursor: default; }
#viewRanking .rk { flex: none; width: 26px; text-align: center; font-family: var(--font-display); font-weight: 800; font-size: 1rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
#viewRanking .av { flex: none; width: 44px; height: 44px; border-radius: 50%; overflow: hidden; background: radial-gradient(circle at 50% 32%, #fff, var(--canvas-2)); box-shadow: inset 0 0 0 3px #fff, 0 3px 7px rgba(46,44,139,.14); display: flex; align-items: flex-end; justify-content: center; }
#viewRanking .av img { width: 118%; margin-bottom: -2px; }
#viewRanking .who { flex: 1; min-width: 0; }
#viewRanking .who .nm { font-family: var(--font-display); font-weight: 800; font-size: 1rem; line-height: 1.1; display: flex; align-items: center; gap: 7px; }
#viewRanking .who .nm .kamu { flex: none; font-family: var(--font-body); font-weight: 900; font-size: .62rem; letter-spacing: .4px; color: #fff; background: var(--navy); padding: 2px 8px; border-radius: 999px; text-transform: uppercase; }
#viewRanking .who .mt { display: flex; align-items: center; gap: 8px; margin-top: 3px; font-size: .75rem; font-weight: 800; color: var(--ink-soft); }
#viewRanking .lv { color: var(--navy); background: var(--navy-soft); border-radius: 7px; padding: 1px 7px; font-weight: 900; }
#viewRanking .fire { display: inline-flex; align-items: center; gap: 4px; color: var(--red-deep); white-space: nowrap; }
#viewRanking .fire.cold { color: var(--ink-faint); }
#viewRanking .fire b { color: inherit; font-weight: 900; }
#viewRanking .rank-fire-num { display: inline-block; line-height: 1; transform: translateY(1px); }
#viewRanking .rank-fire-icon {
  width: 1.08em;
  height: 1.08em;
  flex: none;
  margin: -.16em -1px -.24em 0;
}
.rank-stage .p-tag.fire {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: calc(1em + 8px);
  line-height: 1;
  padding-top: 3px;
  padding-bottom: 3px;
}
.rank-stage .p-tag.fire .rank-fire-icon {
  width: 1em;
  height: 1em;
  margin: 0 -1px 0 -1px;
}
.rank-stage .p-tag.fire .rank-fire-num {
  display: inline-flex;
  align-items: center;
  height: 1.2em;
  line-height: 1;
  color: #FFD1B0;
  transform: none;
}
#viewRanking .xp { flex: none; text-align: right; }
#viewRanking .xp b { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1rem; line-height: 1; font-variant-numeric: tabular-nums; }
#viewRanking .xp span { font-size: .56rem; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
#viewRanking .row.me { border-color: var(--navy); box-shadow: 0 4px 0 0 var(--navy); background: linear-gradient(180deg, var(--navy-soft), #fff 70%); }
#viewRanking .row.me .rk { color: var(--navy); }

/* You-vs-next nudge (inline under the viewer's row, or under the stage if on it) */
#viewRanking .nudge {
  display: flex; align-items: center; gap: 9px; padding: 10px 12px;
  background: var(--green-soft); border: 2px solid #BFEFD3; border-radius: var(--r-md);
  box-shadow: 0 3px 0 0 #BFEFD3;
}
#viewRanking .nudge .em { font-size: 1.1rem; flex: none; }
#viewRanking .nudge p { font-size: .8rem; font-weight: 800; color: var(--green-deep); line-height: 1.35; }
#viewRanking .nudge p b { color: var(--navy); }

.rank-more { align-self: center; margin-top: 2px; }

/* Sticky self-summary: pinned just above the fixed tab bar while scrolling. */
.rank-self {
  position: sticky; bottom: 6px; z-index: 5; margin-top: 4px;
  display: flex; align-items: center; gap: 11px;
  background: linear-gradient(180deg, var(--navy), var(--navy-deep));
  border-radius: var(--r-lg); padding: 10px 14px 10px 11px;
  box-shadow: 0 8px 22px rgba(23,21,63,.4), 0 4px 0 0 #14123a;
}
.rank-self .srk { flex: none; width: 38px; height: 38px; border-radius: 12px; display: grid; place-items: center; font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; color: var(--navy-deep); background: linear-gradient(180deg, var(--yellow), var(--yellow-deep)); box-shadow: 0 2px 0 rgba(0,0,0,.2); }
.rank-self .srk small { display: block; font-size: .5rem; font-weight: 900; color: var(--navy); letter-spacing: .5px; margin-bottom: -2px; }
.rank-self .sbody { flex: 1; min-width: 0; color: #fff; }
.rank-self .snm { font-family: var(--font-display); font-weight: 800; font-size: .95rem; line-height: 1.1; display: flex; align-items: center; gap: 7px; }
.rank-self .snm .kamu { flex: none; font-size: .56rem; font-weight: 900; letter-spacing: .4px; background: var(--yellow); color: var(--navy-deep); padding: 1px 7px; border-radius: 999px; text-transform: uppercase; }
.rank-self .ssub {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  font-size: .7rem;
  font-weight: 800;
  line-height: 1.15;
  color: rgba(255,255,255,.72);
  margin-top: 2px;
}
.rank-self .ssub > span,
.rank-self .ssub em {
  display: inline-flex;
  align-items: center;
  height: 1.15em;
  line-height: 1;
}
.rank-self .ssub .sep { opacity: .9; }
.rank-self .fire.on-dark {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: inherit;
  height: 1.15em;
  line-height: 1;
  vertical-align: 0;
}
.rank-self .fire.on-dark .rank-fire-icon {
  width: .95em;
  height: .95em;
  margin: 0 -1px 0 0;
}
.rank-self .fire.on-dark .rank-fire-num {
  display: inline-flex;
  align-items: center;
  height: 1.15em;
  line-height: 1;
  color: inherit;
  transform: none;
}
.rank-self .ssub em { font-style: normal; color: var(--yellow); }
.rank-self .sxp { flex: none; text-align: right; color: #fff; }
.rank-self .sxp b { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; line-height: 1; font-variant-numeric: tabular-nums; }
.rank-self .sxp span { font-size: .56rem; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: rgba(255,255,255,.6); }

.rank-empty { text-align: center; color: var(--ink-faint); font-weight: 700; padding: 22px; }

@media (prefers-reduced-motion: reduce) {
  .rank-stage .rain, .rank-stage .spark { display: none; }
}

/* ---------- Level-up toast ---------- */
.levelup-toast {
  position: fixed; top: 18px; left: 50%; z-index: 50;
  display: flex; align-items: center; gap: 12px;
  background: var(--navy); border: 3px solid var(--yellow); border-radius: 999px;
  padding: 9px 22px 9px 11px; box-shadow: var(--lift-lg);
  opacity: 0; transform: translateX(-50%) translateY(-18px);
  transition: opacity .3s ease, transform .3s ease;
}
.levelup-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.levelup-toast img { width: 42px; height: 42px; object-fit: contain; }
.lt-kicker { display: block; font-size: .6rem; text-transform: uppercase; letter-spacing: 1.5px; color: var(--yellow); font-weight: 800; }
.lt-level { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1.1rem; color: #fff; }

/* ---------- Animations ---------- */
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@keyframes deal { from { opacity: 0; transform: translateY(16px) scale(.985); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes pop { from { opacity: 0; transform: translateY(14px) scale(.96); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes shake { 10%,90%{transform:translateX(-1px)} 20%,80%{transform:translateX(2px)} 30%,50%,70%{transform:translateX(-4px)} 40%,60%{transform:translateX(4px)} }
@keyframes bob { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-6px)} }
@keyframes drift { 0%,100%{ transform: translate(-50%,-50%) rotate(-7deg); } 50%{ transform: translate(-50%,calc(-50% - 18px)) rotate(7deg); } }
@keyframes pop-bounce { 0%{transform:scale(.6)} 55%{transform:scale(1.15)} 100%{transform:scale(1)} }
@keyframes mascot-shake { 0%,100%{transform:translateX(0) rotate(0)} 25%{transform:translateX(-5px) rotate(-5deg)} 75%{transform:translateX(5px) rotate(5deg)} }
@keyframes welcome-in {
  from { opacity: 0; transform: translateY(12px) scale(.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes welcome-logo-reveal {
  0% { opacity: 0; clip-path: inset(0 50% 0 50%); transform: translateY(-8px) scale(.94); }
  70% { opacity: 1; clip-path: inset(0 0 0 0); transform: translateY(2px) scale(1.02); }
  100% { opacity: 1; clip-path: inset(0 0 0 0); transform: translateY(0) scale(1); }
}
@keyframes welcome-halo {
  from { opacity: 0; transform: scale(.4); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes welcome-halo-breathe {
  0%,100% { transform: scale(1); box-shadow: 0 12px 34px rgba(224,181,0,.24); }
  50% { transform: scale(1.055); box-shadow: 0 16px 40px rgba(224,181,0,.32); }
}
@keyframes welcome-halo-out {
  0% { opacity: 1; transform: scale(1); }
  42% { opacity: 1; transform: scale(1.2); }
  100% { opacity: .88; transform: scale(12); }
}
@keyframes welcome-orbit-in {
  from { opacity: 0; transform: scale(.72) rotate(-18deg); }
  to { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes welcome-orbit-spin {
  from { opacity: 1; transform: rotate(0); }
  to { opacity: 1; transform: rotate(360deg); }
}
@keyframes welcome-letter-pop {
  0% { opacity: 0; transform: translateY(10px) rotate(var(--letter-rotate)) scale(.4); }
  68% { opacity: 1; transform: translateY(-3px) rotate(var(--letter-rotate)) scale(1.12); }
  100% { opacity: 1; transform: translateY(0) rotate(var(--letter-rotate)) scale(1); }
}
@keyframes welcome-letter-out {
  from { opacity: 1; transform: translateY(0) rotate(var(--letter-rotate)) scale(1); }
  to { opacity: 0; transform: translateY(-8px) rotate(var(--letter-rotate)) scale(.7); }
}
@keyframes welcome-fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@keyframes welcome-spark {
  0% { opacity: 0; transform: rotate(var(--spark-angle)) translateY(-36px) scaleY(.2); }
  28% { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--spark-angle)) translateY(var(--spark-distance)) scaleY(1); }
}
@keyframes welcome-mascot-in {
  0% { opacity: 0; transform: translateY(35px) rotate(-9deg) scale(.64); }
  58% { opacity: 1; transform: translateY(-5px) rotate(4deg) scale(1.08); }
  78% { transform: translateY(2px) rotate(-2deg) scale(.98); }
  100% { opacity: 1; transform: translateY(0) rotate(0) scale(1); }
}
@keyframes welcome-mascot-float {
  0%,100% { transform: translateY(0) rotate(0); }
  24% { transform: translateY(-4px) rotate(-1deg); }
  52% { transform: translateY(-7px) rotate(2deg); }
  76% { transform: translateY(-3px) rotate(-1deg); }
}
@keyframes welcome-mascot-out {
  from { opacity: 1; transform: translateY(0) rotate(0) scale(1); }
  to { opacity: 0; transform: translateY(-16px) rotate(4deg) scale(.88); }
}
@keyframes welcome-elements-out {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to { opacity: 0; transform: translateY(-8px) scale(.96); }
}
@keyframes welcome-copy {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes welcome-progress {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}
@keyframes welcome-progress-shine {
  from { left: -14px; opacity: 0; }
  35% { opacity: 1; }
  to { left: 60px; opacity: 0; }
}
@keyframes welcome-dot {
  0%,100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-7px) scale(.85); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  .welcome-halo { opacity: 1; transform: scale(1); }
  .welcome-progress span { transform: translateX(0); }
}

/* ---------- Phone: pin continue, keep loop in the fold ---------- */
@media (max-width: 560px) {
  .welcome::before { margin-left: -78vw; }
  .welcome::after { margin-right: -82vw; }
  .app { padding: 13px 13px 0; gap: 11px; }
  .tabbar { margin: 0 -13px; }
  .view { gap: 11px; }
  .brand { gap: 8px; }
  .play-controls { gap: 6px; }
  .roman-toggle button { min-width: 32px; padding: 7px 8px; }
  .dir-menu-btn { width: 38px; height: 38px; }

  .card { padding: 22px 16px 26px; gap: 12px; min-height: 195px; }
  .question-card { margin-top: 36px; }
  .mascot { width: 72px; height: 76px; top: -40px; right: 6px; }
  .card-meta { padding-right: 62px; }
  .prompt.is-thai { font-size: 2.5rem; }
  .prompt { font-size: 1.55rem; }

  .summary-stats { grid-template-columns: repeat(2, 1fr); }
  .bd-row { grid-template-columns: minmax(48px,auto) 1fr; }
  .bd-row .bd-arti { grid-column: 1 / -1; margin-top: -2px; }

  /* Chips ride beside the greeting when they fit; wrap to their own row
     (spread full-width) only when they don't. */
  .hub-top { flex-wrap: wrap; }
  .hub-hi { flex: 1 1 auto; }
  .hub-hi b { font-size: 1.55rem; }
  .hub-chips { margin-left: auto; }
}

/* Wider screens: a little more generosity. */
@media (min-width: 561px) {
  .app { max-width: 600px; padding: 24px 20px 0; gap: 16px; }
  .view { gap: 16px; }
  .tabbar { margin: 0 -20px; }
  .card { padding: 32px 26px 38px; gap: 18px; min-height: 250px; }
  .question-card { margin-top: 44px; }
  .mascot { width: 98px; height: 104px; top: -52px; }
  .prompt.is-thai { font-size: 3.1rem; }
  .prompt { font-size: 2rem; }
}
