/* ==========================================================================
   Speak88 — styles (hướng 1b "Storefront dày": ink #241B4A + mint #00E5A0 +
   hổ phách #FFB020). Mobile-first, works on Win/mac/iOS/Android.

   VÌ SAO TÊN BIẾN VẪN LÀ --navy / --pink SAU KHI ĐỔI THƯƠNG HIỆU: hai cái tên
   ấy nằm rải khắp file này và 28 view. Đổi TÊN là sửa ~40 file và sót âm thầm
   (một biến không tồn tại thì CSS bỏ qua luật, không báo gì cả); đổi GIÁ TRỊ
   là sửa đúng một khối. Nên đọc chúng theo VAI TRÒ, đừng đọc theo tên màu:
     --navy = nền TỐI     (topbar, hero, nút phụ)
     --pink = hành động CHÍNH — giờ là mint, tức một màu SÁNG. Chữ đặt lên nó
              phải là --mint-on, KHÔNG phải #fff. Đó là cái bẫy lớn nhất của
              đợt đổi màu này.
   ========================================================================== */
:root {
  /* ---- thương hiệu (tên cũ, giá trị 1b) ---- */
  --navy: #241b4a;
  --navy-l: #2e2260;
  --navy-m: #3b2f73;
  --pink: #00e5a0;
  --pink-l: #35f0b8;
  --pink-d: #00a87c;     /* mint dạng CHỮ/link trên nền sáng (mockup dùng đúng màu này cho <a>) */
  --indigo: #4f46e5;
  --green: #10b981;
  --amber: #ffb020;
  --red: #e5484d;

  /* ---- mint ---- */
  --mint-on: #05271c;    /* chữ trên nền mint */
  --mint-d: #00ce90;     /* mint hover */
  --mint-bg: #eafbf4;
  --mint-fg: #00785b;    /* chữ trên --mint-bg */

  /* ---- hổ phách: bài tập được giao, "sắp đạt", cảnh báo mềm ---- */
  --gold: #ffb020;
  --gold-bg: #fff6e5;
  --gold-line: #f3e2bc;
  --gold-fg: #8a5b00;
  --gold-on: #3a2600;

  /* ---- đỏ ghi âm ---- */
  --red-bg: #ffede9;
  --red-halo: #fff6f4;

  /* ---- xám: giữ thang g1..g9, kéo về họ tím-lavender của 1b ---- */
  --g1: #f1eefa; --g2: #e7e4f0; --g3: #c4bdd8; --g4: #9b93b8;
  --g5: #7a719c; --g6: #6c6390; --g7: #574c7d; --g8: #2e2757; --g9: #241b4a;

  /* ---- mặt phẳng ---- */
  --bg: #f7f6fb;
  --card: #ffffff;
  --text: #241b4a;
  --prose: #2e2757;      /* thân văn bản dài — bản ghi ở màn kết quả */
  --muted: #7a719c;
  --label: #9b93b8;      /* nhãn IN HOA 11.5px letterspacing */
  --faint: #c4bdd8;
  --line: #e7e4f0;       /* 1b dựng chiều sâu bằng KẺ 1px, không bằng bóng */
  --hair: #f1eefa;       /* kẻ giữa các hàng trong bảng */
  --track: #efecf7;      /* rãnh thanh tiến độ */
  --hover: #faf9fd;

  /* ---- chữ trên nền tối ---- */
  --on-dark: #b4abd6;
  --on-dark-2: #c3badf;
  --on-dark-3: #9c92c4;
  --on-dark-mint: #9febd2;

  /* ---- tô lỗi trong bản ghi (màn kết quả) ---- */
  --hl-gram: #ffe0a3;
  --hl-vocab: #bff3e0;
  --hl-rep: #f1eefa;

  /* ---- bóng: 1b chỉ có MỘT cái thật, cho vỏ nổi. Còn lại là kẻ 1px ---- */
  --shd-sm: 0 1px 2px rgba(36,27,74,.05);
  --shd: 0 1px 2px rgba(36,27,74,.05);
  --shd-l: 0 16px 40px rgba(36,27,74,.14);
  --shd-pink: 0 6px 16px rgba(0,229,160,.28);

  /* radius scale — 1b siết chặt hơn hệ cũ (12px thẻ, 8px nút, 6px chip) */
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius: 12px;
  --radius-lg: 14px;
  --radius-full: 999px;

  /* spacing scale (4px base) */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px; --sp-8: 48px;

  /* type scale + weights */
  --fs-xs: 11.5px; --fs-sm: 12.5px; --fs-base: 13.5px; --fs-md: 14.5px; --fs-lg: 17px;
  --fs-xl: 21px; --fs-2xl: 25px; --fs-3xl: 30px; --fs-4xl: 34px;
  --fw-md: 500; --fw-sb: 600; --fw-b: 700; --fw-xb: 800;

  /* z-index scale */
  --z-nav: 20; --z-sheet: 55; --z-toast: 50; --z-tip: 60;

  /* motion */
  --ease: cubic-bezier(.4, 0, .2, 1);
  --dur: .18s;

  --font: 'Plus Jakarta Sans', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  --font-head: 'Bricolage Grotesque', var(--font);
}

* { box-sizing: border-box; }
/* Author display rules (.stack, .topbar → flex) override the UA's [hidden]
   rule by cascade origin — restore the expected hide-everywhere semantics. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  /* 1b là hệ DÀY: thân chữ 14.5px, không phải 16px mặc định của trình duyệt.
     Đặt ở body chứ không rải từng luật, để những màn chưa sơn lại vẫn cùng một
     thước với bốn màn đã sơn — nếu không, app đọc như hai sản phẩm ghép lại. */
  font-size: var(--fs-md);
  line-height: 1.5;
  min-height: 100vh;
  min-height: 100dvh; /* iOS < 15.4 ignores dvh and keeps the 100vh above */
}
h1, h2, h3 { font-family: var(--font-head); line-height: 1.2; margin: 0 0 .4em; letter-spacing: -.01em; }
h1 { font-size: var(--fs-2xl); letter-spacing: -.02em; }
h2 { font-size: var(--fs-lg); }
h3 { font-size: var(--fs-md); }
a { color: var(--pink-d); text-decoration: none; }
a:hover { color: #00c58a; }
img { max-width: 100%; }

/* Keyboard focus ring (a11y) — visible only for keyboard/AT users, not mouse taps.
   .btn sets appearance:none which suppresses the UA outline, so restore one here. */
:where(a, button, [role="button"], input, textarea, select, summary, [tabindex]):focus-visible {
  /* KHÔNG dùng --pink ở đây nữa: mint (#00e5a0) trên nền trắng chỉ được ~1.5:1,
     tức một vòng focus gần như vô hình. Ink thì tương phản trên mọi mặt SÁNG;
     riêng trên các mặt TỐI (topbar, màn ghi âm) đảo lại thành mint ngay dưới. */
  outline: 2px solid var(--navy);
  outline-offset: 2px;
  border-radius: inherit;
}
.topbar :focus-visible, .rec-focus :focus-visible, .s8-dark :focus-visible { outline-color: var(--pink); }
:focus:not(:focus-visible) { outline: none; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}
/* Subtle interaction transitions on the interactive primitives. */
.qitem, .fchip, .chip-toggle, .hitem, .tab, .ib-topic { transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease), color var(--dur) var(--ease); }
.qitem:hover { background: var(--hover); }

/* ---- Top bar (Speak88 1b: cao 58px, ink đặc, năm mục) ---- */
.topbar {
  position: sticky; top: 0; z-index: var(--z-nav);
  display: flex; align-items: center; gap: 18px;
  min-height: 58px; padding: 0 20px;
  padding-top: env(safe-area-inset-top);
  background: var(--navy); color: #fff;
}
.brand { display: flex; align-items: center; gap: 8px; color: #fff; font-family: var(--font-head); font-weight: 800; font-size: 20px; letter-spacing: -.02em; flex: 0 0 auto; }
/* Dấu hiệu là ô mint chứa "88" — cùng một hình với icon.svg, dựng bằng CSS y như mockup. */
.brand-mark { display: grid; place-items: center; width: 27px; height: 27px; border-radius: 8px; background: var(--pink); color: var(--mint-on); font-size: 14px; }
.topnav { flex: 1; min-width: 0; display: flex; align-items: center; gap: 2px; }
.topnav > a, .nav-dd-btn { color: var(--on-dark); font-weight: 600; font-size: var(--fs-base); padding: 7px 11px; border-radius: 7px; white-space: nowrap; transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.topnav > a.active, .topnav > a:hover { color: #fff; background: rgba(255,255,255,.12); }

/* Nhóm menu đổ xuống trên desktop */
.nav-dd { position: relative; flex: 0 0 auto; }
.nav-dd-btn { appearance: none; border: 0; background: none; cursor: pointer; font: inherit; font-weight: 600; }
.nav-dd-btn:hover, .nav-dd-btn.active, .nav-dd-btn[aria-expanded="true"] { color: #fff; background: rgba(255,255,255,.12); }
.nav-dd-menu { position: absolute; top: calc(100% + 8px); right: 0; min-width: 190px; z-index: 40;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-md);
  box-shadow: var(--shd-l); padding: 5px; display: flex; flex-direction: column; }
.nav-dd-menu a, .nav-dd-logout { display: block; width: 100%; text-align: left; appearance: none; border: 0; background: none; font: inherit; font-size: var(--fs-base); font-weight: 600; color: var(--g7); padding: 9px 11px; border-radius: var(--radius-sm); cursor: pointer; white-space: nowrap; }
.nav-dd-menu a:hover, .nav-dd-menu a.active { color: var(--navy); background: var(--g1); }
.nav-dd-logout { color: var(--red); }
.nav-dd-logout:hover { background: var(--g1); }

/* Ví + avatar: đẩy sang phải bằng margin-left:auto. Cả hai nằm TRONG .topnav vì
   js/app.js nối sự kiện menu qua selector ".topnav .nav-dd-btn" — để ra ngoài thì
   menu avatar không bao giờ mở được. */
.nav-wallet { margin-left: auto; display: flex; align-items: center; gap: 14px; font-size: var(--fs-base); font-weight: 700; white-space: nowrap; }
.nav-wallet span { display: flex; align-items: center; gap: 5px; }
.nav-me { margin-left: 2px; }
.nav-avatar { display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border-radius: 7px; background: var(--pink); color: var(--mint-on); font-size: 14px; }
.nav-avatar:hover, .nav-avatar[aria-expanded="true"] { background: var(--mint-d); color: var(--mint-on); }
.nav-me .nav-dd-menu { min-width: 176px; }

/* ---- Thanh tab dưới (hiện <980px; nav trên ẩn ở đó) ---- */
.tabbar { position: fixed; bottom: 0; left: 0; right: 0; z-index: var(--z-nav); display: flex; background: var(--card); border-top: 1px solid var(--line); padding-bottom: env(safe-area-inset-bottom); }
.tab { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 8px 2px 6px; min-height: 56px; background: none; border: 0; cursor: pointer; color: var(--g4); font: inherit; font-size: 10.5px; font-weight: var(--fw-b); text-decoration: none; position: relative; }
.tab-ic { font-size: 19px; line-height: 1; }
.tab.active { color: var(--navy); }
.tab .nav-badge { position: absolute; top: 5px; left: calc(50% + 6px); margin: 0; }
@media (min-width: 980px) { .tabbar { display: none; } }
@media (max-width: 979px) {
  /* Ví ở lại trên điện thoại (mockup 2h cũng giữ), chỉ các mục điều hướng đi xuống
     thanh tab + sheet ☰. Nên ẩn TỪNG con, không ẩn cả .topnav. */
  .topnav > a, .topnav > .nav-dd:not(.nav-me) { display: none; }
  .view { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
}

/* ---- Sheet "Thêm" ---- */
.nav-sheet-backdrop { position: fixed; inset: 0; background: rgba(36,27,74,.4); z-index: var(--z-sheet); }
.nav-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: calc(var(--z-sheet) + 1); background: var(--card); border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: var(--shd-l); padding: 8px 12px calc(12px + env(safe-area-inset-bottom)); max-height: 82vh; overflow-y: auto; animation: sheet-up var(--dur) var(--ease); }
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
.nav-sheet-grip { width: 40px; height: 4px; border-radius: 999px; background: var(--g2); margin: 6px auto 10px; }
.nav-sheet-item { display: flex; align-items: center; gap: 12px; width: 100%; padding: 13px 12px; border: 0; background: none; font: inherit; font-size: var(--fs-md); font-weight: var(--fw-sb); color: var(--text); text-decoration: none; border-radius: var(--radius-sm); cursor: pointer; text-align: left; }
.nav-sheet-item:hover, .nav-sheet-item.active { background: var(--g1); }
.nav-sheet-item > span { font-size: 20px; width: 26px; text-align: center; }
.nav-sheet-logout { color: var(--red); }
/* Badge dùng HỔ PHÁCH chứ không mint: mint là màu của "đã xong / hành động chính",
   còn badge nghĩa là "có việc chưa làm". Mockup 1b cũng đánh dấu "2 mới" bằng hổ phách. */
.nav-badge { display: inline-block; min-width: 18px; text-align: center; background: var(--gold); color: var(--gold-on); border-radius: 999px; font-size: 11px; font-weight: 800; line-height: 18px; padding: 0 5px; margin-left: 4px; vertical-align: middle; }
.asub-q { display: inline-block; font-size: 12.5px; font-weight: 600; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--navy); color: var(--navy); background: #fff; cursor: pointer; }
.asub-q:hover { background: var(--navy); color: #fff; }
.asub-q-none { border-color: var(--g2); color: var(--g4); cursor: default; }
.asub-q-none:hover { background: #fff; color: var(--g4); }

/* ---- Layout ---- */
.view { max-width: 760px; margin: 0 auto; padding: 18px 16px 64px; }
.stack { display: flex; flex-direction: column; gap: 16px; }
.row { display: flex; gap: 10px; align-items: center; }
.spread { justify-content: space-between; }
.muted { color: var(--muted); }
.center { text-align: center; }
.small { font-size: 13px; }

/* ---- Cards ---- */
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shd); padding: 18px;
}
.card h2 { font-size: var(--fs-lg); }

/* ---- Buttons ---- */
.btn {
  appearance: none; cursor: pointer; border: 1px solid transparent;
  border-radius: var(--radius-md); padding: 11px 18px; font: inherit; font-weight: 700;
  background: var(--g1); color: var(--g8); transition: transform .04s ease, filter .15s ease, background .15s ease;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
/* Mint là màu SÁNG — chữ trắng lên nó không đọc được. Đây là cái bẫy số một của
   đợt đổi màu, nên nói thẳng ra ở đây thay vì để người sau tự vấp. */
.btn-primary { background: var(--pink); color: var(--mint-on); }
.btn-primary:hover:not(:disabled) { background: var(--mint-d); }
.btn-navy { background: var(--navy); color: #fff; }
.btn-navy:hover:not(:disabled) { background: var(--navy-l); }
.btn-ghost { background: transparent; border-color: rgba(255,255,255,.24); color: #fff; }
.btn-outline { background: #fff; border-color: var(--line); color: var(--g8); }
.btn-block { width: 100%; }
.btn-sm { padding: 8px 14px; font-size: var(--fs-sm); }
/* Mockup 2h ghi rõ: trên điện thoại nút bấm ≥ 48px. Ở khổ desktop nút 1b cố ý mảnh
   (40–46px), nên nâng sàn Ở ĐÂY chứ không nâng toàn cục. */
@media (max-width: 719px) { .btn:not(.btn-sm) { min-height: 48px; } }
.btn-danger { background: var(--red); color: #fff; }
.btn-danger:hover:not(:disabled) { filter: brightness(.94); }
/* Text/link-style button (no chrome) — replaces inline-styled fake links. */
.btn-link { appearance: none; background: none; border: 0; padding: 6px 4px; min-height: 44px; font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-sb); color: var(--navy); text-decoration: underline; cursor: pointer; }
.btn-link:hover { color: var(--pink-d); }
/* Row of buttons that share the width equally (retry/next, activate/reject, …). */
.actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.actions > .btn { flex: 1; }

/* ---- Reusable pieces ---- */
.card-title { font-family: var(--font-head); font-weight: var(--fw-b); color: var(--navy); }
.page-title { margin: 0 0 2px; }
.stat-tile { flex: 1; min-width: 88px; text-align: center; }
.stat-tile .n { font-family: var(--font-head); font-size: var(--fs-2xl); font-weight: var(--fw-xb); line-height: 1.1; }
.stat-tile .l { font-size: var(--fs-sm); color: var(--muted); margin-top: 2px; }
.media-w100 { width: 100%; }
.delta-up { color: var(--green); font-weight: var(--fw-b); }
.delta-down { color: var(--red); font-weight: var(--fw-b); }

/* ---- Empty state (icon + message + optional CTA) ---- */
.empty { text-align: center; padding: 28px 16px; }
.empty .ico { font-size: 34px; line-height: 1; margin-bottom: 8px; }
.empty .msg { color: var(--muted); margin: 0 0 14px; }
.empty .msg:last-child { margin-bottom: 0; }

/* ---- Forms ---- */
label.fld { display: block; font-weight: 600; font-size: 14px; margin-bottom: 6px; color: var(--g7); }
.input {
  width: 100%; padding: 13px 14px; font: inherit; color: var(--text);
  background: #fff; border: 1px solid var(--g2); border-radius: var(--radius-sm);
}
.input:focus { outline: none; border-color: var(--pink-d); box-shadow: 0 0 0 3px rgba(0,168,124,.15); }
textarea.input { min-height: 120px; resize: vertical; line-height: 1.6; }

/* ---- Auth ---- */
.auth-wrap { min-height: calc(100vh - 40px); min-height: calc(100dvh - 40px); display: grid; place-items: center; padding: 24px 16px; }
.auth-card { width: 100%; max-width: 420px; }
.auth-card { padding: 26px 22px; }
.auth-logo { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-bottom: 14px; }
.auth-logo img { width: 56px; height: 56px; }
.auth-logo h1 { font-size: var(--fs-2xl); }
/* Dấu hiệu Speak88 TỰ NÓ đã là một ô bo góc màu mint. Bọc nó trong một ô tối nữa thì
   ra hai lớp ô lồng nhau — nên ở đây chỉ phóng to chính nó, không thêm khung. */
.auth-logo-badge { width: 72px; height: 72px; display: grid; place-items: center; }
.auth-logo-badge img { width: 72px; height: 72px; border-radius: 20px; }
.tabs { display: flex; background: var(--g1); border-radius: 999px; padding: 4px; margin-bottom: 18px; }
.tabs button { flex: 1; border: 0; background: transparent; padding: 10px; border-radius: 999px; font-weight: 700; color: var(--g6); cursor: pointer; min-height: 44px; }
.tabs button.active { background: #fff; color: var(--navy); box-shadow: var(--shd); }

/* ---- Unit / question list ---- */
.hero { background: linear-gradient(135deg, var(--navy), var(--navy-m)); color: #fff; border-radius: var(--radius); padding: var(--sp-5); box-shadow: var(--shd-l); }
.hero h1 { font-size: var(--fs-2xl); }
.hero p { margin: 0; color: #c9d0e8; }
.hero-sub { margin-top: 6px; color: #c9d0e8; font-size: var(--fs-base); }

.section-head { display: flex; align-items: baseline; gap: 10px; margin: 2px 2px 8px; }
.section-head h2 { margin: 0; }
.section-count { font-size: var(--fs-sm); font-weight: var(--fw-sb); color: var(--muted); }
/* 1b là BẢNG, không phải một chồng thẻ: các hàng dính nhau, ngăn bằng kẻ tóc, cả
   khối nằm trong đúng một đường viền. Nên gap về 0 và viền chuyển lên .qlist. */
.qlist { display: flex; flex-direction: column; gap: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.qlist:empty { display: none; }
.qtopic { font-family: var(--font-head); font-weight: 700; color: var(--navy); margin: 0; padding: 9px 14px; font-size: var(--fs-sm); letter-spacing: .04em; text-transform: uppercase; background: var(--bg); border-bottom: 1px solid var(--line); }
.qtopic:first-child { margin-top: 0; }

/* ---- Part 1 topic accordion ---- */
.topic-acc { border: 0; border-bottom: 1px solid var(--line); background: #fff; overflow: hidden; }
.topic-acc:last-child { border-bottom: 0; }
.topic-acc > summary { list-style: none; cursor: pointer; padding: 14px 16px; display: flex; align-items: center; gap: 10px; font-family: var(--font-head); font-weight: 700; color: var(--navy); }
.topic-acc > summary::-webkit-details-marker { display: none; }
.topic-acc > summary::after { content: "⌄"; color: var(--g4); font-weight: 800; }
.topic-acc[open] > summary::after { content: "⌃"; }
.topic-acc[open] > summary { border-bottom: 1px solid var(--line); }
.topic-acc .tp-name { flex: 1; }
.topic-acc .tp-meta { font-family: var(--font); font-size: 12px; color: var(--muted); font-weight: 600; }
.topic-acc .qlist { border: 0; border-radius: 0; }

/* ---- Toolbar: search + filter chips ---- */
.toolbar { display: flex; flex-direction: column; gap: 10px; }
.search-wrap { position: relative; flex: 1; }
.search-ico { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); opacity: .5; font-size: 15px; pointer-events: none; }
.input.search { padding-left: 40px; border-radius: var(--radius-md); }
.fchips { display: flex; gap: 8px; flex-wrap: wrap; }
.fchip { border: 1px solid var(--line); background: #fff; color: var(--g7); border-radius: 999px; padding: 7px 15px; font: inherit; font-weight: 600; font-size: var(--fs-sm); cursor: pointer; min-height: 44px; }
.fchip.active { background: var(--navy); color: #fff; border-color: var(--navy); }
@media (min-width: 560px) { .toolbar { flex-direction: row; align-items: center; } }

/* ---- Unit-card progress ---- */
.ubar { height: 6px; background: var(--g1); border-radius: 999px; overflow: hidden; margin-top: 8px; }
.ubar > i { display: block; height: 100%; background: var(--pink); }

/* ---- Prominent audio replay ---- */
.play-card audio { width: 100%; margin-top: 4px; }
.qitem {
  display: grid; grid-template-columns: 34px minmax(0, 1fr) 74px 62px; align-items: center;
  gap: 12px; text-align: left; width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--hair);
  padding: 11px 14px; cursor: pointer; font: inherit; font-size: var(--fs-base);
}
.qitem:last-child { border-bottom: 0; }
.qnum { color: var(--label); font-weight: 700; font-size: var(--fs-sm); }
.qitem .qtxt { min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.qitem .qdone { font-weight: 700; font-size: var(--fs-sm); color: var(--navy); }
.qitem .qdone.qdone-none { color: var(--faint); }
.qitem .qdone.qfree { color: var(--gold-fg); }   /* transcript-only (Free) — hổ phách, khác hẳn bài đã chấm */
.qitem .s8-go { background: var(--g1); color: var(--navy); }
.qitem:hover .s8-go { background: var(--navy); color: #fff; }
.qitem .chev { color: var(--g3); }
@media (max-width: 520px) {
  /* 74px + 62px + hai khoảng gap ăn mất nửa chiều ngang của một máy 375px, mà câu hỏi
     mới là thứ phải đọc được. Bỏ nút "Nói" — bấm cả hàng vẫn vào đúng chỗ đó. */
  .qitem { grid-template-columns: 26px minmax(0, 1fr) 58px; gap: 8px; padding: 11px 10px; }
  .qitem .s8-go { display: none; }
}

/* ---- Recorder ---- */
.rec-stage { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 10px 0 4px; }
/* Duel: the question stays sealed until the mic is live (js/views/practice.js) */
.q-sealed { color: var(--g4); font-weight: 700; }
.duel-prep { width: 84px; height: 84px; border-radius: 50%; display: grid; place-items: center; font-family: var(--font-head); font-size: 40px; font-weight: 800; color: var(--mint-on); background: var(--pink); box-shadow: var(--shd-pink); }
.mic-btn {
  width: 108px; height: 108px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--pink); color: var(--mint-on); box-shadow: 0 10px 24px rgba(0,229,160,.35);
  display: grid; place-items: center; transition: transform .1s ease, background .2s ease;
}
.mic-btn svg { width: 46px; height: 46px; }
.mic-btn:active { transform: scale(.96); }
.mic-btn.is-recording { background: var(--red); animation: pulse 1.4s infinite; }
.mic-btn:disabled { background: var(--g3); box-shadow: none; cursor: progress; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(239,68,68,.45);} 70% { box-shadow: 0 0 0 20px rgba(239,68,68,0);} 100% { box-shadow: 0 0 0 0 rgba(239,68,68,0);} }
.rec-timer { font-family: var(--font-head); font-weight: 700; font-size: 30px; font-variant-numeric: tabular-nums; color: var(--navy); }
.rec-hint { color: var(--muted); font-size: 14px; }

.progress { width: 100%; height: 10px; background: var(--g1); border-radius: 999px; overflow: hidden; }
.progress > i { display: block; height: 100%; background: var(--pink); width: 0%; transition: width .2s ease; }

/* ---- Result ---- */
.score-hero { display: flex; align-items: center; gap: 18px; }
.score-ring {
  --v: 0; flex: 0 0 108px; width: 108px; height: 108px; border-radius: 50%;
  background: conic-gradient(var(--pink) calc(var(--v) * 1%), var(--track) 0);
  display: grid; place-items: center;
}
.score-ring > span { width: 84px; height: 84px; border-radius: 50%; background: #fff; display: grid; place-items: center; font-family: var(--font-head); font-weight: 800; font-size: var(--fs-3xl); color: var(--navy); }
.score-praise { font-family: var(--font-head); font-weight: 800; font-size: var(--fs-lg); color: var(--pink-d); margin: 2px 0 4px; }
.cefr-badge { display: inline-block; background: var(--navy); color: #fff; font-weight: 800; font-family: var(--font-head); padding: 4px 12px; border-radius: 999px; letter-spacing: .5px; }

.crit { display: flex; flex-direction: column; gap: 14px; }
.crit-row .crit-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 5px; }
.crit-row .crit-name { font-weight: 700; }
.crit-row .crit-score { font-family: var(--font-head); font-weight: 700; color: var(--pink-d); }
.bar { height: 6px; background: var(--track); border-radius: 999px; overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--pink); }
.crit-fb { margin-top: 6px; font-size: 14px; }
.crit-fb .vi { color: var(--muted); }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { background: var(--g1); border-radius: 999px; padding: 6px 12px; font-size: 13px; font-weight: 600; color: var(--g7); }
.chip b { color: var(--navy); }

.pill-tip { background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px; }

/* ---- Annotated transcript + corrections ---- */
.shadow-text { background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; line-height: 1.7; font-size: 15.5px; }
.btn.rec-on { background: #e5484d; border-color: #e5484d; color: #fff; animation: recpulse 1.1s ease-in-out infinite; }
@keyframes recpulse { 0%,100% { box-shadow: 0 0 0 0 rgba(229,72,77,.45); } 50% { box-shadow: 0 0 0 6px rgba(229,72,77,0); } }
.annot-text { line-height: 2.1; font-size: 15.5px; }
.annot-text del.corr-del { text-decoration: line-through; opacity: .55; }   /* removed span in the corrected answer */
/* `mark:where(.hl)` chứ KHÔNG phải `mark.hl`: :where() có độ đặc hiệu 0, nên luật này
   chỉ nặng bằng một tên thẻ (0,0,1) và bốn luật .hl-* bên dưới (0,1,0) mới thắng được nó.
   Viết `mark.hl` là (0,1,1) — nó đè cả `background` lẫn `border-color` của .hl-*, và bản
   ghi tô lỗi hiện ra KHÔNG MÀU: nền trong suốt, gạch chân đen. Lỗi này có từ trước đợt
   đổi giao diện; chỉ những ô vuông chú giải (dùng thẻ <i>, không dính luật này) là có màu,
   nên nhìn thoáng qua trông vẫn như đang chạy. */
mark:where(.hl) { padding: 1px 3px; border-radius: 4px; border-bottom: 2px solid; background: transparent; cursor: help; }
.hl-grammar { background: var(--hl-gram); border-color: #d99a1f; }
.hl-lexical { background: var(--hl-vocab); border-color: var(--pink-d); }
.hl-collocation { background: var(--hl-rep); border-color: #8a7ec4; }
.hl-discourse { background: #e4eefc; border-color: #5b7fc4; }
.legend { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }
.legend span { font-size: 12px; color: var(--g6); display: inline-flex; align-items: center; gap: 6px; }
.legend i { width: 16px; height: 9px; border-radius: 3px; display: inline-block; border-bottom-width: 2px; border-bottom-style: solid; }
.corr-list { margin-top: 14px; }
.corr { padding: 12px 0; border-bottom: 1px solid var(--line); }
.corr:last-child { border-bottom: 0; }
.corr-cat { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .3px; padding: 2px 9px; border-radius: 999px; margin-right: 8px; }
.cat-grammar { background: #fdecef; color: var(--red); }
.cat-lexical { background: #fff5e6; color: #b26a00; }
.cat-collocation { background: #f3f0ff; color: #6a3fe0; }
.cat-discourse { background: #e8f0ff; color: var(--indigo); }
.corr-old { text-decoration: line-through; color: var(--g5); }
.corr-arrow { color: var(--g4); margin: 0 2px; }
.corr-new { color: #0a8f5b; font-weight: 700; }
.callout { border-left: 4px solid var(--amber); background: #fffbeb; padding: 10px 14px; border-radius: 8px; font-size: 14px; }
.sample { background: var(--navy); color: #eef1fb; border-radius: var(--radius-sm); padding: 14px 16px; }
.sample .en { font-weight: 500; }

/* ---- Upgraded answer: color-coded grammar/collocation/phrasal/idiom/vocab/linker ---- */
.up-text { line-height: 2.15; font-size: 15.5px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px 16px; }
/* base mark: no background here so the per-type tint (lower specificity) still applies */
mark.up { padding: 1px 4px; border-radius: 4px; border-bottom-width: 2px; border-bottom-style: solid; color: inherit; cursor: help; }
.up-grammar { background: var(--hl-gram); border-color: #d99a1f; }
.up-collocation { background: var(--hl-rep); border-color: #8a7ec4; }
.up-phrasal { background: var(--hl-vocab); border-color: var(--pink-d); }
.up-idiom { background: #e4eefc; border-color: #5b7fc4; }
.up-vocab { background: var(--mint-bg); border-color: var(--mint-fg); }
.up-linker { background: var(--hl-rep); border-color: #6f63b0; }
.up-notes { margin-top: 14px; }
.up-note { padding: 10px 0; border-bottom: 1px solid var(--line); }
.up-note:last-child { border-bottom: 0; }
.up-badge { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .3px; padding: 2px 9px; border-radius: 999px; margin-right: 8px; white-space: nowrap; }
.up-phrase { font-weight: 700; color: var(--navy); }
.up-mean { color: var(--g6); }
.up-badge.up-grammar { color: var(--gold-fg); }
.up-badge.up-collocation { color: #6f63b0; }
.up-badge.up-phrasal { color: var(--mint-fg); }
.up-badge.up-idiom { color: #3f5f96; }
.up-badge.up-vocab { color: var(--mint-fg); }
.up-badge.up-linker { color: #6f63b0; }

/* ---- Idea Bank ---- */
.ib-topic { text-align: left; }
.ib-topic-ic { flex: 0 0 40px; height: 40px; border-radius: 12px; background: #fdeaf4; display: grid; place-items: center; font-size: 20px; }
.tabs.ib-tabs button { font-size: 13.5px; padding: 8px 6px; }
.ib-read { line-height: 2.2; }
mark.ib-hi { cursor: pointer; }
mark.ib-hi:hover, mark.ib-hi-active { box-shadow: 0 0 0 2px rgba(36,27,74,.14); }

/* tap-to-explain toolbox (fixed popover desktop / bottom-sheet mobile) */
.ib-pop { position: fixed; z-index: 60; width: 320px; max-width: calc(100vw - 24px); background: #fff; border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shd-l); padding: 14px; }
.ib-pop-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.ib-pop-phrase { font-weight: 700; color: var(--navy); flex: 1; }
.ib-pop-x { margin-left: auto; border: 0; background: var(--g1); width: 26px; height: 26px; border-radius: 999px; cursor: pointer; color: var(--g7); font-size: 12px; flex: 0 0 auto; }
.ib-pop-en { color: var(--g8); }
.ib-pop-vi { margin-top: 6px; }
.ib-pop-note { margin-top: 6px; font-size: 13px; color: var(--g6); }
.ib-pop-ex { margin-top: 8px; font-size: 13.5px; color: var(--g7); font-style: italic; border-top: 1px dashed var(--line); padding-top: 8px; }
.ib-pop-exlabel { font-style: normal; font-weight: 800; font-size: 10px; text-transform: uppercase; letter-spacing: .3px; color: var(--pink-d); margin-right: 6px; }
.ib-sheet-backdrop { position: fixed; inset: 0; background: rgba(36,27,74,.35); z-index: 55; }
.ib-pop-sheet { left: 0; right: 0; bottom: 0; top: auto; width: 100%; max-width: 100%; border-radius: 18px 18px 0 0; padding: 18px 18px calc(18px + env(safe-area-inset-bottom)); }

/* type-in gap-fill exercise */
.ib-ex-item { padding: 10px 0; border-bottom: 1px solid var(--line); }
.ib-ex-item:last-child { border-bottom: 0; }
.ib-ex-prompt { line-height: 2.1; }
.ib-gap { display: inline-block; width: 170px; max-width: 100%; padding: 6px 10px; margin: 2px; vertical-align: baseline; }
.ib-gap.ok { border-color: var(--green); background: #ecfdf5; }
.ib-gap.bad { border-color: var(--red); background: #fef2f2; }
.ib-ex-hint { margin-top: 3px; }
.ib-ex-fb { margin-top: 4px; color: var(--red); }
.ib-ex-fb b { color: #0a8f5b; }
.ib-score { margin-top: 12px; font-weight: 600; }
.ib-score-all { color: #0a8f5b; }
.ib-prev { color: var(--g6); font-weight: 600; }
.ib-done { color: var(--green); font-weight: 800; }

/* ---- History ---- */
.hitem { display: flex; align-items: center; gap: 12px; padding: 12px 4px; border-bottom: 1px solid var(--line); cursor: pointer; }
.hitem:last-child { border-bottom: 0; }
.hscore { flex: 0 0 46px; height: 46px; border-radius: 12px; background: var(--navy); color: #fff; display: grid; place-items: center; font-family: var(--font-head); font-weight: 800; }
.hscore.hfree { background: #fff7e6; color: #b8860b; border: 1px solid #e0b000; font-size: 12px; font-weight: 700; } /* transcript-only (Free) attempt */
.hmeta { flex: 1; min-width: 0; }
.hmeta .q { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hmeta .d { color: var(--muted); font-size: 13px; }
.lb-me { background: #eef4ff; border-radius: 10px; } /* highlight the current user's leaderboard row */
/* (079) Hàng của supervip đang tự ẩn. Chỉ quản trị viên mới nhận được hàng này từ
   leaderboard(), nên tô mờ là để PHÂN BIỆT với hàng thật, không phải để che. */
.lb-hidden { opacity: .55; }
/* ---- Leaderboard rows: avatar + class chip + badges ---- */
.lb-av { flex: 0 0 40px; width: 40px; height: 40px; border-radius: 50%; object-fit: cover; background: var(--g2); }
.lb-ini { display: grid; place-items: center; font-family: var(--font-head); font-weight: 800; color: #fff; background: var(--navy); font-size: 15px; }
.lb-class { display: inline-block; font-size: 11px; font-weight: 700; color: var(--navy); background: var(--g2); border-radius: 999px; padding: 1px 8px; vertical-align: middle; }
/* showcase row on a leaderboard entry (chosen badges + titles) */
.lb-show { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 4px; }
.lb-chip { font-size: 12px; line-height: 1.4; cursor: pointer; user-select: none; }
.lb-badge { display: inline-block; }
.lb-title, .pf-title { display: inline-block; font-size: 11px; font-weight: 800; color: #7a5c00; background: linear-gradient(180deg,#fff6d6,#ffe9a8); border: 1px solid #e0b000; border-radius: 999px; padding: 1px 8px; }
.pf-title { font-size: 13px; padding: 3px 10px; }
/* showcase chooser on the profile page */
.pf-choose { display: flex; flex-wrap: wrap; gap: 6px; }
.chip-toggle { font-size: 13px; font-weight: 600; background: var(--g2); color: var(--g6); border: 1px solid var(--line); border-radius: 999px; padding: 4px 10px; cursor: pointer; opacity: .55; }
.chip-toggle.on { opacity: 1; background: #eef4ff; border-color: var(--navy); color: var(--navy); }
/* tap/hover tooltip bubble */
.tip { position: absolute; z-index: 60; max-width: 240px; background: var(--g9); color: #fff; font-size: 12px; font-weight: 600; line-height: 1.35; padding: 6px 10px; border-radius: 8px; box-shadow: var(--shd-l); pointer-events: none; }
.tip[hidden] { display: none; }
/* ---- Profile page (#/account) ---- */
.pf-head { display: flex; gap: 14px; align-items: center; margin-top: 8px; }
/* Mockup 2f dùng ô VUÔNG bo góc 76px cho ảnh đại diện ở trang hồ sơ, không phải hình
   tròn — hình tròn 40px vẫn giữ ở bảng xếp hạng (.lb-av), hai chỗ hai vai trò khác nhau. */
.pf-av-box { flex: 0 0 76px; }
.pf-av { width: 76px; height: 76px; border-radius: 16px; object-fit: cover; background: var(--g2); }
.pf-av.pf-ini { display: grid; place-items: center; font-family: var(--font-head); font-weight: 800; color: var(--pink); background: var(--navy); font-size: 27px; }
.pf-name { margin: 0; font-weight: 800; font-size: var(--fs-2xl); letter-spacing: -.02em; }
.pf-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.pbadge { font-size: 13px; font-weight: 600; background: var(--g2); border-radius: 999px; padding: 3px 10px; }

/* ---- Toast ---- */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%) translateY(20px);
  background: var(--g9); color: #fff; padding: 12px 18px; border-radius: 999px;
  box-shadow: var(--shd-l); opacity: 0; pointer-events: none; transition: all .25s ease;
  max-width: 90vw; text-align: center; font-weight: 600; z-index: 50;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.err { background: var(--red); }
.toast.ok { background: var(--green); }

/* ---- Spinner ---- */
.spinner { width: 22px; height: 22px; border: 3px solid rgba(255,255,255,.4); border-top-color: #fff; border-radius: 50%; animation: spin .8s linear infinite; }
.spinner.dark { border-color: var(--g2); border-top-color: var(--pink); }
@keyframes spin { to { transform: rotate(360deg); } }

.loading-full { min-height: 60vh; min-height: 60dvh; display: grid; place-items: center; }

/* ---- Steps indicator ---- */
.steps { display: flex; gap: 6px; margin: 4px 0 2px; }
.steps > i { flex: 1; height: 5px; border-radius: 999px; background: var(--g1); }
.steps > i.on { background: var(--pink); }

@media (min-width: 620px) {
  .view { padding-top: 24px; }
  .hero h1 { font-size: var(--fs-3xl); }
}

/* ==========================================================================
   Speak88 1b — vỏ trang rộng, thanh bên, hàng danh sách dày, lưới game
   Dùng bởi #/units (trang chủ), #/unit/:id, #/games.

   Chiều sâu ở hệ này đến từ KẺ 1px và nền, gần như không có bóng — nên đừng
   thêm box-shadow vào các thẻ, nó sẽ lạc khỏi cả hệ ngay lập tức.

   Thanh bên trái CHỈ có ở trang chủ, không phải một phần của vỏ app: mockup
   dựng nó ở màn 1b và 2b, còn 2a/2c/2d/2e/2f đều chạy hết chiều ngang.
   ========================================================================== */
.view-wide { max-width: 1360px; padding: 0 0 64px; }
.s8-shell { display: grid; grid-template-columns: 196px minmax(0, 1fr) 292px; align-items: start; min-height: 60vh; }

/* ---- thanh bên trái 196px ---- */
.s8-rail { position: sticky; top: 58px; align-self: stretch; padding: 16px 12px; background: var(--card); border-right: 1px solid var(--line); display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.s8-rail-lb { font-size: 11px; letter-spacing: .1em; font-weight: 800; color: var(--label); padding: 0 8px 8px; }
.s8-rail-sec { min-width: 0; display: flex; flex-direction: column; }
.s8-rail-item { display: flex; align-items: center; gap: 8px; justify-content: space-between; padding: 8px 9px; border: 0; background: none; border-radius: 7px; font: inherit; font-size: var(--fs-base); font-weight: 600; color: var(--g7); text-align: left; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.s8-rail-item:hover { background: var(--bg); }
.s8-rail-item.active { background: var(--g1); color: var(--navy); }
.s8-rail-item b { font-weight: 600; color: var(--label); flex: 0 0 auto; }
.s8-rail-item b.hot { color: var(--gold-fg); font-weight: 700; }
.s8-rail-chips { display: flex; flex-wrap: wrap; gap: 5px; padding: 0 4px; }
.s8-rail-chips .fchip { padding: 5px 9px; border-radius: var(--radius-sm); font-size: var(--fs-sm); font-weight: 600; }
.s8-rail-note { margin-top: auto; padding: 13px; border-radius: 10px; background: var(--g1); font-size: var(--fs-sm); color: var(--g7); line-height: 1.5; }
.s8-rail-note b { display: block; font-size: var(--fs-base); color: var(--navy); margin-bottom: 4px; }

/* ---- cột giữa ---- */
.s8-main { min-width: 0; padding: 16px 18px 34px; display: flex; flex-direction: column; gap: 20px; }
.s8-sec { min-width: 0; }
.s8-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding-bottom: 10px; border-bottom: 1px solid var(--line); margin-bottom: 10px; }
.s8-sec-head h2 { margin: 0; font-size: var(--fs-lg); font-weight: 800; }
.s8-more { appearance: none; border: 0; background: none; font: inherit; font-size: var(--fs-sm); font-weight: 700; color: var(--pink-d); cursor: pointer; padding: 4px 2px; }
.s8-more:hover { color: var(--mint-d); }

/* ---- hero ---- */
.s8-hero-row { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 12px; }
.s8-hero { position: relative; min-width: 0; min-height: 246px; overflow: hidden; border-radius: var(--radius); padding: 26px 28px; color: #fff; display: flex; flex-direction: column; justify-content: flex-end; background: linear-gradient(135deg, var(--navy-l) 0%, var(--navy) 60%); }
.s8-hero-tag { position: absolute; top: 16px; left: 28px; padding: 4px 9px; border-radius: 5px; background: var(--gold); color: var(--gold-on); font-size: var(--fs-xs); font-weight: 800; letter-spacing: .05em; }
.s8-hero-emoji { position: absolute; top: 26px; right: 28px; font-size: 64px; opacity: .3; pointer-events: none; }
.s8-hero h1 { margin: 0 0 8px; font-size: clamp(24px, 2.6vw, var(--fs-4xl)); line-height: 1.08; font-weight: 800; max-width: 19ch; overflow-wrap: anywhere; }
.s8-hero p { margin: 0 0 14px; font-size: var(--fs-md); color: var(--on-dark-2); max-width: 52ch; }
.s8-hero-cta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.s8-hero-side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.s8-feat { flex: 1; min-width: 0; display: flex; gap: 12px; align-items: flex-start; text-align: left; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); padding: 14px; font: inherit; cursor: pointer; }
.s8-feat:hover { border-color: var(--navy); }
/* `:first-child` chứ KHÔNG phải `> span`. Nút này có HAI span con: ô biểu tượng, rồi khối
   chữ (<b> + <small>). Luật cũ nhắm cả hai, nên khối chữ bị ép về 62×62: "Ngân hàng ý
   tưởng" xuống ba dòng trong một cột 62px, còn dòng mô tả tràn khỏi nút và đè lên mục
   ngay dưới. Đo ở khổ 375px: nút cao 92px trong khi nội dung cần 155px. */
.s8-feat > span:first-child { flex: 0 0 auto; display: grid; place-items: center; width: 62px; height: 62px; border-radius: 9px; font-size: 27px; }
/* min-width:0 là bắt buộc chứ không phải trang trí: thiếu nó thì một từ dài không ngắt
   được và ô flex phình rộng hơn nút. */
.s8-feat > span + span { flex: 1 1 auto; min-width: 0; }
.s8-feat b { display: block; font-size: var(--fs-md); color: var(--text); }
.s8-feat small { display: block; margin-top: 3px; font-size: var(--fs-sm); color: var(--muted); line-height: 1.45; }

/* ---- hàng danh sách dày ---- */
.s8-rows { display: flex; flex-direction: column; }
.s8-row { display: grid; grid-template-columns: 76px minmax(0, 1fr) 128px 78px 62px; align-items: center; gap: 14px; padding: 9px 10px; border: 0; border-radius: var(--radius-md); background: none; font: inherit; text-align: left; cursor: pointer; width: 100%; }
.s8-row:hover { background: var(--card); }
.s8-row-art { height: 46px; border-radius: var(--radius-sm); display: grid; place-items: center; font-size: 22px; }
.s8-row-copy { min-width: 0; }
.s8-row-copy > b { display: block; font-size: var(--fs-md); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-tags { display: flex; gap: 5px; margin-top: 5px; flex-wrap: wrap; }
.s8-tag { padding: 2px 7px; border-radius: 4px; background: var(--g1); font-size: var(--fs-xs); font-weight: 600; color: var(--g7); }
.s8-tag-gold { background: var(--gold-bg); color: var(--gold-fg); font-weight: 700; }
.s8-tag-mint { background: var(--mint-bg); color: var(--mint-fg); font-weight: 700; }
.s8-row-prog { font-size: var(--fs-sm); color: var(--muted); min-width: 0; }
.s8-mini-bar { height: 5px; margin-top: 5px; border-radius: 3px; background: var(--track); overflow: hidden; }
.s8-mini-bar > i { display: block; height: 100%; background: var(--pink); }
.s8-row-best { font-size: var(--fs-sm); color: var(--muted); }
.s8-row-best b { display: block; color: var(--navy); font-size: var(--fs-md); }
.s8-go { justify-self: end; padding: 6px 11px; border-radius: var(--radius-sm); background: var(--navy); color: #fff; font-size: var(--fs-sm); font-weight: 700; white-space: nowrap; }

/* ---- lưới game (dùng chung trang chủ + #/games) ---- */
.s8-game-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.s8-game { min-width: 0; display: flex; flex-direction: column; text-align: left; border: 1px solid var(--line); border-radius: 10px; background: var(--card); overflow: hidden; padding: 0; font: inherit; cursor: pointer; }
.s8-game:hover { border-color: var(--navy); }
.s8-game-art { height: 84px; display: grid; place-items: center; font-size: 32px; }
.s8-game-copy { padding: 10px 11px 12px; min-width: 0; }
.s8-game-copy b { display: block; font-size: var(--fs-base); color: var(--text); }
.s8-game-copy small { display: block; margin-top: 2px; font-size: var(--fs-sm); color: var(--muted); }

/* ---- thanh bên phải 292px ---- */
.s8-side { position: sticky; top: 58px; align-self: stretch; padding: 16px 16px 34px; background: var(--card); border-left: 1px solid var(--line); display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.s8-side-sec { min-width: 0; }
.s8-side-sec + .s8-side-sec { padding-top: 16px; border-top: 1px solid var(--line); }
.s8-side-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.s8-side-head b { font-family: var(--font-head); font-size: 15px; font-weight: 800; }
.s8-side-head span { font-size: var(--fs-sm); color: var(--label); }
.s8-lb-row { display: flex; align-items: center; gap: 9px; padding: 7px 8px; border-radius: 7px; font-size: var(--fs-base); }
.s8-lb-row > b:first-child { width: 16px; color: var(--label); flex: 0 0 auto; }
.s8-lb-row > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-lb-1 { background: var(--gold-bg); }
.s8-lb-1 > b:first-child { color: var(--gold-fg); }
.s8-lb-me { background: var(--mint-bg); }
.s8-lb-me > b:first-child { color: var(--pink-d); }
.s8-band-card { padding: 14px; border-radius: 10px; background: var(--navy); color: #fff; }
.s8-band-card > b { display: block; font-size: var(--fs-md); margin-bottom: 8px; }
.s8-band-track { height: 6px; border-radius: 3px; background: rgba(255,255,255,.16); overflow: hidden; }
.s8-band-track > i { display: block; height: 100%; background: var(--pink); }
.s8-band-card small { display: block; margin-top: 8px; font-size: var(--fs-sm); color: var(--on-dark); }

/* ---- nhiệm vụ trong rail phải ---- */
.s8-quest { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: var(--fs-sm); min-width: 0; }
.s8-quest > span:first-child { flex: 0 0 14px; color: var(--label); }
.s8-quest.done > span:first-child { color: var(--pink-d); }
.s8-quest > span:nth-child(2) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-quest.done > span:nth-child(2) { color: var(--muted); text-decoration: line-through; }
.s8-quest > b { flex: 0 0 auto; color: var(--label); }
.s8-quest.done > b { color: var(--text); }
.s8-chest { margin-top: 12px; padding: 10px 12px; border-radius: var(--radius-md); background: var(--g1); font-size: var(--fs-sm); color: var(--g7); }
.s8-chest .btn { width: 100%; }
.s8-stamps { letter-spacing: 4px; color: var(--faint); }
.s8-stamps .on { color: var(--pink-d); }

/* ---- trang đơn giản (#/games) ---- */
.s8-page { max-width: 1000px; margin: 0 auto; padding: 22px 18px 40px; display: flex; flex-direction: column; gap: 16px; }
.s8-page-head h1 { margin: 0 0 3px; font-size: var(--fs-2xl); font-weight: 800; }
.s8-page-head p { margin: 0; font-size: var(--fs-base); color: var(--muted); }
.s8-note { margin: 0; font-size: var(--fs-sm); color: var(--muted); }

/* ---- co giãn ---- */
@media (max-width: 1179px) {
  /* Rail trái biến mất chứ không co lại: mọi mục trong nó đều đã có đường vào thứ hai
     (nav trên hoặc sheet ☰), nên co lại chỉ tạo một cột hẹp khó bấm mà không thêm gì. */
  .s8-shell { grid-template-columns: minmax(0, 1fr) 292px; }
  .s8-rail { display: none; }
}
@media (max-width: 1023px) {
  .s8-hero-row { grid-template-columns: minmax(0, 1fr); }
  .s8-game-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 979px) {
  .s8-shell { grid-template-columns: minmax(0, 1fr); }
  .s8-side { position: static; border-left: 0; border-top: 1px solid var(--line); }
  .s8-main { padding: 14px 14px 24px; gap: 18px; }
}
@media (max-width: 719px) {
  .s8-game-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .s8-hero { min-height: 210px; padding: 22px 18px; }
  .s8-hero-emoji { font-size: 46px; top: 18px; right: 16px; }
  /* Hàng dày co về hai dòng: cột tiến độ tụt xuống trải ngang, bỏ cột điểm tốt nhất
     (số đó đã có trong màn chi tiết chủ đề — ở đây nó chỉ ăn chỗ của tên đề). */
  .s8-row { grid-template-columns: 56px minmax(0, 1fr) 58px; gap: 10px; padding: 9px 4px; }
  .s8-row-art { height: 40px; font-size: 19px; }
  .s8-row-best { display: none; }
  .s8-row-prog { grid-column: 2 / 4; }
  .s8-page { padding: 16px 14px 32px; }
}
@media (max-width: 419px) {
  .s8-game-grid { grid-template-columns: minmax(0, 1fr); }
  .s8-main { padding-inline: 10px; }
}

/* ==========================================================================
   Gamification: sao chủ đề · nhiệm vụ/rương · tiến bộ (band/spark/heatmap)
   ========================================================================== */

/* ---- Sao chủ đề (topic stars) ---- */
.tstar { font-size: 12px; letter-spacing: 1px; color: var(--amber); white-space: nowrap; vertical-align: 1px; }

/* ---- Nhiệm vụ hôm nay → rương ---- */
.quest-card { display: flex; flex-direction: column; gap: 10px; }
.quest-head { display: flex; align-items: center; gap: 8px; }
.quest-head h2 { margin: 0; flex: 1; }
.quest-pts { font-weight: var(--fw-xb); color: var(--indigo); font-size: var(--fs-sm); white-space: nowrap; }
.quest-list { display: flex; flex-direction: column; gap: 6px; }
.quest-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--radius-sm); background: var(--bg); border: 1px solid var(--line); }
.quest-item.done { background: #ecfdf5; border-color: #a7f3d0; }
.quest-item .q-ic { width: 20px; text-align: center; }
.quest-item .q-lb { flex: 1; font-size: var(--fs-sm); }
.quest-item.done .q-lb { color: var(--g6); }
.quest-item .q-prog { font-variant-numeric: tabular-nums; font-weight: var(--fw-b); color: var(--muted); font-size: var(--fs-xs); }
/* (065) Nhiệm vụ THƯỞNG — không tính vào con dấu ngày, nên phải nhìn ra là khác. Viền đứt
   là cách rẻ nhất để nói "cái này không bắt buộc" mà không cần thêm một dòng chữ. */
.quest-item.bonus { border-style: dashed; }
.quest-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.stamp-dots { display: flex; gap: 4px; font-size: 15px; line-height: 1; }
.stamp-dot { filter: grayscale(1) opacity(.4); }
.stamp-dot.on { filter: none; }
.quest-note { font-size: var(--fs-xs); color: var(--muted); }

/* ---- Hành trình Band ---- */
.band-road { display: flex; align-items: center; overflow-x: auto; padding: 8px 2px 4px; -webkit-overflow-scrolling: touch; }
.br-stop { display: flex; flex-direction: column; align-items: center; gap: 3px; flex: 0 0 auto; }
.br-dot { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 13px; background: var(--g1); color: var(--g4); border: 2px solid var(--g2); }
.br-band { font-size: 11px; font-weight: var(--fw-b); color: var(--muted); font-variant-numeric: tabular-nums; }
.br-stop.reached .br-dot { background: var(--pink); color: var(--mint-on); border-color: var(--pink); }
.br-stop.reached .br-band { color: var(--pink-d); }
.br-stop.target .br-dot { background: #fff; color: var(--amber); border-color: var(--amber); box-shadow: 0 0 0 3px rgba(245,158,11,.18); }
.br-stop.target.reached .br-dot { background: var(--amber); color: #fff; }
.br-link { flex: 1 0 14px; height: 3px; background: var(--g2); align-self: flex-start; margin: 12px -1px 0; border-radius: 2px; min-width: 14px; }

/* ---- Sparkline (xu hướng điểm) ---- */
.spark { width: 100%; height: 64px; display: block; }
.spark-line { stroke: var(--pink); stroke-width: 2.5; vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
.spark-fill { fill: rgba(0,229,160,.14); stroke: none; }
.spark-dot { fill: var(--pink); stroke: #fff; stroke-width: 2; }
.spark-ends { display: flex; justify-content: space-between; font-size: var(--fs-xs); color: var(--muted); margin-top: 4px; font-variant-numeric: tabular-nums; }

/* ---- 4 tiêu chí (premium detail / free teaser) ---- */
.crit-row { display: flex; align-items: center; gap: 10px; margin: 8px 0; }
.crit-lb { flex: 0 0 84px; font-size: var(--fs-sm); font-weight: var(--fw-sb); }
.crit-track { flex: 1; height: 8px; background: var(--g1); border-radius: 999px; overflow: hidden; }
.crit-track > i { display: block; height: 100%; border-radius: 999px; background: var(--pink); }
.crit-val { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: var(--fw-b); font-size: var(--fs-sm); }
.crit-val small { color: var(--muted); font-weight: var(--fw-md); }
.crit-hint { margin: 12px 0 0; font-size: var(--fs-sm); background: #fff7ed; border: 1px solid #fed7aa; padding: 8px 10px; border-radius: var(--radius-sm); }
.pro-tag { font-size: 10px; font-weight: var(--fw-xb); letter-spacing: .04em; color: var(--amber); border: 1px solid var(--amber); padding: 1px 6px; border-radius: 999px; vertical-align: 2px; }
.lock-wrap { position: relative; border-radius: var(--radius-sm); overflow: hidden; }
.lock-blur { filter: blur(5px); opacity: .6; pointer-events: none; padding: 4px 0; }
.lock-over { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; text-align: center; padding: 12px; background: rgba(255,255,255,.55); }
.lock-over .lock-ico { font-size: 22px; }
.lock-over p { margin: 0; font-size: var(--fs-sm); color: var(--g7); max-width: 34ch; }

/* ---- Điểm mạnh & điểm cần sửa (#/progress) ---- */
.sk-overview { margin: 0 0 14px; }
.sk-uplift { display: flex; gap: 10px; align-items: flex-start; background: #eef2ff; border: 1px solid #c7d2fe; padding: 10px 12px; border-radius: var(--radius-sm); font-size: var(--fs-sm); line-height: 1.55; }
.sk-uplift-ic { font-size: 16px; line-height: 1.35; flex: 0 0 auto; }
.sk-sec { font-size: var(--fs-sm); font-weight: var(--fw-xb); margin: 18px 0 8px; color: var(--g7); }
.sk { border: 1px solid var(--line); border-left-width: 4px; border-radius: var(--radius-sm); padding: 12px; margin: 10px 0; background: var(--bg); }
.sk-good { border-left-color: #10b981; }
.sk-bad { border-left-color: #f59e0b; }
.sk-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sk-ico { font-size: 16px; line-height: 1; }
.sk-name { font-weight: var(--fw-xb); font-size: var(--fs-sm); }
.sk-score { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: var(--fw-xb); font-size: var(--fs-sm); }
.sk-score small { color: var(--muted); font-weight: var(--fw-md); }
.sk-trend { font-size: var(--fs-xs); font-weight: var(--fw-b); padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
.sk-trend.up { background: #ecfdf5; color: #047857; }
.sk-trend.down { background: #fef2f2; color: #b91c1c; }
.sk-trend.flat { background: var(--g1); color: var(--muted); }
.sk-track { display: block; height: 8px; background: var(--g1); border-radius: 999px; overflow: hidden; margin: 10px 0 2px; }
.sk-track > i { display: block; height: 100%; border-radius: 999px; background: var(--pink); }
.sk-why { margin: 8px 0 0; font-size: var(--fs-sm); line-height: 1.6; color: var(--g7); }
.sk-trendnote { color: var(--muted); }
.sk-do { margin: 12px 0 5px; font-size: var(--fs-xs); font-weight: var(--fw-xb); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.sk-steps { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 7px; font-size: var(--fs-sm); line-height: 1.6; }
.sk-steps li::marker { font-weight: var(--fw-xb); color: var(--indigo); }
.sk-note { margin: 10px 0 0; font-size: var(--fs-sm); line-height: 1.6; padding: 9px 11px; border-radius: var(--radius-sm); border: 1px solid var(--line); }
.sk-note.ok { background: #ecfdf5; border-color: #a7f3d0; }
.sk-note.warn { background: #fff7ed; border-color: #fed7aa; }

/* ---- Heatmap lịch luyện ---- */
.hm-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; }
.hm-grid { display: flex; gap: 3px; width: max-content; }
.hm-col { display: flex; flex-direction: column; gap: 3px; }
.hm-cell { width: 13px; height: 13px; border-radius: 3px; background: var(--g1); flex: 0 0 auto; }
.hm-cell[data-lv="1"] { background: #b7e4c7; }
.hm-cell[data-lv="2"] { background: #74c69d; }
.hm-cell[data-lv="3"] { background: #40916c; }
.hm-cell[data-lv="4"] { background: #1b5e3f; }
.hm-cell[data-lv="x"] { background: transparent; }
.hm-legend { display: flex; align-items: center; gap: 4px; margin-top: 10px; font-size: var(--fs-xs); color: var(--muted); }
.hm-legend .hm-cell { width: 12px; height: 12px; }

/* super student-monitor (#/monitor) */
.mon-dist { display: flex; height: 14px; border-radius: 999px; overflow: hidden; background: var(--g1); }
.mon-dist span { display: block; min-width: 3px; }
.mon-legs { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; font-size: var(--fs-sm); color: var(--muted); }
.mon-leg { display: inline-flex; align-items: center; gap: 6px; }
.mon-leg i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.mon-leg b { color: var(--text); }
.mon-dot { flex: 0 0 11px; width: 11px; height: 11px; border-radius: 50%; }
.mon-row .mon-chev { flex: 0 0 auto; color: var(--g4); font-size: 22px; line-height: 1; }
.mon-row.open { background: #f5f8ff; }
.mon-detail { background: #f7f9fc; border-bottom: 1px solid var(--line); padding: 12px 8px; border-radius: 0 0 10px 10px; }
.mon-det-in { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 16px; }
.mon-det-h { font-size: var(--fs-xs); font-weight: 700; color: var(--muted); margin-bottom: 8px; text-transform: uppercase; letter-spacing: .03em; }
.mon-att-list { display: flex; flex-direction: column; gap: 3px; }
.mon-att { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 5px 7px; border-radius: 8px; cursor: pointer; text-decoration: none; color: inherit; }
.mon-att:hover { background: #eef2fb; }
.mon-att span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mon-att b { flex: 0 0 auto; font-weight: 700; }
.mon-att i { flex: 0 0 auto; color: var(--muted); font-style: normal; font-size: 12px; }

/* ==========================================================================
   "Phòng Xinh" room decorator (#/room). All rules scoped under .rm-root so the
   game's cozy palette + generic class names never leak into the rest of the app.
   The game's own CSS vars (--bg/--panel/--gold/…) are redeclared here and only
   cascade to .rm-root descendants. Full-bleed: negative margins cancel the .view
   padding; #rmApp is sized to the viewport minus the app chrome (avoids :has()).
   ========================================================================== */
.rm-root {
  --bg: #efe2c9; --panel: #fbf3e2; --panel2: #f5e8cf; --ink: #4a3a30; --line: #d8c4a2;
  --accent: #7cc4a6; --accent-d: #5aa588; --gold: #ffcf4d; --gold-d: #e6a92e; --blush: #f2b8c6;
  --shadow: 0 4px 0 rgba(120,90,60,.18);
  margin: -18px -16px -64px;                 /* cancel .view padding (18px top, 16px sides, 64px bottom) */
  color: var(--ink);
  font-family: system-ui, "Segoe UI", Roboto, sans-serif;
  -webkit-user-select: none; user-select: none;
}
.rm-root #rmApp {
  display: flex; flex-direction: column; max-width: 900px; margin: 0 auto;
  height: calc(100vh - 60px);                /* old-Safari fallback */
  height: calc(100dvh - 60px);               /* viewport minus the app top bar */
  overflow: hidden;
}
@media (max-width: 719px) {
  .rm-root { margin-bottom: calc(-72px - env(safe-area-inset-bottom)); } /* cancel .view's tab-bar padding */
  /* mobile: hằng số 124 (60 topbar + 64 tabbar) sai trên iPhone tai thỏ chạy standalone —
     đúng chế độ index.html:10,12 nhắm tới. Ở đó .topbar cộng env(safe-area-inset-top)
     và .tabbar cộng env(safe-area-inset-bottom), chrome thật thành 87+90=177 ⇒ #rmApp
     thừa 53px và đáy #rmShop chui sau thanh tab, không bấm được. Cộng thẳng hai inset
     vào thay vì đoán: máy không tai thỏ thì cả hai bằng 0 và con số về đúng như cũ. */
  .rm-root #rmApp { height: calc(100vh - 124px); }
  .rm-root #rmApp {
    height: calc(100dvh - 60px - 56px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  }
}

.rm-root #rmTopbar { display: flex; align-items: center; gap: 8px; padding: 8px 10px; }
.rm-root #rmCoins { display: flex; align-items: center; gap: 6px; background: var(--panel); border: 2px solid var(--line);
  border-radius: 14px; padding: 5px 12px; font-weight: 800; font-size: 17px; box-shadow: var(--shadow); }
.rm-root .rm-c { width: 16px; height: 16px; border-radius: 50%; flex: 0 0 auto;
  background: radial-gradient(circle at 35% 30%, #ffe89a, var(--gold) 60%, var(--gold-d)); border: 2px solid var(--gold-d); }
.rm-root #rmRoomname { flex: 1; text-align: center; font-weight: 800; font-size: 16px; opacity: .85; }
/* ---- 083: đồng hồ thu nhập nội thất, dán ở góc phòng ---- */
/* Góc DƯỚI PHẢI. Ba góc kia đã có chủ và cả ba đều là overlay nên không có gì đẩy nhau
   ra — chồng lên là chồng im: #rmNpc (nút Khách gõ cửa) giữ right/top 8px, .rm-pop-wrap
   (thẻ báo việc) trải hết dải trên từ left 8 tới right 60, .rm-pin-chip giữ left/bottom
   8px trên điện thoại. Bản đầu của 083 đặt chip ở trên phải và nuốt luôn nút Khách gõ
   cửa — một nút CÓ badge, tức là thứ sinh ra để được nhìn thấy.
   Overlay chứ không chiếm chỗ: thanh trên đã chật tới mức phải đẻ ra sheet ⋯, còn sân
   khấu trên điện thoại chỉ còn ~280px chiều cao. Cùng khuôn .rm-pin-chip. */
.rm-root .rm-idle {
  position: absolute; right: 8px; bottom: 8px; z-index: 4;
  padding: 5px 10px; border-radius: 999px;
  border: 2px solid var(--line); background: rgba(255, 253, 246, .92); color: var(--ink);
  font: inherit; font-size: 12px; font-weight: 800; white-space: nowrap; cursor: pointer;
  box-shadow: var(--shadow);
}
.rm-root .rm-idle.on { border-color: var(--gold-d); background: #fff6dd; }
.rm-root .rm-idle:active { transform: translateY(1px); box-shadow: none; }
/* Nhãn độ ấm trên thẻ hàng: món sắp đẩy xu/giờ lên một nấc thì nói to hơn. */
.rm-root .rm-card .rm-cozy { font-size: 9px; font-weight: 800; text-align: center; line-height: 1.15;
  margin-top: 2px; opacity: .72; }
.rm-root .rm-card .rm-cozy.up { opacity: 1; color: var(--gold-d); }
.rm-root .rm-top-actions { display: flex; gap: 6px; }
/* mobile: `flex: 0 0 auto` là BẮT BUỘC, không phải trang trí. Mặc định flex-shrink là 1,
   nên hàng nút (12 nút = 546px) nhét vào một hàng rộng 339px sẽ co từng nút xuống
   min-content ≈ 21px: emoji bị cắt, và .rm-badge ở right:-6px nhảy sang đè nút bên cạnh.
   Engine giấu bớt nút sau ⋯ trên điện thoại, nhưng 5 nút còn lại vẫn phải không-co khi
   tên phòng dài đẩy #rmMid ra. */
.rm-root .rm-tbtn { flex: 0 0 auto; }
.rm-root .rm-tbtn { width: 40px; height: 40px; border-radius: 12px; border: 2px solid var(--line); background: var(--panel);
  font-size: 18px; font-weight: 800; cursor: pointer; box-shadow: var(--shadow); display: grid; place-items: center; color: var(--ink); }
.rm-root .rm-tbtn:active { transform: translateY(2px); box-shadow: none; }
.rm-root #rmBtnLang { font-size: 14px; }

.rm-root #rmTabs { display: flex; gap: 6px; padding: 0 10px 8px; overflow-x: auto; }
.rm-root #rmTabs button { flex: 1 0 auto; white-space: nowrap; padding: 8px 12px; border-radius: 12px 12px 0 0;
  border: 2px solid var(--line); border-bottom: none; background: var(--panel2); font-weight: 800; font-size: 14px;
  cursor: pointer; color: var(--ink); opacity: .7; }
.rm-root #rmTabs button.on { background: var(--panel); opacity: 1; box-shadow: 0 -3px 0 var(--accent) inset; }

.rm-root #rmStage { flex: 1; min-height: 0; position: relative; margin: 0 10px; border-radius: 16px; overflow: hidden;
  border: 3px solid #cdae82; background: #e7cfa4; box-shadow: inset 0 3px 10px rgba(120,80,40,.15); touch-action: none; }
.rm-root #rmCanvas { display: block; width: 100%; height: 100%; touch-action: none; }
.rm-root .rm-mbtn { border: none; border-radius: 10px; padding: 7px 11px; font-size: 15px; font-weight: 800; cursor: pointer;
  background: #fff; color: var(--ink); }
.rm-root .rm-mbtn.go { background: var(--accent); color: #10352a; }
.rm-root .rm-mbtn.danger { background: #f0967f; color: #4a1a10; }

.rm-root #rmShop { padding: 8px 6px 10px; }
.rm-root #rmShopstrip { display: flex; gap: 8px; overflow-x: auto; padding: 2px 6px 6px; }
.rm-root .rm-card { flex: 0 0 auto; width: 78px; border: 2px solid var(--line); border-radius: 14px; background: var(--panel);
  padding: 5px; cursor: pointer; box-shadow: var(--shadow); position: relative; }
.rm-root .rm-card:active { transform: translateY(2px); box-shadow: none; }
.rm-root .rm-card canvas { width: 100%; height: 52px; display: block; image-rendering: pixelated; background: #f6ecd7; border-radius: 8px; }
.rm-root .rm-card .rm-nm { font-size: 10px; font-weight: 700; text-align: center; line-height: 1.1; margin-top: 3px; height: 22px; overflow: hidden; }
.rm-root .rm-card .rm-pr { display: flex; align-items: center; justify-content: center; gap: 3px; font-size: 11px; font-weight: 800; margin-top: 1px; }
.rm-root .rm-card .rm-pr .rm-c { width: 11px; height: 11px; border: 1px solid var(--gold-d); }
.rm-root .rm-card .rm-own { color: var(--accent-d); }
.rm-root .rm-group { border-style: dashed; }
.rm-root .rm-group .rm-gcount { font-size: 11px; font-weight: 800; color: var(--accent-d); }
.rm-root .rm-back { display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--panel2); }
.rm-root .rm-back .rm-backic { font-size: 28px; font-weight: 900; line-height: 1; color: var(--accent-d); height: 52px; display: flex; align-items: center; }
.rm-root .rm-parts { display: flex; gap: 6px; flex-wrap: wrap; margin: 4px 0 8px; }
.rm-root .rm-pbtn { border: 2px solid var(--line); background: var(--panel); border-radius: 10px; padding: 6px 12px; font: inherit; font-weight: 800; font-size: 13px; cursor: pointer; }
.rm-root .rm-pbtn.on { background: var(--accent); color: #fff; border-color: var(--accent-d); }
.rm-root .rm-duel-row { display: flex; align-items: center; gap: 6px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 13px; font-weight: 600; }
/* Tên + lớp + "vừa luyện lúc nào" không lọt một dòng trên điện thoại — cho xuống
   dòng thay vì cắt "…" (040, cùng lý do với .rm-raid-nm ở 032). */
.rm-root .rm-duel-row span { flex: 1; min-width: 0; white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }
.rm-root .rm-duel-inc { background: #fff7e6; border: 1px solid #e0b000; border-radius: 10px; padding: 6px 10px; margin: 4px 0 8px; }
.rm-root .rm-duel-out { font-size: 12px; color: var(--muted); margin: 2px 0 8px; }
/* 053: kết quả trận đã xong. Nhạt hơn khối "lời thách gửi bạn" (không cần hành động),
   nhưng hàng CHƯA XEM thì đánh dấu — đó là thứ người đi thách vào đây để tìm. */
.rm-root .rm-duel-rec { background: var(--bg2, #f6f7fb); border-radius: 10px; padding: 6px 10px; margin: 4px 0 8px; }
.rm-root .rm-duel-rec b { display: block; font-size: 13px; margin-bottom: 2px; }
.rm-root .rm-duel-rec .rm-duel-row:last-child { border-bottom: 0; }
.rm-root .rm-duel-row.rm-new { position: relative; padding-left: 10px; }
.rm-root .rm-duel-row.rm-new::before { content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 6px; height: 6px; border-radius: 50%; background: #e0492e; }
.rm-root .rm-chest-win { text-align: center; font-size: 18px; font-weight: 900; color: var(--accent-d); padding: 10px 0; }

.rm-root #rmModalWrap { position: fixed; inset: 0; background: rgba(60,45,35,.5); display: none; align-items: center; justify-content: center;
  padding: 18px; z-index: 60; }
.rm-root #rmModalWrap.on { display: flex; }
.rm-root #rmModal { width: 100%; max-width: 380px; max-height: 84%; overflow-y: auto; background: var(--panel); border: 3px solid var(--line);
  border-radius: 18px; padding: 16px; box-shadow: 0 10px 30px rgba(0,0,0,.3); }
.rm-root #rmModal h2 { margin: 0 0 10px; font-size: 19px; }
.rm-root .rm-task { display: flex; align-items: center; gap: 10px; padding: 8px; border: 2px solid var(--line); border-radius: 12px; margin-bottom: 7px; background: var(--panel2); }
.rm-root .rm-task.done { opacity: .8; }
.rm-root .rm-task .rm-box { width: 22px; height: 22px; border-radius: 6px; border: 2px solid var(--accent-d); flex: 0 0 auto; display: grid; place-items: center; font-weight: 900; color: var(--accent-d); }
.rm-root .rm-task.done .rm-box { background: var(--accent); color: #fff; }
.rm-root .rm-task .rm-tt { flex: 1; font-size: 13px; font-weight: 700; }
.rm-root .rm-task .rm-rw { font-size: 15px; font-weight: 800; color: var(--gold-d); white-space: nowrap; }
.rm-root #rmModal ul { padding-left: 18px; margin: 6px 0; }
.rm-root #rmModal li { font-size: 13px; margin-bottom: 6px; line-height: 1.35; }
.rm-root .rm-row { display: flex; gap: 8px; margin-top: 12px; }
.rm-root .rm-row .rm-mbtn { flex: 1; padding: 11px; }

/* ---- 024 idle/tycoon layer ---- */
.rm-root #rmMid { flex: 1; text-align: center; min-width: 0; }
.rm-root #rmStars { font-size: 13px; line-height: 1; letter-spacing: 1px; }
.rm-root #rmStars i { font-style: normal; color: #d8c4a2; }
.rm-root #rmStars i.on { color: var(--gold-d); }
.rm-root #rmStars .rm-gstar { font-size: 11px; }
.rm-root .rm-tbtn { position: relative; }
.rm-root .rm-badge { position: absolute; top: -6px; right: -6px; min-width: 17px; padding: 0 3px; border-radius: 999px;
  background: var(--gold); border: 2px solid var(--gold-d); color: #5a3d00; font-size: 10px; line-height: 14px; font-weight: 900; }
.rm-root .rm-shimmer { animation: rmShimmer 1.6s ease-in-out infinite; border-color: var(--gold-d); }
@keyframes rmShimmer {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,207,77,0), var(--shadow); }
  50% { box-shadow: 0 0 0 4px rgba(255,207,77,.45), var(--shadow); }
}
.rm-root .rm-prog { position: relative; height: 14px; margin-top: 3px; border-radius: 7px; background: var(--panel2);
  border: 1px solid var(--line); overflow: hidden; }
.rm-root .rm-prog i { position: absolute; inset: 0 auto 0 0; background: var(--gold); opacity: .55; }
.rm-root .rm-prog b { position: relative; display: block; text-align: center; font-size: 9px; line-height: 12px; }
.rm-root .rm-lockb { font-size: 10px; font-weight: 800; color: var(--grayD, #8a8175); }
.rm-root #rmNpc { position: absolute; right: 8px; top: 8px; width: 44px; height: 44px; padding: 4px; border-radius: 12px;
  border: 2px solid var(--line); background: var(--panel); cursor: pointer; box-shadow: var(--shadow); }
.rm-root #rmNpc canvas { width: 100%; height: 100%; image-rendering: pixelated; display: block; }
.rm-root #rmNpc.rm-npc-has { border-color: var(--gold-d); }
.rm-root #rmNpc.rm-npc-has::after { content: "!"; position: absolute; top: -7px; right: -5px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--gold); border: 2px solid var(--gold-d); color: #5a3d00; font-size: 11px;
  line-height: 13px; font-weight: 900; text-align: center; }
.rm-root .rm-hint { font-size: 12px; font-weight: 600; color: var(--ink); opacity: .75; margin: 4px 0; }
.rm-root .rm-frag { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.rm-root .rm-frag-row { display: flex; gap: 6px; }
.rm-root .rm-frag-cell { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 2px;
  border: 2px solid var(--line); border-radius: 12px; background: var(--panel2); font-size: 12px; font-weight: 800; }
.rm-root .rm-frag-cell.dim { opacity: .45; }
.rm-root .rm-frag-cell canvas { width: 28px; height: 28px; image-rendering: pixelated; }
.rm-root .rm-frag-btn { padding: 3px 8px; font-size: 12px; }
.rm-root .rm-npc-reward { font-size: 15px; font-weight: 800; text-align: center; padding: 8px; background: var(--panel2);
  border: 2px solid var(--line); border-radius: 12px; }
.rm-root .rm-skins { display: flex; flex-wrap: wrap; gap: 6px; }
.rm-root .rm-skins .rm-mbtn { border: 2px solid var(--line); font-size: 13px; }
.rm-root #rmStage.rm-bk-sky { background: #bfe0f2; border-color: #8fc4e0; }
.rm-root #rmStage.rm-bk-sunset { background: #f2cba8; border-color: #e0a878; }

/* 025 "alive room": wish line under the header + pet-cat modal bits */
.rm-root .rm-wish { text-align: center; font-size: 12px; font-weight: 700; opacity: .78;
  padding: 0 12px 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rm-root .rm-pet-face { display: grid; place-items: center; margin: 2px 0 6px; }
.rm-root .rm-pet-face canvas { width: 64px; height: 64px; image-rendering: pixelated; }
.rm-root .rm-pet-lv { text-align: center; font-weight: 800; font-size: 14px; }
.rm-root .rm-pet-next { text-align: center; font-size: 12px; font-weight: 600; opacity: .75; margin-top: 2px; }
.rm-root .rm-pet-mood { text-align: center; font-size: 13px; font-weight: 600; opacity: .85; margin: 6px 0; }
.rm-root .rm-pet-phrase { background: var(--panel2); border: 2px solid var(--line); border-radius: 12px;
  padding: 10px; text-align: center; font-weight: 800; font-size: 16px; line-height: 1.3; }
.rm-root .rm-pet-phrase small { display: block; font-size: 12px; font-weight: 600; opacity: .7; margin-top: 4px; }

/* 025 "Đột kích vui": shield chip, revenge ping, raid-modal classmate rows + feed */
.rm-root .rm-shield { font-size: 12px; font-weight: 800; margin-left: 4px; white-space: nowrap; }
.rm-root .rm-tbtn.rm-ping { border-color: var(--gold-d); }
.rm-root .rm-tbtn.rm-ping::after { content: "!"; position: absolute; top: -7px; right: -5px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--gold-d); color: #fff; font-size: 11px; font-weight: 900;
  display: grid; place-items: center; }
.rm-root .rm-raid-tk { text-align: center; font-size: 13px; font-weight: 800; margin: 2px 0 8px; }
.rm-root .rm-raid-rev { display: flex; align-items: center; gap: 8px; padding: 8px; margin-bottom: 8px;
  border: 2px solid var(--gold-d); background: #fff7e0; border-radius: 12px; font-size: 12px; font-weight: 800; }
.rm-root .rm-raid-rev span { flex: 1; min-width: 0; }
.rm-root .rm-raid-row { display: flex; align-items: center; gap: 8px; padding: 7px; margin-bottom: 7px;
  border: 2px solid var(--line); border-radius: 12px; background: var(--panel2); }
.rm-root .rm-raid-row.dim { opacity: .6; }
.rm-root .rm-raid-av { width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto; display: grid; place-items: center;
  font-weight: 900; font-size: 14px; color: #fff; background: var(--accent); }
/* Tên bạn học phải HIỆN ĐỦ: tên Việt có dấu + tên lớp không lọt một dòng 13px trên
   điện thoại, nên cho xuống dòng thay vì cắt "…" (032). */
.rm-root .rm-raid-nm { flex: 1; min-width: 0; font-size: 13px; font-weight: 800;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }
.rm-root .rm-raid-nm small { display: block; font-weight: 700; opacity: .7; font-size: 11px; }
.rm-root .rm-raid-row .rm-mbtn { padding: 6px 7px; font-size: 12px; white-space: nowrap; }
.rm-root .rm-raid-grp { font-size: 11px; font-weight: 800; opacity: .6; text-transform: uppercase;
  letter-spacing: .04em; margin: 8px 0 4px; }
.rm-root .rm-raid-rest { font-size: 11px; font-weight: 700; opacity: .65; white-space: nowrap; }
.rm-root .rm-raid-feed { margin-top: 10px; }
.rm-root .rm-raid-feed b { display: block; font-size: 13px; margin-bottom: 3px; }
.rm-root .rm-raid-feed div { font-size: 12px; font-weight: 600; opacity: .8; padding: 3px 0; }
.rm-root .rm-raid-off { margin: 10px 0 2px; }
.rm-root .rm-raid-off .rm-mbtn { width: 100%; border: 2px solid var(--line); }

/* ---- 080 nghề 💼 + quán 🏪 ---- */
/* Chip nghề nối sau tên phòng ở header. `inline` chứ không `block`: nó là vế thứ hai
   của một dòng ("Phòng ngủ · ✂️ Thợ cắt tóc"), và #rmRoomname đã bị cắt bởi flex nên
   một phần tử block ở đây sẽ đẩy #rmStars xuống hàng dưới trên điện thoại. */
.rm-root .rm-jobchip { font-weight: 800; opacity: .8; }
.rm-root .rm-job-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin: 8px 0; }
.rm-root .rm-job { border: 2px solid var(--line); border-radius: 12px; background: var(--card, #fff);
  padding: 8px 4px; cursor: pointer; display: grid; gap: 2px; justify-items: center; min-height: 76px; }
.rm-root .rm-job.on { border-color: var(--accent); background: var(--accent-w, #eafaf3); }
.rm-root .rm-job.lock { opacity: .45; cursor: default; }
.rm-root .rm-job-em { font-size: 20px; line-height: 1; }
.rm-root .rm-job-nm { font-size: 12px; font-weight: 800; text-align: center; line-height: 1.15; }
.rm-root .rm-job-un { font-size: 10px; font-style: normal; font-weight: 700; opacity: .6; text-align: center; }
/* Báo cáo cuối ca. Khối này là phần thưởng thị giác của cả tính năng, nên nó được nền
   riêng — nếu trộn vào thân bảng thì "17 khách · +18 xu" đọc như một dòng thống kê. */
.rm-root .rm-shop-rep { text-align: center; border: 2px solid var(--line); border-radius: 14px;
  padding: 10px 8px; margin-bottom: 10px; background: var(--accent-w, #eafaf3); }
.rm-root .rm-shop-rep h2 { margin: 0 0 4px; }
.rm-root .rm-shop-take { font-size: 17px; font-weight: 800; margin-top: 4px; }
.rm-root .rm-shop-quote { font-size: 13px; font-weight: 600; opacity: .75; margin-top: 6px; font-style: italic; }
.rm-root .rm-shop-line { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 800; margin-top: 6px; }
.rm-root .rm-shop-stars { font-size: 13px; line-height: 1; letter-spacing: 1px; }
.rm-root .rm-shop-stars i { font-style: normal; color: #d8c4a2; }
.rm-root .rm-shop-stars i.on { color: var(--gold-d); }
.rm-root .rm-visit-job { display: block; font-size: 12px; font-weight: 700; opacity: .8; }

/* ---- 082: hàng đang ẩn trên bảng xếp hạng (chỉ supervip nhìn thấy) ---- */
/* Cùng độ mờ .55 với .lb-hidden của bảng học tập — ba bảng phải trông giống nhau, nếu
   không thì "đang ẩn" ở chỗ này lại đọc như một trạng thái khác ở chỗ kia. */
.rm-root .rm-board-hidden { opacity: .55; }
.rm-root .rm-board-hidtag { font-size: 10px; font-weight: 800; opacity: .75; white-space: nowrap; }

/* ---- 026 "My Room": wardrobe 👕 + friend visits + avatar head chips ---- */
.rm-root .rm-wd-slot { margin: 8px 0 2px; }
.rm-root .rm-wd-lb { display: block; font-size: 13px; margin-bottom: 4px; }
.rm-root .rm-wd-strip { display: flex; gap: 6px; overflow-x: auto; padding: 2px 0 6px; }
.rm-root .rm-wd-card { flex: 0 0 auto; width: 66px; border: 2px solid var(--line); border-radius: 12px;
  background: var(--panel2); padding: 4px 3px; font: inherit; color: inherit; cursor: pointer; text-align: center; }
.rm-root .rm-wd-card:active { transform: translateY(1px); }
.rm-root .rm-wd-card.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent) inset; }
.rm-root .rm-wd-card canvas { width: 40px; height: 40px; image-rendering: pixelated; display: block;
  margin: 0 auto; background: #f6ecd7; border-radius: 8px; }
.rm-root .rm-wd-card .rm-wd-nm { display: block; font-size: 10px; font-weight: 700; line-height: 1.1;
  height: 22px; overflow: hidden; margin-top: 2px; }
.rm-root .rm-wd-card .rm-wd-pr { display: flex; align-items: center; justify-content: center; gap: 3px;
  font-size: 10px; font-weight: 800; }
.rm-root .rm-wd-card .rm-wd-pr .rm-c { width: 10px; height: 10px; border: 1px solid var(--gold-d); }
.rm-root .rm-wd-none { display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: 16px; min-height: 74px; }
.rm-root .rm-raid-avcv { width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
  image-rendering: pixelated; border: 2px solid var(--line); background: #f6ecd7; }
.rm-root .rm-raid-nmbtn { flex: 1; min-width: 0; font: inherit; font-size: 13px; font-weight: 800;
  text-align: left; background: none; border: none; padding: 0; cursor: pointer; color: inherit;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }
.rm-root .rm-raid-nmbtn small { display: block; font-weight: 700; opacity: .7; font-size: 11px; }
.rm-root .rm-visit-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.rm-root .rm-visit-av { width: 40px; height: 40px; border-radius: 50%; image-rendering: pixelated;
  border: 2px solid var(--line); background: #f6ecd7; flex: 0 0 auto; }
.rm-root .rm-visit-nm { font-size: 15px; font-weight: 800; }
.rm-root .rm-visit-nm small { display: block; font-size: 12px; font-weight: 700; opacity: .75; }
.rm-root .rm-visit-cv { display: block; width: 100%; height: auto; border: 2px solid var(--line);
  border-radius: 12px; image-rendering: pixelated; background: #f6ecd7; }
.rm-root .rm-visit-re { display: flex; gap: 8px; justify-content: center; align-items: center; margin-top: 10px; }
.rm-root .rm-visit-rbtn { font-size: 18px; padding: 8px 14px; border: 2px solid var(--line); }
.rm-root .rm-visit-rbtn:disabled { opacity: .45; cursor: default; }
.rm-root .rm-visit-sent { font-size: 12px; font-weight: 800; color: var(--accent-d); }
/* 059: 12 emoji không lọt một hàng ngang trên 375px — cho gói thành lưới. */
.rm-root .rm-visit-re { flex-wrap: wrap; gap: 6px; }
.rm-root .rm-visit-rbtn { font-size: 18px; padding: 7px 10px; }

/* ---- 059 hộp thư ✉️ + ô để lại lời nhắn ---- */
.rm-root .rm-msg { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.rm-root .rm-msg-box { width: 100%; box-sizing: border-box; resize: vertical; font: inherit; font-size: 13px;
  padding: 8px 10px; border: 2px solid var(--line); border-radius: 12px; background: var(--panel2); color: inherit; }
.rm-root .rm-msg-foot { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.rm-root .rm-msg-count { flex: 0 0 auto; font-size: 11px; font-weight: 800; opacity: .65; font-variant-numeric: tabular-nums; }
/* Quá 200 điểm mã: server sẽ từ chối, nên nói ra TRƯỚC khi bấm gửi. */
.rm-root .rm-msg-count.over { color: #e0492e; opacity: 1; }
.rm-root .rm-msg-foot .rm-mbtn { flex: 1; }
.rm-root .rm-msg-foot .rm-mbtn:disabled { opacity: .45; cursor: default; }
.rm-root .rm-inbox { display: flex; flex-direction: column; gap: 7px; margin: 6px 0 2px; }
.rm-root .rm-inbox-row { padding: 8px; border: 2px solid var(--line); border-radius: 12px;
  background: var(--panel2); font-size: 13px; font-weight: 600; }
/* Chấm đỏ cho hàng CHƯA XEM — cùng dấu hiệu với .rm-duel-row.rm-new (053). */
.rm-root .rm-inbox-row.rm-new { position: relative; padding-left: 16px; border-color: var(--gold-d); }
.rm-root .rm-inbox-row.rm-new::before { content: ""; position: absolute; left: 6px; top: 14px;
  width: 6px; height: 6px; border-radius: 50%; background: #e0492e; }
.rm-root .rm-inbox-msg { line-height: 1.35; overflow-wrap: anywhere; }
.rm-root .rm-inbox-pinned { font-size: 11px; font-weight: 800; color: var(--accent-d); white-space: nowrap; }
.rm-root .rm-inbox-act { display: flex; gap: 6px; margin-top: 6px; }
.rm-root .rm-inbox-act .rm-mbtn { flex: 1; padding: 6px 8px; font-size: 12px; }
.rm-root .rm-inbox-pick { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.rm-root .rm-inbox-pick .rm-hint { flex: 1 0 100%; margin: 0; }
.rm-root .rm-inbox-pick .rm-mbtn { padding: 5px 9px; font-size: 12px; }

/* ---- 060 tường giấy nhớ 📌 (overlay trong sân khấu + trong bảng thăm phòng) ---- */
/* Dải ghim ĐỨNG TRONG sân khấu, ở dải be bên trái phòng. Trước đây nó là một <section>
   nằm DƯỚI #rmStage, mà #rmStage là `flex: 1` trong một cột — nên mỗi tờ giấy ghim lại
   bóp chiều cao phòng (đo trên 1566×760: ô gạch 48px → 38px với hai tờ). Cùng đúng cái
   lý do đã khiến bản điện thoại phải thu dải về một cái chip. Overlay thì không đẩy ai,
   và chỗ nó đứng vốn đã là khoảng trống — engine chỉ bật khi `ox` (dải be trái, do
   layout() đo) đủ rộng, nên nó KHÔNG BAO GIỜ đè lên phòng. */
.rm-root .rm-pins { position: absolute; left: 8px; bottom: 8px; z-index: 4;
  display: flex; flex-direction: column; width: 156px; max-height: calc(100% - 62px);
  padding: 0; pointer-events: none; }
/* `display: flex` của tác giả thắng `[hidden] { display: none }` của UA — không có dòng
   này thì el.hidden = true trong paintPins() không giấu được gì cả. */
.rm-root .rm-pins[hidden] { display: none; }
.rm-root .rm-pins-hd { font-size: 11px; font-weight: 800; opacity: .6; text-transform: uppercase;
  letter-spacing: .04em; margin-bottom: 4px; }
/* Cuộn NGANG: năm tờ giấy xếp dọc đẩy cả canvas ra khỏi màn hình điện thoại. */
.rm-root .rm-pins-in { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; }
/* …trừ trong sân khấu: ở đó chiều DỌC mới là thứ dư, còn chiều ngang chỉ có dải be.
   Bó vào #rmPins để bảng ghé thăm và modal đọc tường giữ nguyên dải ngang. */
.rm-root #rmPins .rm-pins-in { flex-direction: column; overflow-x: hidden; overflow-y: auto;
  padding-bottom: 0; }
.rm-root #rmPins .rm-pin { width: 100%; }
/* Chỉ TỜ GIẤY bắt chuột. Cả khối mà bắt thì nó nuốt luôn cú chạm vào phòng — dải be là
   vùng canvas, onCanvasTap vẫn phải nhận được cú chạm xuyên qua đây. */
.rm-root #rmPins .rm-pin { pointer-events: auto; }
.rm-root .rm-pin { position: relative; flex: 0 0 auto; width: 148px; padding: 8px 10px 8px 8px;
  border: 2px solid #e7d08a; border-radius: 4px 12px 4px 12px; background: #fff8dc;
  color: #4a3b12; box-shadow: var(--shadow); font-size: 12px; }
.rm-root .rm-pin-rm { display: block; font-size: 10px; font-weight: 800; opacity: .65; margin-bottom: 2px; }
.rm-root .rm-pin-body { font-weight: 600; line-height: 1.3; overflow-wrap: anywhere;
  max-height: 60px; overflow-y: auto; }
.rm-root .rm-pin-by { font-size: 11px; font-weight: 800; opacity: .7; margin-top: 4px; }
.rm-root .rm-pin-x { position: absolute; top: -7px; right: -7px; width: 20px; height: 20px; padding: 0;
  border-radius: 50%; border: 2px solid var(--line); background: var(--panel); color: inherit;
  font: inherit; font-size: 11px; font-weight: 900; line-height: 1; cursor: pointer; }

/* ---- 060 thẻ báo việc sống (góc trên sân khấu) ---- */
.rm-root .rm-pop-wrap { position: absolute; left: 8px; top: 8px; right: 60px; z-index: 5;
  display: flex; flex-direction: column; gap: 6px; align-items: flex-start; pointer-events: none; }
.rm-root .rm-pop { pointer-events: auto; max-width: 100%; text-align: left; font: inherit; font-size: 12px;
  font-weight: 800; padding: 7px 11px; border-radius: 999px; border: 2px solid var(--gold-d);
  background: #fff7e0; color: #5a3d00; box-shadow: var(--shadow); cursor: pointer;
  animation: rmPopIn .28s cubic-bezier(.34,1.56,.64,1); }
@keyframes rmPopIn { 0% { transform: translateY(-8px); opacity: 0; } 100% { transform: none; opacity: 1; } }
.rm-root .rm-pop-list { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 2px;
  font-size: 14px; font-weight: 700; }

/* ---- 060 ô tìm bạn 🔍 ---- */
.rm-root .rm-search { width: 100%; box-sizing: border-box; font: inherit; font-size: 13px; font-weight: 600;
  padding: 8px 10px; margin: 4px 0 2px; border: 2px solid var(--line); border-radius: 12px;
  background: var(--panel2); color: inherit; }

/* ---- 054/060 bảng xếp hạng My Room (modal 🏆) ---- */
.rm-root .rm-board { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 2px; }
.rm-root .rm-board-row { display: flex; align-items: center; gap: 8px; padding: 6px 7px;
  border: 2px solid var(--line); border-radius: 12px; background: var(--panel2); }
.rm-root .rm-board-row.rm-board-me { border-color: var(--accent); background: #eef7ff; }
.rm-root .rm-board-rk { flex: 0 0 26px; text-align: center; font-size: 14px; font-weight: 900; }
.rm-root .rm-board-av { width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto; object-fit: cover;
  border: 2px solid var(--line); background: #f6ecd7; }
.rm-root .rm-board-ini { display: grid; place-items: center; font-weight: 900; font-size: 13px;
  color: #fff; background: var(--accent); }
.rm-root .rm-board-nm { flex: 1; min-width: 0; font-size: 13px; font-weight: 800;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }
.rm-root .rm-board-nm small { display: block; font-weight: 700; opacity: .72; font-size: 11px; }

/* ---- 083: hàng bảng xếp hạng là một cánh cửa, và nghề hiện trên mọi danh sách ---- */
/* Hàng của người khác là <button>, hàng của mình vẫn là <div> (không tự ghé phòng mình
   được) — nên phải gỡ hết mặc định của nút, nếu không hai loại hàng trông khác nhau. */
.rm-root button.rm-board-row { width: 100%; text-align: left; font: inherit; color: inherit;
  cursor: pointer; box-shadow: 0 2px 0 var(--line); }
.rm-root button.rm-board-row:active { transform: translateY(2px); box-shadow: none; }
.rm-root .rm-board-job,
.rm-root .rm-raid-job { display: block; font-size: 11px; font-weight: 800; opacity: .85;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rm-root .rm-raid-job .rm-shop-stars,
.rm-root .rm-board-job .rm-shop-stars { font-size: 10px; letter-spacing: 0; }

/* ============================================================================
   mobile — khổ điện thoại. Mọi thứ dưới đây là hệ quả của một lần đo trên 375×812 và
   360×640; con số 44px là ngưỡng vùng chạm tối thiểu, không phải thẩm mỹ.
   ============================================================================ */

/* ---- B1: vùng chạm 44×44 ---- */
/* .rm-mbtn đang là padding 7px 11px ⇒ cao ~32px. Dùng min-height + grid để chữ vẫn
   canh giữa, thay vì độn padding (padding làm vỡ mấy hàng đã canh theo chiều cao). */
.rm-root .rm-mbtn { min-height: 44px; display: inline-grid; place-items: center; }
.rm-root .rm-pbtn { min-height: 44px; }
.rm-root #rmTabs button { min-height: 44px; }
/* Ba chỗ này cố ý nhỏ chữ (12px) để lọt hàng — giữ nguyên cỡ chữ, chỉ nới vùng chạm. */
.rm-root .rm-raid-row .rm-mbtn,
.rm-root .rm-inbox-act .rm-mbtn,
.rm-root .rm-inbox-pick .rm-mbtn { min-height: 44px; }
.rm-root .rm-visit-rbtn { min-height: 44px; min-width: 44px; }
.rm-root .rm-frag-btn { min-height: 44px; }
/* .rm-pin-x từng là 20×20 và nằm NGOÀI thẻ (top/right: -7px) bên trong một vùng
   overflow-x — vừa khó bấm, vừa đè thẻ bên cạnh, vừa cộng vào chiều rộng cuộn. */
.rm-root .rm-pin-x { top: 2px; right: 2px; width: 32px; height: 32px; font-size: 14px; }
.rm-root .rm-pin { padding-right: 36px; }

/* ---- B2: nút Đóng phải thấy được mà không cần cuộn ---- */
/* Bảng đột kích ~1950px, hộp thư tới ~3000px, bảng xếp hạng cả trường ~11000px trong
   một khung cao 560px — nút "Đóng" ở đáy nghĩa là cuộn 3–20 màn hình mới đóng được. */
.rm-root #rmModal h2 {
  position: sticky; top: -16px; z-index: 1;
  margin: -16px -16px 10px; padding: 14px 52px 10px 16px;
  background: var(--panel); border-radius: 15px 15px 0 0;
  box-shadow: 0 1px 0 var(--line);
}
.rm-root .rm-x {
  position: absolute; top: 8px; right: 8px; width: 40px; height: 40px; z-index: 2;
  border: 2px solid var(--line); border-radius: 12px; background: var(--panel2);
  font: inherit; font-size: 18px; font-weight: 900; line-height: 1; color: inherit; cursor: pointer;
}
.rm-root #rmModal { position: relative; overscroll-behavior: contain; }

/* ---- B3/B4: ô nhập ---- */
/* 16px là ngưỡng iOS Safari THÔI tự phóng to trang khi focus. Dưới ngưỡng là trang
   phóng to và không tự thu lại khi blur — đúng lúc học sinh đang gõ dở một lời nhắn. */
.rm-root .rm-msg-box, .rm-root .rm-search { font-size: 16px; }
/* .rm-root đặt user-select:none (dòng 611) và #rmModalWrap là con của nó ⇒ textarea kế
   thừa, iOS chặn luôn kính lúp, tay kéo chọn và menu Dán. Trả lại cho riêng ô nhập. */
.rm-root input, .rm-root textarea { -webkit-user-select: text; user-select: text; }


/* ---- B5: bốn dải cuộn ngang phải khai trục ---- */
.rm-root #rmTabs, .rm-root #rmShopstrip,
.rm-root .rm-wd-strip, .rm-root .rm-pins-in { touch-action: pan-x; overscroll-behavior-x: contain; }
/* .rm-pin-body từng là vùng cuộn DỌC nằm trong vùng cuộn NGANG nằm trong modal cuộn dọc
   — ba tầng, vuốt chéo là xổ số. Cắt bằng ellipsis, muốn đọc đủ thì mở modal tường. */
.rm-root .rm-pin-body { overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; }

/* ---- mobile sheet ⋯ ---- */
.rm-root .rm-more { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 2px; }
.rm-root .rm-more-item { justify-items: start; grid-auto-flow: column; justify-content: space-between;
  width: 100%; padding: 11px 14px; font-size: 15px; text-align: left; background: var(--panel2);
  border: 2px solid var(--line); }
.rm-root .rm-more-n { min-width: 22px; padding: 0 6px; border-radius: 999px;
  background: var(--gold); border: 2px solid var(--gold-d); color: #5a3d00; font-size: 12px; font-weight: 900; }

/* ---- mobile chip ghim (thay dải trên điện thoại) ---- */
.rm-root .rm-pin-chip {
  position: absolute; left: 8px; bottom: 8px; z-index: 4;
  min-height: 36px; padding: 6px 12px; border-radius: 999px;
  border: 2px solid #e7d08a; background: #fff8dc; color: #4a3b12;
  font: inherit; font-size: 13px; font-weight: 800; cursor: pointer; box-shadow: var(--shadow);
}
/* Dải ghim / chip KHÔNG còn chia theo mốc 720px. Từ 08/2026 dải nằm trong dải be bên
   trái phòng, nên câu hỏi đúng không phải "màn hình rộng bao nhiêu" mà "còn trống bao
   nhiêu bên cạnh phòng" — hai chuyện khác nhau: một cửa sổ 900px nhưng THẤP thì phòng
   nhỏ lại và dải be rộng ra. paintPins() đo thẳng `ox` mà layout() vừa tính và chọn
   một trong hai; media query cứng ở đây chỉ chọi lại nó. */

/* ---- mobile bảng xếp hạng: dấu ngắt trước hàng "của mình" kéo từ ngoài trang vào ---- */
.rm-root .rm-board-gap { text-align: center; font-weight: 900; opacity: .45; line-height: 1; padding: 2px 0; }

/* "My Room +N xu" reward chip on the result view (app-level, outside .rm-root) */
.room-reward-chip { display: inline-flex; align-items: center; gap: 7px; margin-top: 10px; padding: 7px 14px;
  background: #fff7e0; border: 2px solid #e6a92e; border-radius: 999px; font-weight: 800; font-size: 14px;
  color: #6b4a00; animation: coinPop .45s cubic-bezier(.34,1.56,.64,1); }
.room-reward-chip .chip-coin { width: 16px; height: 16px; border-radius: 50%; flex: 0 0 auto;
  background: radial-gradient(circle at 35% 30%, #ffe89a, #ffcf4d 60%, #e6a92e); border: 2px solid #e6a92e; }
.room-reward-chip .chip-combo { font-size: 12px; color: #b56a00; }
@keyframes coinPop { 0% { transform: scale(.4); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }

/* ==========================================================================
   (v2) My Room — cột phải "Nhiệm vụ phòng". CHỈ từ 1024px: dưới mức đó #rmApp
   giữ nguyên flex một cột như trước, không đổi một pixel nào của khổ điện thoại.
   Chuyển flex -> grid nên phải chỉ định cột cho từng con: bốn phần cũ nằm cột 1,
   aside nằm cột 2 và trải hết bốn hàng.
   ========================================================================== */
.rm-root #rmSide { display: none; }
@media (min-width: 1024px) {
  .rm-root #rmApp {
    display: grid; max-width: 1220px;
    grid-template-columns: minmax(0, 1fr) 300px;
    grid-template-rows: auto auto 1fr auto;
    column-gap: 14px;
  }
  .rm-root #rmTopbar { grid-column: 1; grid-row: 1; }
  .rm-root #rmTabs   { grid-column: 1; grid-row: 2; }
  .rm-root #rmStage  { grid-column: 1; grid-row: 3; }
  .rm-root #rmShop   { grid-column: 1; grid-row: 4; }
  .rm-root #rmSide {
    display: block; grid-column: 2; grid-row: 1 / -1;
    overflow-y: auto; padding: 8px 10px 10px 0;
  }
  .rm-root .rm-side-card {
    background: var(--panel); border: 2px solid var(--line); border-radius: 16px;
    padding: 11px 12px; box-shadow: var(--shadow); margin-bottom: 12px;
  }
  .rm-root .rm-side-card h4 { margin: 0 0 8px; font-size: 14px; display: flex; gap: 6px; align-items: center; }
  .rm-root .rm-q { display: flex; align-items: center; gap: 8px; padding: 7px 0; }
  .rm-root .rm-q + .rm-q { border-top: 1px dashed var(--line); }
  .rm-root .rm-q .ic { font-size: 18px; flex: 0 0 auto; }
  .rm-root .rm-q .t { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; line-height: 1.25; }
  .rm-root .rm-q .v { font-size: 12px; font-weight: 800; opacity: .65; flex: 0 0 auto; }
  .rm-root .rm-q .v.done { color: var(--accent-d); opacity: 1; }
  .rm-root .rm-side-reward {
    background: #fff6dd; border: 2px solid var(--gold-d); border-radius: 14px;
    padding: 9px 11px; font-size: 12px; font-weight: 700; display: flex; gap: 8px; align-items: center;
  }
}

/* ==========================================================================
   Speak88 1b — 2a "Chi tiết chủ đề" (#/unit/:id)
   ========================================================================== */
.s8-detail { max-width: 1320px; margin: 0 auto; padding: 16px 22px 40px; }
.s8-crumb { font-size: var(--fs-sm); color: var(--muted); margin-bottom: 14px; }
.s8-crumb b { color: var(--navy); }
.s8-crumb-link { appearance: none; border: 0; background: none; font: inherit; color: var(--muted); cursor: pointer; padding: 0; }
.s8-crumb-link:hover { color: var(--pink-d); }
.s8-detail-grid { display: grid; grid-template-columns: minmax(0, 1fr) 316px; gap: 16px; align-items: start; }
.s8-detail-main { min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.s8-detail-side { min-width: 0; display: flex; flex-direction: column; gap: 12px; }

/* thẻ chung của hệ 1b: KẺ 1px, không bóng */
.s8-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; min-width: 0; }
.s8-card-pad { padding: 16px; }
.s8-card-gold { background: var(--gold-bg); border-color: var(--gold-line); color: var(--gold-fg); font-size: var(--fs-base); line-height: 1.5; }
.s8-card-gold b { display: block; font-size: var(--fs-md); margin-bottom: 3px; color: var(--gold-fg); }
.s8-card-ink { background: var(--navy); color: #fff; padding: 15px; }
.s8-card-ink b { display: block; font-size: var(--fs-md); margin-bottom: 5px; }
.s8-card-ink p { margin: 0 0 11px; font-size: var(--fs-sm); color: var(--on-dark); line-height: 1.5; }
.btn-gold { background: var(--gold); color: var(--gold-on); }
.btn-gold:hover:not(:disabled) { background: #f5a50f; }

/* banner: mockup để một chỗ trống 16:9 ghi "ẢNH BANNER" — app chưa có ảnh chủ đề, nên
   dùng đúng nền chuyển sắc + emoji của bộ đề thay vì vẽ một ô xám chờ ảnh mãi mãi. */
.s8-banner { height: 190px; display: grid; place-items: center; font-size: 62px;
  background: linear-gradient(135deg, var(--navy-l), var(--navy) 65%); }
.s8-banner-body { padding: 20px 22px 22px; }
.s8-banner-body h1 { margin: 0 0 8px; font-size: var(--fs-3xl); font-weight: 800; }
.s8-banner-body p { margin: 0 0 14px; font-size: var(--fs-md); line-height: 1.6; color: var(--t3); max-width: 76ch; }
.s8-stats3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.s8-stats3 span { display: block; font-size: var(--fs-xs); letter-spacing: .06em; color: var(--label); font-weight: 700; }
.s8-stats3 b { font-size: var(--fs-lg); font-family: var(--font-head); }

/* tab: gạch chân 2px như mockup. Đây là ba ĐƯỜNG DẪN, không phải ba khung nội dung. */
.s8-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); font-size: var(--fs-md); font-weight: 600; color: var(--muted); flex-wrap: wrap; }
.s8-tab { appearance: none; border: 0; background: none; font: inherit; font-weight: 600; color: var(--muted); padding: 10px 14px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.s8-tab:hover { color: var(--navy); }
.s8-tab.active { color: var(--navy); font-weight: 700; border-bottom-color: var(--navy); }
.s8-tab b { color: var(--label); font-weight: 600; }

/* hàng khoá-giá trị trong thẻ tiến độ */
.s8-kv { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); font-size: var(--fs-base); }
.s8-kv > div { display: flex; justify-content: space-between; gap: 10px; }
.s8-kv span { color: var(--muted); }

/* "Bộ đề khác" */
.s8-mini-row { display: flex; gap: 10px; align-items: center; width: 100%; text-align: left; appearance: none; border: 0; background: none; font: inherit; padding: 6px 0; cursor: pointer; min-width: 0; }
.s8-mini-row > span:first-child { flex: 0 0 40px; height: 34px; border-radius: var(--radius-sm); display: grid; place-items: center; font-size: 17px; }
.s8-mini-row > span:last-child { min-width: 0; }
.s8-mini-row b { display: block; font-size: var(--fs-base); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-mini-row small { display: block; font-size: var(--fs-sm); color: var(--label); }
.s8-mini-row:hover b { color: var(--pink-d); }

@media (max-width: 979px) {
  .s8-detail { padding: 14px 14px 32px; }
  .s8-detail-grid { grid-template-columns: minmax(0, 1fr); }
  .s8-banner { height: 150px; font-size: 46px; }
  .s8-banner-body { padding: 16px; }
  .s8-banner-body h1 { font-size: var(--fs-2xl); }
}
@media (max-width: 520px) {
  .s8-detail { padding: 12px 10px 32px; }
  .s8-stats3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
  .s8-stats3 b { font-size: var(--fs-md); }
  .s8-tab { padding: 9px 10px; font-size: var(--fs-base); }
}

/* ==========================================================================
   Speak88 1b — 2c "Luyện nói" (#/practice/:unit/:q)
   Chế độ TẬP TRUNG: thanh trên + thanh tab đi chỗ khác, chỉ còn đề bài và mic.
   ========================================================================== */
body.s8-focus .topbar, body.s8-focus .tabbar { display: none; }
body.s8-focus .view { padding-bottom: 0; }

/* ---- Đang ở trong một trò chơi (body.s8-play) --------------------------------------
   Khác s8-focus ở ĐÚNG một điểm, và điểm ấy là cả lý do phải có thêm một lớp riêng:
   s8-focus ẩn CẢ hai thanh. Màn ghi âm chịu được vì nó có nút thoát riêng; trong game thì
   CHỈ My Gang có nút back (js/gang/screens/levelmap.js:49), bốn game kia không có gì cả —
   ẩn nốt thanh trên là nhốt học sinh trong game, không còn đường ra nào ngoài nút Back
   của trình duyệt. Nên: ẩn thanh TAB DƯỚI, giữ thanh TRÊN (logo Speak88 trỏ #/units).

   Thanh tab dưới là position:fixed cao 56px + env(safe-area-inset-bottom) — trên iPhone
   tai thỏ là ~90px. Với bốn game có luật mobile thì 90px ấy bị TRỪ khỏi chiều cao sân;
   với My Gang thì không trừ gì cả, nên nó nằm ĐÈ lên mép dưới sân chơi. */
body.s8-play .tabbar { display: none; }
@media (max-width: 979px) {
  /* .view chừa sẵn padding đáy để tránh thanh tab; thanh tab biến mất thì padding ấy
     thành khoảng trống thật. Khung game triệt tiêu nó bằng lề âm — đặt cả hai về 0 để
     chiều cao trang bằng đúng topbar + sân, không dư một pixel nào. */
  body.s8-play .view { padding-bottom: 0; }
  body.s8-play .rm-root { margin-bottom: 0; }
}
@media (max-width: 719px) {
  /* My Room đang trừ 56px của thanh tab. Thanh tab không còn ⇒ trả 56px ấy lại cho sân.
     Vẫn trừ safe-area để HUD không chui xuống dưới vạch home indicator. */
  body.s8-play .rm-root #rmApp {
    height: calc(100vh - 60px);
    height: calc(100dvh - 60px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  }
}
/* CHỈ My Room nằm ở đây, vì My Room vốn ở trong file này. Bốn game kia có file CSS riêng,
   và tools/test.mjs canh không cho selector gốc của chúng xuất hiện trong ispeak.css —
   bằng một phép includes() trên CẢ file, nên chú thích cũng tính. Vì vậy khối s8-play của
   forge/kingdom/pets/gang nằm ở css/{forge,kingdom,pets,gang}.css, và tên selector của
   chúng cố ý không được viết ra ở đây. */

.s8-rec { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.s8-rec-bar { display: flex; align-items: center; gap: 16px; min-height: 52px; padding: 0 20px;
  padding-top: env(safe-area-inset-top); background: var(--navy); color: #fff; font-size: var(--fs-base); }
.s8-rec-exit { appearance: none; border: 0; background: none; font: inherit; font-weight: 700; color: #fff; cursor: pointer; padding: 6px 2px; flex: 0 0 auto; }
.s8-rec-unit { color: var(--on-dark); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-rec-prog { margin-left: auto; display: flex; align-items: center; gap: 8px; color: var(--on-dark); white-space: nowrap; flex: 0 0 auto; }
.s8-pips { display: flex; gap: 3px; }
.s8-pips > i { width: 16px; height: 4px; border-radius: 2px; background: rgba(255,255,255,.2); }
.s8-pips > i.on { background: var(--pink); }
.s8-pipbar { width: 90px; height: 4px; border-radius: 2px; background: rgba(255,255,255,.2); overflow: hidden; }
.s8-pipbar > i { display: block; height: 100%; background: var(--pink); }
.s8-rec-chip { padding: 4px 10px; border-radius: 999px; background: rgba(255,255,255,.1); font-weight: 700; flex: 0 0 auto; }

.s8-rec-body { flex: 1; display: flex; justify-content: center; padding: 18px 20px 34px; }
.s8-rec-card { width: 100%; max-width: 720px; padding: 26px 28px 30px; align-self: flex-start; }
.s8-rec-eyebrow { margin-bottom: 14px; }
.s8-rec-eyebrow .s8-tag { padding: 4px 10px; letter-spacing: .05em; font-weight: 800; text-transform: uppercase; }
.s8-rec-card h2 { margin: 0 0 14px; font-size: var(--fs-2xl); line-height: 1.25; font-weight: 700; max-width: 34ch; }
.s8-rec-say { padding: 14px 16px; border-radius: 10px; background: var(--bg); font-size: var(--fs-md);
  line-height: 1.7; color: var(--t2); white-space: pre-line; margin-bottom: 6px; }

/* Vòng quầng quanh mic — mockup vẽ một vòng 118px với quầng 10px cùng họ màu. */
.rec-halo { width: 118px; height: 118px; border-radius: 999px; display: grid; place-items: center;
  background: var(--mint-bg); box-shadow: 0 0 0 10px #f2fdf8; }
.rec-halo.is-recording { background: var(--red-bg); box-shadow: 0 0 0 10px var(--red-halo); }
.rec-halo .mic-btn { width: 84px; height: 84px; box-shadow: none; }
.rec-halo .mic-btn svg { width: 38px; height: 38px; }
.rec-halo .mic-btn.is-recording { animation: none; }   /* quầng đã nói "đang ghi" rồi */

/* Dải sóng. Cao 44px = đúng khổ của mockup; cột 5px, cách 3px. */
.rec-wave { display: flex; align-items: flex-end; gap: 3px; height: 44px; }
.rec-wave > i { width: 5px; height: 3px; border-radius: 3px; background: var(--red); transition: height .08s linear; }
/* Máy không có Web Audio: một dải tĩnh, cố tình nhạt và không nhúc nhích — nói thật là
   "không đo được mức âm" thay vì giả vờ có nhịp. */
.rec-wave-flat > i { height: 8px; background: var(--track); transition: none; }

.rec-timer { font-family: var(--font-head); font-weight: 700; font-size: var(--fs-4xl); font-variant-numeric: tabular-nums; color: var(--navy); letter-spacing: -.01em; }

@media (max-width: 719px) {
  .s8-rec-bar { gap: 10px; padding: 0 14px; padding-top: env(safe-area-inset-top); }
  .s8-rec-unit { display: none; }        /* tên bộ đề nhường chỗ cho "Câu n/m" + dải pip */
  .s8-rec-body { padding: 14px 12px 28px; }
  .s8-rec-card { padding: 18px 16px 24px; }
  .s8-rec-card h2 { font-size: var(--fs-xl); }
  .rec-wave { gap: 2px; height: 38px; }
  .rec-wave > i { width: 4px; }
}
@media (max-width: 420px) {
  /* 44 cột × 6px = 264px, vẫn vừa 375px. Nhưng dưới 420 thì bỏ bớt cho chắc: ẩn nửa
     sau bằng CSS rẻ hơn nhiều so với dựng lại DOM theo khổ máy. */
  .rec-wave > i:nth-child(n+33) { display: none; }
}

/* ==========================================================================
   Speak88 1b — 2d "Kết quả chấm AI" (#/result/:id)
   ========================================================================== */
.s8-res { max-width: 1320px; margin: 0 auto; padding: 16px 22px 40px; display: flex; flex-direction: column; gap: 16px; }
.s8-res > .s8-crumb-link { align-self: flex-start; font-size: var(--fs-base); font-weight: 700; }

.s8-res-hero { display: flex; align-items: center; gap: 20px; padding: 18px 22px; border-radius: var(--radius); background: var(--navy); color: #fff; flex-wrap: wrap; }
/* Vòng điểm: viền mint như mockup, nhưng bên trong là ĐIỂM /100 thật, không phải band. */
.s8-res-ring { flex: 0 0 auto; display: grid; place-items: center; width: 88px; height: 88px; border-radius: 999px; background: rgba(0,229,160,.14); border: 2px solid var(--pink); line-height: 1.05; }
.s8-res-ring b { display: block; font-family: var(--font-head); font-size: var(--fs-3xl); font-weight: 800; color: var(--pink); }
.s8-res-ring span { display: block; font-size: 10.5px; color: var(--on-dark-mint); letter-spacing: .06em; text-align: center; }
.s8-res-copy { flex: 1 1 260px; min-width: 0; }
.s8-res-copy > b { font-family: var(--font-head); font-size: var(--fs-xl); font-weight: 800; }
.s8-res-q { margin-top: 5px; font-size: var(--fs-base); color: var(--on-dark); overflow-wrap: anywhere; }
.s8-res-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 11px; font-size: var(--fs-sm); }
.s8-res-chips > span:not(:empty) { padding: 5px 11px; border-radius: var(--radius-sm); background: rgba(255,255,255,.1); font-weight: 600; }
.s8-res-chips .room-reward-chip { background: none; padding: 0; color: var(--pink); font-weight: 700; }
.s8-res-target { flex: 0 0 auto; text-align: right; font-size: var(--fs-sm); color: var(--on-dark); }
.s8-res-target .s8-band-track { width: 150px; margin: 7px 0 6px; }
.s8-res-act { max-width: 420px; }

.s8-res-grid { display: grid; grid-template-columns: minmax(0, 1fr) 344px; gap: 16px; align-items: start; }
/* Cột phải đứng TRƯỚC trong DOM (thẻ tiêu chí vốn nằm ở đó trong nguồn cũ) nhưng phải
   hiện bên PHẢI — nên chỉ định cột thẳng thay vì đảo thứ tự của cả khối markup. */
.s8-res-main { grid-column: 1; grid-row: 1; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.s8-res-side { grid-column: 2; grid-row: 1; min-width: 0; display: flex; flex-direction: column; gap: 12px; }

/* Tiêu chí: mint khi đạt, hổ phách khi yếu (mốc 70% = STAR_G2 của js/stars.js) */
.crit-row.is-weak .crit-score { color: var(--gold-fg); }
.crit-row.is-weak .bar > i { background: var(--gold); }
.crit-row .crit-score { color: var(--pink-d); }

@media (max-width: 1023px) {
  .s8-res-grid { grid-template-columns: minmax(0, 1fr); }
  .s8-res-main { grid-column: 1; grid-row: 2; }
  .s8-res-side { grid-column: 1; grid-row: 1; }
}
@media (max-width: 719px) {
  .s8-res { padding: 12px 12px 32px; gap: 12px; }
  .s8-res-hero { gap: 14px; padding: 16px; }
  .s8-res-ring { width: 72px; height: 72px; }
  .s8-res-ring b { font-size: var(--fs-2xl); }
  .s8-res-target { flex: 1 1 100%; text-align: left; }
  .s8-res-target .s8-band-track { width: 100%; }
  .s8-res-act { max-width: none; }
  .annot-text, .up-text { font-size: var(--fs-md); line-height: 1.95; }
}

/* ==========================================================================
   Speak88 1b — 2e "Xếp hạng & thành tích" (#/leaderboard)
   ========================================================================== */
.s8-lb { max-width: 1320px; margin: 0 auto; padding: 16px 22px 40px; display: flex; flex-direction: column; gap: 16px; }
.s8-lb-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.s8-lb-head h1 { margin: 0 0 3px; font-size: var(--fs-2xl); font-weight: 800; }
.s8-lb-head p { margin: 0; font-size: var(--fs-base); color: var(--muted); }
.s8-seg-row { display: flex; gap: 10px; flex-wrap: wrap; }
/* Bộ chuyển 1b: một khay trắng viền mảnh, các nút bên trong bo 6px và không có viền
   riêng — khác hẳn dải .fchip tròn dùng ở chỗ lọc. */
.s8-seg { gap: 3px; padding: 3px; border-radius: var(--radius-md); background: var(--card); border: 1px solid var(--line); }
.s8-seg .fchip { min-height: 34px; padding: 6px 11px; border: 0; border-radius: var(--radius-sm); background: none; font-size: var(--fs-sm); }
.s8-seg .fchip.active { background: var(--navy); color: #fff; }

.s8-lb-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 16px; align-items: start; }
.s8-lb-main { min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.s8-lb-side { min-width: 0; display: flex; flex-direction: column; gap: 12px; }

/* bục ba người */
.s8-podium { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.s8-pod { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 16px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }
.s8-pod.is-me { background: var(--mint-bg); border-color: #a9eed4; }
.s8-pod-medal { flex: 0 0 auto; display: grid; place-items: center; width: 46px; height: 46px; border-radius: 999px; background: var(--gold-bg); font-size: 20px; }
.s8-pod.is-me .s8-pod-medal { background: #fff; }
.s8-pod div { min-width: 0; }
.s8-pod b { display: block; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-pod small { display: block; font-size: var(--fs-sm); color: var(--muted); }
.s8-pod.is-me small { color: #3f7a67; }

/* bảng dày — sáu cột, cùng grid cho hàng tiêu đề và hàng dữ liệu */
.s8-lb-th, .s8-lb-row { display: grid; grid-template-columns: 44px minmax(0, 1fr) 170px 66px 78px 82px; gap: 12px; align-items: center; }
.s8-lb-th { padding: 9px 14px; background: var(--bg); border-bottom: 1px solid var(--line); font-size: var(--fs-xs); letter-spacing: .05em; font-weight: 800; color: var(--label); }
.s8-lb-th > span:nth-child(n+4) { text-align: right; }
.s8-lb-row { padding: 10px 14px; border-bottom: 1px solid var(--hair); font-size: var(--fs-base); }
.s8-lb-row:last-child { border-bottom: 0; }
.s8-lb-row.lb-me { background: var(--mint-bg); }
.s8-lb-rank-c { font-weight: 700; color: var(--label); }
.s8-lb-who { display: flex; align-items: center; gap: 9px; min-width: 0; }
.s8-lb-who > span { min-width: 0; }
.s8-lb-who b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
.s8-lb-who .lb-av { flex: 0 0 28px; width: 28px; height: 28px; font-size: 11.5px; }
.s8-lb-title-c { min-width: 0; overflow: hidden; }
.s8-lb-title-c .lb-title { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s8-lb-num { text-align: right; color: var(--muted); white-space: nowrap; }
.s8-lb-num b { color: var(--text); }

/* thẻ "hạng của bạn" */
.s8-lb-eyebrow { font-size: var(--fs-xs); letter-spacing: .08em; font-weight: 700; color: var(--on-dark-3); }
.s8-lb-rank { display: block; font-family: var(--font-head); font-size: var(--fs-3xl); font-weight: 800; margin: 4px 0 6px; }
.s8-lb-rank span { font-size: var(--fs-md); font-weight: 600; color: var(--on-dark); }
.s8-lb-mine { font-size: var(--fs-sm); color: var(--on-dark); line-height: 1.5; }

/* lưới huy hiệu */
.s8-badges { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 9px; }
.s8-badge { text-align: center; padding: 9px 4px; border-radius: 9px; background: var(--g1); }
.s8-badge span { display: block; font-size: 22px; }
.s8-badge small { display: block; margin-top: 4px; font-size: 10.5px; font-weight: 700; color: var(--g7); line-height: 1.25; overflow-wrap: anywhere; }

@media (max-width: 1023px) {
  .s8-lb-grid { grid-template-columns: minmax(0, 1fr); }
  /* Thẻ "hạng của bạn" nhảy lên TRƯỚC bảng: trên máy hẹp, thứ học sinh mở trang để xem
     đầu tiên là hạng của chính mình, không phải hạng của người đứng nhất. */
  .s8-lb-main { grid-row: 2; }
  .s8-lb-side { grid-row: 1; }
  .s8-badges { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (max-width: 719px) {
  .s8-lb { padding: 12px 12px 32px; }
  .s8-podium { grid-template-columns: minmax(0, 1fr); }
  /* Bỏ cột danh hiệu và cột streak: 170px + 66px ăn hết chỗ của TÊN, mà tên mới là thứ
     học sinh dò. Danh hiệu vẫn còn ở dải showcase ngay dưới tên. */
  .s8-lb-th, .s8-lb-row { grid-template-columns: 32px minmax(0, 1fr) 60px 68px; gap: 8px; padding-inline: 10px; }
  /* nth-child cho CẢ hai hàng, không dùng :first-of-type — nó xét TÊN THẺ chứ không xét
     class, nên `.s8-lb-num:first-of-type` không bao giờ khớp (con đầu tiên cũng là span).
     Hậu quả là hàng tiêu đề giấu 2 cột còn hàng dữ liệu chỉ giấu 1, và cả bảng lệch. */
  .s8-lb-th > *:nth-child(3), .s8-lb-row > *:nth-child(3),
  .s8-lb-th > *:nth-child(4), .s8-lb-row > *:nth-child(4) { display: none; }
  .s8-lb-th > span:nth-child(n+5) { text-align: right; }
  .s8-badges { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   Speak88 1b — 2f "Hồ sơ & tiến bộ" (#/account, #/progress)
   ========================================================================== */
.s8-prog { max-width: 1320px; margin: 0 auto; padding: 16px 22px 40px; display: flex; flex-direction: column; gap: 16px; }
.s8-prog > .card, .s8-prog > .s8-card { margin: 0; }

/* Dải số liệu — dùng chung bởi #/progress và #/account. Tự co số cột theo chỗ có,
   nên bỏ bớt một ô (streak = 0 chẳng hạn) không để lại khoảng trống. */
.s8-stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.s8-stat { min-width: 0; padding: 15px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }
.s8-stat > span { display: block; font-size: var(--fs-xs); letter-spacing: .06em; color: var(--label); font-weight: 700; }
.s8-stat > b { display: block; font-family: var(--font-head); font-size: 26px; font-weight: 800; line-height: 1.15; margin-top: 2px; }
.s8-stat > b i { font-style: normal; font-size: var(--fs-md); font-weight: 600; color: var(--muted); }
.s8-stat > small { display: block; font-size: var(--fs-sm); color: var(--muted); margin-top: 2px; }

.s8-prog-2col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.s8-prog-2col .hm-wrap { overflow-x: auto; }

/* Đầu trang hồ sơ */
.pf-chips { margin-top: 7px; }
.pf-head + .s8-stat-row { margin-top: 16px; }

@media (max-width: 899px) {
  .s8-prog-2col { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 719px) {
  .s8-prog { padding: 12px 12px 32px; }
  .s8-stat-row { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; }
  .s8-stat { padding: 12px; }
  .s8-stat > b { font-size: 21px; }
}

/* ==========================================================================
   Speak88 1b — 2b "Thư viện của tôi" (#/library)
   ========================================================================== */
.s8-lib { display: grid; grid-template-columns: 200px minmax(0, 1fr); align-items: start; min-height: 60vh; }
/* Chọn qua `.s8-lib >` cho ĐẶC HIỆU HƠN (0,2,0) luật `.s8-rail { display: none }` của
   trang chủ (0,1,0). Thư viện dùng lại lớp .s8-rail để khỏi chép lại toàn bộ kiểu dáng,
   nhưng nó KHÔNG biến mất ở khổ hẹp như rail trang chủ — ở đây rail LÀ bộ lọc, giấu đi
   là mất tính năng, nên nó chuyển thành dải chip cuộn ngang (xem @media dưới). */
.s8-lib > .s8-lib-rail { display: flex; top: 58px; }
.s8-lib-main { padding: 18px 20px 34px; gap: 16px; }
.s8-lib-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.s8-lib-head h1 { margin: 0 0 3px; font-size: var(--fs-2xl); font-weight: 800; }
.s8-lib-head p { margin: 0; font-size: var(--fs-base); color: var(--muted); }
.s8-lib-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.s8-lib-tools .search-wrap { width: 210px; flex: 0 1 210px; }
.s8-lib-tools .input { min-height: 36px; padding-block: 7px; font-size: var(--fs-sm); }
.s8-lib-sort { width: auto; min-width: 170px; font-weight: 600; }

.s8-lib-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.s8-libcard { position: relative; min-width: 0; border: 1px solid var(--line); border-radius: 10px; background: var(--card); overflow: hidden; }
.s8-libcard:hover { border-color: var(--navy); }
.s8-libcard-go { display: block; width: 100%; text-align: left; border: 0; background: none; padding: 0; font: inherit; cursor: pointer; }
.s8-libcard-art { position: relative; display: grid; place-items: center; height: 92px; font-size: 30px; }
.s8-libcard-part { position: absolute; top: 7px; left: 7px; padding: 3px 7px; border-radius: 4px; background: rgba(36,27,74,.8); color: #fff; font-size: 11px; font-weight: 700; }
.s8-libcard-flag { position: absolute; top: 7px; right: 7px; padding: 3px 7px; border-radius: 4px; font-size: 11px; font-weight: 800; }
.s8-flag-mint { background: var(--pink); color: var(--mint-on); }
.s8-flag-ink { background: var(--navy); color: #fff; }
.s8-flag-gold { background: var(--gold); color: var(--gold-on); }
.s8-libcard-body { display: block; padding: 11px 12px 13px; min-width: 0; }
.s8-libcard-body > b { display: block; font-size: var(--fs-base); line-height: 1.35; color: var(--text);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.s8-libcard-meta { display: flex; justify-content: space-between; gap: 8px; margin: 9px 0 5px; font-size: var(--fs-sm); color: var(--muted); }
.s8-libcard-meta b { color: var(--navy); }
/* Nút dấu trang nổi trên ảnh — vùng chạm 34px, đủ tách khỏi thân thẻ để không bấm nhầm. */
.s8-libcard-save { position: absolute; right: 6px; bottom: 6px; width: 34px; height: 34px; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: 999px; background: var(--card); font-size: 15px; cursor: pointer; line-height: 1; opacity: .75; }
.s8-libcard-save:hover, .s8-libcard-save.on { opacity: 1; border-color: var(--pink-d); }

@media (max-width: 1179px) { .s8-lib-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 979px) {
  .s8-lib { grid-template-columns: minmax(0, 1fr); }
  /* Rail trái thành một dải chip cuộn ngang: ở khổ này một cột 200px ăn mất nửa lưới thẻ,
     mà lưới thẻ mới là nội dung. Vẫn giữ ĐỦ mọi bộ lọc, không giấu cái nào. */
  .s8-lib > .s8-lib-rail { position: static; flex-direction: row; overflow-x: auto; gap: 8px; padding: 10px 12px;
    border-right: 0; border-bottom: 1px solid var(--line); }
  .s8-lib-rail .s8-rail-lb, .s8-lib-rail .s8-rail-note { display: none; }
  .s8-lib-rail .s8-rail-sec { flex-direction: row; gap: 6px; }
  .s8-lib-rail .s8-rail-item { flex: 0 0 auto; border: 1px solid var(--line); border-radius: 999px; padding: 7px 13px; min-height: 38px; }
  .s8-lib-rail .s8-rail-item.active { background: var(--navy); color: #fff; border-color: var(--navy); }
  .s8-lib-rail .s8-rail-item.active b { color: rgba(255,255,255,.7); }
  .s8-lib-main { padding: 14px 14px 28px; }
  .s8-lib-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .s8-lib-tools { width: 100%; }
  .s8-lib-tools .search-wrap { flex: 1 1 auto; width: auto; }
  .s8-lib-sort { flex: 1 1 auto; min-width: 0; }
}
@media (max-width: 400px) { .s8-lib-grid { grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   Speak88 1b — 2g Onboarding ba bước (#/onboarding)
   ========================================================================== */
.s8-onb { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: 24px 16px calc(24px + env(safe-area-inset-bottom)); background: var(--bg); }
.s8-onb-card { width: 100%; max-width: 460px; background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 26px 26px 24px; display: flex; flex-direction: column; }
/* Bước 3 đảo sang nền ink như mockup — đúng lúc chuyển từ "khai báo" sang "thử mic". */
.s8-onb.is-dark { background: var(--navy); }
.s8-onb.is-dark .s8-onb-card { background: var(--navy); border-color: rgba(255,255,255,.14); color: #fff; }
.s8-onb.is-dark h1 { color: #fff; }
.s8-onb.is-dark p, .s8-onb.is-dark .s8-onb-step { color: var(--on-dark); }
.s8-onb.is-dark .s8-onb-note { background: rgba(255,255,255,.07); color: var(--on-dark); }
.s8-onb.is-dark .s8-onb-note b { color: #fff; }
.s8-onb.is-dark .s8-onb-skip { color: var(--on-dark-3); }
.s8-onb.is-dark .s8-onb-back { color: var(--on-dark); }

.s8-onb-top { display: flex; align-items: center; gap: 8px; margin-bottom: 22px; }
.s8-onb-pips { display: flex; gap: 4px; margin-left: auto; }
.s8-onb-pips > i { width: 22px; height: 4px; border-radius: 2px; background: #dcd7ea; }
.s8-onb-pips > i.on { background: var(--navy); }
.s8-onb.is-dark .s8-onb-pips > i { background: rgba(255,255,255,.2); }
.s8-onb.is-dark .s8-onb-pips > i.on { background: var(--pink); }
.s8-onb-back { appearance: none; border: 0; background: none; font: inherit; font-size: var(--fs-base); font-weight: 700; color: var(--g7); cursor: pointer; padding: 4px 2px; }
.s8-onb-step { font-size: var(--fs-sm); letter-spacing: .08em; font-weight: 800; color: var(--label); }
.s8-onb-card h1 { margin: 6px 0 8px; font-size: 26px; font-weight: 800; line-height: 1.15; }
.s8-onb-card p { margin: 0 0 20px; font-size: var(--fs-md); line-height: 1.6; color: var(--t3); }

.s8-onb-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.s8-onb-chip { padding: 10px 16px; border-radius: var(--radius-md); background: #fff; border: 1px solid var(--line); font: inherit; font-size: var(--fs-md); font-weight: 700; cursor: pointer; min-height: 44px; }
.s8-onb-chip.active { background: var(--navy); color: #fff; border-color: var(--navy); }
.s8-onb-field { margin-bottom: 16px; }
.s8-onb-lb { font-size: var(--fs-sm); font-weight: 700; color: var(--g7); margin-bottom: 7px; }
.s8-onb-row { display: flex; gap: 7px; }
.s8-onb-opt { flex: 1; min-width: 0; text-align: center; padding: 11px 4px; border-radius: var(--radius-md); background: #fff; border: 1px solid var(--line); font: inherit; font-size: var(--fs-base); font-weight: 700; cursor: pointer; min-height: 44px; }
.s8-onb-opt.active { background: var(--navy); color: #fff; border-color: var(--navy); }
.s8-onb-note { margin-top: 18px; padding: 13px 14px; border-radius: 10px; background: var(--mint-bg); font-size: var(--fs-base); color: #2f6b58; line-height: 1.55; }
.s8-onb-cta { margin-top: 20px; min-height: 48px; }
.s8-onb-skip { margin-top: 12px; appearance: none; border: 0; background: none; font: inherit; font-size: var(--fs-sm); font-weight: 600; color: var(--muted); cursor: pointer; align-self: center; padding: 8px; }
.s8-onb-skip:hover { color: var(--pink-d); }

.s8-onb-mic { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 6px 0; }
.s8-onb-ring { width: 98px; height: 98px; border-radius: 999px; display: grid; place-items: center; font-size: 34px; cursor: pointer;
  background: rgba(0,229,160,.14); border: 2px solid var(--pink); }
.s8-onb-ring.live { animation: onb-pulse 1.6s ease-in-out infinite; }
@keyframes onb-pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(0,229,160,.35); } 50% { box-shadow: 0 0 0 12px rgba(0,229,160,0); } }
.s8-onb .rec-wave { height: 36px; }
.s8-onb .rec-wave > i { background: var(--pink); }
.s8-onb-micmsg { font-size: var(--fs-base); color: var(--on-dark-mint); text-align: center; min-height: 20px; }

@media (max-width: 420px) {
  .s8-onb-card { padding: 20px 18px 20px; }
  .s8-onb-card h1 { font-size: 22px; }
  .s8-onb-chip { padding: 10px 13px; font-size: var(--fs-base); }
}
