/* Nút loa đọc ví dụ tiếng Nhật trong bài viết — chèn động bởi assets/js/grammar-example-tts.js,
   NẰM TRONG LUỒNG VĂN BẢN (inline) ngay sau từ/câu tiếng Nhật — không dùng position:absolute/badge
   (đã thử qua 5 lần offset/kỹ thuật khác nhau trong 1 phiên làm việc trước, mỗi lần đều lộ ra 1
   kiểu chồng lấn khác nhau tùy vị trí từ trong bài — badge góc trên-phải luôn thắng ở 1 kiểu bố
   cục nhưng thua ở kiểu khác: đè furigana của chính nó, đè ký tự cuối của chính nó, đè dòng phía
   trên nó... — sau khi user xác nhận "không được" với bản padding-reserve mới nhất, đã QUAY LẠI
   HẲN bản inline này, không thử thêm biến thể badge nào nữa). Markup + hiệu ứng lấy nguyên mẫu từ
   mock-up Other/speaker-button-2a.html ("Nút loa 1A — Blueprint outline", bản TRÒN, do user cung
   cấp): nút tròn không viền/không nền lúc rảnh, icon loa SVG outline, loé viền tròn khi bấm, vòng
   viền tròn lan toả khi đang phát, dải cột sóng thay icon lúc đang phát thật.
   KHÁC 1 điểm so với mock-up gốc: màu nghỉ mặc định đổi thành xám mờ (không dùng màu teal thương
   hiệu ngay từ đầu) — hover/focus/loading/playing mới hiện màu teal đầy đủ — giữ đúng yêu cầu trước
   đó "đỡ nổi bật" vì 1 bài có thể có 30-40+ nút cùng lúc.
   Icon nằm trong luồng chữ, kích thước nhỏ (18px, icon 12px) + margin-right tối thiểu 3px (2026-08-23,
   đổi từ margin-left sang margin-right theo yêu cầu — nút vẫn chèn NGAY SAU từ/câu như cũ, chỉ đổi
   phía margin để chừa khoảng cách với NỘI DUNG PHÍA SAU nút thay vì với từ phía trước) — trình
   duyệt TỰ nhường chỗ cho nút trong dòng nên KHÔNG BAO GIỜ đè lên chữ khác, đổi lại chấp nhận ảnh
   hưởng RẤT NHẸ tới luồng chữ (có thể đẩy lệch 1-2px chữ theo sau, không đáng kể/khó nhận ra bằng
   mắt thường) — ĐÃ VERIFY: bài "Cảm ơn/Xin lỗi" ra 0px chênh lệch layout tuyệt đối, bài ngữ pháp
   chênh ~0.8% tổng chiều cao (trung bình <1px/dòng có nút).
   PHẢI tự khai đủ width/height/padding/background/border/border-radius vì style.css (theme gốc
   News Portal) có rule reset TOÀN SITE cho mọi thẻ <button> (height:33px;padding:10px 15px;
   background:#029fb2 mặc định) — thiếu 1 thuộc tính vẫn đủ làm vỡ layout nút tròn nhỏ này. */
.tndg-example-tts-btn {
    position: relative;
    display: inline-grid;
    place-items: center;
    vertical-align: middle;
    width: 18px;
    height: 18px;
    padding: 0;
    margin: 0 3px 0 0;
    background: transparent;
    border: none;
    border-radius: 50%;
    color: rgba(0, 0, 0, .4);
    cursor: pointer;
    transition: background .12s ease, color .12s ease, transform .12s ease;
}
.tndg-example-tts-btn:hover,
.tndg-example-tts-btn:focus-visible {
    background: rgba(2, 159, 178, .12);
    color: var(--color-primary, #029fb2);
}
.tndg-example-tts-btn:active {
    background: rgba(2, 159, 178, .2);
    /* transform CHỈ scale (không kèm translate/top/right định vị nào) — an toàn vì CSS transform
       không bao giờ ảnh hưởng layout/reflow (chỉ là hiệu ứng vẽ), nên phóng to/nhỏ nút lúc bấm
       KHÔNG vi phạm yêu cầu "không làm lệch giao diện ban đầu". */
    transform: scale(.9);
}
.tndg-example-tts-btn:focus-visible {
    outline: 2px solid var(--color-primary, #029fb2);
    outline-offset: 2px;
}

.tndg-example-tts-icon {
    display: grid;
    place-items: center;
}
/* BẪY ĐÃ GẶP (2026-08-23) — theme có 1 rule reset TOÀN SITE ở đầu new-home.css:
   `svg{width:1em;height:1em;fill:currentColor;display:block}` (đã có ghi chú y hệt cho icon khác
   ở new-home.css ~dòng 2452) — CSS luôn thắng thuộc tính HTML (`width`/`height`/`fill` khai trực
   tiếp trong thẻ <svg>), nên icon loa/spinner của tính năng này bị đè: kích thước thực tế render
   ra 14px (=1em, theo font-size kế thừa) thay vì đúng 12px, và `fill="none"` (icon chỉ có viền,
   đúng mock-up Other/speaker-button-2a.html) bị đổi thành `fill:currentColor` (icon bị tô ĐẶC ruột
   thay vì outline rỗng) — đã xác nhận qua getComputedStyle(). Phải tự override lại CẢ 3 thuộc tính
   này bằng class selector (specificity 1 class > 1 thẻ nên thắng, không cần !important). */
.tndg-example-tts-speaker,
.tndg-example-tts-spinner {
    width: 12px;
    height: 12px;
    fill: none;
    display: block;
}
/* Nảy nhẹ khi bấm (class .is-pop gắn/gỡ trong triggerPopEffect() của JS mỗi lần click). */
.tndg-example-tts-btn.is-pop .tndg-example-tts-icon {
    animation: tndg-example-tts-pop 260ms cubic-bezier(.4, 0, .2, 1);
}

/* Loé viền TRÒN khi bấm — 1 vòng tròn viền teal phóng to + mờ dần ra ngoài đúng 1 lần mỗi lượt bấm. */
.tndg-example-tts-flash {
    position: absolute;
    inset: -1px;
    pointer-events: none;
    border: 1px solid var(--color-primary, #029fb2);
    border-radius: 50%;
    opacity: 0;
}
.tndg-example-tts-btn.is-pop .tndg-example-tts-flash {
    animation: tndg-example-tts-flash 460ms ease-out forwards;
}

/* Vòng viền TRÒN lan toả LẶP LẠI liên tục trong lúc đang phát thật (.is-playing) — khác .is-pop
   (chỉ chạy 1 lần khi bấm), vòng này báo hiệu "đang đọc câu này" chừng nào còn đang phát. */
.tndg-example-tts-ring {
    position: absolute;
    inset: -1px;
    pointer-events: none;
    border: 1px solid var(--color-primary, #029fb2);
    border-radius: 50%;
    opacity: 0;
}
.tndg-example-tts-btn.is-playing .tndg-example-tts-ring {
    animation: tndg-example-tts-ring 1400ms ease-out infinite;
}

/* Dải cột sóng (equalizer) THAY THẾ icon loa trong lúc đang phát thật — mỗi cột 1 nhịp/độ trễ khác
   nhau để trông tự nhiên như đang nhảy theo âm thanh (không đồng bộ với audio thật, chỉ là hiệu ứng
   trang trí biểu thị "đang phát"). */
.tndg-example-tts-bars {
    display: none;
    align-items: center;
    gap: 2px;
    height: 11px;
}
.tndg-example-tts-bars span {
    display: block;
    width: 2px;
    background: currentColor;
    transform-origin: center;
}
.tndg-example-tts-bars span:nth-child(1) { height: 50%; animation: tndg-example-tts-bar 520ms ease-in-out infinite; }
.tndg-example-tts-bars span:nth-child(2) { height: 100%; animation: tndg-example-tts-bar 610ms ease-in-out 70ms infinite; }
.tndg-example-tts-bars span:nth-child(3) { height: 70%; animation: tndg-example-tts-bar 700ms ease-in-out 140ms infinite; }
.tndg-example-tts-bars span:nth-child(4) { height: 90%; animation: tndg-example-tts-bar 790ms ease-in-out 210ms infinite; }
.tndg-example-tts-btn.is-playing .tndg-example-tts-bars { display: flex; }
.tndg-example-tts-btn.is-playing .tndg-example-tts-speaker { display: none; }

/* Icon quay tròn THAY THẾ icon loa trong lúc đang chờ Azure trả về mp3 (.is-loading) — dùng 1 SVG
   RIÊNG (không quay thẳng icon loa tại chỗ) cùng kích thước 12×12 hệt icon loa/dải cột sóng, đặt
   trong CÙNG 1 ô grid `.tndg-example-tts-icon` (display:grid;place-items:center) và chỉ hiện đúng 1
   icon tại 1 thời điểm qua display:none/block — kích thước nút (18×18, cố định qua width/height ở
   trên) HOÀN TOÀN không đổi giữa các trạng thái, không có icon nào tự set width/height khác 12px,
   nên tuyệt đối không xê dịch/giãn layout xung quanh khi chuyển đổi giữa các trạng thái. */
.tndg-example-tts-spinner {
    display: none;
    animation: tndg-example-tts-spin .8s linear infinite;
}
.tndg-example-tts-btn.is-loading .tndg-example-tts-spinner {
    display: block;
}
.tndg-example-tts-btn.is-loading .tndg-example-tts-speaker {
    display: none;
}

/* Đang chờ Azure trả về mp3 (is-loading) HOẶC đang phát thật (is-playing) — cả 2 đều là trạng thái
   ĐANG HOẠT ĐỘNG nên hiện màu teal đầy đủ, không mờ nhạt như lúc rảnh. */
.tndg-example-tts-btn.is-loading,
.tndg-example-tts-btn.is-playing {
    color: var(--color-primary, #029fb2);
}
.tndg-example-tts-btn.is-loading {
    pointer-events: none;
}

@keyframes tndg-example-tts-pop {
    0% { transform: scale(1); }
    35% { transform: scale(.88); }
    100% { transform: scale(1); }
}
@keyframes tndg-example-tts-flash {
    0% { opacity: .5; transform: scale(1); }
    100% { opacity: 0; transform: scale(1.75); }
}
@keyframes tndg-example-tts-ring {
    0% { transform: scale(.7); opacity: .55; }
    100% { transform: scale(1.5); opacity: 0; }
}
@keyframes tndg-example-tts-bar {
    0%, 100% { transform: scaleY(.35); }
    50% { transform: scaleY(1); }
}
@keyframes tndg-example-tts-spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .tndg-example-tts-btn * {
        animation: none !important;
    }
}
