/* ============================================================================
   Shadow ZH · demo web. Ngữ pháp thị giác: hướng SƯƠNG, tông đen.
   Bản dựng gốc: mockups/mist/index.html. Đặc tả: context/ui-context.md.

   BA LUẬT CỦA HỆ NÀY, ĐỌC TRƯỚC KHI SỬA
   1. Nét kẻ, không phải hộp. Phân nhóm bằng đường 1px và khoảng trắng. Không
      card, không bóng đổ, không nền tô cho vật thường.
   2. Bán kính bằng 0 ở mọi chỗ. Ngoại lệ duy nhất là chấm tròn báo đang thu.
   3. Son (`--sz-accent`) xuất hiện ĐÚNG HAI CHỖ: nút Nạp video, và vạch trái
      của câu đang đọc. Trạng thái đang thu dùng `--sz-danger`, không dùng son.
      Thêm chỗ thứ ba là mất tác dụng của cả hai chỗ đầu.

   MỘT NỀN DUY NHẤT, KHÔNG NHÁNH SÁNG. Landing (mockups/mist) có ảnh cảnh đêm
   với vùng đen nướng sẵn trong file nên không đặt lên nền sáng được. Demo nối
   thẳng sau landing bằng một cú bấm; cho demo lật sáng là dựng lại đúng vết
   nứt đó, chỉ chậm hơn một nhịp. Extension và side panel vẫn giữ đủ hai nhánh
   theo docx/09 §9.1 — chúng sống trong giao diện của người khác.
   ========================================================================== */

:root {
  /* Bảng màu ĐỔI 2026-09-09 (D62 ①): nền trắng, accent xanh lá. Áp cho CẢ web lẫn ba
     dock extension. Nguồn chuẩn là `design-mockups/web-v2/` (D60), không phải tệp này.
     Bản tối cũ (nền #0a0a0b, đỏ son #c8442e) đã hết hiệu lực.

     XANH LÁ MANG HAI NGHĨA, CÓ CHỦ Ý: accent thương hiệu, và nghĩa "đọc khớp". Nên
     `--sz-match` bằng đúng `--sz-accent`. Kéo theo: "khác" là hổ phách, "sót" là xám.
     `docx/09` §9.1 vẫn đòi cả bốn hạng có ICON riêng — đổi màu mà bỏ icon là làm hỏng
     khả năng đọc của người mù màu, và đó là hồi quy chứ không phải đổi thẩm mỹ. */
  --sz-canvas: #ffffff;
  --sz-canvas-alt: #f2f8f1;
  --sz-surface: #f2f8f1;
  --sz-text: #101a12;
  --sz-text-soft: #4e5f52;
  --sz-text-muted: #7c8b80;
  --sz-border: #e2e9e1;
  --sz-border-strong: #cbd8c9;
  --sz-accent: #197a46;
  --sz-accent-hover: #125c35;
  --sz-on-accent: #fff;
  --sz-match: #197a46;        /* = accent, có chủ ý */
  --sz-differs: #b45309;      /* hổ phách */
  --sz-omit: #8a978c;         /* xám */
  --sz-danger: #b3261e;

  --rule: #cbd8c9;
  --rule-soft: #e2e9e1;
  --void: #e8f2e6;

  --grain: 0;                 /* hạt nhiễu là hiệu ứng của nền tối, bỏ trên nền trắng */
  --pad-x: clamp(18px, 4vw, 44px);
  --ease: cubic-bezier(.22, .61, .24, 1);

  --xanh-100: #e0f1e4;
  --xanh-300: #a8dcb8;
  --chanh: #c2f04a;           /* chỉ dùng TRÊN nền mực, và chỉ với chữ mực */
  --r-anh: 16px;
  --r-dk: 12px;

  /* Bí danh: CSS port thẳng từ `design-mockups/web-v2/` dùng tên token của mockup.
     Giữ bí danh thay vì đổi tên trong CSS port sang là để lần port sau còn dán
     nguyên được, và để chỗ lệch khỏi mockup lộ ra chứ không bị dịch ngầm. */
  --nen: var(--sz-canvas);
  --nen-dai: var(--sz-canvas-alt);
  --nen-sau: #e8f2e6;
  --muc: var(--sz-text);
  --muc-2: var(--sz-text-soft);
  --muc-3: var(--sz-text-muted);
  --vien: var(--sz-border);
  --vien-dam: var(--sz-border-strong);
  --xanh: var(--sz-accent);
  --xanh-dam: var(--sz-accent-hover);
  --ho-phach: var(--sz-differs);
  --xam-sot: var(--sz-omit);
  --do-rong: 1280px;
  --nhip: cubic-bezier(.22,.7,.2,1);
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body { position: relative; }
body {
  background: var(--void);
  color: var(--sz-text);
  font-family: Archivo, "Segoe UI", system-ui, sans-serif;
  font-variation-settings: "wdth" 100;
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
/* Hạt phim. Cùng lớp phủ với landing — thứ duy nhất nối hai trang lại với nhau
   khi demo không có ảnh nào. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 90;
  pointer-events: none; opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Vòng focus 2px chứ không 1px: WCAG 2.2 đòi đường bao dày ít nhất 2px. Màu là
   chữ chứ không phải son — son trên nền đen chỉ đạt khoảng 3,9:1, đủ cho đồ hoạ
   nhưng vòng focus là thứ phải thấy được ngay cả khi liếc qua. */
:focus-visible { outline: 2px solid var(--sz-text); outline-offset: 3px; }

/* CHẶN CỨNG. Không có dòng này thì `#replay-bar { display: flex }` và
   `#playback { display: block }` thắng luật `[hidden] { display: none }` của
   trình duyệt (id 1-0-0 so với thuộc tính 0-1-0), và cả hai khối hiện ra ngay
   từ lúc chưa nạp gì. Đây là lỗi có thật của bản trước. */
[hidden] { display: none !important; }

.sp { letter-spacing: .3em; margin-right: -.3em; }

/* ══════════════════ ba họ chữ, ba vai ══════════════════ */
/* NOTO SERIF SC CHỈ CHO CHỮ HÁN, KHÔNG BAO GIỜ CHO TIẾNG VIỆT.
   Đo trong Chrome 2026-08-25 bằng `document.fonts.check`: bộ này KHÔNG có glyph
   `ừ`, `ộ`, `ụ`, `ỗ`. Đặt một tiêu đề tiếng Việt vào nó thì trình duyệt thay
   từng ký tự một bằng serif dự phòng của hệ điều hành, và một từ như "từng"
   hiện ra bằng hai mặt chữ khác nhau. Rất khó thấy, và thấy rồi thì cả trang
   đọc ra là cẩu thả. Danh sách dưới đây chỉ gồm chỗ chắc chắn là chữ Hán. */
.hanzi, #dock-hanzi, .line .h, .tok b, .crest .zh {
  font-family: "Noto Serif SC", "PingFang SC", "Microsoft YaHei", serif;
  font-weight: 300;
}
/* Chivo Mono cho MỌI THỨ ĐO ĐƯỢC — pinyin, phần trăm, thời lượng, URL. Không
   dùng làm trang phục "kỹ thuật" cho câu chữ thường; dòng trạng thái là câu
   tiếng Việt nên nó dùng chữ thường, không dùng mono. */
.mono, #dock-pinyin, .line .p, .tok i, .badge, #url, #summary, .line .no {
  font-family: "Chivo Mono", ui-monospace, "Cascadia Mono", monospace;
  font-weight: 200;
}
/* Tiêu đề tiếng Việt: Archivo, trục `wdth`. Cái sang của bản tham chiếu nằm ở
   chữ MẢNH VÀ GIÃN, không nằm ở chân chữ, nên bỏ serif ở đây không mất gì. */
.intro h1, .lyrics-head h2 {
  font-family: Archivo, "Segoe UI", system-ui, sans-serif;
  font-variation-settings: "wdth" 108;
  font-weight: 300;
}

/* ══════════════════ thanh đầu trang ══════════════════ */
/* ĐÈ lên ảnh chứ không nằm trên nó: một thanh có nền và có nét dưới sẽ cắt ngang đầu
   ảnh thành một dải riêng. Chữ ở đây luôn sáng vì luôn nằm trên ảnh đêm. */
.crest {
  position: absolute; top: 0; left: 0; right: 0; z-index: 5;
  display: flex; align-items: center; gap: 13px;
  padding: 17px var(--pad-x);
  color: #f4f2ef;
}
.crest .bar { background: #f4f2ef4d; }
.crest .en { color: #f4f2efab; }
.crest .zh {
  font-family: "Noto Serif SC", serif; font-weight: 400;
  font-size: 15px; letter-spacing: .2em; margin-right: -.2em;
}
.crest .bar { width: 1px; height: 13px; background: var(--rule); flex: none; }
.crest .en {
  font-size: 10px; font-weight: 500; letter-spacing: .28em;
  text-transform: uppercase; color: var(--sz-text-muted);
  font-variation-settings: "wdth" 112;
}


/* ============================================================================
   MÀN 1 và DẢI BỐN BƯỚC — lấy nguyên văn từ mockups/mist/index.html.
   Sửa ở một bên phải sửa bên kia, hoặc xoá hẳn bản mockup đi. Hai chỗ khác:
   `.crest` ở trên đã đổi thành lớp đè, và mọi luật `.mist .entry` bị bỏ vì màn 1
   không còn ô nhập — ô nhập chỉ có một, ở màn công cụ.
   ========================================================================== */
/* `.mist` là flex column, nên mọi con của nó mặc định KÉO GIÃN hết chiều ngang, và khung
   kẻ bọc hai chữ 影子 là `inline-grid` nên bị kéo thành một dải ngang suốt màn.
   Trừ lớp ảnh ra: với con `position:absolute` của một flex container, `align-self` khác
   `stretch` làm hộp co về vừa-nội-dung, mà lớp ảnh không có nội dung nào, nên nó cao đúng
   0 và ảnh biến mất hoàn toàn. Cả hai đều là lỗi đã dính — context/ui-context.md điều 4. */
.mist>*:not(.photo){flex:0 0 auto;align-self:center;min-width:0}

/* ══════════════════ MÀN 1 · sương ══════════════════ */
.mist{
  position:relative;isolation:isolate;
  display:flex;flex-direction:column;justify-content:flex-end;
  min-height:min(100svh,1040px);
  padding:clamp(96px,16vh,150px) var(--pad-x) clamp(40px,6vh,72px);
  text-align:center;overflow:hidden;
  background:var(--void);
}
/* Ảnh nền màn 1: một tấm duy nhất, tràn khung, KHÔNG đổi theo chủ đề sáng tối.
   Ảnh là cảnh đêm nên chữ trên màn này luôn là chữ sáng, ở cả hai chủ đề. Đó là
   ngoại lệ có chủ ý và chỉ áp cho màn 1; từ màn 2 trở xuống chữ theo token. */
.mist .photo{
  position:absolute;inset:0;z-index:-3;
/* Neo MÉP DƯỚI, không phải mép trên. Vùng đen nướng sẵn nằm ở đáy ảnh; neo mép
   trên thì màn càng rộng so với cao, cover càng cắt cụt phần đáy đó, và mối hàn
   giữa ảnh với nền trang lộ ra thành một đường ngang. Neo mép dưới thì phần bị
   cắt là khoảng trời phía trên, thứ không ai để ý. */
  background:#000 center bottom/cover no-repeat;
  background-image:image-set(url("img/home.webp") type("image/webp"), url("img/home.jpg"));
}

/* Sương xếp thành lớp như một thung lũng: dải sáng thấp và rộng ở dưới, hai dải
   mờ hơn cao dần, một quầng đứng sau khung chữ. Bản đầu để alpha 14% rồi phủ
   vignette lên, kết quả là màn hình đen trơn: sương không đọc ra được gì. */
.mist::before{
  content:"";position:absolute;inset:-12% -6%;z-index:-2;
  background:radial-gradient(120% 50% at 50% 22%, #ffffff0a 0%, transparent 66%);
}
.mist::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,
    #000000b8 0%, #00000045 13%, transparent 30%,
    #0000008c 56%, #000000e6 74%, #000 88%, var(--void) 100%);
}
/* Chữ của màn 1 nằm trên ảnh đêm nên tự mang màu sáng, không lấy token. */
.mist,.mist .claim{color:#f4f2ef}
.mist .creed{color:#f4f2efd6}
.mist .rubric{color:#f4f2efab}
.mist .seal-frame{border-color:#f4f2ef4d}
.mist .seal-frame span{color:#fff}

/* Dòng chữ Latin nghiêng bé phía trên khung. Ở bản tham chiếu chỗ này là một cụm
   trang trí. Ở đây nó là PINYIN, tức là cách đọc bốn chữ trong khung, nên nó mang
   thông tin chứ không phải để đẹp. */
.rubric{
  margin:0 0 clamp(20px,3vh,30px);
  font-family:"Cormorant Garamond",Georgia,serif;font-style:italic;font-weight:300;
  font-size:clamp(15px,1.7vw,19px);letter-spacing:.12em;color:var(--sz-text-soft);
}

/* Khung kẻ mảnh bọc bốn chữ. Đây là hình chữ ký của bản tham chiếu. */
.seal-frame{
  display:inline-grid;grid-template-columns:repeat(2,auto);
  gap:0 clamp(6px,1.6vw,20px);
  padding:clamp(14px,2.2vw,26px) clamp(18px,2.8vw,34px);
  border:1px solid var(--rule);
}
.seal-frame span{
  font-family:"Noto Serif SC",serif;font-weight:200;
  font-size:clamp(56px,9.6vw,128px);line-height:1.02;
  color:var(--sz-text);
}

.creed{
  margin:clamp(26px,4vh,42px) auto 0;max-width:44ch;
  font-size:clamp(12.5px,1.25vw,14px);line-height:2.35;
  color:var(--sz-text-soft);
}
.creed p{margin:0}
.claim{
  margin:clamp(22px,3.4vh,36px) 0 0;
  font-weight:300;font-variation-settings:"wdth" 106;letter-spacing:.03em;
  font-size:clamp(19px,2.5vw,29px);color:var(--sz-text);
}

/* Ô nhập. Nét kẻ mảnh, không hộp, không bo góc, đúng ngữ pháp của bản tham chiếu.
   Nhãn nằm TRÊN, không nhét vào placeholder: placeholder biến mất ngay khi gõ. */
.entry{margin:0 auto;max-width:680px;width:100%;text-align:left}
.entry label{
  display:block;margin:0 0 12px;
  font-size:10px;letter-spacing:.26em;text-transform:uppercase;
  color:var(--sz-text-muted);font-variation-settings:"wdth" 112;
}
.entry .line{display:flex;align-items:stretch;gap:0;border-bottom:1px solid var(--rule)}
.entry input{
  flex:1;min-width:0;border:0;background:transparent;color:var(--sz-text);
  padding:12px 0;
  font-family:"Chivo Mono",ui-monospace,monospace;font-size:14.5px;font-weight:200;
  letter-spacing:.02em;
}
.entry input::placeholder{color:var(--sz-text-muted);opacity:1}
.entry input:focus{outline:none}
.entry .line:focus-within{border-bottom-color:var(--sz-text)}
/* Con dấu. Một trong đúng hai chỗ có màu son trên cả trang.
   Nhãn là chữ Việt chứ không phải một chữ Hán: nút phải nói nó làm gì. Hình con
   dấu giữ lại ở khối son và ở nét chữ, không phải ở việc đố người dùng đọc chữ. */
.entry button{
  display:inline-flex;align-items:center;gap:9px;
  flex:none;border:0;background:var(--sz-accent);color:var(--sz-on-accent);
  font:inherit;font-size:13.5px;font-weight:600;letter-spacing:.02em;
  padding:0 clamp(20px,2.6vw,30px);margin:0 0 -1px;
  cursor:pointer;
  transition:background-color .3s var(--ease),transform .16s var(--ease);
}
.entry button .sz-icon{
  width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;
}
.entry button:hover{background:var(--sz-accent-hover)}
.entry button:active{transform:translateY(1px)}

/* Cặp chú thích hai dòng của bản tham chiếu, dùng cho số liệu THẬT. */
/* ══════════════════ MÀN 2 · dải bốn bước ══════════════════ */
.band{background:var(--void);padding:clamp(58px,9vh,104px) 0 clamp(46px,7vh,84px)}
/* KHÔNG dùng Noto Serif SC cho câu tiếng Việt. Đo trong Chrome 2026-08-25:
   bộ này thiếu glyph ừ, ộ, ụ, ỗ, nên "Một cụm đi qua bốn bước" hiện ra bằng hai
   mặt chữ trộn nhau. Archivo trục wdth giữ được cái mảnh và giãn của bản tham
   chiếu mà không phải mượn chân chữ. Serif chỉ dành cho chữ Hán. */
.band-title{
  margin:0 auto clamp(38px,5.5vh,64px);padding:0 var(--pad-x);
  text-align:center;font-weight:300;font-variation-settings:"wdth" 108;
  font-size:clamp(17px,2.1vw,24px);letter-spacing:.02em;color:var(--sz-text);
}
.band-title i{font-style:normal;color:var(--sz-text-muted);padding:0 .5em}
.band-title b{font-weight:400}

/* Hồi bốn ô là ẢNH thì dải tràn sát hai mép màn hình, đúng bản tham chiếu. Giờ
   là chữ, tràn sát mép thành cụt chữ, nên trả lại lề như phần còn lại của trang. */
.strip{
  display:grid;grid-template-columns:repeat(4,1fr);gap:0;
  padding:0 var(--pad-x);max-width:1680px;margin:0 auto;
}
.step{position:relative;text-align:center;padding:0 clamp(12px,1.8vw,26px)}
.step+.step{box-shadow:inset 1px 0 0 var(--rule-soft)}

/* Bản trước để bốn tấm ảnh chụp ở đây. Bỏ. Ảnh chụp một người đeo tai nghe chỉ
   nói được "đang học", không nói được bước này khác bước kia chỗ nào. Thay bằng
   CHÍNH MẢNH GIAO DIỆN mà bước đó chạm tới: cụm đang đọc, nút thu, thẻ đối
   chiếu, danh sách câu. Mỗi mảnh dựng bằng đúng component của sản phẩm. */
.vig{
  display:grid;place-items:center;align-content:center;
  min-height:clamp(156px,17vw,208px);
}

/* I · cụm đang đọc */
.v-phrase{display:grid;gap:9px;justify-items:center;width:100%}
.v-phrase .py{
  font-family:"Chivo Mono",ui-monospace,monospace;font-weight:200;
  font-size:10.5px;letter-spacing:.2em;color:var(--sz-text-muted);
}
.v-phrase .hz{
  font-family:"Noto Serif SC",serif;font-weight:200;
  font-size:clamp(21px,2.4vw,28px);line-height:1.3;
  padding:11px clamp(12px,1.6vw,20px);border:1px solid var(--rule);
}
/* Canh đúng mép khung chữ chứ không phải canh giữa cột: lệch vài pixel ở đây
   đọc ra là hỏng chứ không phải là thoáng. */
.v-phrase{position:relative}
.v-phrase .pl{
  height:1px;background:var(--rule-soft);margin-top:3px;
  width:clamp(148px,15vw,196px);
}
.v-phrase .pl i{display:block;height:100%;background:var(--sz-text);width:42%}

/* II · nút thu, đang thu */
.v-rec{display:grid;gap:16px;justify-items:center}
.v-rec .btn{
  display:inline-flex;align-items:center;gap:9px;
  border:1px solid var(--sz-danger);background:transparent;
  color:var(--sz-danger);font:inherit;font-size:12.5px;padding:9px 18px;
}
.v-rec .btn .sz-icon{
  width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;
}
.v-rec .btn .dot{width:6px;height:6px;border-radius:50%;background:currentColor}
@media (prefers-reduced-motion:no-preference){
  .v-rec .btn .dot{animation:sz-pulse 1.1s ease-in-out infinite alternate}
}
@keyframes sz-pulse{from{opacity:.3}to{opacity:1}}
/* Sóng tiếng: chín vạch, cao thấp cố định. Không phải hình trang trí, nó là thứ
   duy nhất trên trang nói được rằng bước này có TIẾNG đi vào. */
.v-rec .wave{display:flex;align-items:center;gap:4px;height:26px}
.v-rec .wave i{width:2px;background:var(--sz-text-soft)}
.v-rec .wave i:nth-child(1),.v-rec .wave i:nth-child(9){height:6px}
.v-rec .wave i:nth-child(2),.v-rec .wave i:nth-child(8){height:13px}
.v-rec .wave i:nth-child(3),.v-rec .wave i:nth-child(7){height:22px}
.v-rec .wave i:nth-child(4),.v-rec .wave i:nth-child(6){height:16px}
.v-rec .wave i:nth-child(5){height:26px}

/* III · thẻ đối chiếu */
.v-toks{display:flex;flex-wrap:wrap;justify-content:center;gap:9px}
.v-toks .tok{padding:0 3px 8px;border-bottom:1px solid var(--rule)}
.v-toks .tok b{font-family:"Noto Serif SC",serif;font-weight:300;font-size:23px;line-height:1.15;display:block}
.v-toks .tok i{
  display:block;margin-top:4px;
  font-family:"Chivo Mono",ui-monospace,monospace;font-style:normal;font-weight:200;
  font-size:9.5px;letter-spacing:.06em;color:var(--sz-text-muted);
}
.v-toks .tok.match{border-bottom-color:var(--sz-match)}
.v-toks .tok.differs{border-bottom-color:var(--sz-differs)}
.v-toks .tok.differs b,.v-toks .tok.differs i{color:var(--sz-differs)}
.v-toks .tok.missing b,.v-toks .tok.missing i{color:var(--sz-omit)}

/* IV · danh sách câu */
.v-lines{width:100%;max-width:250px;display:grid;gap:0;text-align:left}
.v-lines div{
  display:flex;align-items:center;gap:10px;padding:9px 9px 9px 2px;
  border-bottom:1px solid var(--rule-soft);background:transparent;
  font-family:"Noto Serif SC",serif;font-weight:300;font-size:14px;
  color:var(--sz-text-muted);white-space:nowrap;
}
.v-lines div:last-child{border-bottom:0}
.v-lines div span{
  margin-left:auto;flex:none;
  font-family:"Chivo Mono",ui-monospace,monospace;font-weight:200;font-size:9.5px;
  letter-spacing:.06em;
}
.v-lines .now{
  color:var(--sz-text);background:var(--sz-surface);
  box-shadow:inset 2px 0 0 var(--sz-accent);padding-left:12px;
}

/* Viên nang xám của bản tham chiếu. Đây là vật DUY NHẤT trên trang có góc bo. */
.lozenge{
  display:inline-flex;align-items:center;gap:0;
  margin:clamp(22px,3.2vh,34px) auto 0;padding:11px clamp(22px,3vw,34px);
  border-radius:999px;background:var(--sz-surface);
  box-shadow:inset 0 0 0 1px var(--rule-soft);
  font-size:12.5px;color:var(--sz-text);letter-spacing:.02em;
}
.lozenge .bar{width:1px;height:13px;background:var(--rule);margin:0 13px}
.lozenge .sz-icon{
  width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;color:var(--sz-text-soft);
}
.step .cap{margin:clamp(14px,2vh,20px) 0 0}
.step .cap .a{font-size:12.5px;line-height:1.65;color:var(--sz-text-soft)}
.step .cap .b{
  margin-top:7px;
  font-family:"Chivo Mono",ui-monospace,monospace;font-weight:200;
  font-size:10px;letter-spacing:.2em;color:var(--sz-text-muted);
}
.step .cap .b i{
  font-family:"Noto Serif SC",serif;font-style:normal;font-size:12.5px;
  letter-spacing:0;color:var(--sz-text-soft);margin-right:7px;
}


/* ══════════════════ MÀN 3 · công cụ thật ══════════════════ */
/* Cùng nền, cùng lề với dải bốn bước bên trên, nên chỗ nối không thành một vạch. */
.live {
  background: var(--void);
  padding: clamp(54px, 8.5vh, 100px) var(--pad-x) clamp(60px, 9vh, 108px);
}
.live .band-title { margin-bottom: clamp(30px, 4.4vh, 50px); }
.stage { max-width: 880px; margin: 0 auto; }

/* ══════════════════ lời mở ══════════════════ */
.intro { padding: clamp(34px, 6vh, 62px) 0 clamp(28px, 4vh, 44px); }
.intro h1 {
  margin: 0; font-size: clamp(20px, 2.6vw, 27px); line-height: 1.35;
  letter-spacing: .01em;
}
.intro .note {
  margin: 16px 0 0; max-width: 62ch;
  font-size: 13px; line-height: 1.85; color: var(--sz-text-soft);
}
.intro .note strong { font-weight: 500; color: var(--sz-text); }

/* ══════════════════ ô nhập ══════════════════ */
/* Nhãn nằm TRÊN, không nhét vào placeholder: placeholder biến mất ngay khi gõ,
   và lúc đó người dùng không còn cách nào biết ô này chờ cái gì. */
.entry { margin: 0; }
.entry label {
  display: block; margin: 0 0 11px;
  font-size: 10px; letter-spacing: .26em; text-transform: uppercase;
  color: var(--sz-text-muted); font-variation-settings: "wdth" 112;
}
.entry .line-in {
  display: flex; align-items: stretch;
  border-bottom: 1px solid var(--rule);
  transition: border-color .3s var(--ease);
}
.entry .line-in:focus-within { border-bottom-color: var(--sz-text); }
#url {
  flex: 1 1 auto; min-width: 0;
  border: 0; background: transparent; color: var(--sz-text);
  padding: 12px 0; font-size: 14px; letter-spacing: .02em;
}
#url::placeholder { color: var(--sz-text-muted); opacity: 1; }
#url:focus { outline: none; }

/* Nút Nạp. Chỗ son thứ nhất. Nhãn là chữ Việt, không phải một chữ Hán — nút
   phải nói nó làm gì, không đố người dùng đọc chữ. */
#load {
  flex: none; display: inline-flex; align-items: center; gap: 9px;
  border: 0; margin: 0 0 -1px; padding: 0 clamp(18px, 2.4vw, 28px);
  background: var(--sz-accent); color: var(--sz-on-accent);
  font: inherit; font-size: 13.5px; font-weight: 600; letter-spacing: .02em;
  cursor: pointer;
  transition: background-color .3s var(--ease), transform .16s var(--ease);
}
#load:hover { background: var(--sz-accent-hover); }
#load:active { transform: translateY(1px); }

/* ══════════════════ icon ══════════════════ */
/* Path lấy nguyên văn từ demo/youtube.js §icon (nét Tabler, MIT). Nét đi 1,6px
   thay vì 2px cho khớp với nét kẻ 1px của trang. */
.sz-icon {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ══════════════════ dòng trạng thái ══════════════════ */
/* Trạng thái là CÂU, không phải toast. Theo spike S2 chỉ 11/32 video dùng được,
   nên màn hình trượt phải được thiết kế ngang màn hình thành công: nó ở đúng
   một chỗ cố định, không thoáng qua, và luôn nói phải làm gì tiếp. */
#status {
  margin: clamp(22px, 3.4vh, 32px) 0 0;
  padding: 10px 0 10px 14px;
  border-left: 1px solid var(--rule);
  font-size: 13px; line-height: 1.75; letter-spacing: .005em;
  color: var(--sz-text-soft); min-height: 40px;
}

/* ══════════════════ trình phát và dock ══════════════════ */
#stage { margin: clamp(20px, 3vh, 30px) 0 0; }
#player {
  position: relative; aspect-ratio: 16 / 9; background: #000;
  border: 1px solid var(--rule-soft);
  display: grid; place-items: center;
}
/* Lúc chưa có iframe thì KHÔNG giữ khung 16:9. Một ô đen cao gần nửa nghìn
   pixel là thứ to nhất màn hình đầu, và nó đẩy cả hàng nút xuống dưới nếp gấp
   khi trang chưa có gì để xem. Có iframe rồi mới cần đúng tỉ lệ. */
#player[data-empty] { aspect-ratio: auto; min-height: clamp(116px, 17vh, 164px); }
/* Ô trống nói đang chờ gì, thay vì để một hình chữ nhật đen câm. */
#player[data-empty]::before {
  content: attr(data-empty);
  font-family: "Chivo Mono", ui-monospace, monospace; font-weight: 200;
  font-size: 11px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--sz-omit); text-align: center; padding: 0 24px;
}
#player iframe { display: block; width: 100%; height: 100%; border: 0; }

/* Khung kẻ mảnh bọc chữ Hán lớn — hình chữ ký của hệ này, dịch thẳng từ bản
   tham chiếu. Ở đây nó bọc CỤM ĐANG ĐỌC, chữ quan trọng nhất trên màn hình. */
#dock {
  border: 1px solid var(--rule-soft); border-top: 0;
  background: var(--sz-canvas-alt);
  padding: clamp(20px, 3vw, 30px) clamp(18px, 2.6vw, 28px) 0;
  text-align: center;
}
#dock-pinyin {
  font-size: 12px; letter-spacing: .22em; color: var(--sz-text-muted);
}
#dock-hanzi {
  display: inline-block; margin: 14px 0 0;
  padding: 14px clamp(16px, 2.6vw, 28px);
  border: 1px solid var(--rule);
  font-size: clamp(26px, 4vw, 44px); line-height: 1.24;
  letter-spacing: .06em; margin-right: -.06em;
}
#dock-native { margin: 14px 0 0; font-size: 13.5px; color: var(--sz-text-soft); }
/* Không có dòng nghĩa thì nói thẳng, đừng để trống cho người dùng đoán. */
#dock-native.missing { color: var(--sz-text-muted); font-size: 12.5px; font-style: italic; }
/* Thanh tiến độ của cụm. 1px, đúng bề dày nét kẻ của trang. */
#dock .prog {
  height: 1px; background: var(--rule-soft);
  margin: clamp(18px, 2.6vw, 26px) calc(-1 * clamp(18px, 2.6vw, 28px)) 0;
}
#dock .prog i {
  display: block; height: 100%; width: 100%; background: var(--sz-text);
  transform: scaleX(0); transform-origin: left;
}

/* ══════════════════ hàng nút ══════════════════ */
/* Bốn ô sát nhau, chia đều, ngăn bằng nét mảnh — cùng ngữ pháp với dải bốn bước
   của landing, nên hai trang đọc ra là một hệ. */
.acts {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--rule-soft); border-top: 0;
}
.acts.second { grid-template-columns: repeat(2, 1fr); }
.acts button {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  border: 0; border-left: 1px solid var(--rule-soft);
  background: transparent; color: var(--sz-text-soft);
  font: inherit; font-size: 12.5px; padding: 15px 8px;
  cursor: pointer; text-align: center;
  transition: color .3s var(--ease), background-color .3s var(--ease);
}
.acts.second button { font-size: 11.5px; color: var(--sz-text-muted); padding: 12px 8px; }
/* Nhãn nút KHÔNG được xuống dòng: một nút hai dòng nằm giữa hàng bốn nút một
   dòng đọc ra là lỗi bố cục. Nhãn dài nhất là "Đang nghe… bấm để dừng", nên
   trạng thái đang thu hạ cỡ chữ xuống cho vừa thay vì cho nó gãy đôi. */
.acts button .lbl { white-space: nowrap; }
#rec.recording .lbl { font-size: 11.5px; }
.acts.second button .lbl { white-space: normal; line-height: 1.35; }
.acts button:first-child { border-left: 0; }
.acts button:hover:not(:disabled) { color: var(--sz-text); background: var(--sz-surface); }
.acts button:disabled { opacity: .38; cursor: default; }

/* Đang thu. Nét dưới và chữ đỏ nhạt, KHÔNG tô đặc cả ô: một khối đặc nằm giữa
   một hàng toàn nét mảnh đọc ra như lỗi bố cục chứ không như trạng thái. Chấm
   nhấp nháy là dấu hiệu thứ hai, để không truyền tin chỉ bằng màu. */
#rec .sz-icon-stop { display: none; }
#rec.recording .sz-icon-mic { display: none; }
#rec.recording .sz-icon-stop { display: block; }
#rec.recording {
  color: var(--sz-danger);
  background: color-mix(in srgb, var(--sz-danger) 9%, transparent);
  box-shadow: inset 0 -1px 0 var(--sz-danger);
}
#rec.recording::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: none;
}
@media (prefers-reduced-motion: no-preference) {
  #rec.recording::after { animation: sz-pulse 1.1s ease-in-out infinite alternate; }
}
@keyframes sz-pulse { from { opacity: .28 } to { opacity: 1 } }

/* ══════════════════ thanh xem lại ══════════════════ */
#replay-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: clamp(16px, 2.4vh, 22px) 0 0; padding: 11px 14px;
  border: 1px solid var(--rule); background: var(--sz-surface);
  font-size: 12.5px;
}
#replay-what { font-weight: 500; }
#replay-bar .hint { color: var(--sz-text-muted); font-size: 12px; }
#replay-bar button {
  margin-left: auto; display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--rule); background: transparent; color: var(--sz-text);
  font: inherit; font-size: 12px; padding: 6px 14px; cursor: pointer;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
#replay-bar button:hover { border-color: var(--sz-text); }

/* ══════════════════ đối chiếu ══════════════════ */
#feedback { margin: clamp(30px, 4.4vh, 48px) 0 0; }
#heard {
  min-height: 22px; font-size: 13px; color: var(--sz-text-soft);
  padding-left: 14px; border-left: 1px solid var(--rule-soft);
}
/* Chưa thu lần nào thì không có gì để trích. Không có luật này thì còn lại một
   đoạn nét kẻ dọc 22px lửng lơ giữa trang, trông như hỏng chứ không như trống. */
#heard:empty { display: none; }
#overrun:empty { display: none; }
#verdict {
  display: flex; flex-wrap: wrap; gap: clamp(9px, 1.6vw, 18px);
  margin: clamp(18px, 2.6vh, 26px) 0 0;
}
/* Thẻ không có nền, chỉ một nét dưới chân. Bốn hạng, ba màu: sót và thừa dùng
   CHUNG `--sz-omit` theo §9.1, nên hai hạng đó chỉ phân biệt được bằng icon —
   icon ở đây là bắt buộc, không phải trang trí. */
.tok {
  display: grid; justify-items: center; gap: 5px;
  padding: 0 4px 8px; border-bottom: 1px solid var(--rule-soft);
}
.tok b { font-size: 26px; line-height: 1; font-weight: 300; }
.tok i {
  font-style: normal; font-size: 10px; letter-spacing: .08em;
  color: var(--sz-text-muted);
}
.tok .sz-icon { width: 12px; height: 12px; stroke-width: 1.8; }
.tok.match { border-bottom-color: var(--sz-match); }
.tok.match .sz-icon { color: var(--sz-match); }
.tok.differs { border-bottom-color: var(--sz-differs); }
.tok.differs b, .tok.differs i, .tok.differs .sz-icon { color: var(--sz-differs); }
.tok.missing, .tok.extra { border-bottom-color: var(--rule); }
.tok.missing b, .tok.missing i, .tok.missing .sz-icon,
.tok.extra b, .tok.extra i, .tok.extra .sz-icon { color: var(--sz-omit); }

#overrun {
  min-height: 18px; margin: 14px 0 0;
  font-size: 12.5px; color: var(--sz-differs);
}
#playback { display: block; width: 100%; max-width: 420px; margin: 14px 0 0; }

.fineprint {
  margin: clamp(20px, 3vh, 28px) 0 0; max-width: 66ch;
  font-size: 12px; line-height: 1.9; color: var(--sz-text-muted);
}
.fineprint strong { color: var(--sz-text-soft); font-weight: 500; }
.k {
  display: inline-flex; align-items: center; gap: 4px;
  font-weight: 500; white-space: nowrap;
}
.k .sz-icon { width: 12px; height: 12px; }
.k.match { color: var(--sz-match); }
.k.differs { color: var(--sz-differs); }
.k.missing, .k.extra { color: var(--sz-text-soft); }

/* ══════════════════ lời bài ══════════════════ */
#lyrics { margin: clamp(44px, 6.5vh, 76px) 0 0; }
.lyrics-head {
  display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
  padding-bottom: 12px; border-bottom: 1px solid var(--rule);
}
.lyrics-head h2 { margin: 0; font-size: 17px; letter-spacing: .02em; }
#summary { font-size: 11.5px; letter-spacing: .04em; color: var(--sz-text-muted); }
#evict { font-size: 11.5px; color: var(--sz-differs); }

#lines {
  list-style: none; margin: 0; padding: 0;
  max-height: 460px; overflow-y: auto;
}
.line {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 12px 12px 12px 2px;
  border-bottom: 1px solid var(--rule-soft); cursor: pointer;
  transition: background-color .25s var(--ease);
}
.line:last-child { border-bottom: 0; }
.line:hover { background: var(--sz-surface); }
/* Chỗ son thứ hai và cuối cùng. Vạch 2px bên trái, giữ đúng hình của dock
   trong extension để hai bề mặt đọc ra cùng một quy ước. */
.line.cur {
  background: var(--sz-surface);
  box-shadow: inset 2px 0 0 var(--sz-accent);
  padding-left: 12px;
}
.line .no {
  min-width: 26px; padding-top: 5px; flex: none;
  font-family: "Chivo Mono", ui-monospace, monospace; font-weight: 200;
  font-size: 11px; color: var(--sz-omit);
}
.line .body { flex: 1 1 auto; min-width: 0; }
.line .p { font-size: 11px; letter-spacing: .1em; color: var(--sz-text-muted); }
.line .h { font-size: 17px; line-height: 1.5; margin-top: 2px; }
.line .n { font-size: 12.5px; color: var(--sz-text-soft); margin-top: 3px; }
.line.cur .h { color: var(--sz-text); }

/* Điểm khớp của LẦN ĐỌC GẦN NHẤT ở câu đó. Không có bản ghi thì không có huy
   hiệu — chỗ trống nghĩa là chưa luyện, không phải điểm 0. */
.badge {
  flex: none; min-width: 40px; text-align: right; padding-top: 4px;
  font-size: 11.5px; letter-spacing: .04em; color: var(--sz-text-muted);
}
.badge.good { color: var(--sz-match); }
.badge.mid { color: var(--sz-differs); }
.badge.low { color: var(--sz-danger); }
.badge.rec { color: var(--sz-text-soft); }

/* ══════════════════ chân trang ══════════════════ */
footer {
  border-top: 1px solid var(--rule-soft);
  padding: clamp(28px, 4vh, 44px) var(--pad-x);
  text-align: center;
}
footer p {
  margin: 0 auto; max-width: 64ch;
  font-size: 11.5px; line-height: 1.95; color: var(--sz-text-muted);
}

/* ══════════════════ co giãn ══════════════════ */
@media (max-width: 720px) {
  .acts { grid-template-columns: repeat(2, 1fr); }
  .acts button:nth-child(3) { border-left: 0; }
  .acts button:nth-child(n+3) { border-top: 1px solid var(--rule-soft); }
  /* Giấu chữ Latin thì giấu luôn gạch ngăn — bỏ một mình chữ đi thì còn lại
     một vạch đứng không ngăn cách gì cả. */
  .crest .en, .crest .bar { display: none; }
}
@media (max-width: 520px) {
  .entry .line-in { flex-wrap: wrap; }
  #load { width: 100%; justify-content: center; padding: 12px; margin: 0; }
  .acts, .acts.second { grid-template-columns: 1fr; }
  .acts button { border-left: 0; border-top: 1px solid var(--rule-soft); }
  .acts button:first-child { border-top: 0; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

/* ============================================================================
   GIỚI THIỆU & GIÁ — thêm 2026-09-07. Trang bắt đầu BÁN, và đó là lý do luật 3
   ở đầu tệp phải nới: son nay ở BA chỗ — Nạp video · vạch câu đang đọc · nút
   Nâng cấp. Nút cài thì KHÔNG son: cài là miễn phí, trả tiền mới là quyết định.
   Hai hành động trả tiền cùng một màu là hai hành động ngang nhau; chúng không.
   Vẫn nét kẻ, vẫn bán kính 0, vẫn không card.
   ========================================================================== */

/* ── lối đi ở crest ──────────────────────────────────────────────────────── */
.crest .loi-di {
  margin-left: auto; display: flex; gap: 22px;
  font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
  font-variation-settings: "wdth" 112;
}
.crest .loi-di a { color: #f4f2efab; text-decoration: none; padding: 4px 0; border-bottom: 1px solid transparent; }
.crest .loi-di a:hover { color: #f4f2ef; border-bottom-color: #f4f2ef4d; }

/* ── màn cài & ba nền tảng ───────────────────────────────────────────────── */
.cai .noi {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
  max-width: 1120px; margin: 0 auto; padding: 0 var(--pad-x);
}
.cai .noi article { padding: 6px clamp(14px, 2vw, 30px) 10px; }
.cai .noi article + article { box-shadow: inset 1px 0 0 var(--rule-soft); }
.cai .noi .ten {
  font-size: 20px; font-weight: 300; letter-spacing: .01em; margin-bottom: 8px;
  font-variation-settings: "wdth" 108;
}
.cai .noi .phu { font-size: 11px; letter-spacing: .16em; color: var(--sz-text-muted); margin-left: 8px; vertical-align: 3px; }
.cai .noi p { margin: 0; font-size: 13px; line-height: 1.7; color: var(--sz-text-soft); max-width: 34ch; }

.cai-nut { text-align: center; margin-top: clamp(36px, 5vh, 56px); padding: 0 var(--pad-x); }
.nut-cai {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 24px; border: 1px solid var(--sz-border-strong);
  color: var(--sz-text); text-decoration: none;
  font-size: 13.5px; font-weight: 500; letter-spacing: .02em;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.nut-cai[href]:hover { border-color: var(--sz-text); background: var(--sz-surface); }
.nut-cai[aria-disabled="true"] { color: var(--sz-text-muted); border-color: var(--rule-soft); cursor: default; }
.cai-ghi, .gia-ghi {
  margin: 16px auto 0; max-width: 56ch;
  font-size: 12px; line-height: 1.8; color: var(--sz-text-muted);
}

/* ── màn giá ─────────────────────────────────────────────────────────────── */
.so-sanh {
  max-width: 760px; margin: 0 auto; padding: 0 var(--pad-x);
  font-size: 13.5px;
}
.so-sanh .hang {
  display: grid; grid-template-columns: 1fr 92px 112px; align-items: center;
  padding: 11px 0; border-bottom: 1px solid var(--rule-soft);
}
.so-sanh .hang.dau {
  border-bottom-color: var(--rule);
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--sz-text-muted);
}
.so-sanh .hang > div:not(:first-child) { text-align: center; }
.so-sanh [role="rowheader"] { color: var(--sz-text-soft); }
.so-sanh i { font-style: normal; }
.so-sanh i.co { color: var(--sz-match); font-size: 12px; letter-spacing: .08em; }
.so-sanh i.khong { color: var(--sz-omit); }

.bang-gia {
  list-style: none; margin: clamp(34px, 5vh, 52px) auto 0; padding: 0 var(--pad-x);
  max-width: 760px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
  border-top: 1px solid var(--rule-soft); border-bottom: 1px solid var(--rule-soft);
}
.bang-gia li { padding: 22px clamp(14px, 2vw, 26px); border-left: 2px solid transparent; }
.bang-gia li + li { box-shadow: inset 1px 0 0 var(--rule-soft); }
/* Son, chỗ thứ hai — cùng dấu hiệu "vạch trái" với câu đang đọc. */
.bang-gia li.noi { border-left-color: var(--sz-accent); }
.bang-gia .ky { font-size: 15px; margin-bottom: 6px; }
.bang-gia .tien { font-size: 14px; color: var(--sz-text-soft); font-variant-numeric: tabular-nums; }
.bang-gia .tien b { font-size: 26px; font-weight: 300; color: var(--sz-text); font-variation-settings: "wdth" 108; }
.bang-gia .ghi { margin-top: 6px; font-size: 12px; color: var(--sz-text-muted); }
.bang-gia .the {
  margin-left: 8px; padding: 2px 6px; border: 1px solid var(--rule);
  font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--sz-text-muted); vertical-align: 2px;
}

.gia-nut { text-align: center; margin-top: clamp(30px, 4.5vh, 48px); padding: 0 var(--pad-x); }
/* Son, chỗ thứ ba. Xem ghi chú đầu khối. */
.nut-gia {
  display: inline-block; padding: 14px 30px;
  background: var(--sz-accent); color: var(--sz-on-accent); text-decoration: none;
  font-size: 13.5px; font-weight: 600; letter-spacing: .02em;
  transition: background-color .3s var(--ease), transform .16s var(--ease);
}
.nut-gia:hover { background: var(--sz-accent-hover); }
.nut-gia:active { transform: translateY(1px); }

/* ── hỏi nhanh ───────────────────────────────────────────────────────────── */
.hoi-dap { max-width: 640px; margin: 0 auto; padding: 0 var(--pad-x); }
.hoi-dap dt { font-size: 15px; font-weight: 500; margin: 0 0 6px; text-wrap: balance; }
.hoi-dap dd { margin: 0 0 26px; font-size: 13.5px; line-height: 1.75; color: var(--sz-text-soft); }
.hoi-dap dd:last-child { margin-bottom: 0; }
.hoi-dap a { color: var(--sz-text); text-decoration-color: var(--rule); text-underline-offset: 3px; }

/* ── chân trang có lối đi ────────────────────────────────────────────────── */
footer .chan {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 24px;
  margin-bottom: 18px;
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
}
footer .chan a { color: var(--sz-text-muted); text-decoration: none; }
footer .chan a:hover { color: var(--sz-text); }

@media (max-width: 720px) {
  .cai .noi { grid-template-columns: 1fr; }
  .cai .noi article + article { box-shadow: inset 0 1px 0 var(--rule-soft); padding-top: 18px; }
  .bang-gia { grid-template-columns: 1fr; }
  .bang-gia li + li { box-shadow: inset 0 1px 0 var(--rule-soft); }
  .so-sanh .hang { grid-template-columns: 1fr 64px 84px; }
  .crest .loi-di { gap: 14px; }
}
