:root {
    /* ===== Màu chính thức (bảng Config trong Figma) ===== */
    --white: #FFFFFF;
    --smoke: #F4F7F5;
    --ink: #121A16;
    --green: #1B5E3F;
    --gold: #E3A21B;

    /* ===== Màu dẫn xuất ===== */
    --muted: #696984;
    --card-title: #252641;
    --green-10: rgba(27, 94, 63, .10);
    --green-15: rgba(27, 94, 63, .15);
    --green-30: rgba(27, 94, 63, .30);
    --gold-10: rgba(227, 162, 27, .10);
    --gold-30: rgba(227, 162, 27, .30);

    /* Vàng đậm, CHỈ dùng cho thẻ Azota (.eco-card--gold). Ở đó chữ "AZOTA",
       biểu tượng chip và nút "Truy cập" nằm trên nền vàng nhạt #F7E3BB, mà
       --gold đặt lên đó chỉ còn 1.98:1 — vàng trên vàng, gần như mất chữ. Bản
       đậm này đạt 4.34:1.

       KHÔNG mở rộng sang tiêu đề section: đã thử và khách thấy ngả nâu, mất
       sắc vàng thương hiệu (xem chú thích ở .section-title em).

       Cùng mã màu với --warn nhưng CỐ Ý tách tên: --warn mang nghĩa cảnh báo,
       ai sửa màu cảnh báo sau này sẽ đổi nhầm cả màu nhấn của thẻ. */
    --gold-ink: #8A6210;

    /* Nền viên thuốc bọc cụm chữ nhấn cuối tiêu đề section. Để dạng gold ĐỔ
       TRONG SUỐT chứ không phải một mã màu đặc: các section nền sáng dùng hai
       nền khác nhau (--white và --smoke), màu đặc sẽ lộ mép ở một trong hai. */
    --gold-wash: rgba(227, 162, 27, .16);

    /* Dấu lấp lánh ở góc viên thuốc — MỘT sao lớn + MỘT sao nhỏ mờ.
       Dùng làm MẶT NẠ (mask) chứ không phải ảnh nền: màu trong SVG không quan
       trọng, màu thật do background của ::after quyết định, nên đổi màu theo
       nền mà không phải nhân bản URI. `fill-opacity` của sao nhỏ đi thẳng vào
       kênh alpha của mặt nạ, cho ra sắc nhạt hơn — cũng là lý do KHÔNG đặt màu
       ở đây được.

       Hình sinh bằng công thức, không gõ tay. Mỗi cạnh là một cung bậc hai với
       điểm điều khiển lệch khỏi tâm một đoạn k: k âm thì rãnh lõm nông, tay sao
       mập; k dương thì lõm sâu. Kéo quá tay (k ≳ 1.5 ở bán kính 12) là các cạnh
       cắt nhau, sao vỡ thành bốn cánh quạt rời. Hai giá trị dưới (-1.2 và -0.6)
       là mức đã dựng bảng so sánh rồi chọn bằng mắt ở đúng cỡ hiển thị thật.

       Mọi đỉnh phải nằm gọn trong viewBox 32x32; tràn ra là bị xén cụt một tay. */
    --sparkle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M12.4 0Q13.6 11.2 24.8 12.4Q13.6 13.6 12.4 24.8Q11.2 13.6 0 12.4Q11.2 11.2 12.4 0Z'/%3E%3Cpath fill-opacity='.68' d='M25.2 19Q25.8 24.8 31.6 25.4Q25.8 26 25.2 31.8Q24.6 26 18.8 25.4Q24.6 24.8 25.2 19Z'/%3E%3C/svg%3E");
    --blue-30: rgba(115, 193, 248, .30);
    --ink-50: rgba(18, 26, 22, .50);
    --price-old: rgba(29, 38, 46, .50);
    --warn: #8A6210;
    --danger: #BE2828;
    --danger-10: rgba(190, 40, 40, .1);

    /* ===== Chữ ===== */
    --font: 'Montserrat', system-ui, -apple-system, sans-serif;
    /* Cỡ XL chỉ dùng cho tiêu đề hero (khối C2). Giữ 48px của hero trang chủ
       cho cả ba trang; Figma trang Khóa học ghi 60px nhưng nhìn thật thì to
       quá, và hero mọi trang phải đọc lên như một. */
    /* Cận TRÊN của mỗi clamp() là đúng số Figma ở 1920; xuống laptop
       1366/1536 thì cỡ chữ co lại theo bề ngang, nếu không cả trang sẽ "nở"
       ra so với khung nhìn và phải cuộn rất nhiều. Giãn dòng chuyển sang hệ
       số KHÔNG ĐƠN VỊ để tự bám theo cỡ chữ vừa co — mọi nơi dùng --lh-*
       đều đi kèm đúng --fs-* cùng bậc nên đổi cách này là an toàn. */
    --fs-xl: clamp(32px, 2.75vw, 48px);
    --lh-xl: 1.32;
    --fs-lg: clamp(24px, 2.05vw, 32px);
    --lh-lg: 1.22;
    --fs-md: clamp(17px, 1.3vw, 20px);
    --lh-md: 1.2;
    --fs-base: 16px;
    --lh-base: 20px;
    --fs-sm: 13px;
    --lh-sm: 16px;
    --track: .02em;
    --lh-loose: 1.8;
    /* nhịp dòng cho đoạn văn dài */


    /* ===== Bo góc ===== */
    --r-card: 20px;
    --r-box: 15px;
    --r-media: 10px;
    --r-row: 5px;
    --r-pill: 50px;

    /* ===== Đổ bóng ===== */
    --shadow-card: 0 18.83px 47.08px rgba(47, 50, 125, .1);
    --shadow-tile: -4px 4px 4px rgba(0, 0, 0, .25);

    /* DẤU NHÁY KÉP — một hình vector 28x20 theo Figma. Hai dấu đặt cạnh nhau,
       mỗi dấu là một góc phần tư dày: cạnh ngoài bo tròn, chân vuông kéo
       xuống đáy.

       ĐỪNG vẽ bằng cung tròn có đuôi nhọn: thử rồi, ở cỡ 20px nó ra hình giọt
       nước chứ không đọc thành dấu nháy. Cũng ĐỪNG quay lại dùng ký tự nháy
       kép của font — mỗi ký tự đã là hai nét, ghép hai ký tự thành bốn nét.

       Khai ở :root vì có hai nơi dùng: ô trích dẫn trong bài viết (#region
       C13) và thẻ cảm nhận học viên (#region C22). Màu lấy qua mask nên mỗi
       nơi tự chọn tông, không có mã màu nào chép cứng vào chuỗi data URI. */
    --quote-mark:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 20'%3E%3Cpath d='M0 20V11A11 11 0 0 1 11 0v4.6A6.4 6.4 0 0 0 4.6 11H11v9Z'/%3E%3Cpath d='M17 20v-9A11 11 0 0 1 28 0v4.6A6.4 6.4 0 0 0 21.6 11H28v9Z'/%3E%3C/svg%3E");

    /* ===== Bố cục =====
       Bề rộng khung nội dung là MỘT TỈ LỆ CỐ ĐỊNH của khung nhìn (84%), kẹp
       trần ở 1360px — đúng số Figma 1920. KHÔNG quay lại kiểu bậc thang
       breakpoint (1200 → 1050 → 960 → 760): ở đó tỉ lệ nội dung/màn hình đu
       đưa từ 71% tới 94% tuỳ máy, nên ngay trước mỗi mốc trang phình gần hết
       bề ngang ("quá rộng"), qua mốc một cái là tụt xuống còn 74% ("trống hai
       bên"). Đo ngày 2026-09-16: 1281px cho 94%, 1280px cho 82%, 1024px cho
       74% — cùng một trang mà đổi máy là đổi hẳn cảm giác.

       Với min(84vw, 1360px) thì từ 701px tới ~1619px tỉ lệ luôn là 84%, lề hai
       bên nở/thu theo màn chứ không nhảy; từ 1619px trở lên khoá ở 1360px để
       thẻ và dòng chữ không rộng quá bản thiết kế. Thang chữ --fs-* cũng tính
       theo vw nên cỡ chữ và bề rộng cột giờ đi cùng một nhịp.

       GIÁ TRỊ NÀY GIỜ CHỈ CÒN LÀ NỀN cho dải ≤700px (điện thoại) đè lên, và
       cho trình duyệt quá cũ không hiểu khối @media ngay dưới. Từ 701px trở
       lên MỌI TRANG dùng bộ số lề 36px / trần 1600px — xem khối
       "KHUNG RỘNG SÁT VIỀN" bên dưới. */
    --container: min(84vw, 1360px);
    --pad-x: 20px;

    /* --nav-cap là BỀ NGANG, không phải chiều cao: mảng vàng sau logo và bề
       rộng tối thiểu của cụm nút phải. Trước đây nó kiêm luôn vai trò chiều
       cao thanh menu (scroll-padding-top, mốc top của .cd-buy) — sửa một con
       số để chỉnh khoảng nhảy neo là mảng vàng đổi bề ngang theo mà không hiểu
       vì sao. Chiều cao giờ nằm ở ba biến dưới. */
    --nav-cap: 107px;
    --pill-pad: 28px;

    /* Chiều cao thanh menu khi đã dính. Chỉ có --nav-stuck-top và
       --nav-stuck-pill là số gõ tay; --nav-stuck-h tự cộng lại, nên đổi độ cao
       viên thuốc là khoảng nhảy neo và mốc ghim của thẻ mua tự đi theo. */
    --nav-pill-h: 67px;
    --nav-stuck-top: 14px;
    --nav-stuck-pill: 46px;
    --nav-stuck-h: calc(var(--nav-stuck-top) + var(--nav-stuck-pill));

    /* Nhịp dọc dùng chung cho MỌI section. Đổi ba số này là cả trang giãn/thu
       theo, khỏi phải đi sửa từng khối #region. Cận trên là số Figma ở 1920. */
    --sec-y: clamp(40px, 4.2vw, 74px);
    --sec-y-end: clamp(46px, 4.8vw, 84px);
    --sec-head-gap: clamp(24px, 4vw, 42px);

    /* ===== Chuyển động ===== */
    --dur: .45s;
    --ease: cubic-bezier(.4, 0, .2, 1);

    /* Mức nhấc lên khi rê chuột — đổi ở đây là mọi nút đổi theo */
    --lift: -3px;
    --lift-sm: -2px;
}

/* Điện thoại: bỏ hẳn tỉ lệ 84% và cho nội dung chạm sát hai mép, chỉ chừa
   đúng --pad-x. Ở bề ngang này 84vw để lại 16% trắng — trên máy 390px là gần
   32px mỗi bên, đọc rất tù túng. Hai khối cũ (700px và 480px) khai
   calc(100% - 32px) / calc(100% - 24px), nhưng 100% ở đây đo theo body nên
   cộng lại luôn vượt 100% và bị width:100% kẹp về đúng full-bleed — tức hai
   khối cho ra y hệt nhau. Gộp làm một và viết thẳng ý định.

   Mốc 700px là chỗ duy nhất còn nhảy bậc (84vw = 588px, ngay dưới mốc là
   664px). Giữ nguyên vì hai bên là hai ý đồ khác nhau — máy tính cần lề, điện
   thoại cần tràn viền — và không máy thật nào rơi đúng vào khe đó. */
@media (max-width: 700px) {
    :root {
        --container: calc(100% - var(--pad-x) * 2);
    }
}

/* ============================================================
   KHUNG RỘNG SÁT VIỀN — MỌI TRANG
   Trước đây chỉ trang chủ dùng bề rộng này (móc <body class="page-home">),
   các trang còn lại giữ min(84vw, 1360px). Hệ quả: trên màn 1920 trang chủ
   chừa 160px mỗi bên còn trang trong chừa tới 280px, nhìn như hai website
   khác nhau; trên laptop 1440 thì chênh còn rõ hơn (36px so với 115px).
   Khách chốt gộp về một bộ số ngày 2026-09-17, nên khối này giờ khai ở
   :root và áp cho tất cả.

   LỀ NHÌN THẤY LUÔN ĐÚNG 36px ở mọi ngưỡng --pad-x (20/18/16/14px), không
   phải khai lại từng mốc. Chứng minh: .container có
   max-width = --container + 2·pad, nên với --container = 100% - 72px thì
       lề = (100% - (100% - 72px + 2·pad)) / 2 + pad = (72px - 2·pad)/2 + pad
           = 36px - pad + pad = 36px.
   Hai vế pad triệt tiêu nhau.

   DÙNG 100% CHỨ KHÔNG PHẢI 100vw. Trên Windows thanh cuộn chiếm ~17px mà
   100vw vẫn đếm cả phần đó, nên 100vw - 72px sẽ cho lề thật chỉ còn ~27px và
   lệch giữa máy có/không có thanh cuộn. 100% đo theo khối chứa thật nên miễn
   nhiễm — cùng cách khối điện thoại ngay trên đang dùng.

   Trần 1600px là bề rộng CHỮ (chưa tính đệm), bắt đầu ăn từ 1672px trở lên:
   màn 1920 còn 160px lề mỗi bên. Rộng hơn bản Figma 1360px khoảng 18% — khách
   chốt ngày 2026-09-16, chấp nhận thẻ và dòng chữ to hơn thiết kế để đổi lấy
   việc hết khoảng trống hai bên trên laptop.

   Mốc 701px khớp đúng cận dưới của khối điện thoại ngay trên nên không hở dải
   nào; dưới mốc đó điện thoại vẫn tràn viền, chỉ chừa --pad-x.
   ============================================================ */
@media (min-width: 701px) {
    :root {
        --container: min(100% - 72px, 1600px);
    }
}


* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
    /* Cộng 12px cho neo không dán sát gầm thanh menu. KHÔNG dùng --nav-cap ở
       đây nữa: đó là bề ngang, và 107px của nó làm mọi cú nhảy neo dư gần 50px
       khoảng trắng so với chiều cao thật của thanh. */
    scroll-padding-top: calc(var(--nav-stuck-h) + 12px);
    overflow-x: clip;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

body {
    margin: 0;
    font-family: var(--font);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
    background: var(--white);
    overflow-x: clip;
}

/* THẺ FORM KHÔNG TỰ KẾ THỪA FONT CỦA TRANG.
   Trình duyệt áp font riêng của hệ điều hành cho input/textarea/select/button,
   bất kể body khai gì. Thiếu dòng này thì mỗi thẻ form phải tự nhớ khai lại —
   và chỉ cần quên một chỗ là chỗ đó hiện bằng font hệ thống, lệch hẳn với phần
   còn lại của trang. Đó chính là lỗi font ở nút bấm: .btn khai font-size và
   font-weight nhưng quên font-family, nên <a class="btn"> thì đúng font còn
   <button class="btn"> thì sai.

   CHỈ đặt font-family, KHÔNG dùng `font: inherit`. Shorthand ấy kéo theo cả
   font-size và line-height, làm xê dịch chiều cao mọi ô nhập và nút trên toàn
   site — sửa một lỗi font mà đổi luôn bố cục thì không đáng.

   Độ ưu tiên của selector thẻ là thấp nhất nên mọi quy tắc theo class hiện có
   vẫn thắng, kể cả những chỗ đã tự khai font từ trước. */
input,
textarea,
select,
button {
    font-family: var(--font);
}

.container {
    width: 100%;
    max-width: calc(var(--container) + var(--pad-x) * 2);
    margin-inline: auto;
    padding-inline: var(--pad-x);
}


.site-header {
    background: var(--white);
    padding-bottom: 17px;
}

/* min-height 130px để lại 41px chết dưới nội dung: khối cao nhất trong đây là
   logo (15px đệm trên + 74px ảnh = 89px). Hạ còn 116px thì vẫn chừa 11px thở
   dưới logo mà bớt được 15px khoảng trắng giữa cụm liên hệ và thanh menu.
   ĐỔI SỐ NÀY PHẢI ĐỔI --header-h Ở KHỐI C2 THEO, xem ghi chú tại đó. */
.header-top {
    background: var(--smoke);
    min-height: 116px;
    display: flex;
    align-items: start;
    padding-top: 15px;
    overflow: hidden;
    max-height: 150px;
    opacity: 1;
    transition:
        max-height var(--dur) var(--ease),
        min-height var(--dur) var(--ease),
        padding-top var(--dur) var(--ease),
        opacity var(--dur) var(--ease);
}

.header-top-inner {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}

.brand img {
    display: block;
    width: 210px;
    height: 74px;
    object-fit: contain;
}

.header-contacts {
    display: flex;
    align-items: center;
    gap: 53px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.contact-item {
    display: flex;
    align-items: center;
    gap: 10px;
}

.contact-item>div {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.contact-item i {
    flex: none;
    font-size: 32px;
    color: var(--green);
}

.contact-item strong {
    font-weight: 700;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
}

.contact-item a,
.contact-item span {
    font-weight: 400;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}

.nav-sticky {
    position: sticky;
    top: var(--nav-stuck-top);
    z-index: 100;
    margin-top: -33px;
    padding-bottom: 17px;
}

/* GIỮ NGUYÊN CHỖ CHIẾM TRONG LUỒNG — dòng này chống giật, không phải trang trí.
   Viên thuốc co 67 → 46px khi dính. Nếu để .nav-sticky co theo thì cả trang
   ngắn đi 21px, mọi thứ bên dưới tụt lên, và trình duyệt tự bù lại vị trí cuộn
   (scroll anchoring). Vị trí cuộn bị kéo lùi làm thanh rơi lại dưới ngưỡng →
   gỡ is-stuck → viên thuốc phình ra → trang cao lại → bù tiếp: cứ thế lật qua
   lật lại. Đo được 5 lần lật trong một lượt cuộn xuôi.
   Cho khung trong giữ đúng chiều cao lúc chưa dính thì viên thuốc vẫn co mượt
   bên trong, còn chiều cao trang đứng im — hết vòng lặp. Thêm lợi ích: nội
   dung bên dưới không còn giật nảy lên 21px đúng lúc thanh menu dính. */
.nav-sticky>.container {
    min-height: var(--nav-pill-h);
}

/* Khung trong giờ cao hơn viên thuốc 21px khi đã dính. Khoảng trong suốt ấy
   vẫn ăn cú bấm nếu không tắt, che mất nội dung ngay dưới thanh menu. */
.nav-sticky,
.nav-sticky>.container {
    pointer-events: none;
}

.nav-pill {
    pointer-events: auto;
}

.nav-brand {
    display: flex;
    position: relative;
    flex: none;
    align-self: stretch;
    align-items: center;
    justify-content: flex-start;
    /* overflow: hidden; */
    width: var(--pill-pad);
    margin-left: calc(var(--pill-pad) * -1);
    line-height: 0;
    clip-path: inset(0 calc(var(--nav-cap) + 64px) 0 0);
    text-decoration: none;

    /* Lúc CHƯA dính, clip-path ở dưới cắt sạch nav-brand — không logo, không
       tam giác vàng, tuyệt đối không có gì vẽ ra. 37px margin-right trước đây
       cộng với đệm trái 28px của .nav-pill thành 65px khoảng xanh trơn không
       lý do (đo bằng DevTools ngày 2026-08-25: hộp 28×67 rỗng, không có nội
       dung nào bên trong). Hạ về 0: menu bắt đầu ngay sau đúng đệm trái pill
       (28px), không còn khoảng chết. Lúc dính, mảng vàng bung 171px thật sự
       có logo nên vẫn cần chỗ — margin-right 7px của trạng thái is-stuck bên
       dưới giữ nguyên. */
    margin-right: 0;
    transition:
        width var(--dur) var(--ease),
        margin-right var(--dur) var(--ease),
        clip-path var(--dur) var(--ease),
        border-radius var(--dur) var(--ease);
}

.nav-brand::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: calc(var(--nav-cap) + 64px);
    background: var(--gold);
    clip-path: polygon(0 0, calc(100% - 64px) 0, 100% 100%, 0 100%);
}

.nav-brand img {
    position: relative;
    z-index: 1;
    flex: none;
    display: block;
    width: auto;
    height: 33px;
    margin-left: 20px;
}
.nav-sticky.is-stuck .nav-link{
    padding: 1px 7px;
}

/* Chỉ áp dụng từ 1081px lên: dưới ngưỡng đó .nav-link/.nav-cart/.nav-user đã
   có cỡ riêng cho bố cục di động (xem @media max-width:1080px bên dưới) —
   không bọc media thì ba lớp class ở đây (.nav-sticky.is-stuck .nav-cart)
   đặc hiệu hơn nên LUÔN thắng luật 1080px dù màn đang hẹp, làm icon phồng lên
   thay vì giữ đúng cỡ di động đã định. */
@media (min-width: 1081px) {
    .nav-sticky.is-stuck .nav-link {
        font-size: 13px;
    }

    /* font-size không cần khai lại — gốc đã là 20px giống hệt, chỉ còn
       bề ngang là thứ thật sự co lại khi dính. */
    .nav-sticky.is-stuck .nav-cart {
        width: 44px;
    }

    .nav-sticky.is-stuck .nav-user {
        width: 44px;
    }

    /* Menu con đổ xuống dưới mục cha — co theo đúng tỉ lệ 13/15 của .nav-link
       ở trên, kẻo thanh đã gọn lại mà menu rơi xuống vẫn to y nguyên, nhìn
       lệch tông giữa hai khối liền kề nhau. */
    .nav-sticky.is-stuck .nav-mega ul {
        padding: 9px;
    }

    .nav-sticky.is-stuck .nav-mega a {
        padding: 9px 14px;
        font-size: 13px;
    }
}

/* Khoảng 1081–1150px: --container ở quanh 908–966px (84vw), hẹp nhất trong
   các dải còn dùng bố cục menu ngang, nhưng menu + cụm icon phải lúc dính vẫn
   giữ nguyên bề ngang của bậc rộng hơn — tràn khỏi .nav-pill (overflow:hidden)
   và bị cắt mất icon giỏ hàng, icon đăng nhập. Đo bằng DevTools ngày
   2026-08-26: thiếu đúng 58px. Dưới 1081px bố cục đổi hẳn sang menu gộp nên
   hết áp lực; trên 1150px khung đã nới đủ. */
@media (min-width: 1081px) and (max-width: 1150px) {
    .nav-sticky.is-stuck .nav-actions {
        margin-left: 16px;
        min-width: 64px;
    }

    .nav-sticky.is-stuck .main-nav {
        gap: 3px;
    }

    .nav-sticky.is-stuck .nav-link {
        padding: 4px 5px;
        font-size: 12px;
    }

    .nav-sticky.is-stuck .nav-caret {
        margin-left: 2px;
        font-size: 7px;
    }
}

.nav-sticky.is-stuck .nav-brand {
    width: calc(var(--nav-cap) + 64px);
    margin-right: 7px;
    clip-path: inset(0 0 0 0);
}

@media (min-width: 1081px) {
    .nav-brand-name {
        display: none;
    }
}

@media (max-width: 1080px) {
    .nav-brand-name {
        display: block;
        margin-left: 10px;
        font-size: 16px;
        line-height: 1.2;
        font-weight: 700;
        color: var(--white);
        white-space: nowrap;
    }

    .nav-brand {
        width: auto;
        margin-left: 0;
        margin-right: 12px;
        clip-path: none;
    }

    .nav-brand::before {
        display: none;
    }

    .nav-sticky.is-stuck .nav-brand {
        width: auto;
        margin-right: 12px;
        clip-path: none;
    }
}


.nav-sticky.is-stuck .nav-pill {
    box-shadow:
        0 0 0 1px rgba(244, 247, 245, .18),
        0 12px 30px rgba(18, 26, 22, .28);

    min-height: var(--nav-stuck-pill);
}

.nav-auth {
    display: flex;
    align-items: center;
    overflow: hidden;
    max-width: var(--auth-w, 180px);
    opacity: 1;
    transition: max-width var(--dur) var(--ease), opacity var(--dur) var(--ease);
}

.nav-sticky.is-stuck .nav-auth {
    max-width: 40px;
    opacity: 0;
    pointer-events: none;
}

/* right: 0 sẽ neo vào PADDING BOX của .nav-actions, tức là bỏ qua luôn khoảng
   đệm phải và dán icon sát mép viên thuốc. Lấy đúng biến đệm để nó lùi vào
   bằng với phần còn lại. */
.nav-actions>.nav-user {
    position: absolute;
    top: 0;
    bottom: 0;
    right: var(--nav-actions-pad);
    z-index: 2;
    display: grid;
    place-items: center;
    width: 53px;
    opacity: 0;
    pointer-events: none;
    /* Cùng 20px với .nav-cart — xem ghi chú tại đó. */
    font-size: 20px;
    color: var(--green);
    text-decoration: none;
    transition:
        opacity var(--dur) var(--ease),
        color var(--dur) var(--ease),
        width var(--dur) var(--ease),
        font-size var(--dur) var(--ease);
}

.nav-sticky.is-stuck .nav-user {
    opacity: 1;
    pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {

    .nav-brand,
    .nav-auth,
    .nav-user,
    .nav-actions,
    .nav-pill {
        transition: none;
    }
}

.nav-pill {
    position: relative;
    /* min-height PHẢI nằm trong danh sách này. Thiếu nó thì lúc dính, bóng đổ
       và bo góc chuyển mượt 0,45s trong khi chiều cao 67 → 46 nhảy cái rụp —
       cả thanh giật một nhịp ngay giữa hiệu ứng. */
    transition:
        box-shadow var(--dur) var(--ease),
        border-radius var(--dur) var(--ease),
        padding var(--dur) var(--ease),
        min-height var(--dur) var(--ease);
    contain: layout;
    min-height: var(--nav-pill-h);
    display: flex;
    align-items: center;

    /* KHÔNG dùng space-between. Từ 1280px xuống, các @media thu nhỏ chữ menu
       cho vừa thanh; space-between đem chỗ dôi ra CHIA ĐỀU hai bên, nên mép
       trái phình từ 65px lên tới 105px rồi lại tụt về 65px tùy khổ màn — nhìn
       như menu bị đẩy trôi vô cớ. flex-start giữ mép trái cố định, còn chỗ dôi
       dồn hết sang phải, nơi đã có sẵn mảng vàng để nuốt. */
    justify-content: flex-start;
    padding-left: var(--pill-pad);
    background: var(--green);
    border-radius: var(--r-pill);
    box-shadow: 4px -4px 4px rgba(0, 0, 0, .25);
    overflow: hidden;
}

/* Khe và cỡ chữ để dư sẵn chỗ cho mũi tên đổ xuống: mọi mục rồi sẽ có menu
   con, mỗi mũi tên ăn thêm chừng 14px nên sáu mục là mất hơn 80px. */
.main-nav {
    display: flex;
    align-items: center;
    gap: 10px;

    /* flex:1 để KHỐI NÀY nuốt hết chỗ dôi, còn các mục bên trong vẫn dồn trái.
       Không dùng margin-left:auto trên .nav-actions: khối menu có flex-shrink
       mặc định nên nó co lại nhường chỗ, chỗ dôi bị chia đôi và cụm nút phải
       đứng hụt khỏi mép viên thuốc 56px — mảng vàng hở ra một khoảng xanh. */
    flex: 1 1 auto;
    justify-content: flex-start;
}

.nav-link {
    padding: 5px 10px;
    border-radius: var(--r-pill);
    font-size: 15px;
    line-height: var(--lh-base);
    font-weight: 700;
    color: var(--white);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .15s ease;
}

.nav-link:hover {
    background: rgba(255, 255, 255, .14);
}

.nav-link.is-active {
    background: var(--gold);
    color: var(--green);
}

.nav-actions {
    /* Khoảng đệm mép phải để riêng một biến: nút tài khoản nằm absolute nên
       không ăn theo padding của khối này, phải tự lấy đúng con số đó. */
    --nav-actions-pad: 18px;

    position: relative;
    align-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: var(--nav-cap);
    margin-left: 64px;
    padding-right: var(--nav-actions-pad);
    background: var(--gold);
    transition:
        background-color var(--dur) var(--ease),
        margin-left var(--dur) var(--ease),
        min-width var(--dur) var(--ease),
        padding-right var(--dur) var(--ease);
}

.nav-actions::before {
    content: "";
    position: absolute;
    top: -2px;
    bottom: 0;
    left: -63px;
    width: 64px;
    background: var(--gold);
    clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.nav-actions>* {
    position: relative;
    z-index: 1;
}

/* font-size 20px — CÙNG một số với .nav-cart lúc dính và bản di động
   (<=1080px), không phải hằng số mới bịa ra. Trước đây icon 24px trong khi
   .nav-link/.nav-login chỉ 15-16px, nhìn to hẳn so với chữ đứng cạnh —
   "chưa đồng bộ" đúng nghĩa đen. */
.nav-cart {
    display: grid;
    place-items: center;
    align-self: stretch;
    /* Mốc neo cho con số ở góc — xem .nav-cart__badge ngay dưới. */
    position: relative;
    width: 53px;
    font-size: 20px;
    color: var(--green);
    text-decoration: none;
    transition:
        color var(--dur) var(--ease),
        width var(--dur) var(--ease),
        font-size var(--dur) var(--ease);
}

/* Số khóa đang trong giỏ.

   ĐẶT THEO TÂM chứ không theo mép trên: .nav-cart cao bằng viên thuốc, mà viên
   thuốc co từ 67px xuống 46px khi thanh menu dính. Dùng top cố định thì lúc dính
   con số rơi xuống giữa biểu tượng. Lấy 50% rồi lùi nửa chiều cao biểu tượng
   thì nó luôn bám đúng vai phải của chiếc giỏ ở mọi chiều cao.

   Cũng vì .nav-pill có overflow: hidden nên con số phải nằm TRONG khung 53px,
   nhô ra ngoài là bị cắt cụt. */
.nav-cart__badge {
    position: absolute;
    top: calc(50% - 15px);
    right: 4px;
    display: grid;
    place-items: center;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 20px;

    /* Màu badge phải khác CẢ HAI thứ nó chạm vào, không chỉ cái nền:
         - nền .nav-actions: VÀNG  -> badge vàng thì chìm
         - biểu tượng chiếc giỏ: XANH -> badge xanh thì dính liền vào giỏ, nhìn
           ra một khối chứ không ra hai
       Nên lấy màu mực: khác vàng, khác xanh, và chữ trắng bên trong đủ tương
       phản ở cỡ 11px. */
    background: var(--ink);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    color: var(--white);

    /* VÒNG VIỀN CÙNG MÀU NỀN PHÍA SAU — mẹo tách lớp cổ điển. Nó tạo một
       khe hở 2px giữa badge và nét vẽ chiếc giỏ, nên dù hai màu có gần nhau
       đến mấy thì mắt vẫn đọc ra đây là hai vật thể rời.
       Dùng box-shadow chứ không border: border làm phần tử to ra, đẩy lệch vị
       trí đã canh; box-shadow vẽ ra ngoài hộp, không ăn vào kích thước. */
    box-shadow: 0 0 0 2px var(--gold);
}

/* Cùng cỡ chữ với .nav-link ở TỪNG NGƯỠNG — trước dùng var(--fs-base)=16px,
   lệch 1px so với các mục menu đứng ngay cạnh nó. */
.nav-login {
    padding: 0 15px;
    font-size: 15px;
    font-weight: 700;
    color: var(--green);
    text-decoration: none;
    white-space: nowrap;
}

.nav-cart:hover,
.nav-login:hover {
    opacity: .75;
}

.nav-toggle {
    display: grid;
    place-items: center;
    width: 0;
    height: 36px;
    margin-left: 0;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--white);
    font-size: 18px;
    cursor: pointer;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
    transition:
        width var(--dur) var(--ease),
        margin-left var(--dur) var(--ease),
        opacity var(--dur) var(--ease);
}

.nav-sticky.is-stuck .nav-user:hover {
    opacity: .75;
}

/* RESPONSIVE — HEADER & CONTAINER */


/* Ngưỡng này bám theo BỀ RỘNG KHUNG, không phải một con số màn hình đẹp mắt:
   nó phải bật đúng lúc --container tụt xuống dưới 1200px. Mốc 1428px tính
   theo công thức khung CŨ min(84vw, 1360px): 84vw = 1200px rơi vào 1428px.

   Từ 2026-09-17 khung đổi sang min(100% - 72px, 1600px) nên ở 1428px khung
   thực tế đã là 1356px chứ không còn 1200px — tức mốc này giờ bật SỚM hơn
   mức cần thiết khoảng 156px. Cố ý GIỮ NGUYÊN: bật sớm chỉ làm chữ menu nhỏ
   đi một nấc ở dải 1272–1428px (không ai thấy vấn đề), còn dời mốc xuống
   1272px là phải đo lại toàn bộ dải hẹp bên dưới, nơi menu vốn đã chật.

   Đặt sai mốc là tái hiện đúng lỗi cũ (hồi mốc còn nằm ở 1240px): viên thuốc
   đã hẹp lại mà menu vẫn giữ chữ 15px + gap 10px của bậc rộng hơn, hàng flex
   tràn ra và .nav-pill (overflow:hidden) cắt cụt đúng phần cuối — chữ
   "Đăng nhập". Cùng một loại lỗi với khối
   @media (min-width:1081px) and (max-width:1150px) phía trên. */
@media (max-width: 1428px) {
    .main-nav {
        gap: 7px;
    }

    .nav-link {
        padding: 5px 8px;
        font-size: 15px;
    }

    .nav-login {
        font-size: 15px;
    }
}

/* Bậc thu thứ hai, cũng quy theo bề rộng khung: bật khi --container xuống
   dưới 1050px, tức 84vw = 1050px → 1250px (mốc cũ là 1180px hồi khung còn
   nhảy bậc). Cùng lý do với khối trên, mốc này tính theo công thức khung CŨ
   và được giữ nguyên sau khi khung đổi ngày 2026-09-17. */
@media (max-width: 1249px) {
    .header-contacts {
        gap: 24px;
    }

    .main-nav {
        gap: 5px;
    }

    .nav-link {
        padding: 5px 7px;
        font-size:15px;
    }

    .nav-login {
        font-size: 15px;
    }

    .nav-caret {
        margin-left: 4px;
        font-size: 8px;
    }
}

@media (max-width: 1080px) {
    :root {
        --pad-x: 18px;
    }

    .site-header {
        padding-bottom: 12px;
    }

    .header-top {
        max-height: 0;
        min-height: 0;
        padding-top: 0;
        opacity: 0;
        pointer-events: none;
    }

    .nav-sticky {
        margin-top: 0;
        padding-bottom: 10px;
    }

    /* Dưới 1080px bố cục khác hẳn: logo hiện thành huy hiệu tròn, menu thành
       bảng đổ xuống (position:absolute, không còn nằm trong hàng flex). Trả về
       space-between và gỡ hai margin của bản máy bàn. */
    .nav-brand {
        margin-right: 0;
    }

    .nav-pill {
        justify-content: space-between;
        gap: 12px 16px;
        padding: 0px 16px;
        border-radius: 35px;
        overflow: visible;
        box-shadow: 0 8px 20px rgba(18, 26, 22, .18);
    }

    /* Không còn miếng vàng cắt chéo lúc này — huy hiệu tròn tự nó đã nổi
       trên nền xanh, không cần khung nền để chữ khỏi chìm màu. */
    .nav-brand {
        width: auto;
        margin-left: 0;
        clip-path: none;
        border-radius: 50%;
    }

    .nav-brand::before {
        display: none;
    }

    .nav-brand img {
        height: 40px;
        width: 40px;
        margin-left: 5px;
        border-radius: 50%;
    }

    .main-nav {
        position: absolute;
        top: calc(100% + 10px);
        left: 0;
        right: 0;
        z-index: 50;
        flex-direction: column;
        align-items: stretch;
        gap: 4px;
        padding: 10px;
        /* Danh sách gồm mục chính lẫn mục con của mọi trang có menu đổ xuống
           nên dài hơn màn hình điện thoại; khối này position:absolute, không
           làm trang cao thêm, thiếu hai dòng dưới là phần cuối không tài nào
           chạm tới được. */
        max-height: calc(100dvh - 150px);
        overflow-y: auto;
        overscroll-behavior: contain;
        background: var(--green);
        border-radius: var(--r-box);
        box-shadow: 0 12px 30px rgba(18, 26, 22, .28);
        opacity: 0;
        visibility: hidden;
        transform: translateY(-8px);
        transition: opacity .2s ease, transform .2s ease, visibility .2s;
    }

    .nav-sticky.is-open .main-nav {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
    }

    .nav-link {
        text-align: center;
    }

    .nav-actions {
        --nav-actions-pad: 12px;

        margin-left: 0;
        min-width: 0;
        background: transparent;
    }

    .nav-actions::before {
        display: none;
    }

    .nav-cart {
        width: 36px;
        font-size: 20px;
        color: var(--white);
    }

    /* Ngưỡng này khối vàng ẩn đi: giỏ thành TRẮNG nằm trên viên thuốc XANH.
       Vẫn là bài toán cũ với hai màu mới — badge vàng khác cả trắng lẫn xanh,
       và vòng viền đổi sang màu nền mới là màu xanh. */
    .nav-cart__badge {
        right: 0;
        background: var(--gold);
        color: var(--ink);
        box-shadow: 0 0 0 2px var(--green);
    }

    .nav-auth {
        max-width: 0;
        opacity: 0;
        pointer-events: none;
    }

    .nav-actions>.nav-user {
        position: static;
        width: 36px;
        opacity: 1;
        pointer-events: auto;
        font-size: 20px;
        color: var(--white);
    }

    .nav-toggle {
        width: 36px;
        margin-left: 4px;
        opacity: 1;
        pointer-events: auto;
    }
}

@media (max-width: 900px) {
    :root {
        --pad-x: 16px;
    }
}

@media (max-width: 768px) {
    :root {
        --pad-x: 14px;
    }

    .nav-pill {
        gap: 10px;
        border-radius: 35px;
    }

    .nav-brand img {
        height: 34px;
        width: 34px;
    }

    .nav-link {
        padding: 4px 8px;
        font-size: 13px;
    }
}

@media (max-width: 600px) {
    :root {
        --pad-x: 12px;
    }

    .nav-pill {
        border-radius: 35px;
    }

    .nav-link {
        padding: 4px 8px;
        font-size: 12px;
    }
}

/* C2 · BANNER */
.hero {
    /* Hai số điều khiển chiều cao hero, khai một chỗ cho cả ba trang:
       --nav-overlap: phần hero bị kéo lên nằm dưới thanh menu.
       --header-h  : chiều cao thật của .site-header ở ngưỡng màn hình này.
       Ngưỡng nào đổi dáng header (ẩn khối liên hệ, thu thanh menu) thì phải
       đo lại --header-h ở đúng ngưỡng ấy. */
    --nav-overlap: 68px;
    /* = .header-top(116) + .site-header padding-bottom(17) + .nav-sticky(84)
         + margin-top của .nav-sticky(-33) = 184. Đổi bất kỳ số nào trong bốn
         số đó thì tính lại đây, không thì header + hero lệch khỏi 100vh. */
    --header-h: 184px;

    position: relative;
    display: flex;
    flex-direction: column;
    padding: 80px 0 0;
    background: var(--smoke);
    overflow: hidden;
    margin-top: calc(var(--nav-overlap) * -1);

    /* Mở trang ra là header + hero vừa đúng một màn hình. Hero đã bị kéo lên
       --nav-overlap nên phải cộng chừng ấy vào, phần NHÌN THẤY của hai khối
       mới đủ 100vh. Dùng min-height chứ không phải height: nội dung dài hơn
       thì hero cứ việc cao thêm, không bị cắt. */
    min-height: calc(100vh - var(--header-h) + var(--nav-overlap));
}

/* Khung nội dung căng hết chiều cao hero. Cần vì hero giờ cao theo 100vh chứ
   không còn ôm sát nội dung: không có dòng này thì lưới đứng nguyên ở trên,
   ảnh học viên lơ lửng giữa banner và chừa một mảng trống dưới đáy. Có nó thì
   align-items:end của .hero-grid mới ghim được ảnh xuống đáy hero. */
.hero>.container {
    flex: 1;
    min-height: 0;
}

.hero-grid {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 60px;
    align-items: end;
    min-height: 100%;
}

.hero-copy {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-self: center;
    padding-bottom: 30px;
    /* Container query: cho .hero-title dùng cqw ở màn ≥1600px để cỡ chữ tự co
       theo bề rộng CỘT CHỮ THẬT (khác nhau giữa các biến thể hero), thay vì
       đoán theo bề rộng màn hình. Không ảnh hưởng gì dưới 1600px. */
    container-type: inline-size;
}

.hero-title {
    margin: 0 0 20px;
    font-size: var(--fs-xl);
    line-height: var(--lh-xl);
    font-weight: 700;
    color: var(--ink);
}

.hero-title span {
    display: block;
}

.hero-hl {
    color: var(--gold);
}

/* 46ch tính theo chính cỡ chữ của đoạn, nên khi lên 20px thì bề rộng tối đa tự
   nở ra ~500px — đúng khổ 493px trong Figma, không cần khai px cứng. */
.hero-lead {
    max-width: 46ch;
    margin: 0 0 32px;
    color: var(--muted);
}

.hero-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 0 0 20px;
}

.hero-badge {
    padding: 6px 16px;
    border-radius: var(--r-pill);
    background: var(--green-10);
    color: var(--green);
    border: 1px solid var(--green-30);
    font-size: var(--fs-sm);
    font-weight: 600;
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
    cursor: default;
}

.hero-badge:hover {
    background: var(--green);
    color: var(--white);
    border-color: var(--green);
    transform: translateY(-2px);
    box-shadow: 0 4px 14px rgba(27, 94, 63, 0.22);
}

.hero-cta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
}

.hero-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--ink);
    font-weight: 700;
    font-size: var(--fs-sm);
    text-decoration: none;
    padding: 8px 14px;
    border-radius: var(--r-pill);
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

.hero-link i,
.hero-link span {
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.hero-link:hover {
    color: var(--green);
    background: rgba(27, 94, 63, 0.08);
}

.hero-link:hover i,
.hero-link:hover span {
    transform: translateX(5px);
}

.hero-visual {
    position: relative;
    align-self: end;
    line-height: 0;
}

/* 1. Vòng tròn nền .hero-ring nhịp thở xoay + Parallax cuộn trang */
.hero-ring {
    position: absolute;
    top: 70%;
    left: 110%;
    z-index: 0;
    width: 960px;
    max-width: none;
    transform: var(--scroll-transform, translate(-50%, -50%));
    pointer-events: none;
    transition: transform 0.08s linear, opacity 0.2s ease-out;
    animation: heroRingPulse 18s ease-in-out infinite alternate;
}




@keyframes heroRingPulse {
    0% {
        transform: var(--scroll-transform, translate(-50%, -50%)) rotate(0deg) scale(1);
    }

    50% {
        transform: var(--scroll-transform, translate(-50%, -50%)) rotate(5deg) scale(1.03);
    }

    100% {
        transform: var(--scroll-transform, translate(-50%, -50%)) rotate(-4deg) scale(0.98);
    }
}

/* 1b. Vòng tròn trang trí phía trái — chỉ hiện khi màn đủ rộng để lộ khoảng trống */
.hero-ring-left {
    display: none;
    position: absolute;
    top: 50%;
    left: 0;
    z-index: 0;
    /* Mép phải nhìn thấy = 0.42 * width (transform kéo nó sang trái 58%
       chính bề rộng của nó). Đặt theo khoảng trống thật bên trái cột chữ —
       (100vw - --container - pad-x*2)/2 — thay vì % cố định của toàn viewport:
       dùng % cố định thì ở nhiều bề ngang (vd 1432px) vòng tròn tính ra to
       hơn khoảng trống thật và đè lên chữ. Trừ 24px an toàn trước khi chia
       ngược lại cho 0.42; nếu khoảng trống quá hẹp (gần 1280px) kết quả âm,
       trình duyệt tự kẹp về 0 — vòng tròn ẩn đi thay vì tràn ra ngoài. */
    width: calc(((100vw - var(--container) - var(--pad-x) * 2) / 2 - 24px) / 0.42);
    max-width: none;
    opacity: 0.18;
    transform: translate(-58%, -50%) scaleX(-1);
    pointer-events: none;
}

/* .hero-ring-left {
    display: block;
} */

/* Khoảng trống bên trái giờ là một tỉ lệ cố định của màn (8% mỗi bên, trừ
   đệm) nên công thức calc() ở trên chỉ cho ra đường kính 200px khi màn đạt
   1600px — dưới mức đó vòng tròn co thành một chấm nhỏ trông kỳ, nên ẩn hẳn.
   Mốc cũ là 1470px, tính theo khung 1200px cố định của kiểu bậc thang. */
@media (min-width: 1600px) {
    .hero-ring-left {
        display: block;
    }
}

/* Dải 1200–1599px: khoảng trống bên trái cột chữ đã là 76–108px ở mọi bề
   ngang trong dải (trước đây dải này bị cắt đôi bởi cái "hố" 1200–1280px, nơi
   --container rớt xuống 1050px trong khi khung nhìn vẫn rộng — nay khung co
   mượt nên không còn hố nữa). Chỗ trống ấy đủ để khoe vòng tròn, chỉ là chưa
   đủ cho công thức calc() của rule gốc, nên dùng cách tính riêng dưới đây.

   KHÔNG dùng công thức calc() của rule gốc: ở bề ngang này nó cho ra đường
   kính 130–170px, tức một chấm bé có độ cong gắt — nhìn ra cái chấm chứ không
   ra cung tròn. Tách hẳn hai đại lượng vốn bị gộp làm một:
     - width       = ĐƯỜNG KÍNH, cố định 460px  -> cung cong thoải như bản rộng
     - --ring-peek = bề ngang THẬT SỰ ló ra khỏi mép trái màn hình
   translate(-100% + peek) đẩy vòng tròn ra ngoài đúng bằng phần thừa (mốc
   xoay/biến hình mặc định là tâm, nên -100% đưa mép phải về đúng x=0), do đó
   phần nhìn thấy LUÔN bằng --ring-peek dù sau này có đổi đường kính. Peek lấy
   theo khoảng trống thật rồi trừ 20px an toàn nên không bao giờ liếm vào chữ:
   tại 1280px chữ bắt đầu ở 102px, vòng tròn dừng ở 82px.

   Nối liền với rule ≥1600px ở trên: tại 1599px cách này lộ ra 88px, tại
   1600px công thức calc() lộ ra 0.42 × 200 = 84px — chênh 4px, mắt không
   thấy. */
@media (min-width: 1200px) and (max-width: 1599px) {
    .hero-ring-left {
        --ring-peek: calc((100vw - var(--container) - var(--pad-x) * 2) / 2 - 20px);

        display: block;
        width: 460px;
        transform: translate(calc(-100% + var(--ring-peek)), -50%) scaleX(-1);
    }
}

/* Không còn chỗ cho vòng tròn này. Khung đã sát viền 36px nên khoảng trống
   bên trái cột chữ chỉ còn 16px ở mọi bề ngang dưới 1672px — công thức
   calc() cho ra số âm, trình duyệt kẹp về 0 và vòng tròn tự biến mất, không
   sao. Nhưng dải 1672–1855px thì trần 1600px bắt đầu chừa lại chút lề, đủ để
   công thức cho ra đường kính 14–133px: một cái chấm cong gắt nằm dính mép
   trái, trông như vết bẩn chứ không ra hình. Ẩn hẳn trong dải đó.

   1856px là mốc lề vừa đủ 108px để đường kính đạt 200px — đúng ngưỡng "đủ to
   để ra cung tròn" mà rule ≥1600px phía trên đang dùng.

   TRƯỚC ĐÂY rule này chỉ khoá ở .page-home vì chỉ trang chủ có khung sát
   viền. Từ 2026-09-17 mọi trang dùng chung khung ấy nên bỏ luôn tiền tố —
   hero trang Thành tích và Tra cứu điểm cũng có .hero-ring-left và cũng gặp
   đúng cảnh chấm cong dính mép. Cùng độ đặc hiệu (0,1,0) với hai rule
   display:block phía trên, thắng nhờ đứng SAU trong file; đừng dời lên. */
@media (max-width: 1855px) {
    .hero-ring-left {
        display: none;
    }
}

/* 2. Ảnh học viên chính .hero-photo giữ vị trí cố định */
.hero-photo {
    position: relative;
    z-index: 1;
    display: block;

    /* Bề ngang gốc là 120% cột ảnh. Nhưng ảnh cao theo BỀ NGANG (height:auto)
       nên nó không hề biết cửa sổ cao bao nhiêu: trên laptop 14" — nơi khung
       nhìn chỉ còn ~620-760px sau khi trừ thanh trình duyệt — ảnh vẫn giữ
       nguyên chiều cao và đẩy hero vượt quá một màn hình (đo được: 1366x625
       dư 108px, 1600x758 dư 59px, 1536x722 dư 11px). min-height của .hero chỉ
       là SÀN, nội dung cao hơn thì nó cứ cao thêm.

       Vế thứ hai kẹp bề ngang theo CHIỀU CAO CÒN LẠI của hero:
         (chiều cao hero) − (đệm trên 80px), đổi ra bề ngang bằng tỉ lệ ảnh
         1120/967 ≈ 1.158.
       min() lấy vế nhỏ hơn, nên màn đủ cao thì không có gì thay đổi — chỉ màn
       thấp mới thu ảnh lại vừa đúng một màn hình. */
    width: min(120%, calc((100vh - var(--header-h) + var(--nav-overlap) - 80px) * 1.158));
    height: auto;
    vertical-align: bottom;
    margin-bottom: 0;
}

/* 3. Các mảnh trang trí .deco chỉ chuyển động khi lăn/cuộn chuột (Scroll) */
.deco {
    position: absolute;
    z-index: 2;
    pointer-events: none;
    transform: var(--scroll-transform, translate(0, 0));
    transition: transform 0.08s linear, opacity 0.2s ease-out;
    will-change: transform;
}

.deco-xanh {
    top: 77%;
    left: -10%;
    width: 115px;
}

.deco-cam {
    z-index: 0 !important;
    bottom: 1%;
    right: -14%;
    width: 122px;
}

.deco-tgd {
    top: 6%;
    left: 0;
    width: 91px;
}

.deco-tgv {
    bottom: 38%;
    right: -14%;
    width: 71px;
}

@media (prefers-reduced-motion: reduce) {

    .hero-ring,
    .hero-photo,
    .deco,
    .eco-card,
    .eco-card::before {
        animation: none !important;
        transition: none !important;
    }
}

/* ============================================================
   MÀN RẤT LỚN (≥1600px)
   Bề rộng khung do :root lo (min(84vw, 1360px)), khối này chỉ còn chỉnh dáng
   hero. .hero-title dùng cqw (dựa vào
   container-type khai ở .hero-copy) để cỡ chữ tự co theo bề rộng cột chữ
   thật — cột hẹp (hero Khóa học, cố định 560px) tự kẹp gần sàn 48px, cột
   rộng (Trang chủ/Thành tích) lớn dần tới trần 56px; không lên 60px như
   Figma vì mức đó từng bị đánh giá "to quá" khi thử ngày 2026-08-20 (xem
   [[cep-hero-consistency]]). .hero-ring-left dùng chung công thức calc() ở
   rule gốc (xem "1b." phía trên) nên tự né chữ ở mọi bề ngang, không cần
   khai riêng ở đây nữa.
   ============================================================ */
@media (min-width: 1600px) {
    /* KHÔNG khai --container ở đây nữa. min(84vw, 1360px) ở :root đã tự tăng
       mượt qua mốc này (1600px → 1344px) rồi chạm trần 1360px tại 1619px, nên
       thêm một công thức thứ hai chỉ tạo ra chỗ gãy mới. */
    .hero-grid {
        grid-template-columns: 1fr 1.15fr;
        gap: 80px;
    }

    .hero-title {
        font-size: clamp(48px, 9cqw, 56px);
        line-height: clamp(68px, 12.7cqw, 80px);
    }

    .hero-ring {
        width: 1200px;
    }
}

/* ============================================================
   TRANG CHỦ · CÂN LẠI HAI CỘT HERO
   Khung trang chủ đã nới lên (lề 36px, trần 1600px) nhưng nội dung cột chữ
   thì không tự dài ra, nên phần thừa đọng lại thành một mảng trắng giữa chữ
   và ảnh. Đo ở màn 1536: cột chữ được chia 766px trong khi nội dung rộng nhất
   chỉ 530px (hàng ba thẻ "Khai giảng / Còn 12 suất / Học Online"), tức 236px
   chết bên trong cột, cộng khe 60px thành mảng trống ~296px.

   KHÔNG chữa được bằng cách phóng to ảnh: .hero-photo bị kẹp bề ngang theo
   chiều cao còn lại của hero để giữ luật header + hero = 100vh, ở màn này đã
   chạm trần 774px rồi. Nên phần thừa phải trả về cột chữ, bằng hai việc:

   1. Đổi tỉ lệ 1.2fr 1fr  ->  1fr 1.25fr. Cột chữ còn 624px (vừa khít nội
      dung), cột ảnh lên 780px. Ảnh giữ nguyên 774px nhưng dịch sang trái
      142px, kết thúc đúng mép phải khung — hết luôn phần thừa bên phải.
   2. Nới khổ đoạn mô tả 46ch -> 56ch, tức ~616px thay vì ~506px, vừa đủ lấp
      nốt cột chữ 624px. 56ch vẫn nằm trong vùng dễ đọc (45–75 ký tự/dòng).
      Đây là cố ý lệch Figma (khổ gốc 493px), cùng lý do với việc khung rộng
      hơn Figma 18% — xem khối "TRANG CHỦ · KHUNG RỘNG SÁT VIỀN".

   Kết quả: mảng trống giữa hai cột còn ~68px, đúng tầm một khe bình thường.

   SÀN 511px TRONG TRACK, KHÔNG PHẢI MỘT MỐC @media. Tỉ lệ mới cho cột chữ
   hẹp hơn cũ, nên ở khung nhỏ nó tụt xuống dưới 511px — bề ngang thật của
   hàng ba thẻ, đo ở cỡ chữ --fs-sm 13px CỐ ĐỊNH (không co theo màn) — và hàng
   thẻ gãy làm hai dòng, đội hero cao thêm ~34px, phá luật 100vh.

   Viết sàn ấy thẳng vào track bằng minmax(511px, 1fr) thay vì chặn bằng một
   @media: khung rộng thì tỉ lệ 1 : 1.25 chạy bình thường, khung hẹp thì cột
   chữ dừng lại ở 511px và cột ảnh nhận phần còn lại. Không có mốc nào để
   trang giật một nhát khi kéo cửa sổ qua, và cũng khỏi phải tính lại số mỗi
   lần đổi khổ chữ hay khổ thẻ.

   Đặt sau khối ≥1600px để đè được tỉ lệ 1fr 1.15fr của khối đó trên trang
   chủ. Từ 1081px trở lên thôi: dưới mốc đó .hero-grid đã sang 1fr 1fr rồi một
   cột, không còn hai cột lệch để mà cân.
   ============================================================ */
@media (min-width: 1081px) {
    .page-home .hero-grid {
        grid-template-columns: minmax(511px, 1fr) minmax(0, 1.25fr);
        gap: 60px;
    }

    .page-home .hero-lead {
        max-width: 56ch;
    }

    /* ---- MỌI KHỐI TRANG TRÍ PHẢI BÁM ẢNH, KHÔNG BÁM CỘT ----
       Vòng tròn xanh và bốn mảnh .deco đều đặt vị trí bằng % BỀ NGANG CỘT,
       trong khi .hero-photo rộng min(120% cột, trần-theo-chiều-cao). Chừng nào
       ảnh chưa chạm trần thì ảnh đúng bằng 120% cột, hai hệ quy chiếu trùng
       nhau nên không ai thấy vấn đề. Nới cột ảnh ở trên làm 120% cột vượt
       trần: ảnh dừng lại, còn đám trang trí vẫn bám cột nên trôi sang phải,
       rơi ra ngoài ảnh.

       Cách chữa là quy hết về MỘT biến --photo-w, và cho chính .hero-photo
       dùng luôn biến đó. Từ giờ ảnh và trang trí đọc chung một nguồn, không
       thể lệch nhau: sửa công thức là cả cụm đi theo.

       Bốn hệ số dưới đây suy ra từ chính các số cũ, chia cho 120 (nền ảnh ở
       ngưỡng này), nên khi ảnh CHƯA bị kẹp kết quả ra đúng giá trị cũ:
         vòng tròn  110/120 = 0.9167   ->  120% x 0.9167 = 110%   ✓
         mảnh xanh   10/120 = 0.0833   -> -120% x 0.0833 = -10%   ✓
         cam / tam giác viền, mép phải ở 114/120 = 0.95
                                       ->  100% - 120% x 0.95 = -14%  ✓
       .deco-tgd giữ nguyên left: 0 — mép trái ảnh trùng mép trái cột nên nó
       vốn đã bám ảnh, không có gì để bù. */
    .page-home .hero-visual {
        --photo-w: min(120%, calc((100vh - var(--header-h) + var(--nav-overlap) - 80px) * 1.158));
    }

    .page-home .hero-photo {
        width: var(--photo-w);
    }

    .page-home .hero-ring {
        left: calc(var(--photo-w) * 0.9167);
    }

    .page-home .deco-xanh {
        left: calc(var(--photo-w) * -0.0833);
    }

    .page-home .deco-cam,
    .page-home .deco-tgv {
        right: calc(100% - var(--photo-w) * 0.95);
    }
}

/* Cùng cách quy chiếu, lấy đúng bộ số của ngưỡng ≤1280px: nền ảnh 115%, đệm
   trên hero 75px, vòng tròn ở 105%. Chỉ cần khai lại --photo-w và ba hệ số
   chia cho 115 thay vì 120; .hero-photo tự đọc biến mới nên không phải khai
   lại width. Thiếu khối này thì dải 1081–1280px bị tính theo bộ số của ngưỡng
   rộng và lệch ~25px. */
@media (min-width: 1081px) and (max-width: 1280px) {
    .page-home .hero-visual {
        --photo-w: min(115%, calc((100vh - var(--header-h) + var(--nav-overlap) - 75px) * 1.158));
    }

    .page-home .hero-ring {
        left: calc(var(--photo-w) * 0.9130);
    }

    .page-home .deco-xanh {
        left: calc(var(--photo-w) * -0.0870);
    }

    .page-home .deco-cam,
    .page-home .deco-tgv {
        right: calc(100% - var(--photo-w) * 0.9913);
    }
}

/* ============================================================
   RESPONSIVE — HERO SECTION
   ============================================================ */

@media (max-width: 1280px) {
    .hero {
        padding-top: 75px;
        padding-bottom: 0;
    }

    .hero-grid {
        gap: 36px;
        grid-template-columns: 1.15fr 1fr;
        align-items: end;
    }

    .hero-copy {
        align-self: center;
        padding-bottom: 20px;
    }

    .hero-title {
        font-size: 40px;
        line-height: 52px;
    }

    .hero-ring {
        width: 820px;
        left: 105%;
    }

    /* Cùng phép kẹp như bản gốc, chỉ đổi hai số của ngưỡng này: bề ngang nền
       là 115% và đệm trên hero là 75px. Thiếu dòng này thì luật kẹp ở trên bị
       đè mất, và đúng khoảng 1090–1280px hero lại vượt quá một màn hình. */
    .hero-photo {
        width: min(115%, calc((100vh - var(--header-h) + var(--nav-overlap) - 75px) * 1.158));
    }
}

@media (max-width: 1080px) {
    .hero {
        /* Header ở ngưỡng này đã bỏ khối liên hệ phía trên nên thấp hẳn đi */
        --nav-overlap: 48px;
        --header-h: 89px;
        padding: 68px 0 0;
    }

    .hero-grid {
        grid-template-columns: 1fr 1fr;
        gap: 28px;
        align-items: end;
    }

    .hero-copy {
        align-self: center;
        justify-content: center;
        height: auto;
        padding-bottom: 24px;
    }

    .hero-title {
        font-size: 32px;
        line-height: 42px;
        margin-bottom: 16px;
    }

    .hero-lead {
        font-size: 15px;
        line-height: 22px;
        margin-bottom: 24px;
    }

    .hero-badges {
        gap: 8px;
        margin-bottom: 20px;
    }

    .hero-badge {
        padding: 5px 12px;
        font-size: 13px;
    }

    .hero-visual {
        align-self: end;
    }

    .hero-photo {
        width: 100%;
        max-width: 460px;
    }

    .hero-ring {
        width: 640px;
        left: 70%;
        top: 65%;
    }

    .deco-xanh {
        left: -4%;
        width: 80px;
    }

    .deco-cam {
        right: 10%;
        width: 90px;
    }

    .deco-tgd {
        top: 2%;
        width: 70px;
    }

    .deco-tgv {
        right: -8%;
        width: 55px;
    }
}

@media (max-width: 900px) {
    .hero {
        /* Từ tablet dọc trở xuống bỏ luật một-màn-hình: màn cao mà hẹp thì
           hero 100vh chỉ toàn khoảng trống, để nội dung tự quyết chiều cao. */
        --nav-overlap: 30px;
        padding: 50px 0 0;
        height: auto;
        min-height: auto;
    }

    .hero-grid {
        grid-template-columns: 1fr;
        gap: 32px;
        align-items: end;
    }

    .hero-copy {
        height: auto;
        justify-content: flex-start;
        align-self: auto;
        padding-bottom: 0;
    }

    .hero-title {
        font-size: 30px;
        line-height: 38px;
        margin-bottom: 16px;
    }

    .hero-lead {
        max-width: 100%;
        font-size: 14.5px;
        line-height: 22px;
        margin-bottom: 22px;
    }

    .hero-badges {
        gap: 8px;
        margin-bottom: 20px;
    }

    .hero-cta {
        gap: 12px;
    }

    .hero-visual {
        width: 100%;
        max-width: 480px;
        margin: 0 auto;
        margin-top: 60px;
        align-self: end;
        display: flex;
        justify-content: center;
    }

    .hero-photo {
        width: 100%;
        margin: 0 auto;
    }

    .hero-ring {
        width: 600px;
        left: 50%;
        top: 65%;
    }

    .deco-xanh {
        left: -2%;
        width: 70px;
    }

    .deco-cam {
        right: 8%;
        width: 80px;
    }

    .deco-tgd {
        top: 0;
        left: 2%;
        width: 60px;
    }

    .deco-tgv {
        right: 9%;
        width: 45px;
    }
}

@media (max-width: 600px) {
    .hero {
        --nav-overlap: 18px;
        padding: 36px 0 0;
    }

    .hero-grid {
        gap: 24px;
    }

    .hero-title {
        font-size: 24px;
        line-height: 32px;
        margin-bottom: 12px;
    }

    .hero-lead {
        font-size: 13.5px;
        line-height: 20px;
        margin-bottom: 18px;
    }

    .hero-badges {
        gap: 6px;
        margin-bottom: 18px;
    }

    .hero-badge {
        padding: 4px 10px;
        font-size: 12px;
    }

    .hero-cta {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }

    .hero-cta .btn {
        width: 100%;
        text-align: center;
        justify-content: center;
        padding: 11px 18px;
        font-size: 14px;
    }

    .hero-link {
        justify-content: center;
        padding: 6px;
        font-size: 13.5px;
    }

    .hero-visual {
        margin-top: 15px;
        max-width: 320px;
    }

    .hero-ring {
        width: 380px;
    }

    .deco-xanh {
        left: -4%;
        width: 50px;
    }

    .deco-cam {
        right: 5%;
        width: 60px;
    }

    .deco-tgd {
        width: 45px;
    }

    .deco-tgv {
        display: none;
    }
}

/* ============================================================
   CỬA SỔ THẤP — siết nhịp dọc cột chữ để giữ luật một-màn-hình

   Laptop 14" là 1366x768 hoặc 1920x1080@125%; trừ thanh trình duyệt thì khung
   nhìn thật chỉ còn ~600-720px. Ở đó ảnh đã được kẹp theo chiều cao (xem
   .hero-photo), nhưng trên trang Thành tích và Tra cứu điểm thì nút thắt lại
   là CỘT CHỮ: nhãn xuống hai hàng nên cột cao 413px trong khi chỗ chứa chỉ
   393px — hero vượt quá một màn hình đúng 20px.

   Chỉ siết KHOẢNG CÁCH, không đụng cỡ chữ: bốn dòng dưới gỡ ra 44px, đủ cho cả
   hai trang. Chặn dưới ở 901px để không giẫm lên khối @media 900px — nơi luật
   một-màn-hình đã được bỏ hẳn.
   ============================================================ */
@media (min-width: 901px) and (max-height: 720px) {
    .hero-title {
        margin-bottom: 12px;
    }

    .hero-lead {
        margin-bottom: 18px;
    }

    .hero-badges {
        margin-bottom: 12px;
    }

    .hero-copy {
        padding-bottom: 16px;
    }
}

/* ============================================================
   MÀN DỌC — bỏ luật một-màn-hình theo TỈ LỆ, không theo bề ngang

   Khối @media 900px ở trên đã bỏ luật 100vh với lý do "màn cao mà hẹp thì hero
   chỉ toàn khoảng trống", nhưng nó bắt theo BỀ NGANG nên máy tính bảng dựng
   đứng lọt lưới: iPad Pro dọc rộng 1024px (>900 nên luật vẫn áp) mà cao 1366px,
   hero bị ép cao 1366 − 89 + 48 = 1325px trong khi nội dung chỉ cần chừng
   750px. Kết quả là gần 500px trắng trên đầu, chữ trôi xuống giữa còn ảnh dính
   đáy — cả bốn trang có hero đều dính, đo ngày 2026-08-25.

   Điều kiện đúng phải là "cửa sổ cao hơn rộng". Cửa sổ trên máy bàn gần như
   không bao giờ dựng đứng, nên mốc 1/1 chỉ chạm tới tablet dọc và những cửa sổ
   bị kéo hẹp bất thường — đúng những nơi mà ép 100vh là sai.

   Đặt SAU mọi @media của C2 và có cùng độ đặc hiệu (0-1-0) với .hero gốc, nên
   thắng nhờ thứ tự. Đừng dời khối này lên trước phần responsive ở trên.
   ============================================================ */
@media (max-aspect-ratio: 1/1) {
    .hero {
        height: auto;
        min-height: auto;
    }

    /* Hết ép chiều cao thì lưới không còn chỗ thừa để dàn ra nữa: trả cột chữ
       về bám mép dưới cùng cột ảnh, nếu không nó vẫn tự căn giữa theo phần
       .hero-copy { align-self: center } và tách rời khỏi ảnh. */
    .hero-copy {
        align-self: end;
    }
}

/* #region C2b · HERO TRANG THÀNH TÍCH — biến thể của C2

   CHỮ, NÚT VÀ MÀU KHÔNG khai lại ở đây. Hero của mọi trang phải đọc lên như
   một: cùng tiêu đề 48/68, cùng đoạn dẫn 16px màu --muted, cùng nút 13px của
   khối C2. Muốn đổi cỡ chữ hero thì sửa ở C2 để cả hai trang đổi theo, đừng
   thêm ngoại lệ cho riêng trang này.

   Khối này chỉ lo phần thật sự khác: ảnh cách đáy 36px, đĩa tròn nền, vạch
   gradient dưới chân, hai mảnh tam giác đổi chỗ và con tem 500+.

   Mọi selector ở đây có hai class (0-2-0) nên thắng bản gốc (0-1-0) — kể cả
   những rule nằm trong @media, vì media query KHÔNG cộng thêm độ đặc hiệu.
   Hệ quả: thuộc tính nào đã đè ở đây mà cần đổi theo bề ngang màn hình thì
   phải khai lại trong các @media của chính khối này, chứ đừng trông vào
   phần responsive của hero trang chủ. */

/* Trang chủ để ảnh dính sát mép dưới; ở đây Figma chừa 36px dưới chân ảnh.
   Đặt đệm lên .hero chứ không lên .hero-visual: đệm trên khung ảnh sẽ làm
   mọi mốc % của các phần tử absolute bên trong lệch theo. */
.hero--award {
    padding-bottom: 36px;
}

.hero--award .hero-grid {
    align-items: end;
}

/* Kéo CẢ CỤM ẢNH sang trái 6% bề rộng cột.

   Lý do: ảnh bị trần chiều cao kẹp lại (xem .hero--award .hero-photo ngay
   dưới) nên KHÔNG nở theo cột, trong khi margin-left 25% của ảnh, mốc 57%
   của vòng tròn và mốc -7% của con tem đều tính theo % CỘT. Cột rộng ra từ
   2026-09-17 nên ba mốc ấy nở theo còn ảnh thì không: cả cụm trôi sang phải,
   để lại mảng trống lớn giữa hai cột và đẩy con tem ra ngoài mép khung, chen
   vào chỗ mấy nút chat nổi.

   12% chứ không phải 6% như bản đầu. 6% mới chỉ đưa ẢNH về đúng tâm cột, mà
   cụm này còn con tem nhô ra ngoài mép cột 7% nữa: tính cả con tem thì trọng
   tâm cụm vẫn lệch phải ~84px ở 1920, con tem vẫn đè lên vùng mấy nút chat
   nổi ở góc phải. 12% đưa mép phải con tem vào hẳn trong mép khung (~38px)
   và vẫn chừa hơn 100px giữa vòng tròn với mép cột chữ bên trái.

   DÙNG transform CHỨ KHÔNG ĐỤNG VÀO BA MỐC KIA: transform dời cả cụm như một
   khối nên quan hệ ảnh - vòng tròn - vạch - con tem giữ y nguyên, và không
   sinh ra lần dồn lại bố cục nào. Sửa riêng từng mốc thì cụm rã ra. */
@media (min-width: 1081px) {
    .hero--award .hero-visual {
        transform: translateX(-12%);
    }
}

/* Ảnh 346px trong cột 518px → 67%, lệch phải 25% */
/* Kẹp theo chiều cao còn lại giống C2, chỉ khác tỉ lệ ảnh: 692/1036 ≈ 0.668
   (ảnh trang này đứng, không nằm ngang như trang chủ).

   TRỪ 170px CHỨ KHÔNG PHẢI 116px NHƯ TRƯỚC. Từ 2026-09-17 khung nội dung
   rộng ra 1600px cho mọi trang, cột ảnh nở từ ~695px lên ~824px nên vế 67%
   (552px) vượt qua vế chiều cao — trần chiều cao trở thành vế quyết định,
   ảnh cao KỊCH khoảng trống còn lại. Mà con tem .award-stat lại treo ở
   top:-5%, tức nhô lên TRÊN mép ảnh: ảnh cao kịch thì con tem chui vào
   gầm thanh menu.

   Cách tính 170: gọi A = 100vh - header + overlap. Mép trên con tem cách
   đỉnh hero = A - 36 (đệm đáy) - 1,05 x chiều cao ảnh, mà chiều cao ảnh
   = A - K. Muốn mép ấy luôn thấp hơn phần hero bị thanh menu phủ
   (--nav-overlap 68px) cộng 20px an toàn thì K ≥ (124 + 0,05A)/1,05:
   ra 160 ở màn cao 1000px, 164 ở 1080px, 170 ở 1200px. Lấy 170 để phủ hết
   dải màn hình thật. Màn cao hơn nữa thì vế 67% lại nhỏ hơn, ảnh không chạm
   trần nên con tem càng an toàn. */
/* Bề ngang ảnh quy về MỘT biến để đĩa tròn và vạch gradient bên dưới đọc
   chung một nguồn với chính tấm ảnh — cùng cách hero trang chủ đang làm với
   --photo-w (xem khối "MỌI KHỐI TRANG TRÍ PHẢI BÁM ẢNH, KHÔNG BÁM CỘT" ở C2). */
.hero--award .hero-visual {
    --photo-w: min(67%, calc((100vh - var(--header-h) + var(--nav-overlap) - 170px) * 0.668));
}

.hero--award .hero-photo {
    width: var(--photo-w);
    margin-left: 25%;
}

/* Đĩa tròn 514px, tâm trùng tâm ảnh theo chiều ngang và nằm ở 42% chiều cao
   ảnh, nên chân váy nhô hẳn xuống dưới vòng đúng như thiết kế.

   left TÍNH THEO ẢNH, KHÔNG THEO CỘT. Bản cũ ghi left: 57% — đúng ở khổ
   Figma (cột 518, ảnh 347 lệch phải 25% nên tâm ảnh rơi vào 58,5% cột, lệch
   57% chỉ 8px, mắt không thấy). Nhưng ảnh có trần chiều cao nên KHÔNG nở
   theo cột: cột rộng ra thì tâm ảnh tụt về phía trái (ở cột 824px, ảnh 477px
   thì tâm ảnh chỉ còn ở 53,9% cột) trong khi mốc 57% đứng yên — đĩa tròn
   trôi sang phải khỏi tâm ảnh ~25px và càng rộng càng lệch.

   25% là lề trái ảnh, cộng nửa bề ngang ảnh là ra đúng tâm ảnh; .hero-ring
   gốc đã có transform: translate(-50%, -50%) nên chỉ cần đưa mốc tâm vào. */
.hero--award .hero-ring {
    top: 42%;
    left: calc(25% + var(--photo-w) / 2);
    width: 99%;
    max-width: 514px;
}

/* Vạch gradient nằm NGAY DƯỚI đáy ảnh (Figma: y 603.5 so với đáy ảnh 603),
   không luồn sau chân váy — nên cho hẳn xuống dưới khung bằng bottom âm.

   Tâm cũng bám ẢNH chứ không bám cột, cùng lý do với .hero--award .hero-ring
   phía trên: mốc cũ left: 21% đứng yên trong khi tâm ảnh tụt về trái khi cột
   rộng ra, nên vạch trượt sang trái so với chân váy (đo ở 1920: lệch ~33px).
   Ở khổ Figma tâm vạch nằm tại 21% + 73%/2 = 57,5% cột, tức trùng tâm ảnh
   58,5% — nên canh theo tâm ảnh là giữ đúng ý đồ gốc. */
.award-line {
    position: absolute;
    z-index: 2;
    bottom: -6px;
    left: calc(25% + var(--photo-w) / 2);
    width: 73%;
    max-width: 378px;
    transform: translateX(-50%);
    pointer-events: none;
}

/* Con tem 500+: nền smoke, viền đứt nét xanh, nghiêng -5.7deg đúng ma trận
   transform trong Figma (0.99, -0.1, 0.1, 0.99). Không bo góc, không đổ bóng. */
.award-stat {
    position: absolute;
    top: -5%;
    right: -7%;
    z-index: 3;
    width: 163px;
    margin: 0;
    padding: 12px 24px 14px;
    background: var(--smoke);
    border: 1px dashed var(--green);
    text-align: center;
    transform: rotate(-5.7deg);
}

.award-stat strong {
    display: block;
    font-size: 40px;
    line-height: 49px;
    font-weight: 700;
    color: var(--green);
}

/* Gạch ngang trong Figma là một Line riêng; ở đây làm bằng border-top của
   chính dòng chữ dưới — bớt một thẻ rỗng mà nhìn không khác. */
.award-stat span {
    display: block;
    margin-top: 6px;
    padding-top: 7px;
    border-top: 1px solid rgba(29, 38, 46, .7);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
}

/* Con tem tràn 37px ra ngoài container, đúng như Figma. Nhưng từ 1400px trở
   xuống, lề giữa container và mép màn hình không còn đủ chừng ấy nên mép phải
   màn hình sẽ cắt mất một góc tem — kéo nó về sát mép container. */
@media (max-width: 1400px) {
    .award-stat {
        right: 0;
    }
}

/* Hai mảnh tam giác đổi cạnh neo so với bản trang chủ, nên PHẢI trả cạnh cũ
   về auto: ghim cả bốn cạnh thì ảnh bị kéo giãn cho vừa khung, tam giác méo. */
.hero--award .deco-tgv {
    top: 8%;
    left: -10%;
    right: auto;
    bottom: auto;
    width: 67px;
}

.hero--award .deco-tgd {
    top: auto;
    left: 15%;
    bottom: 0;
    width: 78px;
}

@media (max-width: 1280px) {
    .hero--award .hero-visual {
        --photo-w: min(70%, calc((100vh - var(--header-h) + var(--nav-overlap) - 111px) * 0.668));
    }

    .hero--award .hero-photo {
        width: var(--photo-w);
        margin-left: 24%;
    }

    /* Lề trái ảnh ở ngưỡng này là 24% chứ không phải 25%, nên mốc tâm phải
       khai lại — xem ghi chú tại .hero--award .hero-ring ở bản gốc. */
    .hero--award .hero-ring {
        top: 42%;
        left: calc(24% + var(--photo-w) / 2);
        width: 99%;
        max-width: 480px;
    }
}

@media (max-width: 1080px) {
    .hero--award {
        padding-bottom: 28px;
    }

    .hero--award .hero-visual {
        --photo-w: min(84%, 340px);
    }

    .hero--award .hero-photo {
        width: var(--photo-w);
        margin-left: 14%;
    }

    .hero--award .hero-ring {
        top: 42%;
        left: calc(14% + var(--photo-w) / 2);
        width: 112%;
        max-width: 430px;
    }

    /* left là mốc TÂM (vạch có transform: translateX(-50%) từ bản gốc), không
       phải mép trái — nên 16% cũ đổi thành công thức tâm ảnh như .hero-ring. */
    .award-line {
        left: calc(14% + var(--photo-w) / 2);
        width: 84%;
        max-width: 300px;
    }

    .award-stat {
        width: 140px;
        padding: 10px 18px 12px;
    }

    .award-stat strong {
        font-size: 32px;
        line-height: 40px;
    }

    .award-stat span {
        font-size: 14px;
        line-height: 18px;
    }

    .hero--award .deco-tgv {
        left: -8%;
        width: 56px;
    }

    .hero--award .deco-tgd {
        left: 12%;
        width: 64px;
    }
}

@media (max-width: 900px) {
    .hero--award {
        padding-bottom: 22px;
    }

    /* Một cột: .hero-visual thành flex canh giữa, nên bỏ margin lệch phải.
       Ảnh canh giữa khung thì tâm ảnh trùng 50% khung, đúng bằng mốc
       .hero-ring ngay dưới — không cần công thức theo --photo-w như các
       ngưỡng rộng hơn. */
    .hero--award .hero-photo {
        width: 100%;
        max-width: 320px;
        margin-left: auto;
        margin-right: auto;
    }

    .hero--award .hero-ring {
        top: 42%;
        left: 50%;
        width: 118%;
        max-width: 380px;
    }

    /* Vạch gradient tính theo bố cục hai cột, ở một cột nó lệch hẳn khỏi chân */
    .award-line {
        display: none;
    }

    .award-stat {
        top: -2%;
        right: -2%;
        width: 130px;
    }

    .award-stat strong {
        font-size: 28px;
        line-height: 36px;
    }

    .award-stat span {
        font-size: 13px;
        line-height: 17px;
    }

    .hero--award .deco-tgv {
        top: 4%;
        left: 0;
        width: 48px;
    }

    .hero--award .deco-tgd {
        left: 4%;
        bottom: 0;
        width: 46px;
    }
}

@media (max-width: 600px) {
    .hero--award {
        padding-bottom: 16px;
    }

    .hero--award .hero-photo {
        max-width: 250px;
    }

    .hero--award .hero-ring {
        max-width: 320px;
    }

    .award-stat {
        top: 0;
        right: 0;
        width: 112px;
        padding: 8px 12px 10px;
    }

    .award-stat strong {
        font-size: 24px;
        line-height: 30px;
    }

    .award-stat span {
        font-size: 12px;
        line-height: 16px;
    }

    /* .deco-tgv đã bị bản gốc ẩn ở ngưỡng này; chỉ còn tam giác đặc, thu nhỏ lại */
    .hero--award .deco-tgd {
        width: 38px;
    }
}

/* #endregion */
/* #region C2c · DANH SÁCH HỌC VIÊN TRÚNG TUYỂN — trang Thành tích
   Figma: nền xanh, lưới bốn cột hai hàng, thẻ 290x290 bo 10px, khe dọc 25px,
   hai nút tròn 44px nằm NGOÀI container, dãy chấm trang ở dưới.
   Băng trượt dùng lại initCarousel trong app.js; khác duy nhất là track ở đây
   là lưới hai hàng chứ không phải một hàng flex. */
.admitted {
    padding: clamp(36px, 4.2vw, 64px) 0 clamp(44px, 4.8vw, 82px);
    color: var(--smoke);
    background: var(--green);
    overflow: hidden;
}

.admitted-body {
    position: relative;
}

/* grid-auto-flow: column cộng hai hàng cố định = mỗi "cột" chứa hai thẻ liền
   nhau theo thứ tự HTML. initCarousel vẫn chạy đúng vì nó đo vị trí thật của
   từng thẻ chứ không giả định track là một hàng. */
.admitted-track {
    --per-row: 4;
    --track-gap: 14px;

    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - (var(--per-row) - 1) * var(--track-gap)) / var(--per-row));
    grid-template-rows: repeat(2, auto);
    gap: 25px var(--track-gap);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.admitted-track::-webkit-scrollbar {
    display: none;
}

.admitted-card {
    margin: 0;
    overflow: hidden;
    border-radius: var(--r-media);
    scroll-snap-align: start;
}

.admitted-card img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    transition: transform .5s var(--ease);
}

.admitted-card:hover img {
    transform: scale(1.03);
}

/* Nút tròn 44px viền vàng, nền trắng 10%. PHẢI viết hai class: .arrow-btn
   dùng chung nằm SAU khối này trong file, cùng độ đặc hiệu (0-1-0) thì rule
   viết sau thắng — nút sẽ trở lại viền 1px currentColor. */
.admitted .arrow-btn {
    position: absolute;
    top: 50%;
    z-index: 2;
    width: 44px;
    height: 44px;
    font-size: 16px;
    color: var(--gold);
    background: rgba(255, 255, 255, .1);
    border: 2px solid var(--gold);
    box-shadow: 0 4px 60px rgba(41, 44, 124, .15);
    transform: translateY(-50%);
}

.admitted .arrow-btn[data-dir="prev"] {
    left: -73px;
}

.admitted .arrow-btn[data-dir="next"] {
    right: -74px;
}

/* :hover và :active của .arrow-btn khai transform riêng, ghi đè mất phần
   translateY(-50%) đang giữ nút ở giữa — nên phải cộng lại vào cả hai. */
.admitted .arrow-btn:hover {
    color: var(--green);
    background: var(--gold);
    border-color: var(--gold);
    transform: translateY(-50%) translateY(var(--lift-sm));
}

.admitted .arrow-btn:active {
    transform: translateY(-50%) translateY(1px);
}

/* Nút đứng ngoài container 73px, cộng bề ngang 44px là cần 117px lề mỗi bên.

   MỐC 1833px CHỨ KHÔNG PHẢI 1433px NHƯ TRƯỚC. Số cũ tính theo công thức
   khung CŨ min(84vw, 1360px) — khung đó co dần nên lề ngoài container cũng
   nở dần theo, đạt 117px đúng lúc màn hình chạm 1434px.

   Từ 2026-09-17 khung đổi sang min(100% - 72px, 1600px): dưới 1672px lề
   ngoài container LUÔN LÀ 36px CỐ ĐỊNH (không nở theo màn hình nữa, xem khối
   "KHUNG RỘNG SÁT VIỀN" ở :root) — tức 36px < 117px cần, nút luôn bị hụt.
   Đo thật bằng Playwright ngày 2026-09-18: ở 1440–1600px nút chỉ hở 7px bên
   phải (94% thân nút nằm ngoài màn hình, đúng là "bị cắt" như ảnh khách
   gửi); phải tới 1800px mới thấy nguyên vẹn.

   Công thức mốc mới: từ 1672px trở lên container chạm trần 1600px, lề ngoài
   = (vw - 1600) / 2. Cần lề ≥ 117px → vw ≥ 1600 + 234 = 1834px. Dưới mốc đó,
   kể cả 1434–1833px vốn từng đủ chỗ, giờ đều phải đưa nút vào trong. */
@media (max-width: 1833px) {
    .admitted .arrow-btn[data-dir="prev"] {
        left: 8px;
    }

    .admitted .arrow-btn[data-dir="next"] {
        right: 8px;
    }
}

@media (max-width: 1080px) {
    .admitted-track {
        --per-row: 3;
    }
}

@media (max-width: 900px) {
    .admitted {
        padding: 48px 0 60px;
    }

    .admitted-track {
        --per-row: 2;
    }
}

@media (max-width: 600px) {
    .admitted-track {
        --per-row: 1;
        --track-gap: 12px;
        gap: 12px var(--track-gap);
    }

    .admitted .arrow-btn {
        width: 38px;
        height: 38px;
        font-size: 14px;
    }
}

/* #endregion */

/* #region C2d · HERO TRANG KHÓA HỌC — biến thể của C2

   CHỮ, NÚT VÀ MÀU KHÔNG khai lại ở đây. Figma trang này ghi tiêu đề 60px và
   nút 20px — bỏ qua, vì hero của mọi trang phải đọc lên như một: cùng tiêu đề
   48/68, cùng đoạn dẫn 16px màu --muted, cùng nút 13px của khối C2. Muốn đổi
   cỡ chữ hero thì sửa ở C2 để cả ba trang đổi theo.

   Khối này chỉ lo phần thật sự khác: banner cao 639px, chữ dồn về một cột bên
   trái, nửa phải là bức tranh tràn hết mép màn hình gồm bốn lớp — nét chéo
   vàng, dải chéo xanh, ảnh cắt chéo và hai tam giác.

   HỆ TỌA ĐỘ: mọi số đo lấy thẳng từ Figma khổ 1440x639, trong đó y = 0 là mép
   DƯỚI thanh menu. Nhưng .hero bị kéo lên nằm dưới menu bằng margin-top âm nên
   hộp của section cao hơn banner đúng phần bị che. Biến --nav-overlap giữ số
   đó; C2 đổi margin-top ở ngưỡng nào thì phải đổi --nav-overlap ở ngưỡng ấy.

   Mọi selector ở đây hoặc có hai class (0-2-0), hoặc đứng SAU C2 trong file,
   nên thắng bản gốc — kể cả rule nằm trong @media của C2, vì media query
   KHÔNG cộng thêm độ đặc hiệu. Hệ quả: thuộc tính nào đã đè ở đây mà cần đổi
   theo bề ngang màn hình thì phải khai lại trong các @media của chính khối
   này, chứ đừng trông vào phần responsive của hero trang chủ. */

/* Chiều cao KHÔNG khai lại ở đây: dùng đúng công thức 100vh - header của C2 để
   ba hero cao bằng nhau và mở trang ra là vừa một màn hình. Vì thế banner
   không còn giữ tỉ lệ 1440x639 của Figma nữa — mọi lớp tranh bên dưới phải
   khai bề ngang theo % màn hình (xem .course-band / .course-lines). */
.hero--course {
    display: flex;
    align-items: center;
    /* Đệm trên đúng bằng phần chui dưới menu → hộp nội dung khớp banner Figma */
    padding: var(--nav-overlap) 0 0;
}

/* Một cột chữ rộng 560px (Figma: khối chữ 493–524px) thay cho lưới hai cột của
   C2. z-index để chữ luôn nằm trên bức tranh dù tranh đứng sau trong DOM. */
.hero--course .hero-grid {
    position: relative;
    z-index: 1;
    grid-template-columns: minmax(0, 560px);
    gap: 0;
    min-height: 0;
    align-items: center;
}

/* ---------- Bức tranh nửa phải ---------- */

/* Gốc tọa độ dời xuống mép dưới menu để dùng thẳng số % theo chiều dọc của
   Figma. z-index:0 tạo tầng xếp riêng, nhốt gọn z-index của .hero-photo và
   .deco bên trong, khỏi tranh chỗ với phần chữ. */
.course-art {
    position: absolute;
    inset: var(--nav-overlap) 0 0;
    z-index: 0;
    pointer-events: none;
}

/* Hai SVG đã bao sẵn góc nghiêng trong path nên KHÔNG rotate lại. Cả hai xuất
   ở đúng chiều cao banner (639px), nên cho cao 100% khối tranh là về đúng tỉ
   lệ gốc; left là tọa độ x trong Figma chia cho 1440.

   z-index 2 để hai dải nằm TRÊN ảnh: trong Figma dải chéo xanh đè lên mép trái
   tấm ảnh, nhờ vậy nó hiện ra là một hình bình hành trọn vẹn. Bỏ dòng này thì
   .hero-photo (z-index 1 của C2) sẽ xén cụt đuôi dải thành một cạnh thẳng. */
.course-lines,
.course-band {
    position: absolute;
    bottom: 0;
    z-index: 2;
    height: 114%;
}

/* Bề ngang khai theo % MÀN HÌNH chứ không để width:auto ăn theo chiều cao.
   Hero giờ cao theo 100vh nên chiều cao banner đổi theo từng cỡ cửa sổ; nếu
   bề ngang hai dải ăn theo chiều cao thì màn càng thấp dải càng hẹp, mép ảnh
   (đặt theo % màn hình) đứng yên, khe hở giữa chúng lệch tứ tung.
   Hai file SVG đã thêm preserveAspectRatio="none" để chịu kéo dãn dọc — nhờ
   vậy độ nghiêng của dải và của mép ảnh cùng đổi theo tỉ lệ ngang/dọc, luôn
   song song. Số % lấy đúng kích thước dựng ở khổ chuẩn 1440x639. */
.course-lines {
    left: 35%;
    width: 27.53%;
}

.course-band {
    left: 41%;
    width: 31.25%;
}

/* Ảnh bám mép phải màn hình, mép trái cắt chéo SONG SONG với dải xanh — đây là
   điểm dễ làm hỏng cả bố cục: mọi đường chéo trong thiết kế này đều đi xuống thì
   lệch sang TRÁI. Độ nghiêng lấy từ chính path của dai-cheo-xanh.svg: cạnh phải
   chạy từ (345.4, -27.8) xuống (180.7, 646.7), tức dx/dy = -0.244.

   Khung ảnh rộng 635px (từ x = 805 tới mép phải 1440 của Figma) và cao hơn
   banner đúng phần chui dưới thanh menu, tổng 707px. Mép chéo đi hết chiều cao
   đó lệch 707 x 0.244 = 173px = 27.2% bề ngang khung. Điểm sát trái nhất nằm ở
   ĐÁY (0%), điểm lùi phải nhất ở ĐỈNH (27.2%) — viết ngược hai số này là mép
   ảnh chụm vào dải xanh thành hình nêm, sai hẳn thiết kế. */
.course-photo {
    position: absolute;
    top: calc(var(--nav-overlap) * -1);
    right: 0;
    bottom: 0;
    left: 55.9%;
    overflow: hidden;
    clip-path: polygon(27.2% 0, 100% 0, 100% 100%, 0 100%);
}

/* Bản C2 để ảnh rộng 120% và tự do cao; ở đây ảnh phải phủ kín khung đã cắt,
   phần thừa của tấm vuông 1280x1280 giao cho object-fit xén hai bên. */
.hero--course .hero-photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Từ 1080px xuống, C2 kẹp .hero-photo còn max-width 460px và margin auto
       cho bố cục hai cột của trang chủ. Ở đây ảnh là một dải phải phủ kín
       khung đã cắt, nên phải trả hai thuộc tính đó về mặc định — quên là ảnh
       co lại 460px rồi tự nằm giữa, chừa hai vệt nền hai bên. */
    max-width: none;
    margin: 0;
}

/* Hai tam giác đổi cạnh neo so với bản C2, nên PHẢI trả cạnh cũ về auto: ghim
   cả bốn cạnh thì ảnh bị kéo giãn cho vừa khung, tam giác méo. */
.hero--course .deco-tgd {
    top: 17%;
    left: 93.5%;
    width: 79px;
}

.hero--course .deco-tgv {
    top: 84.5%;
    left: 50.7%;
    right: auto;
    bottom: auto;
    width: 71px;
}

/* Lưới chấm 9x9 của Figma: chấm 2.3px, bước 9.5px, mờ dần 0.3 → 0.08 từ trái
   sang phải. Vẽ bằng gradient thay vì ảnh — 81 chấm không đáng một request.
   mask-image lo phần mờ dần: nếu dùng opacity thì cả lưới mờ đều một mức.
   Chỉ hiện từ 1400px trở lên, hẹp hơn thì lề trái container không còn chỗ và
   lưới chấm sẽ đè vào giữa đoạn chữ — cùng lý do với .hero-ring-left ở C2. */
.course-dots {
    display: none;
    position: absolute;
    top: 53.4%;
    left: 5.35%;
    z-index: 0;
    width: 91px;
    height: 91px;
    background-image: radial-gradient(var(--gold) 1.15px, transparent 1.25px);
    background-size: 9.53px 9.53px;
    -webkit-mask-image: linear-gradient(90deg, rgba(0, 0, 0, .3), rgba(0, 0, 0, .08));
    mask-image: linear-gradient(90deg, rgba(0, 0, 0, .3), rgba(0, 0, 0, .08));
    pointer-events: none;
}

@media (min-width: 1400px) {
    .course-dots {
        display: block;
    }
}

/* ---------- Responsive ---------- */

/* Banner co giãn theo tỉ lệ nên KHÔNG đụng tới left của ba lớp tranh ở các
   ngưỡng dưới đây: đổi một số là khe hở giữa dải xanh và ảnh lệch ngay. Chỉ
   cột chữ và cỡ mảnh trang trí cần chỉnh theo bề ngang. */
@media (max-width: 1280px) {
    .hero--course .hero-grid {
        grid-template-columns: minmax(0, 500px);
    }
}

@media (max-width: 1080px) {

    /* Cột chữ hẹp lại 380px: hai dải chéo cao theo banner nên khi màn hẹp đi,
       chúng chiếm phần trăm bề ngang nhiều hơn và bắt đầu liếm vào đoạn dẫn. */
    .hero--course .hero-grid {
        grid-template-columns: minmax(0, 380px);
    }

    .hero--course .deco-tgd {
        width: 62px;
    }

    .hero--course .deco-tgv {
        width: 56px;
    }
}

@media (max-width: 900px) {

    /* Một cột: chữ trên, ảnh thành dải ngang bên dưới. Khối tranh trở về dòng
       chảy thường nên tự rơi xuống dưới .container — đó là lý do trong HTML nó
       đứng sau phần chữ. Dải chéo xanh, nét chéo vàng và hai tam giác ăn theo
       bố cục hai vùng nên ở đây không còn nghĩa: ẩn đi. */
    .hero--course {
        display: block;
        min-height: 0;
        padding: 50px 0 0;
    }

    .hero--course .hero-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .course-art {
        position: relative;
        inset: auto;
        height: 300px;
        margin-top: 28px;
    }

    .course-photo {
        inset: 0;
        clip-path: polygon(0 9%, 100% 0, 100% 100%, 0 100%);
    }

    /* Khung ngang 300px xén tấm ảnh vuông rất sâu; canh giữa thì mất luôn phần
       đầu người. Kéo cửa sổ cắt lên 30% để giữ khuôn mặt trong khung. */
    .hero--course .hero-photo {
        object-position: center 30%;
    }

    .course-band,
    .course-lines,
    .hero--course .deco {
        display: none;
    }
}

@media (max-width: 600px) {
    .hero--course {
        padding: 36px 0 0;
    }

    .course-art {
        height: 220px;
        margin-top: 22px;
    }
}

/* #endregion */

/* ============================================================
   KHỐI TIÊU ĐỀ SECTION  —  dùng lại ở mọi section
   Màu lấy từ currentColor nên chạy được cả nền sáng lẫn nền tối.
   ============================================================ */
.section-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 24px;
    /* margin-top: var(--sec-head-gap); */
    margin-bottom: 32px;
}

.section-eyebrow {
    display: flex;
    align-items: center;
    gap: 11px;
    margin: 0 0 10px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    /* KHÔNG đặt màu ở đây. Nhãn này dùng chung cho cả section nền sáng lẫn
       nền xanh đậm; để nó thừa hưởng color của section thì hai vạch hai bên
       (border-top: currentColor) cũng tự đổi theo. Đặt màu cứng ở đây là
       chữ xanh trên nền xanh ở khối Giáo viên. */
}

.section-eyebrow::before,
.section-eyebrow::after {
    content: "";
    width: 35px;
    border-top: 1px solid currentColor;
}

/* Biến thể: bỏ hai vạch hai bên.
   PHẢI đứng SAU quy tắc gốc: hai selector cùng độ đặc hiệu (0,1,1)
   nên cái viết sau mới thắng. Đặt trước là quy tắc này bị vô hiệu. */
.section-eyebrow--plain::before,
.section-eyebrow--plain::after {
    content: none;
}

/* Hai section này có chữ chính màu đậm nhưng nhãn nhỏ phải xanh theo thiết kế.
   .courses và .teachers không cần dòng nào: nhãn thừa hưởng đúng màu section. */
.featured .section-eyebrow,
.eco .section-eyebrow {
    color: var(--green);
}

/* "Xem tất cả" cũng vậy: .section-more color: inherit lấy đúng màu chữ chính
   (--ink) của .featured, trong khi .courses bên trên (section-level color:
   var(--green)) lại ra xanh — cùng một liên kết mà hai section hiện hai màu.
   Ép về xanh ở đây cho khớp với .courses. */
.featured .section-more {
    color: var(--green);
}

/* Khách chốt 21/09/2026: mọi tiêu đề section CANH TRÁI, và không để mỗi chữ
   trơn nữa mà thêm thanh dọc vàng mở đầu + cụm nhấn cuối bọc trong viên thuốc.
   Trước đó 3/6 tiêu đề trang chủ canh giữa, 3/6 canh trái.

   Phải là flex chứ không để chữ chảy tự nhiên: thanh dọc là ::before, cần nó
   nằm CÙNG HÀNG với chữ và không bị dòng chữ cuốn theo khi tiêu đề xuống dòng. */
.section-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .3em;
    margin: 0;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
}

/* Thanh dọc vàng mở đầu mọi tiêu đề.
   Chiều cao ĐO CỨNG theo em chứ KHÔNG dùng align-self: stretch. Stretch kéo
   thanh phủ hết chiều cao khối flex — tiêu đề dài xuống hai dòng (ví dụ "Cập
   nhật tin tức tuyển sinh quân đội" trên màn hẹp) thì thanh cao gấp đôi, thành
   một vệt vàng sổ dọc cạnh hai dòng chữ. */
.section-title::before {
    content: "";
    flex: none;
    width: clamp(5px, .42vw, 7px);
    height: 1.04em;
    margin-right: .24em;
    border-radius: var(--r-pill);
    background: var(--gold);
}

/* CỤM CHỮ NHẤN CUỐI TIÊU ĐỀ — VÀNG, KHÔNG NGHIÊNG. Khai một lần ở đây cho MỌI
   section, mọi trang.

   Trước đây mỗi section tự khai một kiểu: trang chủ thì .featured và .award
   nghiêng + vàng, .testimonial nghiêng nhưng không đổi màu, còn .admitted
   (trang Thành tích) và .teacher-list (trang Khóa học) lại thẳng + vàng — hai
   chỗ sau còn ghi hẳn chú thích "Figma trang này thì không nghiêng". Cùng một
   component mà ba trang ba kiểu, và trên chính trang chủ thì 3/7 tiêu đề
   nghiêng còn 4/7 thẳng.

   Chốt với khách ngày 2026-09-16: THẲNG HẾT. Montserrat không có bộ italic
   thật nên trình duyệt phải nghiêng giả (oblique), ở cỡ 32px đậm 700 nét bị
   gượng; màu vàng tự nó đã đủ nhấn, thêm nghiêng là nhấn hai lần một chỗ.

   Vàng đọc tốt trên cả hai nền đang dùng: nền sáng (.courses, .featured,
   .eco, .testimonial) và nền xanh đậm (.teachers, .award). */
/* Vàng gốc --gold ở MỌI section, cả nền sáng lẫn nền tối — khách chốt ngày
   16/09/2026 sau khi xem thử bản đậm. Đã thử --gold-ink #8A6210 cho các
   section nền sáng (tương phản 5.48:1 thay vì 2.22:1) nhưng khách thấy ngả
   nâu, mất đúng sắc vàng thương hiệu.

   Đánh đổi đã biết và đã chấp nhận: trên nền sáng cụm chữ này đạt 2.06–2.22:1,
   dưới ngưỡng WCAG 3:1 cho chữ lớn. Đừng "sửa" lại lần nữa nếu không có yêu
   cầu mới — đây là lựa chọn, không phải sót.

   --gold-ink vẫn còn dùng, nhưng chỉ ở thẻ Azota (.eco-card--gold). */
/* Hai biến này là cách DUY NHẤT để đổi màu viên thuốc theo nền section. Đặt
   giá trị mặc định qua tham số dự phòng của var() chứ không khai ở :root, để
   section nào không nói gì thì tự ăn bản nền sáng — khỏi phải nhớ khai lại. */
.section-title em {
    position: relative;
    padding: .1em .56em .16em;
    border-radius: var(--r-pill);
    font-style: normal;
    color: var(--pill-ink, var(--gold));
    background: var(--pill-bg, var(--gold-wash));
}

/* Dấu lấp lánh góc trên phải viên thuốc.
   LUÔN vàng, kể cả trên nền xanh đậm nơi chữ trong viên thuốc là xanh: dấu này
   nằm NGOÀI viên thuốc, đặt trên nền section. Cho nó ăn theo currentColor thì
   ở các section nền tối nó thành xanh đậm trên xanh đậm — biến mất. */
.section-title em::after {
    content: "";
    position: absolute;
    top: -.2em;
    right: -.16em;
    width: .58em;
    height: .58em;
    background: var(--gold);
    -webkit-mask: var(--sparkle) center / contain no-repeat;
    mask: var(--sparkle) center / contain no-repeat;
}

/* SECTION NỀN XANH ĐẬM — đảo viên thuốc: nền vàng đặc, chữ xanh.
   Bản nền sáng dùng vàng đổ trong suốt 16%, đặt lên xanh đậm thì gần như tàng
   hình. Khách chốt 21/09/2026 lấy bản đảo ngược cho tương phản cao.

   .award KHÔNG gộp được vào đây một cách vô điều kiện: nó có biến thể nền sáng
   .award--light (dùng ở khối "Điểm số qua các kỳ thi" trang Thành tích) phải
   trả hai biến về mặc định — xem ngay dưới. */
.teachers,
.award,
.admitted,
.course-list,
.podium {
    --pill-ink: var(--green);
    --pill-bg: var(--gold);
}

/* PHẢI đứng sau khối trên: cùng độ đặc hiệu (0,1,0) nên cái viết sau mới thắng.
   Cùng lý do đã ghi ở chỗ khai .award--light phía dưới file. */
.award--light {
    --pill-ink: var(--gold);
    --pill-bg: var(--gold-wash);
}

/* Biến thể: nhãn, tiêu đề và mô tả xếp chồng (section không có nút bên phải).
   Tên cũ là --center, đổi ngày 21/09/2026 khi khách chốt canh trái hết: giữ
   tên cũ là mỗi lần đọc view lại tưởng chỗ đó đang canh giữa. */
.section-head--stack {
    display: block;
}

/* HAI KHỐI CUỐI TRANG CHỦ THỞ RỘNG HƠN — khách chốt 21/09/2026.
   Vinh danh học viên và Học viên nói gì, 32px chuẩn chung thấy chật.

   Khác hai khối này với phần còn lại: ngay dưới tiêu đề là một DẢI ẢNH/THẺ
   đặc kín chiều ngang (.award-track chạy vô tận, .tmrow-track là lưới thẻ
   trắng) chứ không phải chữ hay khoảng thoáng. Mảng đặc ấy ép lên tiêu đề,
   nên cùng một con số 32px ở đây nhìn chật hơn hẳn ở các section khác.

   Khoanh bằng .page-home vì .award còn dùng cho khối "Điểm số qua các kỳ thi"
   ở trang Thành tích (bản .award--light) — chỉnh chung là đụng cả trang đó,
   mà khách chỉ nói tới trang chủ. .tmrow tự nó đã chỉ có ở trang chủ, gom vào
   đây cho hai khối cùng một luật thay vì rải hai nơi. */
.page-home .award .section-head,
.page-home .tmrow .section-head {
    margin-bottom: clamp(40px, 3.6vw, 58px);
}

/* Dòng mô tả nhỏ dưới tiêu đề section.
   margin ngang PHẢI là 0, không phải auto: auto cộng với max-width sẽ kéo đoạn
   chữ về giữa khung, lệch khỏi thanh dọc vàng bên trái ngay trên nó. */
.section-subtitle {
    max-width: 82ch;
    margin: 12px 0 0;
    font-size: var(--fs-base);
    line-height: 1.7;
    color: var(--muted);
}

.section-nav {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* 13px + gạch chân, khách chốt ngày 16/09/2026. Trước đây 20px
   (--fs-md ở trần) và không gạch chân, to gần bằng tiêu đề section nên tranh
   chỗ với nó; hạ xuống --fs-sm cho đúng vai một liên kết phụ, rồi gạch chân
   để bù lại phần "nhìn ra là bấm được" vừa mất khi chữ nhỏ đi.

   Dùng --fs-sm / --lh-sm chứ không gõ 13px cứng: hai biến này đã là 13/16px
   trong bảng thang chữ, đi qua biến thì sau đổi thang một chỗ là cả site theo.

   text-underline-offset: ở 13px mà để gạch dính sát chân chữ thì nét gạch
   liếm vào phần đuôi của các chữ có dấu (ả, ọ, ữ) — tiếng Việt dấu nhiều nên
   lỗi này lộ hơn hẳn so với tiếng Anh.

   color: inherit phải giữ: liên kết này nằm trên CẢ nền sáng (.courses,
   .featured) lẫn nền xanh đậm (.teachers), ăn theo color của section thì
   không phải khai màu riêng cho từng nơi. */
.section-more {
    margin-right: 10px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    /* font-weight: 700; */
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.section-more:hover {
    opacity: .75;
}

.arrow-btn {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    font-size: 15px;
    color: currentColor;
    background: transparent;
    border: 1px solid currentColor;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        border-color .25s var(--ease),
        transform .25s var(--ease),
        box-shadow .25s var(--ease);
}

.arrow-btn:active {
    transform: translateY(1px);
}

.arrow-btn:hover {
    color: var(--smoke);
    background: var(--gold);
    border-color: var(--gold);
    transform: translateY(var(--lift-sm));
}

/* ============ NÚT DÙNG CHUNG ============ */
.btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 22px;
    border-radius: var(--r-pill);
    font-size: var(--fs-sm);
    font-weight: 700;
    letter-spacing: var(--track);
    text-decoration: none;
    border: 2px solid transparent;
    cursor: pointer;
    overflow: hidden;
    z-index: 1;
    transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

/* Nhấc mặc định cho MỌI nút .btn — .cc-btn, .teacher-link đều thừa hưởng.
   Các biến thể .btn-gold / .btn-green / .btn-ghost khai transform riêng ở dưới
   nên vẫn ghi đè được quy tắc này. */
.btn:hover {
    transform: translateY(var(--lift));
    box-shadow: 0 10px 22px rgba(18, 26, 22, .14);
}

/* PHẢI đứng sau :hover — cùng độ đặc hiệu, viết sau mới thắng, nếu không
   thì lúc bấm giữ chuột nút vẫn ở trạng thái nhấc lên thay vì lún xuống. */
.btn:active {
    transform: translateY(1px) scale(0.98);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}

.btn-gold {
    background: var(--gold);
    color: var(--ink);
    border-color: var(--gold);
}

.btn-gold:hover {
    background: #f4b327;
    border-color: #f4b327;
    color: var(--ink);
    transform: translateY(-3px) scale(1.02);
    box-shadow: 0 8px 22px rgba(227, 162, 27, 0.38);
}

.btn-green {
    background: var(--green);
    color: var(--smoke);
    border-color: var(--green);
}

.btn-green:hover {
    background: #144930;
    border-color: #144930;
    color: var(--white);
    transform: translateY(-3px) scale(1.02);
    box-shadow: 0 8px 22px rgba(27, 94, 63, 0.38);
}

.btn-ghost {
    background: transparent;
    color: var(--green);
    border: 1.5px solid var(--green);
}

.btn-ghost:hover {
    background: var(--green);
    color: var(--white);
    border-color: var(--green);
    transform: translateY(-3px) scale(1.02);
    box-shadow: 0 8px 20px rgba(27, 94, 63, 0.28);
}

/* #region C3 · THỐNG KÊ ẤN TƯỢNG
   Đặc tả: "Khối Thống kê ấn tượng (Counter số): Hiển thị các con số động".
   Dải xanh vắt ngang ngay dưới banner, mỗi ô một con số và một dòng nhãn.
   Hiệu ứng đếm nằm ở initCountUp() trong app.js. */
.stats {
    padding: clamp(26px, 2.9vw, 52px) 0;
    color: var(--smoke);
    background: var(--green);
}

/* Ô CO THEO NỘI DUNG + space-between, KHÔNG phải cột chia đều.
   Đây là chỗ dễ nhầm: cột chia đều (1fr) thì các CỘT bằng nhau, nhưng nội
   dung mỗi ô dài ngắn khác nhau nên phần trống thừa ra ở mỗi cột cũng khác,
   và KHE NHÌN THẤY giữa hai cụm chữ lệch hẳn. Đo trên màn 1536 ngày
   16/09/2026, bốn nhãn rộng 121 / 147 / 78 / 129px cho ra ba khe
   348 / 263 / 379px — chênh nhau tới 116px, mắt thấy ngay là không đều.

   Chuyển sang flex: ô tự co theo nội dung, space-between chia đều phần trống
   còn lại. Ba khe bằng nhau đúng 329px, ô đầu chạm mép trái, ô cuối chạm mép
   phải — thỏa cả "căn đều" lẫn "sát viền" cùng lúc.

   flex chứ không phải grid vì ô phải co theo nội dung; grid-auto-columns:
   max-content cũng làm được nhưng thiếu chỗ thì tràn ra ngoài, còn flex-wrap
   thì xuống dòng. `gap` ở đây là khe TỐI THIỂU: space-between luôn nới rộng
   hơn, gap chỉ có tác dụng lúc khung hẹp tới mức sát nhau.

   Bảng `stats` do admin quản, bật/tắt một dòng là còn ba ô — flex không cần
   biết trước số ô, khỏi lo hụt một ô trống bên phải như repeat(4, 1fr). */
.stats-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: clamp(18px, 2.2vw, 34px);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Ô ĐẦU căn trái, Ô CUỐI căn phải. Ô giờ đã co sát nội dung nên chính cái
   NHÃN (thường là dòng rộng nhất) đã chạm mép rồi; hai luật này lo nốt con
   SỐ bên trên — số hẹp hơn nhãn, để canh giữa thì nó thụt vào so với nhãn,
   thấy rõ nhất ở ô cuối ("25+" hẹp hơn "Giáo viên & trợ giảng" tới 54px).

   :first-child/:last-child chứ đừng gõ số thứ tự — số ô đổi được từ admin. */
@media (min-width: 768px) {
    .stat:first-child {
        text-align: left;
    }

    .stat:last-child {
        text-align: right;
    }
}

.stat {
    text-align: center;
}

.stat-value {
    margin: 0;
    font-size: clamp(28px, 2.55vw, 40px);
    line-height: 1.22;
    font-weight: 700;
    color: var(--white);

    /* Chữ số rộng bằng nhau. Lúc đang đếm, mỗi khung hình là một con số khác;
       với bảng chữ số thường thì '1' hẹp hơn '8' nên bề ngang cả cụm co giãn
       liên tục, nhìn ra là số rung và dòng nhãn dưới bị kéo qua kéo lại. */
    font-variant-numeric: tabular-nums;
}

/* Đuôi +/% nhỏ hơn con số một bậc, đúng như bản thiết kế. */
.stat-suffix {
    font-size: .82em;
}

.stat-label {
    margin: clamp(4px, .5vw, 9px) 0 0;
    font-size: var(--fs-sm);
    line-height: 1.5;
    font-weight: 400;
    color: rgba(244, 247, 245, .85);
}

/* Hai hàng hai cột cho màn hẹp. Phải khai lại display: grid vì hàng ngang ở
   trên đã chuyển sang flex.

   Mốc nâng từ 600px lên 767px: bốn nhãn cộng lại đã 477px, thêm ba khe tối
   thiểu nữa là cần ~540px chỉ riêng cho nội dung. Dưới ngưỡng đó ô bị ép co,
   nhãn dài nhất ("Đạt trên 900/1200 điểm") vỡ hai dòng và hàng so le. Trước
   đây mốc 600px nên dải 601–767px rơi vào đúng vùng vỡ ấy.

   grid chứ không để flex-wrap tự xuống dòng: wrap + space-between thì hàng
   dưới cùng chỉ có một ô và nó dạt hẳn sang trái, nhìn như lỗi. */
@media (max-width: 767px) {
    .stats-grid {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 22px 16px;
    }
}

/* #endregion */

/* #region C4 · KHÓA HỌC */
.courses {
    padding: clamp(38px, 4.2vw, 70px) 0 clamp(44px, 4.8vw, 80px);
    color: var(--green);
    background: var(--white);
}

/* Nhãn, hai vạch và "Xem tất cả" thừa hưởng màu xanh của .courses;
   riêng tiêu đề lớn là màu chữ đậm nên phải nói rõ. */
.courses .section-title {
    color: var(--ink);
}

/* Khối tiêu đề ở đây có thêm một hàng phụ (.courses-head, chỉ để chứa liên
   kết "Xem tất cả") chen giữa tiêu đề và tấm poster thật — không giống mọi
   section khác chỉ có MỘT khối rồi tới thẳng nội dung. Giữ khoảng title→hàng
   phụ này sát nhau (8px, cùng một cụm "đầu trang"), rồi để .courses-head
   gánh đúng 32px chuẩn chung ngay trước tấm poster. */
.courses .section-head--stack {
    margin-bottom: 8px;
}

/* Ba khối này bám đúng bề ngang tấm poster để mép trái phải luôn thẳng hàng,
   kể cả khi poster phải thu hẹp trên màn hình thấp. */
.courses-head {
    margin: 0 0 32px;
}

/* Hàng này giờ chỉ còn mỗi liên kết "Xem tất cả". .section-head là flex với
   justify-content: space-between — luật ấy chỉ dàn hai đầu khi có từ hai con
   trở lên; còn một con thì nó nằm bên TRÁI. margin-left:auto đẩy về phải,
   thẳng hàng với liên kết "Xem tất cả" của các section khác.
   (Nhãn "Khóa học đang khai giảng" từng đứng đây đã bỏ vì trùng tiêu đề.) */
.courses-head .section-nav {
    margin-left: auto;
}

.courses-track {
    display: flex;
    gap: 24px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.courses-track::-webkit-scrollbar {
    display: none;
}

.course-poster {
    position: relative;
    display: block;
    flex: 0 0 100%;
    overflow: hidden;
    border-radius: var(--r-box);
    scroll-snap-align: start;
}

/* Tỉ lệ 21/9 (2.33:1) không khớp banner thật (1072x549 ≈ 1.95:1) — object-fit:
   cover phải cắt để lấp đầy khung rộng hơn ảnh, và phần bị cắt đúng vào chỗ có
   nội dung: logo + chữ "Khai giảng" ở mép trên, dải quà tặng ở mép dưới. Đo
   ngày 2026-08-25: ở khổ laptop 14" (poster giữ nguyên 1000px, --nav-cap khiến
   `vw` không còn tả đúng bề ngang thật của poster từ ~1040px viewport trở lên)
   trần cũ (429px) chỉ bằng 84% chiều cao ảnh cần có — mất gần hết dải trên và
   dưới.
   Đổi sang đúng tỉ lệ gốc của banner thì width:100% tự suy ra đúng chiều cao,
   KHÔNG cắt gì cả ở mọi khổ màn. Trần 520px chỉ còn là lưới an toàn chặn ảnh
   quá khổ (banner tỉ lệ dọc bất thường do admin tự tải lên), không bao giờ
   chạm tới với banner đúng tỉ lệ — 1000px rộng thì cao đúng 512px, dưới trần. */
/* MỨC CẮT ẢNH — đọc kỹ trước khi đổi ba con số dưới.
   Ảnh poster gốc tỉ lệ ~1.95:1, khung hiển thị 16/6 (2.67:1) rộng hơn, nên
   object-fit: cover luôn xén bớt trên/dưới. Đây chính là chỗ từng cắt mất
   logo và dải quà tặng khi khung để 21/9 — 16/6 là số đã sửa lần đó.

   Ngày 16/09/2026 bỏ trần 1000px của cả khối cho thẳng hàng hai mép với các
   section khác, nên poster rộng ra và mức cắt tăng theo:
     rộng 1000px -> khung 1000x375, ảnh phủ 1000x513, cắt 138px (27%)
     rộng 1464px -> khung 1464x520, ảnh phủ 1464x751, cắt 231px (31%)
   max-height: 520px là thứ chặn khung lại; bỏ nó thì hết cắt thêm nhưng
   banner cao 751px, gấp đôi. Khách chốt GIỮ max-height, chấp nhận 31%. */
.course-poster img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 6;
    max-height: 520px;
    object-fit: cover;
    transition: transform .5s var(--ease);
}

.course-poster:hover img {
    transform: scale(1.03);
}

.course-badge {
    position: absolute;
    top: 20px;
    left: 20px;
    padding: 8px 20px;
    font-size: var(--fs-sm);
    font-weight: 700;
    line-height: var(--lh-sm);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--white);
    background: var(--gold);
    border-radius: var(--r-pill);
    border: 2px solid #E3A21B
}

.courses-empty {
    padding: 40px 0;
    text-align: center;
    color: var(--muted);
}

@media (max-width: 700px) {
    .course-badge {
        top: 12px;
        left: 12px;
        padding: 6px 14px;
    }
}

/* Cùng bề ngang với .courses-track (1000px, canh giữa) để ba thẻ tin luôn
   thẳng hàng mép trái/phải với tấm poster phía trên — trước đây khối này
   trải hết .container (tới 1200px) trong khi poster bị khóa 1000px, nên ở
   màn rộng thẻ tin lấn ra ngoài cả hai bên so với poster. */
.news-strip {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    margin: 26px 0 0;
}

.news-item {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 16px;
    color: var(--ink);
    border-radius: var(--r-row);
    text-decoration: none;
    transition: background .25s ease;
}

.news-item:hover {
    background: var(--green-10);
}

.news-date {
    flex: none;
    padding: 7px 11px;
    font-size: var(--fs-sm);
    font-weight: 700;
    line-height: var(--lh-sm);
    color: var(--green);
    background: var(--white);
    border-radius: var(--r-row);
}

.news-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 15px;
    line-height: 1.5;
}

@media (max-width: 900px) {
    .news-strip {
        grid-template-columns: 1fr;
        gap: 12px;
    }
}

/* #endregion */


/* #region C5 · KHÓA HỌC NỔI BẬT */
.featured {
    padding: var(--sec-y) 0 var(--sec-y-end);
    color: var(--ink);
    background: var(--smoke);
}

/* Nút mũi tên ở section này nền sáng nên dùng xanh, không dùng vàng như bên Giáo viên */
.featured .arrow-btn.is-active,
.featured .arrow-btn:hover {
    color: var(--white);
    background: var(--green);
    border-color: var(--green);
}

.featured-track {
    --per-row: 3;
    --track-gap: 30px;

    display: flex;
    gap: var(--track-gap);
    padding: 6px 0 10px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.featured-track::-webkit-scrollbar {
    display: none;
}

/* Thẻ là cột dọc; .cc-info có margin-top:auto nên khối thông tin,
   giá và nút luôn dính đáy, ba thẻ mô tả dài ngắn khác nhau vẫn thẳng hàng. */
.course-card {
    display: flex;
    flex-direction: column;
    flex: 0 0 calc((100% - (var(--per-row) - 1) * var(--track-gap)) / var(--per-row));
    padding: 16px;
    background: var(--white);
    border-radius: var(--r-card);
    box-shadow: 0 6px 20px rgba(18, 26, 22, .08);
    scroll-snap-align: start;
}

/* height: auto là BẮT BUỘC. Thẻ <img> có width="600" height="300" (giữ lại để
   trình duyệt chừa sẵn chỗ, tránh giật layout), nhưng thuộc tính height ấy là
   một "presentational hint" — khi CSS không khai height thì nó thắng, và
   aspect-ratio bên dưới bị vô hiệu: ảnh rộng 348px mà vẫn cao đúng 300px.
   Trả height về auto thì aspect-ratio mới thật sự điều khiển chiều cao. */
.cc-media {
    position: relative;
    width: 100%;
    overflow: hidden;
    border-radius: var(--r-media);
    background: var(--smoke);
}

.cc-thumb {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 2 / 1;
    object-fit: cover;
    border-radius: inherit;

    transition:
        transform .45s cubic-bezier(.2, .7, .3, 1),
        filter .35s ease;
}

/* Tạo lớp tối rất nhẹ để chữ trên ảnh dễ đọc */
.cc-media::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;

    z-index: 1;
}

.cc-meta {
    position: absolute;
    z-index: 2;

    top: 12px;
    left: 12px;
    right: 12px;

    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;

    margin: 0;

    font-size: 12px;
    line-height: 1.2;

    color: #fff;
}

.cc-meta span {
    display: inline-flex;
    align-items: center;
    gap: 6px;

    min-width: 0;
    padding: 2px 6px;

    color: #fff;

    background: rgba(15, 26, 20, .72);
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 999px;

    box-shadow: 0 4px 14px rgba(0, 0, 0, .15);

    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
}

.cc-meta i {
    flex: none;
    font-size: 11px;
    color: #fff;
}


.cc-name {
    margin: 10px 0 0;
    font-size: 17px;
    line-height: 1.35;
    font-weight: 700;
    color: var(--card-title);
}

.cc-name a {
    color: inherit;
    text-decoration: none;
}

.cc-name a:hover {
    color: var(--green);
}


.cc-stats {
    position: absolute;
    z-index: 2;

    left: 12px;
    right: 12px;
    bottom: 12px;

    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;

    margin: 0;

    font-size: 12px;
    line-height: 1.2;
}

.cc-rating,
.cc-students {
    display: inline-flex;
    align-items: center;
    gap: 6px;

    padding: 2px 6px;

    border-radius: 999px;

    box-shadow: 0 4px 14px rgba(0, 0, 0, .16);

    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
}


/* Rating nổi bật hơn */
.cc-rating {
    font-weight: 700;

    color: #3d2a00;
    background: rgba(255, 211, 77, .95);
    border: 1px solid rgba(255, 255, 255, .3);
}

.cc-rating i {
    color: #a66800;
}


/* Học viên - nền kính tối */
.cc-students {
    color: #fff;

    background: rgba(15, 26, 20, .72);
    border: 1px solid rgba(255, 255, 255, .18);
}

.cc-students i {
    font-size: 11px;
}

.cc-info {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: auto;
    padding: 12px 14px;
    font-size: var(--fs-sm);
    line-height: 1.5;
    color: var(--ink);
    background: var(--smoke);
    border-radius: var(--r-media);
}

.cc-info p {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 0;
}

.cc-info i {
    flex: none;
    margin-top: 2px;
    color: var(--green);
}

.cc-price {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: 14px 0 0;
}

.cc-price strong {
    font-size: 21px;
    line-height: 1.2;
    font-weight: 700;
    color: var(--green);
}

.cc-price sup {
    font-size: .55em;
    vertical-align: super;
}

.cc-price del {
    font-size: var(--fs-sm);
    color: var(--price-old);
}

.cc-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 14px;
}

/* Nút "Thêm giỏ hàng" nằm trong một <form> để gửi POST kèm CSRF. Bọc thêm một
   tầng như vậy là <form> trở thành Ô LƯỚI, còn <button> tụt xuống thành cháu —
   nó sẽ co lại bằng bề ngang chữ thay vì chiếm nửa hàng.

   display: contents xóa HỘP của <form> chứ không xóa hành vi gửi form: con của nó
   lên thẳng làm ô lưới, mà bấm nút vẫn submit bình thường. Cách kia — cho
   <form> width:100% — không cứu được vì nút bên trong vẫn không biết phải cao
   bằng nút anh em ở ô bên cạnh. */
.cc-actions form {
    display: contents;
}

.cc-btn {
    padding: 9px 12px;
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: 0;
    border-radius: var(--r-pill);
}

.btn.cc-btn--ghost {
    color: var(--green);
    background: var(--white);
    border: 1px solid var(--green-30);
}

.cc-btn--ghost:hover {
    border-color: var(--green);
}

.cc-btn--solid {
    color: var(--white);
    background: var(--green);
    border: 1px solid var(--green);
}

.cc-btn--solid:hover {
    background: var(--ink);
    border-color: var(--ink);
}

.btn.cc-btn--wide {
    gap: 8px;
    width: 100%;
    margin-top: 10px;
    color: var(--green);
    background: var(--white);
    border: 1px solid var(--green-30);
}

.cc-btn--wide:hover {
    border-color: var(--green);
}

.course-card:hover .cc-thumb {
    transform: scale(1.035);
    filter: brightness(.94);
}

@media (max-width: 1024px) {
    .featured-track {
        --per-row: 2;
    }
}

@media (max-width: 700px) {
    .featured-track {
        --per-row: 1;
        --track-gap: 20px;
    }
}

/* #endregion */

/* #region C5b · DANH SÁCH KHÓA HỌC — trang /khoa-hoc

   Ruột thẻ dùng lại nguyên bộ .cc-* của C5: cùng nội dung, chỉ khác cách xếp.
   Ở đây là thẻ NGANG 1204x465 — ảnh một bên, thông tin một bên, so le nhau qua
   từng thẻ. Mọi selector đều gắn .course-card--row (0-2-0) và khối này đứng SAU
   C5 trong file, nên C5 ngoài trang chủ không bị đụng tới.

   Số đo lấy từ Figma khổ 1440: thẻ 1204 (đúng bề ngang container), đệm 15,
   ảnh 554, cột chữ 599 đệm 18/28, các dòng cách nhau 8. */

.course-list {
    padding: 67px 0 84px;
    color: var(--smoke);
    background: var(--green);
}

.course-list .section-head {
    margin-bottom: 32px;
}

/* Bản THẺ NGANG so le — hiện KHÔNG dùng, giữ lại theo yêu cầu của khách để có
   thể quay lại bất cứ lúc nào (đổi partial trong courses/index.php). */
.course-rows {
    display: flex;
    flex-direction: column;
    gap: 30px;
}

/* Bản LƯỚI — đang dùng. Cùng bộ thẻ dọc với khối "Khóa học nổi bật" ngoài
   trang chủ, chỉ khác cách xếp: trang chủ là băng cuộn ngang (.featured-track,
   display:flex + overflow-x), còn đây là lưới 3 cột đứng yên. Vì
   `courses_per_page` là 6 nên một trang vừa đúng hai hàng.

   Khai lại --per-row và --track-gap dù grid không dùng tới: .course-card có
   `flex: 0 0 calc(... var(--per-row) ...)` viết cho băng cuộn của trang chủ.
   Trong lưới thì thuộc tính flex bị bỏ qua nên không ảnh hưởng gì, nhưng để
   biến không xác định thì cả dòng calc thành lỗi — khai sẵn cho sạch, và để
   thẻ vẫn chạy đúng nếu có ngày ai đó đổi khối này về flex. */
.course-grid {
    --per-row: 3;
    --track-gap: 30px;

    display: grid;
    grid-template-columns: repeat(var(--per-row), minmax(0, 1fr));
    gap: var(--track-gap);
    align-items: stretch;
}

.course-card--row {
    flex-direction: row;
    align-items: stretch;
    padding: 15px;
    border-radius: var(--r-box);
    box-shadow: 4px 4px 6px rgba(0, 0, 0, .25);
}

/* ---------- Cột ảnh ---------- */

/* 554/1174 (bề ngang thẻ đã trừ hai lần đệm) = 47.2% */
.course-card--row .cc-media {
    position: relative;
    display: block;
    flex: 0 0 30%;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--r-box);
}

/* So le: thẻ chẵn đưa ảnh sang trái. Dùng order thay vì đảo HTML để phần chữ
   luôn đứng trước trong DOM — trình đọc màn hình gặp tên khóa trước tấm ảnh. */
.course-card--row:nth-child(even) .cc-media {
    order: -1;
}

/* Card lẻ: badge bên phải */
.course-card--row:nth-child(odd) .course-badge {
    left: auto;
    right: 12px;
}

/* Card chẵn: badge bên trái */
.course-card--row:nth-child(even) .course-badge {
    left: 12px;
    right: auto;
}

/* Bản C5 khóa ảnh ở tỉ lệ 2:1; ở đây ảnh phải phủ kín cả cột nên bỏ aspect-ratio.

   position:absolute là để ảnh KHÔNG tham gia tính chiều cao thẻ. Cứ để ảnh
   trong dòng chảy thì mỗi thẻ cao một kiểu: poster dọc (1080x1350) căng cột
   ảnh lên 692px kéo cả thẻ cao theo, thẻ nào poster ngang thì chỉ 465px. Đẩy
   ảnh ra khỏi dòng chảy thì chiều cao thẻ chỉ do cột chữ quyết định — mọi thẻ
   bằng nhau, còn ảnh cứ phủ kín khung rồi để object-fit xén phần thừa. */
.course-card--row .cc-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    object-fit: cover;
    border-radius: var(--r-box);
}

/* Con tem ở trang chủ màu vàng, Figma trang này vẽ màu xanh */
.course-card--row .course-badge {
    top: 14px;
    right: 12px;
    padding: 7px 21px;
    letter-spacing: 0;
    color: var(--white);
    background: var(--green);
}

/* ---------- Cột thông tin ---------- */

.course-card--row .cc-body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
    padding: 18px 28px;
}

.course-card--row .cc-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 16px;
}

/* Vì HTML meta đang đứng trước name,
   đổi vị trí bằng grid */
.course-card--row .cc-meta {
    grid-column: 2;
    grid-row: 1;

    position: static;
    inset: auto;

    display: flex;
    align-items: center;
    gap: 7px;

    margin: 0;
}

.course-card--row .cc-actions  {
    grid-template-columns: 1fr 1fr 1fr;
}

.course-card--row .cc-meta span {
    background: var(--green);   
    font-weight: 500;
}

.course-card--row .cc-name {
    grid-column: 1;
    grid-row: 1;

    min-width: 0;
    margin: 0;
}

.course-card--row .cc-info,
.course-card--row .cc-price,
.course-card--row .cc-actions {
    grid-column: 1 / -1;
}

@media (max-width: 700px) {

    .course-card--row .cc-body {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
    }

    .course-card--row .cc-meta {
        order: 1;

        flex-wrap: wrap;
        justify-content: flex-start;

        margin-bottom: 8px;
    }

    .course-card--row .cc-name {
        order: 2;
    }


    .course-card--row .cc-info {
        order: 4;
    }

    .course-card--row .cc-price {
        order: 5;
    }

    .course-card--row .cc-actions {
        order: 6;
    }
}

/* Thẻ ngang rộng gấp ba thẻ 1/3 của C5 nên chữ cũng lên một cỡ: nhãn 16,
   tên khóa 32, mô tả 16, nhịp dòng 180% — đúng Figma trang này. */
.course-card--row .cc-meta {
    margin-top: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    letter-spacing: var(--track);
    font-weight: 700;
    color: var(--green);
}

/* Thời lượng nhẹ hơn tên danh mục */
.course-card--row .cc-meta span+span {
    font-weight: 500;
}

.course-card--row .cc-meta i {
    font-size: 17px;
}

/* Chặn hai dòng: tên khóa do admin nhập, một cái tên dài bất thường mà xuống
   ba dòng là thẻ đó cao hơn hẳn các thẻ còn lại. */
.course-card--row .cc-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0;
    font-size: var(--fs-lg);
    line-height: 1.65;
    letter-spacing: var(--track);
    color: var(--ink);
}


.course-card--row .cc-stats {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    letter-spacing: var(--track);
}

.course-card--row .cc-rating i {
    font-size: 17px;
}

.course-card--row .cc-students {
    color: var(--white);
}

/* Khối lịch học: nền xanh nhạt 15%, bo 15px như Figma (C5 dùng nền khói) */
.course-card--row .cc-info {
    margin-top: 0;
    gap: 8px;
    padding: 10px 20px;
    font-size: var(--fs-base);
    line-height: 1.4;
    background: var(--green-15);
    border-radius: var(--r-box);
}

.course-card--row .cc-info i {
    margin-top: 3px;
    font-size: 18px;
}

/* ---------- Giá ---------- */

.course-card--row .cc-price {
    align-items: center;
    gap: 15px;
    margin: 0;
}

.course-card--row .cc-price strong {
    font-size: 20px;
    line-height: 24px;
    letter-spacing: var(--track);
}

/* "đ" trong Figma là chữ nhỏ có gạch chân, dùng cho cả giá bán lẫn giá gốc */
.course-card--row .cc-price sup {
    text-decoration: underline;
}

.course-card--row .cc-price del {
    font-size: 13px;
    line-height: 16px;
    letter-spacing: var(--track);
}

.course-card--row .cc-price del sup {
    font-size: .7em;
}

.cc-off {
    padding: 1px 10px;
    font-size: 13px;
    line-height: var(--lh-loose);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--green);
    background: rgba(27, 94, 63, .2);
    border-radius: var(--r-pill);
}

/* ---------- Nút ---------- */

/* Figma: hai nút 260px trong hàng 543 → khe 23px */
.course-card--row .cc-actions {
    gap: 23px;
    margin-top: 0;
}

/* Nút ở đây cao 33px, bo 20px, chữ 16px và KHÔNG đổ bóng như .btn dùng chung */
.course-card--row .cc-btn {
    padding: 6px 10px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    border-width: 1px;
    border-radius: 20px;
    box-shadow: none;
}

.course-card--row .cc-btn--ghost {
    font-weight: 600;
    color: var(--ink);
    border-color: var(--ink-50);
}

.course-card--row .cc-btn--ghost:hover {
    color: var(--green);
    border-color: var(--green);
}

.course-card--row .cc-btn--solid {
    color: var(--smoke);
}

.course-card--row .cc-btn--wide {
    margin-top: 0;
    border-color: var(--green);
}

.course-card--row .cc-btn--wide i {
    font-size: 20px;
}

/* ---------- Con tem trạng thái ---------- */

/* Khóa đã qua: tem xám trầm để không hứa nhầm là vẫn còn tuyển sinh */
.course-badge--past {
    background: rgba(18, 26, 22, .55);
}

/* ---------- Chuyển trang ---------- */

/* Dải nút tròn canh giữa dưới danh sách. Màu lấy currentColor của section
   (màu khói trên nền xanh) nên không phải khai màu riêng. */
.pager {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
    margin-top: 40px;
}

.pager-btn {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    font-size: 15px;
    font-weight: 700;
    color: currentColor;
    text-decoration: none;
    border: 1px solid currentColor;
    border-radius: var(--r-pill);
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        border-color .25s var(--ease),
        transform .25s var(--ease);
}

.pager-btn:hover {
    color: var(--green);
    background: var(--smoke);
    border-color: var(--smoke);
    transform: translateY(var(--lift-sm));
}

/* Trang đang xem — đổ nền vàng, không có trạng thái hover vì bấm cũng vô ích */
.pager-btn.is-active {
    color: var(--ink);
    background: var(--gold);
    border-color: var(--gold);
}

/* Mũi tên ở hai đầu dải khi đã hết trang để đi */
.pager-btn.is-off {
    opacity: .35;
}

/* ---------- Responsive ---------- */

/* Thẻ ngang cần ít nhất ~1100px mới đủ chỗ cho hai cột; hẹp hơn thì xếp dọc:
   ảnh lên trên, thông tin xuống dưới, bỏ luôn luật so le. */
@media (max-width: 1080px) {
    /* Ba thẻ dọc cạnh nhau dưới 1080px thì mỗi thẻ hẹp quá, tên khóa học vỡ
       thành bốn năm dòng. Xuống hai cột — số khóa mỗi trang là 6 nên vẫn chia
       chẵn, thành ba hàng đều. */
    .course-grid {
        --per-row: 2;
        --track-gap: 20px;
    }

    .course-card--row {
        flex-direction: column;
        min-height: 0;
    }

    .course-card--row .cc-media,
    .course-card--row:nth-child(even) .cc-media {
        order: -1;
        flex: none;
        /* Poster của khóa học là ảnh ngang; giữ khung dọc 554/435 của bố cục
           hai cột thì ảnh cao lút màn hình. */
        aspect-ratio: 2 / 1;
    }

    .course-card--row .cc-body {
        padding: 18px 10px 10px;
    }

    .course-card--row .cc-name {
        font-size: 26px;
        line-height: 1.4;
    }
}

@media (max-width: 700px) {
    .course-list {
        padding: 48px 0 56px;
    }

    .course-list .section-head {
        margin-bottom: 30px;
    }

    .course-rows {
        gap: 20px;
    }

    /* Một cột: dưới 700px hai thẻ cạnh nhau còn chưa đầy 160px mỗi bên. */
    .course-grid {
        --per-row: 1;
    }

    .course-card--row {
        padding: 10px;
    }

    .course-card--row .cc-body {
        gap: 6px;
        padding: 14px 6px 6px;
    }

    .course-card--row .cc-name {
        font-size: 21px;
    }

    .course-card--row .cc-meta,
    .course-card--row .cc-stats,
    .course-card--row .cc-info,
    .course-card--row .cc-btn {
        font-size: 14px;
    }

    /* Hai nút xếp chồng cho đủ chỗ chữ */
    .course-card--row .cc-actions {
        grid-template-columns: 1fr;
        gap: 10px;
    }
}

/* #endregion */


/* #region C5c · TRANG CHI TIẾT KHÓA HỌC — /khoa-hoc/{slug}

   Hai tầng: tầng trên nền trắng (giới thiệu + thẻ mua), tầng dưới nền xanh
   (nội dung + giảng viên + khóa liên quan). Số đo Figma khổ 1440: cột trái 600,
   thẻ mua 480, khối dưới chia 766 / 359 cách nhau 74. */

/* ---------- Tầng trên ---------- */

.cd-head {
    padding: 43px 0 60px;
    background: var(--white);
}

.cd-crumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .8);
}

.cd-crumb a {
    color: inherit;
    text-decoration: none;
}

.cd-crumb a:hover {
    color: var(--green);
    text-decoration: underline;
}

.cd-crumb strong {
    font-weight: 700;
    color: var(--green);
}

/* Figma: cột chữ 600, thẻ mua 480, khe 119. Cột trái để 1fr chứ không khóa
   600px — màn rộng hơn 1440 thì ảnh poster giãn theo thay vì bỏ trống. */
.cd-head-grid {
    display: grid;
    grid-template-columns: 1fr 480px;
    gap: 119px;
    margin-top: 20px;
    align-items: start;
}

.cd-title {
    margin: 0;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    color: var(--ink);
}

.cd-lead {
    margin: 14px 0 0;
    font-size: var(--fs-base);
    line-height: 1.5;
    color: var(--ink);
}

.cd-stats {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 28px;
    margin-top: 18px;
    font-size: var(--fs-base);
    line-height: 1.8;
    letter-spacing: var(--track);
    color: var(--ink);
}

.cd-rating {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-weight: 700;
}

.cd-rating i {
    color: var(--gold);
}

/* Poster do admin tải lên, tỉ lệ không đoán trước được. Khóa khung 600x338 của
   Figma bằng aspect-ratio rồi cover: mọi khóa học có khung ảnh bằng nhau, thẻ
   không bị xô lệch vì một tấm ảnh cao bất thường. */
.cd-poster {
    display: block;
    width: 100%;
    margin-top: 25px;
    aspect-ratio: 600 / 338;
    object-fit: cover;
    border-radius: var(--r-media);
}

/* ---------- Thẻ mua ---------- */

/* Trang này dài, phần dưới toàn nội dung chi tiết, mà nút "Đăng ký học" phải
   luôn trong tầm với. position: sticky lo việc đó, không cần dòng JS nào.
   Mốc top phải trừ chiều cao thanh menu dính, không thì thẻ chui xuống dưới nó. */
.cd-buy {
    position: sticky;
    top: calc(var(--nav-stuck-h) + 16px);
    padding: 30px 20px;
    background: var(--smoke);
    border: .5px solid rgba(18, 26, 22, .2);
    border-radius: var(--r-box);
    box-shadow: 4px 4px 4px rgba(0, 0, 0, .25);
}

.cd-price {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 15px;
    margin: 0;
}

.cd-price strong {
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--green);
}

.cd-price del {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 400;
    letter-spacing: var(--track);
    color: var(--price-old);
}

/* Chữ "đ" nhỏ có gạch chân, dùng cho cả giá bán lẫn giá gốc — giống hệt quy
   ước ở thẻ khóa học trang danh sách. */
.cd-price sup {
    font-size: .55em;
    text-decoration: underline;
    vertical-align: super;
}

.cd-save {
    display: inline-flex;
    align-items: center;
    margin: 12px 0 0;
    padding: 5px 15px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--green);
    background: rgba(27, 94, 63, .2);
    border-radius: var(--r-pill);
}

.cd-facts {
    margin-top: 20px;
    padding: 12px 10px;
    background: var(--green-10);
    border-radius: var(--r-media);
}

.cd-facts p {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin: 0;
    padding: 8px 0;
    font-size: var(--fs-base);
    line-height: 1.4;
    letter-spacing: .03em;
    color: var(--ink);
}

.cd-facts i {
    margin-top: 3px;
    font-size: 17px;
    color: var(--green);
}

/* ---------- Nút trong thẻ mua ---------- */

/* Không dùng .btn dùng chung: Figma cho bộ nút này bo 20px (không phải viên
   thuốc), cỡ chữ 13 và không đổ bóng. font-family: inherit là bắt buộc vì
   "Thêm giỏ hàng" là <button>, mà nút không tự thừa hưởng font của trang. */
.cd-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 11px 10px;
    font-family: inherit;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    letter-spacing: var(--track);
    text-decoration: none;
    border-radius: 20px;
    cursor: pointer;
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        border-color .25s var(--ease),
        transform .25s var(--ease);
}

.cd-btn:hover {
    transform: translateY(var(--lift-sm));
}

.cd-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-top: 22px;
}

/* Cùng lý do với .cc-actions form ở khối C5 — xem ghi chú đầy đủ tại đó. */
.cd-actions form {
    display: contents;
}

.cd-btn--ghost {
    font-weight: 600;
    color: var(--ink);
    background: transparent;
    border: .5px solid rgba(18, 26, 22, .5);
}

.cd-btn--ghost:hover {
    color: var(--green);
    border-color: var(--green);
}

.cd-btn--solid {
    color: var(--smoke);
    background: var(--green);
    border: .5px solid var(--green);
}

.cd-btn--solid:hover {
    background: #144930;
    border-color: #144930;
}

.cd-btn--line {
    margin-top: 12px;
    color: var(--green);
    background: transparent;
    border: .5px solid var(--green);
}

.cd-btn--line:hover {
    color: var(--smoke);
    background: var(--green);
}

/* Viền đứt nét: Figma dùng nó để tách "Test đầu vào" khỏi hai nút mua ở trên —
   đây là việc phụ, làm thử chứ không phải bước đăng ký. */
.cd-btn--dash {
    margin-top: 12px;
    color: var(--green);
    background: var(--green-10);
    border: 1px dashed var(--green);
}

.cd-btn--dash:hover {
    color: var(--smoke);
    background: var(--green);
}

.cd-note {
    margin: 12px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    text-align: center;
    letter-spacing: var(--track);
    color: var(--ink-50);
}

/* ---------- Tầng dưới ---------- */

.cd-body {
    padding: 61px 0 80px;
    color: var(--smoke);
    background: var(--green);
}

/* Figma: 766 + 74 + 359 = 1199, vừa đúng container 1200 */
.cd-body-grid {
    display: grid;
    grid-template-columns: 1fr 359px;
    gap: 74px;
    align-items: start;
}

.cd-h2 {
    margin: 0;
    font-size: var(--fs-md);
    line-height: 22px;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--smoke);
}

/* Khoảng cách giữa các khối trong cột trái. Dùng * + .cd-h2 thay vì margin-top
   cứng: mọi khối đều có thể vắng mặt, nên khối nào rơi lên đầu cũng không bị
   đội thêm một khe thừa phía trên. */
*+.cd-h2,
*+.cd-h2-row {
    margin-top: 55px;
}

.cd-h2-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
}

.cd-count {
    margin: 0;
    font-size: var(--fs-base);
    line-height: 22px;
    letter-spacing: .03em;
    color: rgba(244, 247, 245, .7);
}

/* ---------- Bạn sẽ học được gì ---------- */

.cd-outcomes {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 31px;
    margin: 30px 0 0;
    padding: 0;
    list-style: none;
}

.cd-outcomes li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 10px;
    font-size: var(--fs-base);
    line-height: 22px;
    letter-spacing: .03em;
    color: rgba(18, 26, 22, .8);
    background: var(--white);
    border-radius: var(--r-row);
    box-shadow: 0 4px 4px rgba(0, 0, 0, .25);
}

.cd-outcomes i {
    flex: none;
    font-size: 14px;
    color: var(--gold);
}

/* ---------- Nội dung khoá học ---------- */

.cd-chapters {
    display: flex;
    flex-direction: column;
    gap: 28px;
    margin-top: 30px;
}

.cd-chapter {
    padding: 15px 22px;
    background: var(--white);
    border-radius: var(--r-media);
    box-shadow: 0 4px 4px rgba(0, 0, 0, .25);
}

/* Bỏ tam giác mặc định của <summary>. PHẢI khai cả hai dòng — Safari cũ chỉ
   nghe ::-webkit-details-marker, các trình duyệt khác nghe list-style. */
.cd-chapter-head {
    display: flex;
    align-items: center;
    gap: 17px;
    list-style: none;
    cursor: pointer;
}

.cd-chapter-head::-webkit-details-marker {
    display: none;
}

.cd-chapter-no {
    display: grid;
    flex: none;
    place-items: center;
    width: 30px;
    height: 30px;
    font-size: var(--fs-base);
    line-height: 22px;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--green);
    background: rgba(27, 94, 63, .2);
    border-radius: var(--r-pill);
}

.cd-chapter-text {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 2px;
}

.cd-chapter-name {
    font-size: var(--fs-base);
    line-height: 22px;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--ink);
}

.cd-chapter-meta {
    font-size: var(--fs-sm);
    line-height: 22px;
    letter-spacing: .03em;
    color: var(--ink);
}

.cd-chapter-arrow {
    flex: none;
    font-size: 15px;
    color: var(--green);
    transition: transform .25s var(--ease);
}

/* Mũi tên lật khi chương mở. [open] là thuộc tính trình duyệt tự bật/tắt trên
   <details>, nên không cần một dòng JS nào theo dõi trạng thái. */
.cd-chapter[open] .cd-chapter-arrow {
    transform: rotate(180deg);
}

.cd-lessons {
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* thụt vào cho thẳng hàng với chữ tiêu đề chương: 30 (số) + 17 (khe) */
    margin: 16px 0 0 47px;
    padding: 0;
    list-style: none;
}

.cd-lessons li {
    display: flex;
    align-items: flex-start;
    gap: 5px;
    font-size: var(--fs-base);
    line-height: 22px;
    letter-spacing: .03em;
    color: rgba(18, 26, 22, .7);
}

.cd-lessons i {
    margin-top: 3px;
    font-size: 15px;
    color: var(--green);
}

/* ---------- Giảng viên đứng lớp ---------- */

/* Trải hết bề ngang lưới hai cột. 1 / -1 nghĩa là "từ vạch đầu tới vạch cuối",
   không phải "hai cột" — nên nếu sau này lưới đổi số cột thì dòng này vẫn đúng.
   Nằm sau .cd-main và .cd-side trong HTML nên tự rơi xuống hàng thứ hai. */
.cd-teach {
    grid-column: 1 / -1;
    margin-top: 25px;
}

.cd-teachers {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 30px;
    margin-top: 30px;
}

.cd-teacher {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 10px 20px;
    background: var(--smoke);
    border-radius: var(--r-media);
}

.cd-teacher-avatar {
    flex: none;
    width: 88px;
    height: 88px;
    object-fit: cover;
    border-radius: var(--r-pill);
}

.cd-teacher-name {
    margin: 0;
    font-size: var(--fs-base);
    line-height: 22px;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--ink);
}

.cd-teacher-role {
    margin: 8px 0 0;
    font-size: var(--fs-base);
    line-height: 22px;
    font-weight: 500;
    letter-spacing: .03em;
    color: var(--green);
}

.cd-teacher-bio {
    margin: 10px 0 0;
    font-size: var(--fs-base);
    line-height: 22px;
    letter-spacing: .03em;
    color: var(--ink);
}

/* ---------- Khoá học liên quan ---------- */

.cd-related {
    display: flex;
    flex-direction: column;
    gap: 15px;
    margin-top: 40px;
}

.cd-rel {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 10px;
    text-decoration: none;
    background: var(--white);
    border-radius: var(--r-media);
    box-shadow: 0 4px 4px rgba(0, 0, 0, .25);
    transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}

.cd-rel:hover {
    transform: translateY(var(--lift-sm));
    box-shadow: 0 10px 18px rgba(0, 0, 0, .3);
}

.cd-rel>span {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.cd-rel-thumb {
    flex: none;
    width: 87px;
    height: 61px;
    object-fit: cover;
    border-radius: var(--r-row);
}

/* Tên khóa do admin nhập, có cái rất dài; chặn hai dòng để mọi thẻ cao bằng
   nhau, phần thừa cắt bằng dấu ba chấm. */
.cd-rel-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: var(--fs-base);
    line-height: 22px;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--ink);
}

.cd-rel-price {
    font-size: var(--fs-base);
    line-height: 22px;
    font-weight: 500;
    letter-spacing: .03em;
    color: var(--green);
}

/* Nút nằm trên nền xanh nên lấy màu khói, viền mảnh — đủ thấy là bấm được mà
   không tranh chấp với nút "Đăng ký học" ở thẻ mua phía trên. */
.cd-rel-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-top: 20px;
    padding: 11px 10px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--smoke);
    text-decoration: none;
    border: 1px solid rgba(244, 247, 245, .5);
    border-radius: 20px;
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        border-color .25s var(--ease),
        transform .25s var(--ease);
}

.cd-rel-more:hover {
    color: var(--green);
    background: var(--smoke);
    border-color: var(--smoke);
    transform: translateY(var(--lift-sm));
}

.cd-rel-more i {
    font-size: 12px;
    transition: transform .25s var(--ease);
}

.cd-rel-more:hover i {
    transform: translateX(3px);
}

/* ---------- Responsive ---------- */

/* Dưới 1080px thẻ mua hết chỗ đứng cạnh cột chữ: bỏ dính, đưa xuống dưới phần
   giới thiệu. Cột "Khoá học liên quan" cũng xuống dưới cùng. */
@media (max-width: 1080px) {

    .cd-head-grid,
    .cd-body-grid {
        grid-template-columns: 1fr;
        gap: 40px;
    }

    .cd-buy {
        position: static;
    }

    /* Xếp một cột thì thứ tự HTML thành thứ tự đọc: nội dung → giảng viên →
       gợi ý khóa khác. Cột gợi ý đứng trước khối giảng viên trong HTML (vì
       trên desktop nó nằm bên phải), nên phải đẩy xuống cuối bằng order. */
    .cd-side {
        order: 1;
    }

    .cd-teach {
        margin-top: 0;
    }

    .cd-outcomes {
        grid-template-columns: repeat(2, 1fr);
        gap: 20px;
    }
}

@media (max-width: 760px) {
    .cd-head {
        padding: 24px 0 40px;
    }

    .cd-body {
        padding: 40px 0 56px;
    }

    .cd-title {
        font-size: 24px;
        line-height: 32px;
    }

    *+.cd-h2,
    *+.cd-h2-row {
        margin-top: 40px;
    }

    .cd-outcomes,
    .cd-teachers {
        grid-template-columns: 1fr;
    }

    .cd-chapters {
        gap: 16px;
    }

    .cd-chapter {
        padding: 14px 16px;
    }

    .cd-lessons {
        margin-left: 0;
    }

    /* Hai nút mua xếp chồng cho đủ chỗ chữ */
    .cd-actions {
        grid-template-columns: 1fr;
    }

    .cd-teacher {
        flex-direction: column;
        align-items: flex-start;
        padding: 16px;
    }
}

/* #endregion */


/* #region C7 · HỆ SINH THÁI HỌC TẬP
   Số đo lấy trực tiếp từ Figma: thẻ 653px, bo góc 30px, tiêu đề 32/39,
   chữ và chip 16/24, icon chip 30px, đường kẻ trên nút. */
/* Nền section giữ TRẮNG. Cái cần nổi lên là hai tấm thẻ Azota/Daymai, nên màu
   đặt ở .eco-card (xem dưới) chứ không đặt ở đây — tô cả section thì thẻ vẫn
   chìm y như cũ, chỉ là chìm trong một màu khác.

   Nếu sau này có ý định tô section: khối trên (.featured) đã là --smoke nên
   dùng --smoke ở đây là hai khối dính liền; khối dưới (.teachers) và kế nữa
   (.award) đều --green đậm nên tô đậm ở đây là ba khối tối liên tiếp. */
.eco {
    padding: clamp(36px, 4.2vw, 64px) 0 clamp(38px, 4.8vw, 70px);
    color: var(--ink);
    background: var(--white);
}

/* Khung riêng, rộng hơn container 1200 vì thiết kế quy định 653 x 2 + 29 = 1335 */
.eco-wide {
    width: 100%;
    margin-inline: auto;
    padding-inline: var(--pad-x);
}

.eco-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 29px;

    /* KHÔNG tự khai margin-top ở đây nữa. .eco-grid nằm trong một .container
       RIÊNG (.eco-wide), tách khỏi .container chứa .section-head — margin-top
       ở đây từng cộng dồn qua kiểu co margin giữa hai khối lân cận (lấy số
       LỚN HƠN) với margin-bottom 32px của .section-head, ra 34px chứ không
       phải 32px đúng chuẩn chung. Bỏ hẳn, để margin-bottom của .section-head
       là nguồn duy nhất quyết định khoảng cách. */
}

/* THẺ AZOTA / DAYMAI — dựng lại theo mockup ngày 18/09/2026.
   Nền gần trắng pha chút sắc thương hiệu + hai vòng tròn mờ góc phải, viền
   mảnh cùng tông; đầu thẻ là logo + tên + khẩu hiệu giãn chữ; bên phải là ảnh
   minh họa; ba chip chia đều; nút tô gradient trải hết bề ngang.

   Mọi màu của thẻ đi qua sáu biến dưới đây, bản Azota chỉ khai lại sáu dòng.
   --tint là bộ ba R, G, B (không phải màu hoàn chỉnh) để ghép alpha tùy chỗ. */
.eco-card {
    --tint: 27, 94, 63;
    --accent: var(--green);
    --accent-line: rgba(27, 94, 63, .4);
    --cta-bg: linear-gradient(180deg, #227049 0%, #17523A 100%);
    --cta-ink: var(--white);
    --cta-shadow: rgba(27, 94, 63, .3);

    position: relative;
    display: flex;
    flex-direction: column;
    gap: clamp(18px, 1.6vw, 26px);
    padding: clamp(20px, 2.2vw, 40px) clamp(20px, 2.4vw, 44px);
    overflow: hidden;
    /* Container query: tiêu đề, logo, ảnh chọn cỡ theo bề rộng THẺ THẬT (cqw)
       chứ không theo màn hình — thẻ chia đôi ở màn rộng, chiếm trọn hàng dưới 1024px. */
    container-type: inline-size;
    background:
        radial-gradient(circle at 92% -6%, rgba(var(--tint), .10) 0 15%, transparent 15.3%),
        radial-gradient(circle at 70% -14%, rgba(var(--tint), .07) 0 13%, transparent 13.3%),
        linear-gradient(135deg, rgba(var(--tint), .07) 0%, rgba(255, 255, 255, .96) 55%, rgba(var(--tint), .05) 100%),
        var(--white);
    border: 1px solid rgba(var(--tint), .35);
    border-radius: 24px;
    box-shadow: 0 10px 30px rgba(var(--tint), .10);
    /* translate + scale (KHÔNG phải transform) cho hiệu ứng nhấc thẻ khi hover,
       còn rotate để riêng cho animation lắc bên dưới. Ba thuộc tính độc lập,
       trình duyệt tự cộng dồn, không cái nào đè mất cái nào. */
    transition: translate var(--dur) var(--ease), scale var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
    animation: eco-card-shake 6s ease-in-out infinite;
}

.eco-card:hover {
    translate: 0 var(--lift);
    scale: 1.03;
    box-shadow: 0 18px 36px rgba(var(--tint), .18);
    /* Đứng yên khi đang được rê chuột đọc, khỏi "chạy trốn" khỏi con trỏ. */
    animation-play-state: paused;
}

/* Lắc nhẹ định kỳ để kéo mắt về khối này. Nghỉ phần lớn chu kỳ, chỉ lắc ở
   cuối — dồn % về cuối thay vì animation-delay, để paused ở trên dừng đúng
   chỗ đang lắc dở, không bị nhảy khi tiếp tục. */
@keyframes eco-card-shake {

    0%, 92%, 100% {
        rotate: 0deg;
    }

    93%, 97% {
        rotate: -1.5deg;
    }

    95%, 99% {
        rotate: 1.5deg;
    }
}

/* Quầng sáng "thở" quanh thẻ, tách khỏi box-shadow của .eco-card (dùng cho
   hover) để hai cơ chế không giành nhau. Chỉ animate opacity cho rẻ. */
.eco-card::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px rgba(var(--tint), .45), inset 0 0 28px rgba(var(--tint), .18);
    opacity: 0;
    pointer-events: none;
    will-change: opacity;
    animation: eco-card-glow 2.4s ease-in-out infinite;
}

@keyframes eco-card-glow {
    0%, 100% { opacity: 0; }
    50%      { opacity: .7; }
}

/* Bản Azota. --accent để --gold gốc (không phải --gold-ink): trong mockup chữ
   "AZOTA" và icon chip đều là vàng thương hiệu, còn chữ đọc thật (tiêu đề, mô
   tả, nhãn chip) vẫn là --ink nên không mất tương phản. Nút vàng nên chữ nút
   chuyển sang --ink — chữ trắng trên vàng chỉ đạt ~2:1. */
.eco-card--gold {
    --tint: 227, 162, 27;
    --accent: var(--gold);
    --accent-line: rgba(227, 162, 27, .45);
    --cta-bg: linear-gradient(180deg, #F4BE45 0%, #E3A21B 100%);
    --cta-ink: var(--ink);
    --cta-shadow: rgba(227, 162, 27, .35);
}

/* Lưới hai cột: cột chữ trái, ảnh minh họa phải chạy dọc cả ba hàng chữ. */
.eco-top {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(150px, 36cqw, 290px);
    grid-template-areas:
        "head  illust"
        "title illust"
        "desc  illust";
    grid-template-rows: auto auto 1fr;
    column-gap: clamp(8px, 2cqw, 20px);
    align-items: start;
}

.eco-head {
    grid-area: head;
    display: flex;
    align-items: center;
    gap: clamp(12px, 2.4cqw, 18px);
    margin-bottom: clamp(14px, 3cqw, 24px);
}

.eco-logo {
    flex: none;
    width: clamp(56px, 11cqw, 84px);
    height: clamp(48px, 9.5cqw, 72px);
    object-fit: contain;
}

.eco-brand {
    margin: 0;
    font-size: clamp(20px, 4.2cqw, 30px);
    line-height: 1.15;
    font-weight: 800;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--accent);
}

.eco-tagline {
    margin: 6px 0 0;
    font-size: clamp(10px, 1.9cqw, 13px);
    line-height: 1.3;
    font-weight: 500;
    letter-spacing: .3em;
    text-transform: uppercase;
    color: #6B7470;
}

.eco-title {
    grid-area: title;
    margin: 0 0 clamp(8px, 1.6cqw, 14px);
    font-size: clamp(22px, 6.4cqw, 42px);
    line-height: 1.2;
    font-weight: 800;
    color: var(--ink);
}

.eco-desc {
    grid-area: desc;
    margin: 0;
    font-size: clamp(14px, 2.9cqw, 18px);
    line-height: 1.55;
    color: #5A635F;
}

.eco-illust {
    grid-area: illust;
    align-self: center;
    width: 100%;
    height: auto;
    filter: drop-shadow(0 12px 18px rgba(var(--tint), .12));
}

/* Ba cột auto: cột rộng theo độ dài chữ ("Tài liệu khóa học" được phần rộng
   hơn) rồi cùng giãn cho kín bề ngang, nên chữ chip nằm MỘT DÒNG (nowrap).
   Không dùng flex-wrap: chip Daymai dài hơn sẽ rớt xuống hàng hai trong khi
   Azota vẫn một hàng — hai thẻ lệch. Thẻ hẹp dưới 520px thì @container bên
   dưới đổi chip sang icon-trên-chữ và cho ngắt dòng, khỏi tràn ngang trang. */
.eco-chips {
    display: grid;
    grid-template-columns: auto auto auto;
    gap: clamp(8px, 2cqw, 18px);
    margin: 0;
    padding: 0;
    list-style: none;
}

.eco-chip {
    display: flex;
    align-items: center;
    gap: clamp(8px, 1.5cqw, 12px);
    padding: clamp(10px, 2cqw, 16px) clamp(10px, 2cqw, 18px);
    font-size: clamp(12px, 2.3cqw, 16px);
    line-height: 1.3;
    font-weight: 500;
    white-space: nowrap;
    color: var(--ink);
    background: rgba(255, 255, 255, .85);
    border: 1px solid var(--accent-line);
    border-radius: 12px;
}

/* Thẻ hẹp (điện thoại): icon lên trên, chữ canh giữa bên dưới — ba cột chỉ
   còn ~100px, xếp ngang thì icon ăn mất nửa chỗ của chữ. */
@container (max-width: 520px) {
    .eco-chips {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .eco-chip {
        white-space: normal;
        flex-direction: column;
        justify-content: center;
        gap: 6px;
        text-align: center;
    }
}

.eco-chip i {
    flex: none;
    width: 1.3em;
    font-size: clamp(18px, 3.6cqw, 26px);
    text-align: center;
    color: var(--accent);
}

.eco-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    min-height: clamp(48px, 9cqw, 62px);
    padding: 10px 24px;
    font-size: clamp(15px, 3cqw, 20px);
    line-height: 1.3;
    font-weight: 700;
    color: var(--cta-ink);
    background: var(--cta-bg);
    border-radius: 14px;
    box-shadow: 0 8px 18px var(--cta-shadow);
    text-decoration: none;
    transition:
        filter .25s var(--ease),
        transform .25s var(--ease),
        box-shadow .25s var(--ease);
}

.eco-cta i {
    transition: transform .25s var(--ease);
}

.eco-cta:hover {
    filter: brightness(1.05);
    transform: translateY(var(--lift));
    box-shadow: 0 12px 24px var(--cta-shadow);
}

.eco-cta:hover i {
    transform: translateX(4px);
}

.eco-cta:active {
    transform: translateY(1px);
}

.eco-strip {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    margin: var(--sec-head-gap) 0 0;
    padding: 0;
    list-style: none;
}

.eco-feature {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 4px 16px;
    font-size: var(--fs-sm);
    line-height: 1.4;
    font-weight: 600;
}

.eco-feature+.eco-feature {
    border-left: 2px solid var(--green-30);
}

.eco-feature-icon {
    display: grid;
    place-items: center;
    flex: none;
    width: clamp(38px, 2.7vw, 44px);
    height: clamp(38px, 2.7vw, 44px);
    font-size: clamp(16px, 1.15vw, 18px);
    color: var(--green);
    background: var(--smoke);
    border-radius: 50%;
}

/* ĐÃ GỠ khối @media (max-width: 1400px) từng thu logo/chip/nút ở đây. Nó tạo
   một bậc nhảy: 1401px thì logo 175, 1399px thì tụt còn 150 — nên màn rộng
   luôn thấy khối này to bất thường. Mọi số đo trong khối đó giờ là clamp()
   liên tục ở trên, co đều chứ không nhảy bậc. Hai khối 1024px và 600px bên
   dưới thì GIỮ, vì chúng đổi BỐ CỤC (hai cột thành một, logo xếp trên chữ)
   chứ không phải chỉnh kích thước. */

@media (max-width: 1024px) {
    .eco-grid {
        grid-template-columns: 1fr;
    }

    .eco-strip {
        grid-template-columns: 1fr 1fr;
        row-gap: 22px;
    }

    .eco-feature:nth-child(3) {
        border-left: 0;
    }
}

@media (max-width: 600px) {
    .eco-card {
        padding: 20px;
    }

    /* Ảnh minh họa thu nhỏ lên cạnh đầu thẻ; tiêu đề và mô tả chiếm trọn hàng. */
    .eco-top {
        grid-template-columns: minmax(0, 1fr) 34%;
        grid-template-areas:
            "head  illust"
            "title title"
            "desc  desc";
        grid-template-rows: auto;
    }

    .eco-head {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .eco-tagline {
        letter-spacing: .2em;
    }

    .eco-strip {
        grid-template-columns: 1fr;
    }

    .eco-feature {
        justify-content: flex-start;
        border-left: 0 !important;
    }
}

/* #endregion */


/* #region C8 · DẢI ẢNH CHẠY — Bảng vinh danh (trang chủ) và Điểm số (trang Thành tích)
   Figma: tiêu đề 32/39, dải ảnh 5 thẻ 262x315 khe 25px (tổng 1410px), hai đầu
   phủ lớp mờ dần rộng ~240px. Hai bản chỉ khác tông màu nên nền và ba mốc của
   lớp mờ đi qua biến; bản sáng .award--light chỉ khai lại đúng bốn dòng đó. */
.award {
    --award-bg: var(--green);
    --award-fade-mid: rgba(27, 94, 63, .55);
    --award-fade-end: rgba(27, 94, 63, 0);

    padding: clamp(36px, 4.2vw, 64px) 0 clamp(44px, 4.8vw, 82px);
    color: var(--smoke);
    background: var(--award-bg);
    overflow: hidden;
}

/* Ở TRANG CHỦ, khối này nằm NGAY SAU .teachers — cả hai cùng nền xanh đậm
   var(--green), không có đường phân cách nào giữa chúng. Padding-top riêng
   của khối này (36-64px) CỘNG THÊM padding-bottom của .teachers (36-60px)
   thành 72-124px một mảng xanh liền — mắt không thấy hai section, chỉ thấy
   một khoảng hở bất thường. Khách chốt 22/09/2026: bớt hẳn padding-top ở
   ĐÚNG chỗ này.

   Không đổi con số gốc của .award (nó còn dùng cho khối "Điểm số qua các kỳ
   thi" ở trang Thành tích, nền trắng, không có kiểu chồng nền này — xem
   .award--light) nên khoanh riêng bằng .page-home, cùng cách đã dùng ở khối
   margin-bottom bên dưới. */
.page-home .award {
    padding-top: clamp(8px, 1vw, 16px);
}

/* Bản nền sáng. PHẢI đứng sau .award: cùng độ đặc hiệu (0,1,0) nên rule viết
   sau mới thắng. Chữ, nhãn và hai vạch đều ăn theo color nên tự đổi màu. */
.award--light {
    --award-bg: var(--white);
    --award-fade-mid: rgba(255, 255, 255, .55);
    --award-fade-end: rgba(255, 255, 255, 0);

    color: var(--ink);
}

/* Dòng mô tả ở đây là chữ sáng cỡ 16px, khác mặc định (13px, màu xám) */
.award .section-subtitle,
.admitted .section-subtitle {
    max-width: 621px;
    margin-top: 12px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: inherit;
}

/* Dải ảnh rộng hơn khung nhìn là CÓ CHỦ ĐÍCH — overflow:hidden cắt phần thừa,
   hai lớp mờ dần che chỗ cắt để không thấy ảnh đứt ngang. */
/* KHÔNG tự khai margin-top ở đây. .award-row nằm ngoài .container chứa
   .section-head (để dải ảnh tràn full-width) — margin-top riêng ở đây từng
   co với margin-bottom 32px của .section-head theo số LỚN HƠN, ra 37px chứ
   không phải 32px đúng chuẩn chung. Bỏ hẳn, để margin-bottom của .section-head
   là nguồn duy nhất quyết định khoảng cách. */
.award-row {
    position: relative;
}

/* Băng chạy vô tận. Danh sách được in hai lần trong HTML; một chu kỳ dịch đúng
   bề ngang của bản gốc (--count thẻ + --count khe) rồi lặp lại — bản sao vừa
   trượt vào đúng chỗ bản gốc vừa rời đi, nên không thấy điểm nối. */
.award-track {
    --card-w: 262px;
    --card-gap: 25px;
    --speed: 40s;

    display: flex;
    gap: var(--card-gap);
    width: max-content;
    will-change: transform;
    animation: award-marquee var(--speed) linear infinite;
}

@keyframes award-marquee {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(calc(var(--count) * (var(--card-w) + var(--card-gap)) * -1));
    }
}

/* Rê chuột vào thì dừng, để người xem kịp nhìn kỹ một gương mặt */
.award-row:hover .award-track {
    animation-play-state: paused;
}

.award-item {
    flex: none;
    width: var(--card-w);
    margin: 0;
    aspect-ratio: 262 / 315;
    overflow: hidden;
    background: var(--white);
    border-radius: var(--r-media);
}

.award-item img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.award-row::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1;
    width: 240px;
    pointer-events: none;
    /* Điểm dừng cuối PHẢI là alpha 0, không phải .05 — còn 5% màu là mép lớp phủ
       nhảy đột ngột xuống 0 và hiện ra một vạch dọc. Ba mốc giữa làm độ mờ
       giảm cong thay vì tuyến tính, mắt không bắt được ranh giới. */
    background: linear-gradient(90deg,
            var(--award-bg) 0%,
            var(--award-bg) 34%,
            var(--award-fade-mid) 66%,
            var(--award-fade-end) 100%);
}

.award-row::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    z-index: 1;
    width: 240px;
    pointer-events: none;
    background: linear-gradient(270deg,
            var(--award-bg) 0%,
            var(--award-bg) 34%,
            var(--award-fade-mid) 66%,
            var(--award-fade-end) 100%);
}

/* Chỉ đổi hai biến; bề ngang thẻ và quãng đường mỗi chu kỳ tự tính lại theo. */
@media (max-width: 900px) {
    .award {
        padding: 52px 0 60px;
    }

    .award-track {
        --card-w: 200px;
        --card-gap: 16px;
        --speed: 32s;
    }

    .award-row::before,
    .award-row::after {
        width: 120px;
    }
}

@media (max-width: 600px) {
    .award-track {
        --card-w: 158px;
        --card-gap: 14px;
        --speed: 26s;
    }

    .award-row::before,
    .award-row::after {
        width: 70px;
    }
}

/* Người bật chế độ giảm chuyển động: dừng hẳn, đưa dải về canh giữa như cũ */
@media (prefers-reduced-motion: reduce) {
    .award-track {
        width: auto;
        justify-content: center;
        animation: none;
    }
}

/* #endregion */


/* ============================================================
   C6 · GIÁO VIÊN
   ============================================================ */
.teachers {
    padding: var(--sec-y) 0 clamp(36px, 3.4vw, 60px);
    color: var(--smoke);
    background: var(--green);
}


.teachers-track {
    /* Trần 50px đúng số Figma ở 1920. Trước đây gap cứng 50px không co theo
       màn hình như mọi khe khác trong trang — ở khổ laptop 14" khoảng trắng
       giữa ba thẻ nhìn rộng bất thường so với phần còn lại của trang. */
    --teachers-gap: clamp(28px, 2.6vw, 50px);

    display: flex;
    gap: var(--teachers-gap);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.teachers-track::-webkit-scrollbar {
    display: none;
}

.teacher {
    /* Hai số đo gốc của thẻ, mọi khoảng cách bên dưới suy ra từ đây */
    --photo-h: clamp(180px, 13.5vw, 230px);
    /* chiều cao ảnh */
    --photo-out: clamp(72px, 5.6vw, 95px);
    /* phần ảnh nhô lên phía trên thân thẻ */

    position: relative;
    display: flex;
    /* 100px = 2 khe cũ CỐ ĐỊNH ở 50px — giờ khe co giãn nên phải tính lại
       bằng đúng biến --teachers-gap, không thì 3 thẻ hụt/dư khỏi hàng. */
    flex: 0 0 calc((100% - 2 * var(--teachers-gap)) / 3);
    padding-top: var(--photo-out);
    scroll-snap-align: start;
    transition: transform var(--dur) var(--ease);
}

.teacher:hover {
    transform: translateY(-8px);
}

.teacher-photo {
    position: absolute;
    top: 0;
    left: 50%;
    width: clamp(160px, 11.5vw, 196px);
    height: var(--photo-h);
    object-fit: cover;
    transform: translateX(-50%);
    filter: drop-shadow(0 10px 10px rgba(0, 0, 0, .25));
    transition: transform var(--dur) var(--ease);
}

.teacher:hover .teacher-photo {
    transform: translateX(-50%) scale(1.06);
}

.teacher-body {
    /* trên = phần ảnh nằm trong thẻ + khoảng hở tới tên */
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: calc(var(--photo-h) - var(--photo-out) + 20px) clamp(28px, 2.4vw, 40px) clamp(22px, 2vw, 32px);
    text-align: center;
    background: var(--smoke);
    box-shadow: 2px 2px 10px 2px rgba(0, 0, 0, .25);
    transition: box-shadow var(--dur) var(--ease);
}

.teacher:hover .teacher-body {
    box-shadow: 0 22px 40px rgba(0, 0, 0, .3);
}

.teacher-name {
    margin: 0;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--card-title);
}

.teacher-role {
    margin: 4px 0 0;
    font-weight: bold;
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    letter-spacing: var(--track);
    color: var(--green);
}

.teacher-bio {
    margin: 8px 0 0;
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    letter-spacing: var(--track);
    color: var(--muted);
}

/* margin-top: auto đẩy nút xuống đáy, ba thẻ dài ngắn khác nhau
   vẫn có nút thẳng hàng */
.teacher-link {
    width: 100%;
    margin-top: auto;
    padding: 6px 10px;
    font-size: var(--fs-base);
    font-weight: 400;
    line-height: var(--lh-loose);
    letter-spacing: var(--track);
    color: var(--smoke);
    background: var(--green);
    border: 2px solid var(--smoke);
    transition: all .5s;
}

.teacher-link:hover {
    background: var(--ink);
    border-color: var(--ink);
}

.teachers-dots,
.admitted-dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-top: clamp(24px, 2.6vw, 36px);
}

.teacher-dot,
.admitted-dot {
    width: 10px;
    height: 10px;
    padding: 0;
    background: rgba(244, 247, 245, .35);
    border: none;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}

.teacher-dot.is-active,
.admitted-dot.is-active {
    width: 28px;
    background: var(--gold);
}

@media (max-width: 1024px) {
    .section-head {
        flex-wrap: wrap;
    }

    .teacher {
        flex: 0 0 calc((100% - var(--teachers-gap)) / 2);
    }
}

@media (max-width: 700px) {
    .teachers-track {
        --teachers-gap: 24px;
    }

    .teacher {
        flex: 0 0 100%;
    }

    .teacher-body {
        padding-inline: 24px;
    }
}



/* #region C6b · DANH SÁCH GIÁO VIÊN — trang /khoa-hoc

   Thẻ dùng lại NGUYÊN bộ .teacher-* của C6 ở trên: cùng ảnh nhô lên đầu, cùng
   thân khói, cùng cỡ chữ. Khối này chỉ khai những gì KHÁC, và mọi selector đều
   gắn .teacher-list nên khối Giáo viên ngoài trang chủ không bị đụng tới.

   Số đo lấy từ Figma khổ 1440: thẻ 268.4, khe 40, bốn thẻ vừa đúng container
   1200; hai hàng cách nhau 73; ảnh 188x189 nhô lên 95. */

.teacher-list {
    /* Figma: nhãn bắt đầu ở y=56, đáy section cách dải phân trang 87 */
    padding: 56px 0 87px;
    color: var(--ink);
    background: var(--white);
}

/* Chữ vàng trong tiêu đề. Quy ước <em> của dự án chỉ đánh dấu ngữ nghĩa, còn
   tô màu thì mỗi section tự khai — phải tắt cả font-style vì mặc định của
   trình duyệt cho <em> là in nghiêng, Figma trang này thì không nghiêng. */
.teacher-list .section-head {
    margin-bottom: 32px;
}

/* ---------- Dải chip lọc theo môn ---------- */

.subject-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 20px;
}

/* Chip là <a> khi bấm được và <span> khi đang chọn, nên KHÔNG dùng
   display:inline-flex mặc định của thẻ — khai thẳng ở đây cho cả hai. */
.chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 5px 20px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    background: var(--green-10);
    border-radius: var(--r-pill);
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        transform .25s var(--ease);
}

.chip:hover {
    background: var(--green-30);
    transform: translateY(var(--lift-sm));
}

/* Môn đang lọc — nền vàng chữ xanh. Không có :hover vì đây là <span>,
   bấm vào cũng chỉ tải lại đúng trang đang xem. */
.chip.is-active {
    color: var(--green);
    background: var(--gold);
}

/* ---------- Lưới thẻ ---------- */

/* Figma: dải chip kết thúc ở y=170, hàng thẻ đầu bắt đầu y=229 */
.teacher-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    /* hàng cách 73, cột cách 40 */
    gap: 73px 40px;
    margin-top: 59px;
}

/* Thẻ ở đây hẹp hơn bản trang chủ (268 so với 367) nên ảnh thấp lại và thân
   thẻ thu đệm ngang. Đổi --photo-h là phần đệm trên của .teacher-body tự tính
   lại theo — công thức calc() nằm ở C6, không phải chép lại vào đây. */
.teacher-list .teacher {
    --photo-h: 189px;
    --photo-out: 95px;
}

.teacher-list .teacher-photo {
    width: 188px;
}

/* Nút "Xem hồ sơ" ở đây là <button> (mở hộp thoại) chứ không phải <a> như bản
   trang chủ, mà <button> KHÔNG tự thừa hưởng font của trang — thiếu dòng này
   chữ trên nút nhảy về font mặc định của hệ điều hành. */
.teacher-list .teacher-link {
    font-family: inherit;
}

.teacher-list .teacher-body {
    /* Figma: chữ rộng 237.39 trong thẻ 268.4 → chừa 15 mỗi bên;
       đáy nút cách đáy thẻ 28 */
    padding-inline: 15px;
    padding-bottom: 28px;
}

.teachers-empty {
    margin: 59px 0 0;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    text-align: center;
    color: var(--muted);
}

/* ---------- Chuyển trang trên nền sáng ---------- */

/* Bản gốc .pager ở khối C5b lấy màu theo currentColor vì nó nằm trên nền xanh.
   Section này nền TRẮNG nên currentColor là màu mực — không có biến thể này
   thì dải nút ra màu đen thay vì xanh như Figma. */
.pager--light .pager-btn {
    color: var(--green);
    background: var(--green-10);
    border-color: var(--green-30);
}

.pager--light .pager-btn:hover {
    color: var(--smoke);
    background: var(--green);
    border-color: var(--green);
}

/* Trang đang xem: Figma vẽ nền xanh đặc chữ khói, khác bản nền vàng của C5b */
.pager--light .pager-btn.is-active {
    color: var(--smoke);
    background: var(--green);
    border-color: var(--green);
}

/* ---------- Responsive ---------- */

/* Bốn cột cần khoảng 1060px bề ngang container mới đủ chỗ cho tấm ảnh 188px;
   hẹp hơn thì rút còn hai cột rồi một cột. Các quy tắc `flex` của .teacher
   trong C6 không đụng tới đây: thẻ nằm trong grid nên flex bị bỏ qua. */
@media (max-width: 1100px) {
    .teacher-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 60px 30px;
    }
}

@media (max-width: 700px) {
    .teacher-list {
        padding: 40px 0 56px;
    }

    .subject-chips {
        gap: 10px;
    }

    .chip {
        padding: 5px 16px;
        font-size: var(--fs-sm);
        line-height: var(--lh-sm);
    }

    .teacher-grid {
        grid-template-columns: 1fr;
        gap: 50px;
        margin-top: 36px;
    }

    .teachers-empty {
        margin-top: 36px;
    }
}

/* #endregion */


/* #region C6c · HỘP CHI TIẾT GIÁO VIÊN — mở từ thẻ ở section trên

   Cùng khuôn với lightbox xem ảnh ở cuối file: <dialog> phủ kín màn hình, tự vẽ
   lớp nền tối bằng background của chính nó thay vì ::backdrop, rồi canh giữa
   phần ruột bằng grid. Lý do y hệt bên đó — mỗi trình duyệt tô ::backdrop một
   kiểu, còn nền của chính thẻ thì ở đâu cũng như nhau.

   Số đo Figma khổ 1440: hộp 1196x655 bo 20, cột ảnh 518 (43.3%), cột chữ bắt
   đầu ở x=579 tức cách mép cột ảnh 61. */

.tprof {
    position: fixed;
    inset: 0;
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    padding: 20px;
    background: transparent;
    border: 0;
}

.tprof[open] {
    display: grid;
    place-items: center;
    background: rgba(18, 26, 22, .86);
}

.tprof-box {
    position: relative;
    display: grid;
    /* 518/1196 — cột ảnh cố định theo tỉ lệ, cột chữ ăn phần còn lại */
    grid-template-columns: 43.3% 1fr;
    /* Số đo Figma (1196x655) chiếm gần hết màn hình thường, nên thu lại còn
       khoảng 82% — vẫn giữ đúng tỉ lệ cột ảnh/cột chữ 43.3%/1fr ở trên. */
    width: min(980px, 100%);
    /* Chiều cao CỐ ĐỊNH, không phải max-height: để max-height thì hộp co theo
       nội dung, gặp giáo viên có tiểu sử ngắn là cột ảnh trống hoác một mảng. */
    height: min(540px, 100%);
    overflow: hidden;
    background: var(--white);
    border-radius: var(--r-card);
    animation: tprof-in .25s var(--ease);
}

@keyframes tprof-in {
    from {
        opacity: 0;
        transform: scale(.96);
    }
}

/* ---------- Cột ảnh ---------- */

/* Ảnh dán đáy cột và giữ nguyên tỉ lệ. Figma dựng bằng ảnh toàn thân đã tách
   nền; dữ liệu thật thì cột avatar có thể là ảnh vuông chụp bán thân, nên
   object-fit: contain để tấm nào cũng vào trọn khung, không bị cắt mất đầu. */
.tprof-media {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    overflow: hidden;
    background: var(--smoke);
}

/* Ảnh phủ KÍN cột, không chừa lề. object-fit: cover phóng ảnh tới khi lấp đầy
   cả hai chiều rồi cắt phần thừa, giữ nguyên tỉ lệ nên không tấm nào bị kéo
   méo. Đánh đổi có thật: ảnh ngang (chụp nhóm, chụp lớp) sẽ bị cắt mạnh hai
   bên vì cột này dọc — ảnh chân dung dọc là loại hợp nhất với khung. */
.tprof-photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ---------- Cột chữ ---------- */

/* Figma: chữ bắt đầu ở y=65, cách mép cột ảnh 61. Chừa phải rộng hơn để không
   chạy vào nút đóng ở góc. overflow-y: auto vì tiểu sử do admin nhập, một bài
   dài bất thường phải cuộn trong hộp chứ không được đội hộp cao quá màn hình. */
.tprof-body {
    display: flex;
    flex-direction: column;
    padding: 48px 64px 44px 46px;
    overflow-y: auto;
}

.tprof-subject {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    color: var(--green);
}

.tprof-name {
    margin: 4px 0 0;
    font-size: 26px;
    line-height: 32px;
    font-weight: 700;
    color: var(--ink);
}

.tprof-role {
    margin: 8px 0 0;
    font-size: 18px;
    line-height: 22px;
    font-weight: 500;
    color: var(--green);
}

/* ---------- Hai con tem ---------- */

/* Figma xếp hai tem thành hai hàng riêng, mỗi tem ôm sát chữ. flex-wrap +
   align-items: flex-start giữ đúng nét đó mà vẫn cho hai tem ngắn nằm chung
   một hàng nếu đủ chỗ. */
.tprof-tags {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    margin-top: 16px;
}

.tprof-tag {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 2px 14px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    color: var(--ink);
    max-width: 100%;
    background: rgba(18, 26, 22, .1);
    border-radius: var(--r-pill);
}

/* Bằng cấp do admin nhập, có bản dài cả dòng; icon phải neo lên đầu để khi chữ
   xuống dòng thứ hai nó không trôi ra giữa viên thuốc. */
.tprof-tag i {
    align-self: flex-start;
    margin-top: 3px;
    font-size: 15px;
    color: var(--green);
}

/* ---------- Tiểu sử và châm ngôn ---------- */

.tprof-bio {
    margin: 20px 0 0;
    font-size: var(--fs-sm);
    line-height: 1.5;
    letter-spacing: .03em;
    text-align: justify;
    color: var(--ink);
}

/* Đường kẻ ngăn là border-top của chính câu châm ngôn, không phải một thẻ <hr>
   riêng — châm ngôn trống thì đường kẻ biến mất theo, khỏi để lại vạch cụt. */
.tprof-motto {
    margin: 22px 0 0;
    padding-top: 12px;
    font-family: 'Cormorant', Georgia, serif;
    font-size: 19px;
    line-height: 24px;
    font-style: italic;
    font-weight: 700;
    color: var(--green);
    border-top: 1px solid rgba(18, 26, 22, .5);
}

/* ---------- Nút và nút đóng ---------- */

/* margin-top: auto ghim nút xuống đáy cột: tiểu sử dài ngắn khác nhau thì nút
   vẫn nằm đúng một chỗ. Không dùng class .btn dùng chung vì Figma cho nút này
   cỡ chữ 20 và không đổ bóng. */
.tprof-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: flex-start;
    /* flex: none là bắt buộc — nút là con của cột flex .tprof-body, thiếu dòng
       này nó bị co dẹp còn vài pixel khi cột chật, nuốt luôn chữ bên trong. */
    flex: none;
    min-width: 240px;
    margin-top: auto;
    padding: 9px 18px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 500;
    color: var(--smoke);
    text-decoration: none;
    background: var(--green);
    border-radius: var(--r-pill);
    transition:
        background-color .25s var(--ease),
        transform .25s var(--ease);
}

.tprof-cta:hover {
    background: #144930;
    transform: translateY(var(--lift-sm));
}

.tprof-close {
    position: absolute;
    top: 14px;
    right: 14px;
    z-index: 1;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    padding: 0;
    font-size: 15px;
    color: var(--ink);
    background: rgba(18, 26, 22, .1);
    border: 0;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        transform .25s var(--ease);
}

.tprof-close:hover {
    color: var(--smoke);
    background: var(--green);
    transform: scale(1.06);
}

/* ---------- Responsive ---------- */

/* Hai cột cần khoảng 900px mới đủ chỗ; hẹp hơn thì xếp dọc, ảnh thành một dải
   ngang bên trên. Chiều cao hộp bỏ trần 655px để phần chữ còn chỗ cuộn. */
@media (max-width: 900px) {
    .tprof-box {
        grid-template-columns: 1fr;
        max-height: 100%;
        overflow-y: auto;
    }

    .tprof-media {
        height: 240px;
    }

    .tprof-body {
        padding: 28px 24px 32px;
        overflow: visible;
    }

    .tprof-cta {
        min-width: 0;
        width: 100%;
        margin-top: 30px;
    }
}

@media (max-width: 600px) {
    .tprof {
        padding: 12px;
    }

    .tprof-name {
        font-size: 26px;
        line-height: 32px;
    }

    .tprof-role,
    .tprof-cta {
        font-size: var(--fs-base);
        line-height: var(--lh-base);
    }

    .tprof-tags {
        gap: 12px;
        margin-top: 16px;
    }

    .tprof-bio {
        margin-top: 20px;
        text-align: left;
    }

    .tprof-motto {
        margin-top: 24px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tprof-box {
        animation: none;
    }
}

/* #endregion */

/* ============ FOOTER ============ */
/* BẢNG MÀU CHÂN TRANG GOM VỀ MỘT CHỖ.
   Màu nền chân trang đã đổi qua đổi lại vài lần, mà mỗi lần đổi phải sửa năm
   chỗ rải rác bên dưới — sót một chỗ là chữ tàng hình. Nay năm giá trị ấy thành
   năm biến khai ngay tại đây; đổi cả chân trang chỉ là sửa khối này.

   Nút mạng xã hội KHÔNG lấy từ bảng này: mỗi nút dùng đúng màu nhận diện của
   nền tảng (Facebook xanh dương, YouTube đỏ, TikTok đen) — xem .footer-socials.

   Bản NỀN TỐI (nếu cần quay lại) — thay đúng năm dòng dưới bằng:
       --fo-bg: var(--ink);  --fo-text: var(--smoke);  --fo-head: var(--gold);
       --fo-icon: var(--gold);  --fo-line: rgba(244, 247, 245, .12);
   và bật lại tấm nền sáng sau logo ở .footer-brand img (xem ghi chú ở đó). */
.site-footer {
    --fo-bg:   var(--smoke);
    --fo-text: var(--ink);
    --fo-head: var(--green);
    --fo-icon: var(--green);
    --fo-line: var(--green-15);

    background: var(--fo-bg);
    color: var(--fo-text);

    /* Không phải trang nào cũng kết thúc bằng khối CTA nền xanh — trang kết
       thúc bằng nền sáng thì viền này là ranh giới duy nhất. */
    border-top: 1px solid var(--fo-line);
}

/* Bốn cột theo mẫu khách duyệt. Cột Liên hệ rộng nhất vì nó gánh cả logo,
   địa chỉ nhiều dòng, email và số điện thoại; ba cột còn lại chỉ là danh sách
   chữ ngắn nên chia đều. */
.footer-grid {
    display: grid;
    /* Cột 4 "Chính sách điều khoản" phải đủ rộng để tiêu đề nằm gọn 1 dòng;
       bù lại thu cột 1 và khe cột lại một chút. */
    grid-template-columns: 1.5fr 1fr 1.15fr 1.4fr;
    gap: 32px;
    padding-block: 20px;
}

/* Nền chân trang đang SÁNG nên logo thả trực tiếp là đúng — file logo vốn vẽ
   cho nền sáng, dòng "LUYỆN THI QUÂN ĐỘI" dưới huy hiệu là chữ xanh đậm.
   NẾU QUAY LẠI NỀN TỐI: dòng chữ ấy tụt xuống 2.29:1, gần như không đọc được.
   Khi đó bỏ ghi chú ba dòng padding/border-radius/background bên dưới để đặt
   logo lên một tấm nền sáng riêng, đưa tương phản về 7.16:1. */
.footer-brand img {
    display: block;
    box-sizing: content-box;
    width: 180px;
    height: auto;
    margin-block: 4px 14px;
    /* padding: 10px 14px; border-radius: 12px; background: var(--smoke); */
}

/* Địa chỉ, email, số điện thoại trong cột Liên hệ dùng chung dáng "biểu tượng
   + chữ" với cột Chăm sóc khách hàng, nên gom một chỗ thay vì lặp hai lần. */
.footer-brand p,
.footer-care p {
    display: flex;
    gap: 10px;
    align-items: flex-start;
}

.footer-brand p i,
.footer-care i {
    color: var(--fo-icon);
    font-size: 14px;
    margin-top: 4px;
    flex: none;
}

/* Mỗi mục trong cột Danh mục có biểu tượng tài liệu đứng trước, theo mẫu. */
.footer-links a {
    display: flex;
    gap: 10px;
    align-items: baseline;
}

.footer-links a i {
    color: var(--fo-icon);
    font-size: 13px;
    flex: none;
}

.footer-socials {
    display: flex;
    gap: 12px;
    margin-top: 22px;
}

.footer-socials a {
    text-decoration: none;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    /* Nền mặc định = màu thương hiệu CEP, phòng khi thêm nền tảng mới chưa kịp
       khai màu riêng bên dưới. Glyph luôn trắng cho nổi trên nền đặc. */
    background: var(--green);
    color: #fff !important;
    font-size: 15px;
    transition:
        background-color .25s var(--ease),
        transform .25s var(--ease);
}

/* Mỗi nút dùng đúng màu nhận diện của nền tảng; hover đậm/nhạt hơn một bậc
   kèm nhấc nhẹ. Class do footer.php sinh ra từ khóa 'name' của $socials. */
.footer-socials .social-facebook { background: #1877F2; }
.footer-socials .social-youtube  { background: #FF0000; }
.footer-socials .social-tiktok   { background: #000000; }

.footer-socials .social-facebook:hover { background: #1466D8; }
.footer-socials .social-youtube:hover  { background: #D90000; }
.footer-socials .social-tiktok:hover   { background: #26262E; }

.footer-socials a:hover {
    transform: translateY(var(--lift-sm));
}

.footer-col {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.footer-col h3 {
    margin: 0 0 4px;
    font-size: var(--fs-base);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--fo-head);
    text-wrap: balance;
}

.footer-col a,
.footer-col p {
    margin: 0;
    font-size: var(--fs-sm);
    line-height: 22px;
    color: var(--fo-text);
    opacity: .85;
    text-decoration: none;
    overflow-wrap: anywhere;
}

.footer-col a:hover {
    opacity: 1;
    color: var(--fo-head);
}

/* Huy hiệu "Đã thông báo Bộ Công Thương" ở cuối cột Chính sách.
   Chỉ hiện khi admin đã điền cả ảnh lẫn link hồ sơ — xem footer.php. */
.footer-bct {
    margin-top: 8px;
    align-self: flex-start;
    opacity: 1;
}

.footer-bct img {
    display: block;
    width: 160px;
    height: auto;
}

.footer-bottom {
    border-top: 1px solid var(--fo-line);
    padding-block: 10px;
    text-align: center;
    font-size: var(--fs-sm);
    opacity: .7;
}

.footer-bottom a{
    text-decoration: none;
}
@media (max-width: 1080px) {
    .footer-grid {/
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 600px) {
    .footer-grid {
        grid-template-columns: 1fr;
        gap: 32px;
        padding-block: 40px;
    }
}

/* ============================================================
   GIẢM CHUYỂN ĐỘNG
   Người bật "reduce motion" trong hệ điều hành: bỏ mọi hiệu ứng
   nhấc nút. Màu và bóng vẫn đổi, nên nút vẫn phản hồi rõ ràng —
   chỉ không còn thứ trượt qua trượt lại gây khó chịu.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {

    .btn,
    .btn:hover,
    .btn:active,
    .arrow-btn:hover,
    .arrow-btn:active,
    .eco-cta:hover,
    .eco-cta:active,
    .footer-socials a:hover {
        transform: none;
    }
}


/* #region C9 · HỌC VIÊN NÓI GÌ VỀ CEP
   Gốc Figma: cột trái 569, cột phải 545x560, khe 83.
   Cột phải dựng bằng PHẦN TRĂM của khung 545x560 nên cả cụm ảnh + thẻ + nút
   thu nhỏ đồng đều khi màn hình hẹp, thay vì rời rạc từng mảnh. */
.testimonial {
    padding: var(--sec-y) 0;
    color: var(--ink);
    background: var(--smoke);
}

.tm-grid {
    display: grid;
    grid-template-columns: 569fr 545fr;
    gap: clamp(32px, 6.9vw, 83px);
    align-items: start;
}

.tm-copy {
    padding-top: 55px;
}

.testimonial .section-eyebrow {
    color: var(--green);
}

/* Section duy nhất có hai vạch màu đen thay vì cùng màu chữ */
.testimonial .section-eyebrow::before,
.testimonial .section-eyebrow::after {
    border-top-color: var(--ink);
}

.testimonial .section-title {
    margin-bottom: 32px;
}

.tm-intro {
    display: flex;
    flex-direction: column;
    gap: 20px;
    margin-bottom: clamp(24px, 3.6vw, 43px);
}

.tm-intro p {
    margin: 0;
    font-size: clamp(15px, 1.5vw, 18px);
    line-height: 1.5;
    letter-spacing: var(--track);
    color: var(--ink);
}

.tm-cta {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 0 21px 0 22px;
    font-size: var(--fs-base);
    line-height: 26px;
    font-weight: 400;
    letter-spacing: var(--track);
    color: var(--green);
    text-decoration: none;
    border: 1px solid var(--green);
    border-radius: 80px;
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        transform .25s var(--ease);
}

.tm-cta-icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 49px;
    height: 49px;
    margin-right: -25px;
    font-size: 15px;
    color: var(--green);
    background: var(--smoke);
    border: 1px solid var(--green);
    border-radius: 50%;
    transition: color .25s var(--ease), background-color .25s var(--ease);
}

.tm-cta:hover {
    color: var(--white);
    background: var(--green);
    transform: translateY(var(--lift-sm));
}

.tm-cta:hover .tm-cta-icon {
    color: var(--green);
    background: var(--white);
}

/* ---------- Cột phải ---------- */

/* aspect-ratio thay cho height cứng: khung co lại thì mọi mốc % bên trong
   co theo, giữ nguyên bố cục đè nhau của ảnh và thẻ trích dẫn. */
.tm-stage {
    position: relative;
    width: 100%;
    max-width: clamp(380px, 34vw, 545px);
    aspect-ratio: 545 / 560;
}

.tm-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .3s var(--ease), visibility .3s var(--ease);
}

.tm-slide.is-active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* Ảnh và thẻ vào LỆCH NHỊP nhau: ảnh trượt ngang, thẻ dâng lên, thẻ chậm hơn
   0,12 giây. Hai lớp chuyển động khác hướng khác thời điểm tạo cảm giác chiều
   sâu, thay vì cả mảng cùng mờ hiện như một tấm phẳng. */
.tm-photo {
    display: block;
    width: 71.2%;
    height: 85.9%;
    object-fit: cover;
    border-radius: 20px;
    opacity: 0;
    transform: translateX(7%) scale(.97);
    transition: opacity .5s var(--ease), transform .5s var(--ease);
}

.tm-slide.is-active .tm-photo {
    opacity: 1;
    transform: none;
    transition-delay: .08s;
}

.tm-card {
    position: absolute;
    left: 11.75%;
    top: 59.8%;
    width: 88.25%;
    margin: 0;
    padding:
        clamp(16px, 2.3vw, 27px) clamp(14px, 1.5vw, 18px) clamp(16px, 2.3vw, 27px) clamp(22px, 3.1vw, 37px);
    background: var(--white);
    border-radius: 20px;
    box-shadow: 2px 4px 60px rgba(41, 44, 124, .1);
    overflow: hidden;
    opacity: 0;
    transform: translateY(26px);
    transition: opacity .5s var(--ease), transform .5s var(--ease);
}

.tm-slide.is-active .tm-card {
    opacity: 1;
    transform: none;
    transition-delay: .2s;
}

.tm-card::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: clamp(9px, 1.2vw, 14px);
    background: var(--green);
}

.tm-quote {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0;
    font-size: clamp(15px, 1.65vw, 20px);
    line-height: 1.8;
    letter-spacing: var(--track);
    color: rgba(29, 38, 46, .7);
}

.tm-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-top: clamp(10px, 1.6vw, 19px);
}

.tm-name {
    font-size: clamp(15px, 1.65vw, 20px);
    line-height: 1.8;
    font-weight: 500;
    letter-spacing: var(--track);
    color: rgba(29, 38, 46, .7);
}

.tm-stars {
    display: inline-flex;
    flex: none;
    gap: 4px;
    font-size: clamp(15px, 1.65vw, 20px);
    color: var(--gold);
}

/* Tâm nút trùng mép phải tấm ảnh; đặt theo % rồi kéo lùi nửa kích thước
   nên nó bám đúng chỗ ở mọi bề ngang. */
.tm-next {
    position: absolute;
    left: 71.4%;
    top: 38.4%;
    z-index: 2;
    display: grid;
    place-items: center;
    width: clamp(52px, 6.6vw, 80px);
    height: clamp(52px, 6.6vw, 80px);
    padding: 0;
    font-size: clamp(15px, 1.8vw, 22px);
    color: var(--green);
    background: var(--white);
    border: none;
    border-radius: 50%;
    box-shadow: 0 4px 60px rgba(41, 44, 124, .15);
    cursor: pointer;
    transform: translate(-50%, -50%);
    transition:
        color .25s var(--ease),
        background-color .25s var(--ease),
        transform .25s var(--ease);
}

/* Đã có translate(-50%,-50%) nên phần nhấc phải cộng dồn vào, không ghi đè */
.tm-next:hover {
    color: var(--white);
    background: var(--green);
    transform: translate(-50%, calc(-50% + var(--lift-sm)));
}

.tm-next:active {
    transform: translate(-50%, calc(-50% + 1px));
}

/* Máy tính bảng: hai cột thành một, cụm ảnh canh giữa */
@media (max-width: 1080px) {
    .testimonial {
        padding: 56px 0;
    }

    .tm-grid {
        grid-template-columns: 1fr;
        gap: 44px;
    }

    .tm-copy {
        padding-top: 0;
    }

    .tm-stage {
        margin-inline: auto;
    }

    .tm-quote,
    .tm-name,
    .tm-stars {
        font-size: 18px;
    }

    .tm-intro p {
        font-size: 16px;
    }
}

/* Điện thoại: bỏ kiểu đè nhau, xếp dọc — thẻ hẹp quá thì chữ không đọc nổi */
@media (max-width: 700px) {
    .tm-stage {
        max-width: 420px;
        aspect-ratio: auto;
    }

    .tm-slide {
        position: static;
        display: none;
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }

    .tm-slide.is-active {
        display: block;
    }

    .tm-photo {
        width: 100%;
        height: auto;
        aspect-ratio: 388 / 481;
        transform: none;
        opacity: 1;
    }

    .tm-card {
        position: relative;
        left: auto;
        top: auto;
        width: 92%;
        margin: -64px auto 0;
        transform: none;
        opacity: 1;
    }

    .tm-next {
        left: auto;
        right: 4px;
        top: 30%;
        transform: translateY(-50%);
    }

    .tm-next:hover,
    .tm-next:active {
        transform: translateY(-50%);
    }

    .tm-meta {
        flex-wrap: wrap;
        gap: 8px;
    }
}

@media (prefers-reduced-motion: reduce) {

    .tm-photo,
    .tm-card {
        transform: none;
        transition: opacity .2s linear;
    }

    .tm-cta:hover {
        transform: none;
    }

    .tm-next:hover,
    .tm-next:active {
        transform: translate(-50%, -50%);
    }
}

/* #endregion */


/* #region C10 · ĐĂNG KÝ NHẬN TƯ VẤN
   Figma: nền xanh, thẻ trắng 958x611 bo 15px, hai cột 410px khe 26px,
   các hàng cách nhau 41px, ô nhập cao 42px bo 5px, nút vàng cao 60px. */
.cta {
    padding: clamp(40px, 4.6vw, 78px) 0;
    color: var(--smoke);
    background: var(--green);
}

.cta-head {
    max-width: 920px;
    margin-inline: auto;
    text-align: center;
}

.cta-title {
    margin: 0;
    font-size: clamp(22px, 2.6vw, 32px);
    line-height: 1.5;
    font-weight: 800;
    letter-spacing: var(--track);
    text-transform: uppercase;
    color: var(--gold);
}

.cta-sub {
    margin: 6px 0 0;
    font-size: clamp(15px, 1.6vw, 20px);
    line-height: 1.4;
    font-weight: 400;
    letter-spacing: var(--track);
    color: var(--smoke);
}

.cta-form {
    max-width: 700px;
    margin: clamp(20px, 2.1vw, 38px) auto 0;
    padding: clamp(20px, 2.3vw, 44px) clamp(20px, 2.6vw, 46px);
    background: var(--white);
    border-radius: var(--r-box);
    box-shadow: 4px 4px 10px rgba(0, 0, 0, .25);
}

/* Một quy tắc lo toàn bộ khoảng cách giữa các hàng, co giãn liên tục
   theo bề ngang thay vì nhảy bậc ở từng ngưỡng.
   Figma cho 41px, nhưng ở khổ thật cộng với đệm thẻ thì hơn 40% lòng thẻ là
   chỗ trống — biểu mẫu 5 hàng mà trải dài như 8 hàng. */
.cta-form>*+* {
    margin-top: clamp(16px, 1.65vw, 30px);
}

.cta-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(18px, 2vw, 26px);
}

.cta-field {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.cta-field label {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--ink);
}

.cta-field label span {
    color: #E11D48;
}


.cta-field select,
.cta-field textarea,
.cta-field input {
    width: 100%;
    padding: 10px 15px;
    font: var(--font);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
    background: var(--white);
    border: 1px solid rgba(18, 26, 22, .3);
    border-radius: var(--r-row);
    transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}

/* Mũi tên riêng thay mũi tên mặc định của hệ điều hành, để ba ô trông giống nhau */
.cta-field select {
    padding-right: 42px;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7' viewBox='0 0 12 7'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23121A16' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 15px center;
}

.cta-field textarea {
    min-height: clamp(80px, 6.2vw, 104px);
    resize: vertical;
}

.cta-field input::placeholder,
.cta-field textarea::placeholder {
    color: rgba(18, 26, 22, .7);
}

/* Viền đậm lên KÈM quầng sáng: chỉ đổi màu viền 1px thì người mắt kém
   khó nhận ra ô nào đang được chọn. */
.cta-field input:focus,
.cta-field select:focus,
.cta-field textarea:focus {
    outline: none;
    border-color: var(--green);
    box-shadow: 0 0 0 3px var(--green-15);
}

/* Chỉ tô đỏ ô sai SAU KHI người dùng đã nhập rồi bỏ trống —
   :invalid trần sẽ bôi đỏ cả biểu mẫu ngay lúc trang vừa mở. */
.cta-field input:user-invalid,
.cta-field select:user-invalid,
.cta-field textarea:user-invalid {
    border-color: #E11D48;
}

/* KHÔNG để width:100%: thẻ trắng rộng 858px bên trong, nút trải hết chừng ấy
   thì đọc lên như một dải băng vàng chứ không ra dáng nút bấm. Chặn 420px rồi
   canh giữa; min() giữ cho nút vẫn co vừa thẻ ở màn hẹp.
   Đệm dọc 18px giữ nguyên ở 1920 để nút cao đúng 60px như Figma, xuống laptop
   mới co lại theo. */
.cta-submit {
    display: block;
    /* width: min(100%, 420px); */
    margin-inline: auto;
    padding: clamp(12px, .94vw, 18px) clamp(20px, 2vw, 32px);
    font-family: inherit;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--ink);
    background: var(--gold);
    border: none;
    border-radius: var(--r-pill);
    box-shadow: 4px 4px 3.6px rgba(255, 255, 255, .3);
    cursor: pointer;
    transition:
        background-color .25s var(--ease),
        transform .25s var(--ease),
        box-shadow .25s var(--ease);
}

.cta-submit:active {
    transform: translateY(1px);
}

/* Chỉ máy có chuột thật mới chạy hiệu ứng rê chuột. Trên điện thoại,
   :hover bị "kẹt" sau khi chạm — nút vẫn sáng và nhấc lên cho tới khi
   người dùng chạm chỗ khác. */
@media (hover: hover) {
    .cta-submit:hover {
        background: #F4B327;
        transform: translateY(var(--lift));
        box-shadow: 0 10px 24px rgba(0, 0, 0, .25);
    }
}

/* Ngón tay cần vùng chạm tối thiểu 44px (hướng dẫn của cả Apple lẫn Google).
   Ô cao 42px theo Figma là đủ cho chuột nhưng hụt cho ngón tay. */
@media (pointer: coarse) {

    .cta-field select,
    .cta-field input {
        min-height: 48px;
    }

    .cta-submit {
        min-height: 52px;
    }
}

/* Ngưỡng duy nhất của khối này: hai cột thành một.
   Mọi kích thước khác đã co giãn liên tục bằng clamp() nên không cần thêm bậc. */
@media (max-width: 700px) {
    .cta-row {
        grid-template-columns: 1fr;
    }

    .cta-submit {
        padding: 15px 10px;
        font-size: var(--fs-base);
    }
}

@media (prefers-reduced-motion: reduce) {

    .cta-submit:hover,
    .cta-submit:active {
        transform: none;
    }
}

/* Thông báo và lỗi của biểu mẫu tư vấn. Dùng lại đúng bộ màu của .cform-alert
   bên trang Liên hệ để hai biểu mẫu nói cùng một ngôn ngữ. */
.cta-alert {
    margin: 0 0 clamp(18px, 2.4vw, 28px);
    padding: 12px 16px;
    font-size: var(--fs-sm);
    font-weight: 600;
    border-radius: var(--r-row);
}

.cta-alert--ok {
    color: var(--green);
    background: var(--green-10);
}

.cta-alert--error {
    color: #E11D48;
    background: rgba(225, 29, 72, .08);
}

/* Lỗi của từng ô nằm sát dưới ô đó. .cta-field là flex dọc gap 13px nên chỉ
   cần kéo lên một chút cho lỗi dính vào ô của nó thay vì lơ lửng giữa hai ô. */
.cta-err {
    margin: -5px 0 0;
    font-size: 12px;
    font-weight: 600;
    color: #E11D48;
}

/* #endregion */


/* ============================================================
   ĐIỆN THOẠI — TIÊU ĐỀ SECTION XẾP DỌC, VẪN CANH TRÁI
   Đặt ở CUỐI file để thắng mọi quy tắc đã khai trước đó.

   Khối này TRƯỚC 21/09/2026 canh GIỮA tiêu đề trên màn hẹp. Bỏ hẳn phần canh
   giữa vì nó chọi thẳng với thiết kế mới: thanh dọc vàng là mốc mở đầu nằm sát
   mép trái, đẩy cả cụm vào giữa thì thanh trôi lơ lửng giữa màn hình, mất đúng
   ý nghĩa của nó. Vẫn giữ flex-direction: column — trên màn hẹp tiêu đề và nút
   "Xem tất cả" không đủ chỗ đứng cạnh nhau.
   ============================================================ */
@media (max-width: 700px) {

    /* .section-head gốc là flex ngang (tiêu đề trái, nút phải).
       Trên điện thoại xếp dọc. align-items: flex-start chứ không để mặc định
       stretch: stretch kéo nút "Xem tất cả" rộng hết hàng. */
    .section-head {
        flex-direction: column;
        align-items: flex-start;
        gap: 18px;
    }
}


/* ============================================================
   MENU ĐỔ XUỐNG CÁC MỤC TRANG CHỦ + CUỘN MƯỢT
   ============================================================ */

/* Cuộn mượt khi bấm liên kết #id. Làm bằng CSS nên không cần JavaScript. */
html {
    scroll-behavior: smooth;
}

/* ĐÃ GỠ: section[id] { scroll-margin-top: 96px }
   Việc "chừa chỗ cho thanh menu dính" đã có `scroll-padding-top: var(--nav-cap)`
   khai ở :root lo trọn rồi. Giữ cả hai là hai cơ chế cùng làm một việc và
   CỘNG DỒN: neo dừng ở 107 + 96 = 203px thay vì 107px, tức dư gần một trăm
   pixel trắng trên đỉnh mỗi lần nhảy tới section.
   Lỗi này chỉ lộ ra khi so hai loại đích: neo trỏ vào <div> (ví dụ
   #bang-xep-hang) dừng đúng 107px, còn neo trỏ vào <section id> thì lệch —
   cùng một trang, hai kết quả khác nhau. Đừng thêm lại. */

/* Mũi tên đi kèm mọi mục nên phải gọn: mỗi pixel ở đây nhân với số mục. */
.nav-caret {
    margin-left: 5px;
    font-size: 9px;
    transition: transform .25s var(--ease);
}

/* Khối đổ xuống là CON CỦA .nav-sticky, không nằm trong .nav-pill —
   viên thuốc có overflow:hidden nên đặt bên trong sẽ bị cắt cụt.

   pointer-events: auto LÀ BẮT BUỘC, không phải thừa. .nav-mega là con trực
   tiếp của .nav-sticky > .container — khối cha ấy bị đặt pointer-events:none
   (chống giật khi dính, xem ghi chú tại .nav-sticky > .container) rồi chỉ mở
   lại đúng cho .nav-pill. .nav-mega là ANH EM của .nav-pill chứ không phải
   con của nó nên KHÔNG được mở lại theo — thiếu dòng này, cả khối đổ xuống
   lẫn mọi liên kết bên trong nó im lìm trước chuột: rê chuột vào thấy đúng
   toạ độ nhưng document.elementFromPoint() xuyên qua nó, hover không bắt,
   bấm không trúng. Đây mới là lý do thật của "rê xuống bị ẩn, không bấm
   được" — không phải khoảng cách hay hẹn giờ đóng ở app.js. */
.nav-mega {
    position: absolute;
    pointer-events: auto;
    left: var(--mega-left, 48px);

    /* app.js đo thẳng từ đáy MỤC CHA thật rồi ghi vào --mega-top. Trước đây
       đặt cứng calc(100% - 17px) — tính theo chiều cao DÀNH SẴN của .nav-sticky
       (67px, giữ cố định để chống giật khi dính) chứ không phải chiều cao THẬT
       của viên thuốc (46px lúc đã dính). Hai số lệch nhau 21px, cộng với việc
       mục cha còn thấp hơn viên thuốc một khoảng do canh giữa theo chiều dọc,
       ra một dải "chết" cao tới 33px mà chuột đi qua không tính là đang rê vào
       đâu cả — rê chậm là quá 180ms của dong(), khối đổ xuống tắt giữa chừng
       trước khi chạm tới. --mega-top loại hẳn dải chết đó vì luôn khớp đúng vị
       trí thật, không suy qua phần trăm của khối cha nữa. */
    top: var(--mega-top, calc(100% - 17px));
    z-index: 90;
    width: max-content;
    min-width: 248px;
    max-width: 320px;
    padding-top: 10px;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}

.nav-mega ul {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 10px;
    list-style: none;
    background: var(--white);
    border-radius: var(--r-box);
    box-shadow: 0 18px 40px rgba(18, 26, 22, .24);
}

.nav-mega a {
    display: block;
    padding: 11px 16px;
    font-size: 15px;
    line-height: 1.4;
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    border-radius: 8px;
    white-space: nowrap;
    transition: color .2s var(--ease), background-color .2s var(--ease);
}

/* Chỉ tô nền khi rê chuột hoặc khi tới bằng bàn phím — không có trạng thái
   "đang xem" cố định. */
.nav-mega a:hover,
.nav-mega a:focus-visible {
    font-weight: 700;
    color: var(--white);
    background: var(--green);
}

/* Trước đây mở bằng :has() vì chỉ có MỘT khối đổ xuống. Nay mỗi mục cha có
   khối riêng, mà CSS không diễn tả được "khối nào ứng với mục đang rê chuột"
   khi hai phần tử ở hai nhánh DOM khác nhau — nên app.js gắn class .is-open
   cho đúng cặp. */
.nav-mega.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.nav-link.is-open .nav-caret {
    transform: rotate(180deg);
}

/* Bản trong danh sách burger chỉ dành cho màn hình hẹp */
.nav-sub-head,
.nav-link--sub {
    display: none;
}

@media (max-width: 1080px) {

    /* Màn hình cảm ứng không có "rê chuột" thật sự — bỏ khối đổ xuống,
       các mục đã có sẵn trong danh sách burger bên dưới. */
    .nav-mega {
        display: none;
    }

    .nav-caret {
        display: none;
    }

    .nav-sub-head {
        display: block;
        margin-top: 6px;
        padding: 8px 12px 2px;
        font-size: var(--fs-sm);
        font-weight: 700;
        letter-spacing: .08em;
        text-transform: uppercase;
        color: var(--gold);
        border-top: 1px solid rgba(244, 247, 245, .18);
    }

    .nav-link--sub {
        display: block;
        font-size: 14px;
        font-weight: 500;
        opacity: .92;
    }
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}


/* ============================================================
   MENU MỤC TRANG CHỦ — MÁY TÍNH BẢNG & ĐIỆN THOẠI
   ============================================================ */
@media (max-width: 1080px) {

    /* Danh sách burger nay có 14 mục (6 mục chính + nhãn + 7 mục trang chủ).
       Trên điện thoại nằm ngang, ngần đó vượt quá chiều cao màn hình và
       phần cuối không với tới được. Cho phép cuộn trong bảng. */
    .nav-sticky .main-nav {
        max-height: calc(100svh - 130px);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* Vùng chạm tối thiểu 44px cho ngón tay; 5px đệm của bản desktop
       chỉ cho ra 30px, quá nhỏ để bấm chính xác. */
    .nav-sticky .nav-link {
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
    }

    .nav-link--sub {
        min-height: 42px;
    }

    /* ĐÃ GỠ bản mobile của section[id] { scroll-margin-top } — cùng lý do
       cộng dồn đã ghi ở khối desktop phía trên. */
}

/* ===================== TRANG ĐĂNG NHẬP ===================== */
.auth {
    position: relative;
    margin-top: -68px;
    padding-block: 56px 96px;
    background: var(--smoke);
}

.auth-card {
    max-width: 460px;
    margin-inline: auto;
    margin-top: 68px;
    padding: 40px 32px;
    background: var(--white);
    border: 1px solid var(--green-15);
    border-radius: var(--r-card);
    box-shadow: 0 12px 32px rgba(18, 26, 22, .08);
}

.auth-head {
    text-align: center;
    margin-bottom: 28px;
}

.auth-title {
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    color: var(--green);
    margin: 0 0 6px;
}

.auth-sub {
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
    margin: 0;
}

.auth-alert {
    margin: 0 0 18px;
    padding: 12px 14px;
    border-radius: var(--r-row);
    font-size: var(--fs-sm);
    line-height: var(--lh-loose);
}

.auth-alert--error {
    background: rgba(190, 40, 40, .08);
    border-left: 3px solid var(--danger);
    color: #8E1F1F;
}

.auth-alert--warn {
    background: var(--gold-10);
    border-left: 3px solid var(--gold);
    color: var(--warn);
}

/* Câu trả lời của biểu mẫu quên mật khẩu. Dùng xanh thương hiệu chứ không
   phải xanh "thành công" mặc định — và cố ý KHÔNG kèm biểu tượng dấu tích:
   câu ấy là "nếu số này có tài khoản thì đã gửi", một lời trung tính, không
   phải lời xác nhận đã gửi thật. Dấu tích sẽ nói nhiều hơn sự thật. */
.auth-alert--ok {
    background: var(--green-10);
    border-left: 3px solid var(--green);
    color: var(--green);
}

.auth-field {
    margin-bottom: 18px;
}

.auth-field label {
    display: block;
    margin-bottom: 6px;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--ink);
}

.auth-field input {
    width: 100%;
    padding: 12px 14px;
    font-family: var(--font);
    font-size: var(--fs-base);
    color: var(--ink);
    background: var(--white);
    border: 1px solid var(--green-30);
    border-radius: var(--r-row);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* Bỏ outline mặc định thì BẮT BUỘC thay bằng dấu hiệu khác, nếu không
   người dùng bàn phím mất hoàn toàn khả năng biết đang ở ô nào. */
.auth-field input:focus {
    outline: none;
    border-color: var(--green);
    box-shadow: 0 0 0 3px var(--green-10);
}

/* Bám thẳng vào aria-invalid thay vì thêm class riêng: trạng thái lỗi
   chỉ có một nguồn sự thật cho cả phần nhìn lẫn trình đọc màn hình. */
.auth-field input[aria-invalid="true"] {
    border-color: var(--danger);
}

.auth-field input[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 3px rgba(190, 40, 40, .12);
}

.auth-error {
    margin: 6px 0 0;
    font-size: var(--fs-sm);
    color: var(--danger);
}

/* ----- Nút ẩn/hiện mật khẩu (mục 3.1 tài liệu yêu cầu) ----- */

.auth-input-wrap {
    position: relative;
}

/* Chừa chỗ cho nút con mắt, nếu không mật khẩu dài sẽ chạy xuống dưới nó.
   Chỉ nhắm ô nằm trong khối bọc, các ô khác giữ nguyên đệm cũ. */
.auth-input-wrap input {
    padding-right: 46px;
}

.auth-eye {
    position: absolute;
    top: 50%;
    right: 4px;
    transform: translateY(-50%);

    /* 40px là mức tối thiểu bấm trúng bằng ngón tay. Bản thân biểu tượng chỉ
       ~16px, để nguyên thì trên điện thoại rất hay bấm trượt ra ngoài. */
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;

    padding: 0;
    background: none;
    border: 0;
    border-radius: var(--r-row);
    color: var(--muted);
    font-size: 15px;
    cursor: pointer;
    transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.auth-eye:hover {
    color: var(--green);
    background: var(--green-10);
}

.auth-eye:focus-visible {
    outline: none;
    color: var(--green);
    box-shadow: 0 0 0 3px var(--green-10);
}

/* Đang hiện mật khẩu: đổi màu để trạng thái nhìn thấy được, không chỉ dựa vào
   việc biểu tượng đổi từ con mắt sang con mắt gạch chéo (khác biệt khá nhỏ). */
.auth-eye[aria-pressed="true"] {
    color: var(--green);
}

/* ----- Chữ phụ trong biểu mẫu ----- */

.auth-hint {
    margin: 6px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-loose);
    color: var(--muted);
}

.auth-forgot {
    margin: -6px 0 18px;
    text-align: right;
    font-size: var(--fs-sm);
}

.auth-forgot a {
    color: var(--green);
    font-weight: 600;
}

/* Nhắc tên đăng nhập ở trang đặt mật khẩu — người dùng đến từ hộp thư nên rất
   dễ tưởng mình đăng nhập bằng email. */
.auth-ident {
    margin: 0 0 20px;
    padding: 11px 14px;
    background: var(--green-10);
    border-radius: var(--r-row);
    font-size: var(--fs-sm);
    color: var(--ink);
    text-align: center;
}

.auth-ident strong {
    color: var(--green);
}

.auth-submit {
    width: 100%;
    margin-top: 6px;
    padding-block: 13px;
    font-size: var(--fs-base);
}

.auth-note {
    margin: 22px 0 0;
    text-align: center;
    font-size: var(--fs-sm);
    line-height: var(--lh-loose);
    color: var(--muted);
}

.auth-note a {
    color: var(--green);
    font-weight: 600;
}

@media (max-width: 520px) {
    .auth {
        padding-block: 32px 56px;
    }

    .auth-card {
        padding: 28px 20px;
    }
}

/* ============================================================
   C11 · XEM ẢNH LỚN — dùng chung cho dải vinh danh, bảng điểm
   và lưới trúng tuyển.
   ============================================================ */

/* Ảnh trở thành nút bấm được, nhưng phải trông y như trước: nút mang sẵn
   viền, nền và đệm của trình duyệt nên phải gỡ hết. */
.zoom-btn {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    background: none;
    border: 0;
    cursor: zoom-in;
}

.zoom-btn:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
}

/* Thẻ <dialog> mặc định co theo nội dung và canh giữa bằng margin auto;
   ở đây ghim inset: 0 cho phủ kín khung nhìn, vừa để vùng tối quanh ảnh bấm
   được vào là đóng, vừa khỏi phụ thuộc cách từng trình duyệt tô ::backdrop. */
.lb {
    position: fixed;
    inset: 0;
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    overflow: hidden;
}

/* Chỉ hiện dạng lưới KHI đang mở — <dialog> lúc đóng phải giữ display:none,
   viết display:grid ở .lb là hộp nằm chình ình trên trang. */
.lb[open] {
    display: grid;
    place-items: center;
    background: rgba(18, 26, 22, .86);
}

/* Khung xem CỐ ĐỊNH nên hộp không đổi khổ mỗi lần mở một tấm khác — ảnh tải
   lên đủ mọi tỉ lệ, từ 1727x1535 gần vuông tới 763x998 dọc đứng.
   object-fit: contain giữ nguyên tỉ lệ gốc: ảnh dọc chạm mép trên dưới, ảnh
   ngang chạm mép trái phải, không tấm nào bị cắt hay kéo méo. Đánh đổi: ảnh
   gốc nhỏ hơn khung sẽ được phóng lên nên hơi mất nét. */
.lb-img {
    width: min(92vw, 860px);
    height: min(82dvh, 760px);
    object-fit: contain;
    animation: lb-in .25s var(--ease);
}

@keyframes lb-in {
    from {
        opacity: 0;
        transform: scale(.96);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

.lb-close {
    position: absolute;
    top: 20px;
    right: 20px;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    font-size: 18px;
    color: var(--white);
    background: rgba(255, 255, 255, .14);
    border: 1px solid rgba(255, 255, 255, .35);
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.lb-close:hover {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--ink);
    transform: scale(1.06);
}

@media (max-width: 600px) {
    .lb-close {
        top: 12px;
        right: 12px;
        width: 38px;
        height: 38px;
        font-size: 16px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lb-img {
        animation: none;
    }
}


/* #region C12 · TRANG LIÊN HỆ — /lien-he */


/* ============================================================
   C12a · HERO
   ============================================================ */

/* Hero THẤP, cố tình không dùng .hero của khối C2.
   .hero cao trọn một màn hình vì có ảnh học viên lấp đầy cột phải; trang Liên
   hệ không có ảnh nào, kéo lên 100vh chỉ còn một mảng xanh rỗng. Cùng cách làm
   với hero trang Tin tức. Cỡ chữ tiêu đề thì vẫn mượn --fs-xl/--lh-xl của C2
   để hero các trang đọc lên như một. */
.chero {
    position: relative;
    /* Bản gốc theo đúng 322px của khối tròn Figma, nhưng đệm đáy tới 137px bỏ
       trống cả một mảng xanh khi tiêu đề chỉ có một dòng — đo trên màn 14" (1536px)
       ngày 2026-08-26 thấy rõ. Hạ xuống 200px/đệm đáy 90px: khối tròn (height:100%)
       co theo tỉ lệ, nhỏ lại một chút chứ không bị lệch, còn lưới chấm ở .chero-dots
       vẫn đủ cách chữ tiêu đề (xem lại nếu co thêm nữa, dễ đè lên chữ).

       margin-top thêm ngày 2026-09-19: .nav-sticky (thanh menu, xem C1) chiếm
       84px trong luồng rồi kéo lên -33px để viên thuốc nổi đè lên .site-header,
       tổng lại đáy khối header luôn dừng ở 184px bất kể trang — phần dư giữa
       đáy viên thuốc và mép xanh của .chero vốn là NỀN TRẮNG TRƠN, không do
       chero tạo ra. Trước đây đệm đỉnh chero còn dày (32-56px) nên mắt không
       thấy rõ chỗ nối; từ khi hero rút gọn xuống 12-18px, khoảng trắng ấy lộ
       hẳn ra thành một dải cụt lủn ngay trên đầu chữ. Margin-top này là
       khoảng cách CHỦ ĐỘNG, tách bạch với đệm bên trong chero. */
    margin-top: 16px;
    min-height: 200px;
    padding: clamp(32px, 3.6vw, 35px) 0 clamp(35px, 6vw, 90px);
    overflow: hidden;
    color: var(--white);
    background: var(--green);
}

.chero-crumb {
    grid-area: crumb;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    letter-spacing: var(--track);
    color: rgba(255, 255, 255, .55);
}

.chero-crumb a {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.chero-crumb a:hover {
    color: var(--white);
}

.chero-crumb [aria-current] {
    color: var(--gold);
    font-weight: 600;
}

/* Ba khối chữ nằm chung một lưới hai cột. Cột phải (đoạn dẫn) trải qua CẢ HAI
   hàng nên nó bắt đầu ngang hàng breadcrumb chứ không phải ngang dòng tiêu đề —
   đúng như Figma. Để breadcrumb ngoài lưới thì đoạn dẫn tụt xuống cả một dòng.
   align-items: start giữ cho đoạn dẫn không bị kéo giãn theo chiều cao tiêu đề. */
.chero-grid {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 330px);
    grid-template-areas:
        "crumb lead"
        "title lead";
    align-items: start;
    gap: 14px clamp(28px, 4vw, 64px);
}

.chero-title {
    grid-area: title;
    margin: 0;
    font-size: var(--fs-xl);
    line-height: var(--lh-xl);
    font-weight: 700;
    letter-spacing: -.5px;
    color: var(--white);
}

/* Chữ nghiêng vàng cuối tiêu đề: GIỮ NGUYÊN Montserrat, chỉ nghiêng và đổi
   màu — đúng cách hai khối C5 và C8 đang làm (.featured/.award .section-title
   em). Cormorant chỉ dành cho câu châm ngôn giáo viên, đừng kéo sang đây. */
.chero-title strong {
    /* font-style: italic; */
    color: var(--gold);
}

/* Figma cho đoạn dẫn bắt đầu thấp hơn breadcrumb chừng một dòng. */
.chero-lead {
    grid-area: lead;
    /* margin: 22px 0 0; */
    font-size: var(--fs-sm);
    line-height: 1.75;
    color: rgba(255, 255, 255, .62);
}

/* ---------- Ba mảnh trang trí ---------- */

/* Lưới chấm nằm sát mép TRÁI MÀN HÌNH chứ không theo mép container: trong
   Figma nó tràn ra ngoài khổ nội dung. Dùng clamp để ở màn hẹp nó lùi vào,
   khỏi chui xuống dưới chữ. */
.chero-dots {
    position: absolute;
    left: clamp(14px, 5vw, 72px);
    bottom: clamp(16px, 1.8vw, 25px);
    z-index: 1;
    width: 70px;
    height: 70px;
    opacity: .35;
    background-image: radial-gradient(circle, var(--white) 1.3px, transparent 1.5px);
    background-size: 14px 14px;
}

/* Khối tròn Figma đã cắt sẵn theo mép phải khung 1440 (đường tròn thật rộng
   458px nhưng viewBox chỉ giữ 345px), nên dán sát right: 0 là ra đúng phần
   nhìn thấy trong thiết kế.

   height: 100% + width: auto để hình giữ tỉ lệ và luôn phủ trọn chiều cao
   hero: hero cao thêm bao nhiêu ở màn hẹp thì đường cong nở theo bấy nhiêu,
   không bao giờ hở một dải xanh phẳng ở đáy. */
.chero-art {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 0;
    height: 100%;
    width: auto;
    max-width: none;
    pointer-events: none;
}

/* Tam giác dùng lại file của banner trang chủ — bản xuất Figma của trang này
   cho ra ĐÚNG path ấy (M1.5 1.5 L68.97 33.77 L13.23 74.83 Z, viền #F2921D dày
   3), nên không cần thêm file mới.

   Hai số 23 và 21 đọc thẳng từ bản xuất: trong khung 345x322, tam giác nằm ở
   x 251.5-322.5 và y 224.5-301.5, tức cách mép phải 23px và mép đáy 20.5px.
   Khối tròn dán sát right: 0 nên hai mốc này tính luôn từ mép hero. */
.chero-tri {
    position: absolute;
    right: clamp(12px, 1.6vw, 23px);
    bottom: clamp(14px, 1.5vw, 21px);
    z-index: 1;
    width: clamp(44px, 4.9vw, 71px);
    height: auto;
    pointer-events: none;
}

/* ---------- Biến thể CĂN GIỮA riêng cho hero Liên hệ ---------- */

/* Bản gốc chia hai cột (tiêu đề trái, đoạn dẫn ghim góc trên-phải) để lại một
   mảng xanh trống lớn phía dưới tiêu đề vì đoạn dẫn không đủ dài để lấp cột
   phải — nhìn lệch hẳn sang trái. Xếp lại thành MỘT cột, dồn cả ba dòng vào
   giữa: tiêu đề và đoạn dẫn giờ liền mạch theo chiều dọc, không còn khoảng
   trống rời rạc. Trang Tin tức (.chero--news) cũng dùng cùng kiểu bố cục căn
   giữa này — xem khối C13a. */
.chero--contact {
    /* Hạ tiếp xuống ~15px mỗi bên cho khớp .chero--news (khối C13a) — cả hai
       cùng một kiểu bố cục căn giữa nên nên đọc cao bằng nhau; 56/64px cũ để
       lại dải xanh dư hẳn so với bản Tin tức đã thu gọn.

       clamp() thay vì 15px cứng: màn rất hẹp co về 12px cho đỡ chật khi đoạn
       dẫn xuống hai dòng, màn rất rộng nới lên 18px để dải xanh trên dưới
       không mỏng dính so với bề ngang lúc đó.

       min-height ĐÈ LẠI 200px của .chero gốc. Sau khi gộp row-gap còn 6px
       (xem .chero--contact .chero-grid), nội dung thật (crumb + tiêu đề +
       mô tả + padding) chỉ cao ~172px — sàn 200px cũ ép khối cao hơn 28px,
       mà .chero-grid không tự giãn đều (chỉ neo trên) nên toàn bộ phần dư
       dồn xuống ĐÁY, đúng cái khoảng trắng khách vừa chỉ ra. Hạ sàn xuống
       172px để khối hugging sát nội dung, không dư khoảng nào ở dưới. */
    min-height: 172px;
    padding: clamp(12px, 1.4vw, 18px) 0;
}

.chero--contact .chero-grid {
    /* Một cột ở MỌI bề ngang, không chỉ từ 860px trở xuống như bản gốc.
       KHÔNG dùng justify-items: center — grid co ô lại vừa khít nội dung
       (max-content), khiến đoạn dẫn dài mất chỗ để xuống dòng và tràn ra
       ngoài màn hình hẹp. Để ô giữ nguyên full-width (stretch mặc định) rồi
       căn chữ bằng text-align, đoạn văn vẫn ngắt dòng đúng theo bề ngang
       container. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
        "crumb"
        "title"
        "lead";
    /* row-gap riêng 6px, thay vì thừa hưởng 14px của bản gốc hai cột (khoảng
       đó đo cho lưới "crumb lead / title lead" nằm cạnh nhau, không phải xếp
       chồng). Cộng thêm margin-top cũ 8px của .chero-lead nữa thì tổng
       khoảng cách tiêu đề - mô tả bị dư tới 22px dù đã thu gọn — dồn về một
       nguồn duy nhất cho dễ kiểm soát: .chero-lead bỏ hẳn margin-top, gap ở
       đây quyết định toàn bộ. */
    row-gap: 6px;
    max-width: 640px;
    margin: 0 auto;
    text-align: center;
}

.chero--contact .chero-crumb {
    justify-content: center;
}

.chero--contact .chero-lead {
    max-width: 520px;
    margin: 0 auto;
    padding-right: 0;
}


/* ============================================================
   C12b · THÔNG TIN LIÊN HỆ
   ============================================================ */

.cinfo {
    padding: clamp(40px, 5vw, 68px) 0 clamp(48px, 6vw, 80px);
    background: var(--smoke);
}

/* Đường kẻ dưới tiêu đề là border-bottom của chính tiêu đề, không phải thẻ
   <hr> riêng — bớt một thẻ rỗng mà nhìn không khác. */
.cinfo-title {
    margin: 0 0 32px;
    padding-bottom: 20px;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    color: var(--ink);
    border-bottom: 1px solid rgba(18, 26, 22, .12);
}

/* Hai hàng chứ không phải hai cột lồng nhau: đoạn dẫn chiếm riêng hàng trên
   bên trái, hàng dưới mới là danh sách thẻ và thẻ chi tiết. Gộp đoạn dẫn với
   danh sách vào một div cột thì thẻ chi tiết bị kéo lên ngang đoạn dẫn, lệch
   khỏi đỉnh thẻ kênh đầu tiên. Cùng lối với .cplace-grid bên dưới.

   Figma khung 1200: cột thẻ 735, khe 50, thẻ chi tiết 415. Thu hẹp còn 340:
   ở 415 thẻ rộng hơn hẳn nội dung bên trong (số hotline, hai nút) nên hàng
   "KÊNH TIẾP NHẬN — ĐANG HOẠT ĐỘNG" và khối giờ làm việc bị đẩy dạt ra hai
   biên, để lại mảng trống giữa.

   RỒI NỚI LẠI LÊN 375. 340 hụt: giá trị dài nhất là đường dẫn Fanpage
   (facebook.com/cep.qdc), đo ở đúng cỡ chữ .cpanel-value (27px, đậm 700,
   giãn chữ -0.4px) ra 283px, trong khi lòng thẻ 340 - 2x26 đệm = 288px — dư
   vỏn vẹn 5px. Máy nào render Montserrat nhỉnh hơn 2% là đường dẫn rớt xuống
   dòng hai, đúng như ảnh khách gửi ngày 2026-09-17. 375 cho lòng thẻ 323px,
   dư 40px, vẫn hẹp hơn hẳn mốc 415 từng bị chê rộng.

   ĐỪNG HẠ XUỐNG DƯỚI 375 nếu chưa đo lại bề ngang chuỗi dài nhất: mốc chặn
   là chuỗi giá trị, không phải hai nút hành động. */
.cinfo-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 375px);
    grid-template-areas:
        "lead ."
        "list panel";
    gap: clamp(18px, 2vw, 26px) clamp(24px, 3.4vw, 50px);
}

.cinfo-lead {
    grid-area: lead;
    max-width: 57ch;
    margin: 0;
    font-size: var(--fs-base);
    line-height: 1.6;
    color: var(--muted);
}

.cchan-list {
    grid-area: list;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* ---------- Thẻ một kênh ---------- */

/* Là <button> nên phải gỡ sạch nền, viền và canh chữ mặc định của trình
   duyệt, rồi dựng lại từ đầu. Đổi lại được miễn phí: bấm bằng phím Enter/Space
   và vào được bằng Tab. */
.cchan {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
        "no    kind  tick"
        "value value tick"
        "desc  desc  tick";
    align-items: center;
    gap: 4px 10px;
    width: 100%;
    padding: 18px 22px;
    font-family: inherit;
    text-align: left;
    background: var(--white);

    /* Viền trong suốt chứ không phải 0: thẻ đang chọn chỉ việc tô màu cho nó,
       kích thước thẻ không đổi nên cả cột không nhích mỗi lần đổi kênh. Trong
       Figma thẻ thường không có nét viền nào, chỉ nổi lên bằng bóng đổ. */
    border: 1px solid transparent;
    border-radius: var(--r-media);
    box-shadow: 0 4px 14px rgba(18, 26, 22, .06);
    cursor: pointer;
    transition:
        border-color var(--dur) var(--ease),
        box-shadow var(--dur) var(--ease),
        transform var(--dur) var(--ease);
}

.cchan:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}

/* Thẻ đang chọn: viền xanh và bóng đổ đậm hơn. */
.cchan.is-active {
    border-color: var(--green);
    box-shadow: 0 10px 26px rgba(27, 94, 63, .12);
}

@media (hover: hover) {
    .cchan:hover {
        border-color: var(--green-30);
        transform: translateY(var(--lift-sm));
    }
}

.cchan-no {
    grid-area: no;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    color: var(--gold);
}

.cchan-kind {
    grid-area: kind;
    justify-self: start;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(18, 26, 22, .45);
}

.cchan-value {
    grid-area: value;
    font-size: 18px;
    line-height: 24px;
    font-weight: 700;
    color: var(--ink);
}

.cchan-desc {
    grid-area: desc;
    font-size: 12px;
    line-height: 1.55;
    color: var(--muted);
}

/* Dấu tích trải suốt ba hàng nên tự nằm giữa thẻ theo chiều dọc, không phải
   canh tay bằng margin. */
.cchan-tick {
    grid-area: tick;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    font-size: 11px;
    color: rgba(18, 26, 22, .22);
    border: 1.5px solid rgba(18, 26, 22, .16);
    border-radius: 50%;
    transition:
        color var(--dur) var(--ease),
        background-color var(--dur) var(--ease),
        border-color var(--dur) var(--ease);
}

.cchan.is-active .cchan-tick {
    color: var(--white);
    background: var(--green);
    border-color: var(--green);
}

/* ---------- Thẻ chi tiết kênh ---------- */

/* align-self: start là điều kiện để position: sticky chạy được. Mặc định ô
   lưới bị kéo cao bằng cả hàng, mà phần tử cao bằng khung cuộn thì không còn
   chỗ nào để dính. */
.cinfo-panels {
    grid-area: panel;
    align-self: start;
    position: sticky;
    top: 24px;
}

/* Nhịp dọc bên trong bám Figma: thẻ cao ~336px ở khung 1200 và đáy của nó
   ngang đáy thẻ kênh thứ ba. Nới rộng hơn là thẻ tụt xuống quá thẻ thứ tư. */
.cpanel {
    display: flex;
    flex-direction: column;
    padding: clamp(20px, 2.2vw, 26px);
    color: var(--white);
    background: var(--green);
    border-radius: var(--r-media);
    box-shadow: 0 16px 36px rgba(27, 94, 63, .18);
}

/* Ba kênh không được chọn ẩn bằng thuộc tính hidden do JavaScript bật/tắt.
   Cần dòng này vì display: flex ở trên mạnh hơn hidden mặc định của trình
   duyệt — thiếu nó thì cả bốn thẻ cùng hiện. */
.cpanel[hidden] {
    display: none;
}

.cpanel-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 16px;
    border-bottom: 1px solid rgba(255, 255, 255, .14);
}

.cpanel-eyebrow {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .58);
}

/* Chấm tròn trước chữ "Đang hoạt động" làm bằng ::before, không phải ký tự •
   — ký tự thật sẽ bị trình đọc màn hình đọc thành "dấu chấm tròn đen lớn". */
.cpanel-state {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--gold);
}

.cpanel-state::before {
    content: "";
    width: 6px;
    height: 6px;
    background: var(--gold);
    border-radius: 50%;
}

.cpanel-name {
    margin: 14px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    color: rgba(255, 255, 255, .8);
}

.cpanel-value {
    margin: 5px 0 0;
    font-size: 27px;
    line-height: 34px;
    font-weight: 700;
    letter-spacing: -.4px;
    color: var(--white);

    /* Giá trị dài nhất là một đường dẫn (facebook.com/...) và không có dấu
       cách nào để xuống dòng — thiếu dòng này nó đẩy rộng cả thẻ. */
    overflow-wrap: anywhere;
}

/* 24px chứ không phải 16px như trước. Nhịp dọc trong thẻ là 14 - 5 - 16, tức
   tên và số điện thoại là một cặp sát nhau (5px), rồi dòng chú thích nhỏ ngăn
   giữa số với hàng nút. Gỡ dòng ấy đi mà giữ nguyên 16px thì hàng nút dán gần
   như sát đáy con số — mắt đọc thành một cụm liền, mất ranh giới giữa "thông
   tin" và "hành động". 24px trả lại đúng khoảng ngắt ấy. */
.cpanel-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 24px;
}

.cpanel-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    font-size: 12px;
    font-weight: 700;
    color: var(--ink);
    text-decoration: none;
    background: var(--gold);
    border-radius: 6px;
    transition:
        background-color var(--dur) var(--ease),
        transform var(--dur) var(--ease);
}

.cpanel-btn i {
    transition: transform var(--dur) var(--ease);
}

.cpanel-btn--ghost {
    background: var(--white);
}

@media (hover: hover) {
    .cpanel-btn:hover {
        transform: translateY(var(--lift-sm));
    }

    .cpanel-btn:hover i {
        transform: translateX(4px);
    }
}

.cpanel-meta {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px 20px;
    margin: 17px 0 0;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, .14);
}

.cpanel-meta dt {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .5);
}

.cpanel-meta dd {
    margin: 6px 0 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--white);
}

/* Kênh không công bố thời gian phản hồi (hiện chỉ có Hotline — xem
   ContactController::channels()): lưới hai cột co về MỘT cột, để ô "Thời
   gian làm việc" không đứng lẻ loi cạnh một khoảng trống bên phải. */
.cpanel-meta--single {
    grid-template-columns: 1fr;
}

/* Cột "Phản hồi" tô vàng để mắt bắt được ngay con số người dùng quan tâm
   nhất — bao lâu thì có người trả lời. */
.cpanel-meta div:last-child dd {
    color: var(--gold);
}


/* ============================================================
   C12c · ĐỊA CHỈ VÀ GỬI LỜI NHẮN
   ============================================================ */

.cplace {
    padding: clamp(44px, 5.4vw, 74px) 0 clamp(50px, 6vw, 82px);
    color: var(--white);
    background: var(--green);
}

.cplace-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 330px);
    align-items: end;
    gap: clamp(24px, 4vw, 60px);
    margin-bottom: 32px;
    padding-bottom: 20px;
    border-bottom: 1px solid rgba(255, 255, 255, .16);
}

.cplace-title {
    margin: 0;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    color: var(--white);
}

.cplace-intro {
    margin: 0;
    font-size: 12px;
    line-height: 1.7;
    color: rgba(255, 255, 255, .58);
}

/* Nhãn "Địa chỉ trung tâm" chỉ đứng trên cột trái, nhưng đỉnh thẻ bản đồ và
   đỉnh biểu mẫu vẫn phải thẳng hàng. Cách bọc mỗi cột vào một div sẽ đẩy thẻ
   bản đồ tụt xuống đúng bằng chiều cao cái nhãn. Nên tách hẳn thành hai hàng:
   hàng trên chỉ có nhãn, hàng dưới là bản đồ và biểu mẫu — hai thẻ cùng hàng
   thì tự khớp đỉnh, không phải canh tay bằng margin. */
.cplace-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
        "eyebrow ."
        "map     form";
    gap: 12px clamp(24px, 3vw, 44px);
    align-items: start;
}

.cplace-eyebrow {
    grid-area: eyebrow;
    margin: 0;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--gold);
}

/* ---------- Thẻ bản đồ ---------- */

.cmap {
    grid-area: map;
    overflow: hidden;
    background: var(--white);
    border-radius: var(--r-media);
    box-shadow: var(--shadow-card);
}

.cmap-addr {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 16px 18px;
}

.cmap-addr i {
    margin-top: 2px;
    font-size: 14px;
    color: var(--gold);
}

.cmap-street {
    margin: 0;
    font-size: var(--fs-sm);
    line-height: 1.5;
    font-weight: 700;
    color: var(--ink);
}

.cmap-note {
    margin: 4px 0 0;
    font-size: 11px;
    line-height: 1.5;
    color: var(--muted);
}

/* Khung giữ sẵn tỉ lệ để bản đồ không làm trang giật khi tải xong: chỗ trống
   đã được chừa đúng bằng chiều cao thật ngay từ lần vẽ đầu tiên. */
.cmap-frame {
    aspect-ratio: 16 / 10;
    background: #e8ece9;
}

.cmap-frame iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

.cmap-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    border-top: 1px solid rgba(18, 26, 22, .08);
}

.cmap-hours span {
    display: block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--muted);
}

.cmap-hours strong {
    display: block;
    margin-top: 4px;
    font-size: 12px;
    font-weight: 700;
    color: var(--ink);
}

.cmap-go {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    font-size: 12px;
    font-weight: 700;
    color: var(--green);
    text-decoration: none;
    background: var(--smoke);
    border-radius: 6px;
    transition:
        background-color var(--dur) var(--ease),
        color var(--dur) var(--ease);
}

.cmap-go i {
    transition: transform var(--dur) var(--ease);
}

@media (hover: hover) {
    .cmap-go:hover {
        color: var(--white);
        background: var(--green);
    }

    .cmap-go:hover i {
        transform: translateX(4px);
    }
}

/* ---------- Biểu mẫu ---------- */

.cform {
    grid-area: form;
    overflow: hidden;
    background: var(--white);
    border-radius: var(--r-media);
    box-shadow: var(--shadow-card);
}

.cform-head {
    margin: 0;
    padding: 14px 20px;
    font-size: 13px;
    font-weight: 700;
    /* letter-spacing: .05em; */
    /* text-transform: uppercase; */
    text-align: center;
    color: var(--ink);
    background: var(--gold);
}

.cform-body {
    padding: clamp(22px, 2.6vw, 32px);
}

/* Một quy tắc lo hết khoảng cách giữa các hàng, giống cách khối C10 làm. */
.cform-body>*+* {
    margin-top: clamp(18px, 2.2vw, 26px);
}

.cform-alert {
    margin: 0;
    padding: 10px 14px;
    font-size: 12px;
    font-weight: 600;
    color: var(--green);
    background: var(--green-10);
    border-radius: var(--r-row);
}

.cform-alert--error {
    color: #E11D48;
    background: rgba(225, 29, 72, .08);
}

/* Bẫy mật ong: đẩy hẳn ra ngoài màn hình thay vì display: none hay
   visibility: hidden — bot biết thừa hai cách đó là bẫy nên né, còn ô nằm ngoài
   khung nhìn thì trong DOM vẫn là một ô nhập bình thường.
   left âm không sinh thanh cuộn ngang, khác với right/width dương. */
.cform-trap,
.cta-trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.cform-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(16px, 2vw, 24px);
}

.cform-field label {
    display: block;
    margin-bottom: 8px;
    font-size: 13px;
    font-weight: 700;
    /* letter-spacing: .14em; */
    /* text-transform: uppercase; */
    color: var(--ink);
}

.cform-field label span {
    color: #E11D48;
}

/* Ô nhập chỉ có một gạch chân, đúng thiết kế. font: inherit là bắt buộc — ô
   nhập KHÔNG tự thừa hưởng font của trang, thiếu nó chữ nhảy về font mặc định
   của hệ điều hành. */
.cform-field input,
.cform-field textarea {
    display: block;
    width: 100%;
    padding: 8px 2px;
    font: var(--font);
    font-size: var(--fs-sm);
    color: var(--ink);
    background: transparent;
    border: 0;
    border-bottom: 1px solid rgba(18, 26, 22, .22);
    border-radius: 0;
    transition: border-color var(--dur) var(--ease);
}

/* Ô nội dung là khung kín chứ không phải gạch chân: đoạn văn nhiều dòng mà chỉ
   có một vạch dưới đáy thì không nhìn ra vùng gõ tới đâu. */
.cform-field textarea {
    padding: 12px 14px;
    border: 1px solid rgba(18, 26, 22, .22);
    border-radius: 6px;
    resize: vertical;
}

.cform-field input::placeholder,
.cform-field textarea::placeholder {
    color: rgba(18, 26, 22, .35);
}

.cform-field input:focus,
.cform-field textarea:focus {
    outline: none;
    border-color: var(--green);
}

/* Chỉ tô đỏ SAU KHI người dùng đã nhập rồi bỏ trống — :invalid trần sẽ bôi đỏ
   cả biểu mẫu ngay lúc trang vừa mở. */
.cform-field input:user-invalid,
.cform-field textarea:user-invalid,
.cform-field [aria-invalid="true"] {
    border-color: #E11D48;
}

.cform-error {
    margin: 6px 0 0;
    font-size: 11px;
    font-weight: 600;
    color: #E11D48;
}

.cform-submit {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-inline: auto;
    padding: 13px 34px;
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: 700;
    /* letter-spacing: var(--track); */
    color: var(--ink);
    background: var(--gold);
    border: none;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition:
        background-color var(--dur) var(--ease),
        transform var(--dur) var(--ease),
        box-shadow var(--dur) var(--ease);
}

.cform-submit i {
    transition: transform var(--dur) var(--ease);
}

.cform-submit:active {
    transform: translateY(1px);
}

@media (hover: hover) {
    .cform-submit:hover {
        background: #F4B327;
        transform: translateY(var(--lift));
        box-shadow: 0 10px 24px rgba(18, 26, 22, .18);
    }

    .cform-submit:hover i {
        transform: translateX(3px);
    }
}


/* ============================================================
   C12d · CÁC NGƯỠNG MÀN HÌNH
   ============================================================ */

/* 1080px: thẻ chi tiết kênh hết chỗ đứng cạnh danh sách. Cho nó xuống dưới và
   bỏ sticky — dính vào đỉnh màn hình khi đã nằm dưới danh sách thì nó che mất
   chính danh sách đó. */
@media (max-width: 1080px) {

    .cinfo-grid {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "lead"
            "list"
            "panel";
    }

    /* Một cột thì ba khối xếp dọc theo đúng thứ tự trong HTML. */
    .cplace-grid {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "eyebrow"
            "map"
            "form";
        row-gap: clamp(20px, 3vw, 32px);
    }

    .cplace-eyebrow {
        margin-bottom: -12px;
    }

    .cinfo-panels {
        position: static;
    }

    .cpanel-value {
        font-size: 24px;
        line-height: 32px;
    }
}

/* 860px: hai cột chữ của hero và của khối địa chỉ gộp làm một. Đĩa tròn thu
   nhỏ lại vì lúc này nó chiếm gần hết bề ngang hero. */
@media (max-width: 860px) {

    .cplace-head {
        grid-template-columns: minmax(0, 1fr);
        align-items: start;
    }

    /* Một cột thì ba khối xếp dọc theo thứ tự trong HTML. */
    .chero-grid {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "crumb"
            "title"
            "lead";
    }

    /* Tam giác vẫn ngồi ở góc dưới phải, mà hero còn một cột thì dòng chữ dẫn
       chạy thẳng tới sát nó. Chừa sẵn khoảng trống bằng bề ngang tam giác cộng
       lề của nó, thay vì thu hẹp cả đoạn văn. */
    .chero-lead {
        margin-top: 4px;
        padding-right: clamp(52px, 9vw, 96px);
    }

    /* Hai cột hero gộp làm một thì đoạn chữ dẫn tụt xuống đúng chỗ lưới chấm
       đang nằm, chữ chồng lên chấm. Bỏ chấm đi thay vì đẩy chữ lên: hero này
       vốn đã thấp, nới thêm đệm đáy chỉ để chừa chỗ cho một mảng trang trí là
       không đáng. */
    .chero-dots {
        display: none;
    }

    .cinfo-lead {
        max-width: none;
    }
}

/* 600px: điện thoại. */
@media (max-width: 600px) {

    /* Tam giác nằm ngay cạnh chữ chứ không còn là mảnh trang trí ở rìa nữa.
       Bỏ nó đi thì đoạn chữ dẫn lấy lại được khoảng chừa ở trên. */
    .chero-tri {
        display: none;
    }

    .chero-lead {
        padding-right: 0;
    }

    .cchan {
        padding: 16px 18px;
    }

    .cchan-value {
        font-size: 16px;
        line-height: 22px;
    }

    .cpanel-actions .cpanel-btn {
        flex: 1;
        justify-content: center;
    }

    .cpanel-meta,
    .cform-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .cform-submit {
        width: 100%;
    }
}

/* Ngón tay cần vùng chạm tối thiểu 44px (hướng dẫn của cả Apple lẫn Google).
   Ô nhập gạch chân cao theo cỡ chữ nên hụt khá nhiều so với mốc đó. */
@media (pointer: coarse) {

    .cform-field input {
        min-height: 46px;
    }

    .cform-submit {
        min-height: 52px;
    }
}

@media (prefers-reduced-motion: reduce) {

    .cchan,
    .cpanel-btn,
    .cmap-go,
    .cform-submit {
        transition: none;
    }

    .cchan:hover,
    .cpanel-btn:hover,
    .cform-submit:hover,
    .cform-submit:active {
        transform: none;
    }
}

/* #endregion */


/* =====================================================================
   #region C13 · TRANG TIN TỨC — /tin-tuc và /tin-tuc/{slug}

   Gộp về đây từ file news.css cũ. File ấy tự khai một bộ token song song
   (--cep-news-green #176348, --cep-fs-sm 12px, container 1180px) trong khi
   app.css đã sẵn bộ chuẩn đúng Figma (--green #1B5E3F, --fs-sm 13px,
   --container 1200px). Hai bộ cùng mô tả một hệ thiết kế thì sớm muộn cũng
   trôi khỏi nhau, và nó đã trôi thật: chữ trang Tin tức nhỏ hơn thiết kế cả
   một bậc rưỡi. Đừng khai token riêng cho trang nào nữa.
   ===================================================================== */


@keyframes cepFloatIn {
    from {
        opacity: 0;
        transform: translateY(15px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}


/* ============================================================
   C13a · HERO — banner thấp
   ============================================================ */

/* KHÔNG có class hero riêng cho trang này. Bản xuất Figma trang Tin tức cho
   ra ĐÚNG banner của trang Liên hệ: cao 322px, cùng đường tròn (tâm x=1362.5,
   y=195, đường kính 458 trong khổ 1440), cùng tam giác viền #F2921D dày 3.
   Nên hero ở đây dùng thẳng .chero của khối C12a — chép giá trị ra một bộ
   .news-hero__* riêng thì đúng vết xe mà news.css vừa gây ra.

   Bố cục căn giữa MỘT cột giống trang Liên hệ (.chero--contact): nội dung
   cân đối, không còn khoảng trống thừa do cột phải lệch. Lưới chấm vẫn giữ
   kích thước riêng theo Figma. */

/* ---------- Biến thể CĂN GIỮA cho hero Tin tức ---------- */

/* Trước đây dùng bố cục hai cột (tiêu đề trái, đoạn dẫn ghim góc trên-phải)
   giống bản gốc .chero-grid. Khi tiêu đề ngắn, cột trái để trống một mảng xanh
   lớn, nhìn lệch hẳn sang trái. Chuyển sang MỘT cột căn giữa giống trang Liên
   hệ (.chero--contact) để nội dung cân đối, không thừa khoảng trống. */
.chero--news {
    /* Cùng công thức với .chero--contact (khối C12a) — hai trang chung một
       kiểu bố cục căn giữa nên đệm trên/dưới phải đọc cao bằng nhau, kể cả
       min-height (xem ghi chú tại .chero--contact vì sao phải đè lại). */
    min-height: 172px;
    padding: clamp(12px, 1.4vw, 18px) 0;
}

.chero--news .chero-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
        "crumb"
        "title"
        "lead";
    /* Cùng lý do với .chero--contact ở C12a: gộp row-gap + margin-top của
       .chero-lead (14 + 8 = 22px) về một nguồn duy nhất, 6px. */
    row-gap: 6px;
    max-width: 640px;
    margin: 0 auto;
    text-align: center;
}

.chero--news .chero-crumb {
    justify-content: center;
}

.chero--news .chero-lead {
    max-width: 520px;
    margin: 0 auto;
    padding-right: 0;
}

/* Lưới chấm: giữ kích thước 93x80 và cỡ chấm của Figma, chỉ lùi ra mép trái. */
.chero--news .chero-dots {
    left: clamp(14px, 2.8vw, 40px);
    width: 93px;
    height: 80px;
    background-size: 11.6px 11.6px;
}


/* ============================================================
   C13c · THANH LỌC CHUYÊN MỤC
   ============================================================ */

.news-list-section {
    padding: clamp(38px, 4.4vw, 62px) 0 clamp(48px, 5.6vw, 80px);
}

.news-toolbar {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 20px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--ink-50);
}

.news-toolbar__caption {
    display: block;
    margin-bottom: 5px;
    color: var(--ink-50);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
}

.news-toolbar__count {
    color: rgba(18, 26, 22, .7);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    white-space: nowrap;
}

/* Chỉ là nhãn, không phải nút bấm: việc chọn chuyên mục đã chuyển hẳn lên menu
   đổ xuống của mục "Thông tin tuyển sinh" trên thanh điều hướng. Để hai chỗ
   cùng lọc được thì người đọc phải đoán xem chỗ nào mới là chỗ chính. */
.news-toolbar__current {
    display: block;
    color: var(--ink);
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
}


/* ============================================================
   C13d · DANH SÁCH TIN

   Tên khối là .news-row chứ KHÔNG phải .news-item — đừng đổi lại. Dải tin ở
   trang chủ (khối C4) đã chiếm tên .news-item từ trước. Hồi news.css còn là
   file riêng thì hai bên không gặp nhau vì file ấy chỉ nạp ở /tin-tuc; gộp
   vào app.css xong là app.css nạp mọi trang, khối này thắng vì nằm sau, và
   dải tin trang chủ lĩnh nguyên min-height 183px lẫn đường kẻ chân.
   ============================================================ */

/* Figma dựng mỗi dòng là [số + nội dung] — khe co giãn — [ảnh 292], chứ không
   phải ba cột đều nhau: khối chữ rộng tối đa 762 rồi dừng, phần thừa dồn hết
   vào khe giữa. Nên dùng flex + space-between, không dùng grid ba cột. */
.news-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: clamp(20px, 3vw, 40px);
    min-height: 183px;
    padding: 15px 0;
    border-bottom: 1px solid rgba(18, 26, 22, .3);
    animation: cepFloatIn .6s var(--ease) both;
}

.news-row__main {
    display: flex;
    align-items: flex-start;
    gap: 20px;
    min-width: 0;
    max-width: 762px;
}

.news-row__number {
    flex: none;
    width: 32px;
    color: var(--gold);
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 800;
    letter-spacing: .05em;
}

.news-row__content {
    min-width: 0;
}

.news-row .news-meta {
    margin-bottom: 10px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
}

.news-row__title {
    margin: 0 0 10px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
}

.news-row__title a {
    color: var(--ink);
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.news-row__title a:hover {
    color: var(--green);
}

.news-row__excerpt {
    display: -webkit-box;
    margin: 0;
    overflow: hidden;
    color: rgba(18, 26, 22, .7);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

.news-row__thumbnail {
    flex: none;
    display: block;
    width: clamp(190px, 21vw, 292px);
    height: clamp(100px, 11vw, 153px);
    overflow: hidden;
    background: var(--smoke);
    border-radius: var(--r-media);
}

.news-row__thumbnail img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--dur) var(--ease);
}

.news-row:hover .news-row__thumbnail img {
    transform: scale(1.035);
}


/* ============================================================
   C13e · PHÂN TRANG — dùng lại .pager của khối C5b

   KHÔNG khai dải nút riêng cho trang này. Trang Tin tức dùng thẳng
   `.pager .pager--light`, cùng thành phần với danh sách khóa học, danh
   sách giáo viên và bảng điểm, nên khối này không còn quy tắc nào.

   Bản cũ (.news-pagination) gần trùng .pager nhưng lệch ở mọi số đo:
   nút 40px thay vì 36px, khe 15px thay vì 10px, ô số nền đặc không viền
   còn hai mũi tên lại có viền. Đây là mảnh cuối cùng của file news.css cũ
   được gộp về — xem ghi chú mở đầu khối C13 để biết vì sao không khai
   riêng cho từng trang nữa.
   Cần đổi dáng phân trang thì sửa .pager ở C5b để mọi trang đổi theo.
   ============================================================ */


/* ============================================================
   C13f · KHÔNG CÓ BÀI VIẾT
   ============================================================ */

.news-empty {
    padding: 70px 20px;
    color: var(--muted);
    text-align: center;
}

.news-empty i {
    font-size: 32px;
    color: var(--green-30);
}

.news-empty h2 {
    margin: 14px 0 6px;
    color: var(--ink);
    font-size: var(--fs-md);
    line-height: var(--lh-md);
}

.news-empty p {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
}


/* ============================================================
   C13g · TRANG CHI TIẾT BÀI VIẾT — /tin-tuc/{slug}
   ============================================================ */


/* ---------- Banner ---------- */

/* Cao 300 thay vì 200 của trang danh sách: Figma xếp thêm đoạn tóm tắt, một
   đường kẻ và dòng tác giả xuống dưới tiêu đề. Vẫn là banner xanh ấy, cùng
   khối tròn và tam giác, chỉ khác chiều cao và số dòng chữ. Bản gốc 433px cùng
   lý do như .chero — bài tiêu đề ngắn, một dòng thì đáy hero trống hẳn ra. */
.article-hero {
    position: relative;
    min-height: 300px;
    padding: clamp(32px, 3.6vw, 52px) 0 clamp(28px, 2.4vw, 34px);
    overflow: hidden;
    color: var(--smoke);
    background: var(--green);
}

.article-hero>.container {
    position: relative;
    z-index: 2;
}

/* Dùng lại đúng hai file SVG của hero trang Liên hệ và Tin tức. Figma xoay
   khối tròn -65deg, nhưng xoay một đường tròn thì hình không đổi — chỉ hướng
   dải màu chuyển, mắt không phân biệt được — nên chỉ xoay tam giác. */
.article-hero__art {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 0;
    width: auto;
    height: 100%;
    max-width: none;
    pointer-events: none;
}

.article-hero__tri {
    position: absolute;
    right: clamp(18px, 3.4vw, 49px);
    top: 58%;
    z-index: 1;
    width: clamp(40px, 4.4vw, 63px);
    height: auto;
    transform: rotate(-74deg);
    pointer-events: none;
}

.article-breadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
    color: var(--smoke);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
}

.article-breadcrumb a {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.article-breadcrumb a:hover {
    color: var(--white);
}

/* Class chứ không phải [aria-current]: mục cuối của đường dẫn là chuyên mục,
   mà chuyên mục là một trang KHÁC — đánh dấu aria-current ở đó là nói dối
   trình đọc màn hình chỉ để lấy màu vàng.

   Phải viết lồng hai class (0-2-0) chứ không dùng class đơn: rule
   `.article-breadcrumb a` ở trên là 0-1-1, class đơn 0-1-0 thua nó, màu vàng
   sẽ bị `color: inherit` nuốt mất. */
.article-breadcrumb .article-breadcrumb__last {
    color: var(--gold);
    font-weight: 600;
}

/* Figma cho tiêu đề khung 1079 chứ không trọn 1200: chừa góc phải cho khối
   tròn, kẻo dòng chữ chạy đè lên chỗ đường cong sáng nhất. */
/* Cỡ chữ vẫn là --fs-xl dùng chung của hero mọi trang. Riêng GIÃN DÒNG lấy
   theo Figma trang này (59px) chứ không lấy --lh-xl (68px): tiêu đề trang thì
   luôn gọn một dòng nên giãn dòng không bao giờ lộ ra, còn tiêu đề bài viết
   thường xuống hai ba dòng — để 68px là các dòng rời rạc hẳn nhau. */
.article-hero__title {
    max-width: 1079px;
    margin: 0;
    color: var(--smoke);
    font-size: var(--fs-xl);
    /* 59/48 = 1.23 — vẫn đúng số Figma ở 1920, nhưng viết theo hệ số để khi
       --fs-xl co lại ở laptop thì giãn dòng co theo, không bị hở toác. */
    line-height: 1.23;
    font-weight: 700;
    letter-spacing: -.5px;
}

.article-hero__excerpt {
    max-width: 718px;
    margin: 18px 0 0;
    color: rgba(244, 247, 245, .7);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
}

/* Đường kẻ ngang trong Figma là một Line riêng; ở đây làm bằng border-top của
   chính dòng tác giả — bớt một thẻ rỗng mà nhìn không khác. */
/* KHÔNG cho xuống hàng (flex-wrap mặc định là nowrap, giữ nguyên).
   Vạch dọc ngăn tên với ngày là border-left của chính thẻ <time>; hễ <time>
   bị đẩy xuống hàng mới là vạch ấy đứng chơ vơ ở đầu dòng, trông như lỗi hiển
   thị. Từng vá bằng cách xóa vạch ở ngưỡng 480px, nhưng đo lại thì chỗ xuống
   hàng phụ thuộc ĐỘ DÀI TÊN TÁC GIẢ chứ không phải bề ngang màn hình — tên dài
   là nó xuống hàng ngay ở 481px, tên ngắn thì tới 320px vẫn không.
   Cấm xuống hàng rồi cho khối tên co lại là hết hẳn lớp lỗi này. */
.article-author {
    display: flex;
    align-items: center;
    gap: 15px;
    max-width: 1079px;
    margin-top: clamp(20px, 2.3vw, 33px);
    padding-top: clamp(12px, 1.1vw, 16px);
    border-top: 1px solid rgba(255, 255, 255, .5);
}

/* min-width: 0 để khối tên chịu co lại — thiếu nó thì phần tử flex không bao
   giờ hẹp hơn nội dung, và tên dài sẽ đẩy ngày văng khỏi màn hình. */
.article-author__who {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.article-author time {
    flex: none;
}

.article-author__avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 34px;
    height: 34px;
    color: var(--smoke);
    background: rgba(255, 255, 255, .17);
    border-radius: 50%;
    font-size: var(--fs-sm);
}

.article-author strong {
    display: block;
    color: var(--smoke);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
}

.article-author__role {
    display: block;
    margin-top: 3px;
    color: rgba(244, 247, 245, .7);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
}

/* Vạch dọc ngăn tên tác giả với ngày đăng. align-self: stretch để vạch cao
   bằng cả khối tên hai dòng, không chỉ cao bằng một dòng ngày. */
.article-author time {
    display: flex;
    align-items: center;
    align-self: stretch;
    padding-left: 15px;
    color: rgba(244, 247, 245, .7);
    border-left: 1px solid rgba(255, 255, 255, .7);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
}


/* ---------- Khung hai cột ---------- */

.article-main {
    padding: clamp(32px, 3.3vw, 47px) 0 clamp(48px, 5vw, 72px);
    background: var(--white);
}

/* Figma khổ 1200: cột bài 722, khe 42, cột phụ 432.
   Cột phụ CO theo bề ngang chứ không ghim cứng 432: ghim cứng thì ở quãng
   1000-1100px nó vẫn chiếm hơn 40% màn hình, cột bài teo còn hơn 500px trong
   khi đây mới là phần người ta vào để đọc. clamp chạm trần đúng 432 từ 1440.

   TRẦN 860px CHO CỘT BÀI, thêm ngày 2026-09-17 cùng lúc với việc nới khung
   lên 1600px: để 1fr thì ở màn 1920 cột bài rộng tới ~1130px, mỗi dòng hơn
   140 ký tự — quá dài, mắt đọc xong một dòng là lạc chỗ xuống dòng sau
   (vùng dễ đọc là 45–90 ký tự). 860px là đúng con số .legal-body đang dùng
   cho văn bản dài của trang Điều khoản, giữ hai nơi cùng một khổ đọc.

   space-between đẩy phần dôi ra vào KHE GIỮA hai cột thay vì bỏ trống bên
   phải: cột bài vẫn bám mép trái khung, cột phụ vẫn bám mép phải, nhìn ra
   bố cục hai cột có chủ đích chứ không phải khối bị lệch. */
.article-grid {
    display: grid;
    grid-template-columns: minmax(0, 860px) clamp(300px, 30vw, 432px);
    justify-content: space-between;
    align-items: start;
    gap: clamp(28px, 2.9vw, 42px);
}

.article-content {
    min-width: 0;
}


/* ---------- Chữ trong bài ---------- */

/* Nhịp dòng 25px và giãn chữ .03em là con số Figma dùng cho MỌI đoạn văn của
   bài, khác hẳn nhịp 20px của phần còn lại trong site — bài đọc dài cần thoáng
   hơn. Khai ở đây một lần rồi các thẻ con thừa hưởng. */
.article-prose {
    color: var(--ink);
    font-size: var(--fs-base);
    line-height: 25px;
    letter-spacing: .03em;

    /* Căn đều hai lề — chữ chạm cả mép trái lẫn mép phải trên mọi dòng, khác
       với mặc định lệch trái làm mép phải răng cưa như ảnh khách gửi. */
    text-align: justify;
}

.article-prose p {
    margin: 0 0 18px;

    /* Chặn "chữ mồ côi": dòng cuối một đoạn văn justify không bị kéo giãn
       (đó là quy tắc của chính text-align: justify), nhưng nó vẫn có thể chỉ
       còn ĐÚNG MỘT CHỮ trơ trọi nếu chữ trước đó vừa khít hết dòng áp chót.
       text-wrap: pretty là thuộc tính trình duyệt tự cân dòng để tránh đúng
       tình huống ấy, không cần đo chữ bằng tay hay chèn &nbsp; thủ công vào
       nội dung CKEditor.

       Trình duyệt CHƯA HỖ TRỢ (Safari, Firefox cũ) thì thuộc tính này bị bỏ
       qua lặng lẽ — đoạn văn vẫn justify bình thường, chỉ là thỉnh thoảng còn
       một chữ mồ côi như trước, không có gì hỏng. */
    text-wrap: pretty;
}

/* Chữ cái mở bài: Montserrat NGHIÊNG đậm 48px màu xanh, thả chìm hai dòng. */
.article-prose>p:first-child::first-letter {
    float: left;
    margin: 0 10px 0 0;
    color: var(--green);
    font-size: 48px;
    line-height: 44px;
    font-style: italic;
    font-weight: 700;
}

.article-prose h2 {
    margin: 33px 0 18px;
    color: var(--ink);
    font-size: var(--fs-md);
    line-height: 25px;
    font-weight: 800;
    letter-spacing: .03em;
}

.article-prose h3 {
    margin: 26px 0 14px;
    color: var(--ink);
    font-size: var(--fs-base);
    line-height: 25px;
    font-weight: 800;
    letter-spacing: .03em;
}

.article-prose h4 {
    margin: 22px 0 12px;
    color: var(--ink);
    font-size: var(--fs-base);
    line-height: 25px;
    font-weight: 700;
}

/* Figma vẽ đầu dòng là một chấm vàng 8.8px cách chữ 15px, không phải marker
   mặc định của trình duyệt — nên bỏ list-style và tự vẽ bằng ::before. */
.article-prose ul {
    margin: 0 0 18px;
    padding: 0;
    list-style: none;
}

.article-prose ul li {
    position: relative;
    margin-bottom: 10px;
    padding-left: 24px;
}

.article-prose ul li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 8px;
    width: 9px;
    height: 9px;
    background: var(--gold);
    border-radius: 50%;
}

/* Danh sách đánh số vẫn giữ marker thật để giữ đúng thứ tự khi đọc bằng
   trình đọc màn hình; chỉ đổi màu số cho khớp bảng màu. */
.article-prose ol {
    margin: 0 0 18px;
    padding-left: 22px;
}

.article-prose ol li {
    margin-bottom: 10px;
}

.article-prose ol li::marker {
    color: var(--gold);
    font-weight: 700;
}

.article-prose strong {
    color: var(--ink);
    font-weight: 700;
}

.article-prose a {
    color: var(--green);
    font-weight: 600;
}

.article-prose figure {
    margin: 33px 0;
}

.article-prose img {
    display: block;
    max-width: 100%;
    height: auto;
    margin-inline: auto;
    border-radius: var(--r-box);
}

.article-prose figcaption {
    margin-top: 14px;
    color: var(--ink);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-style: italic;
    letter-spacing: normal;
    text-align: center;
}

/* Ô trích dẫn: nền xanh nhạt bo 15, dấu nháy vàng đứng riêng một dòng phía
   trên chứ không nằm thụt vào lề trái như kiểu blockquote thường thấy. */
.article-prose blockquote {
    /* --quote-mark nay khai ở :root (đầu file) vì thẻ cảm nhận ở #region C22
       dùng chung đúng hình ấy. Lý do vì sao là hình vector chứ không phải ký
       tự nháy của font cũng ghi ở đó. */
    margin: 33px 0;
    padding: 15px 20px;
    color: var(--green);
    background: var(--green-10);
    border: 0;
    border-radius: var(--r-box);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-style: italic;
    font-weight: 500;
    letter-spacing: normal;
}

/* Dấu nháy: Figma vẽ MỘT hình vector 28x20 màu vàng.
   Bản trước dùng content: "\201C\201D" — hai ký tự nháy kép, mà mỗi ký tự đã
   là hai nét, nên màn hình hiện ra bốn nét chứ không phải một dấu nháy.
   Nay vẽ thẳng bằng SVG nhúng: đúng khổ 28x20 của Figma, không phụ thuộc font
   nào tải kịp hay không, và màu lấy qua mask nên vẫn là --gold chứ không phải
   một mã màu chép cứng vào chuỗi data URI. */
.article-prose blockquote::before {
    content: "";
    display: block;
    width: 28px;
    height: 20px;
    margin-bottom: 15px;
    background-color: var(--gold);
    -webkit-mask-image: var(--quote-mark);
    mask-image: var(--quote-mark);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: left center;
    mask-position: left center;
}

.article-prose blockquote p {
    margin: 0 0 10px;
}

.article-prose blockquote p:last-child {
    margin-bottom: 0;
}

/* Dòng cuối của ô trích là tên người nói — mờ hơn câu trích. Chặn :only-child
   để ô chỉ có ĐÚNG một đoạn thì đoạn ấy vẫn là câu trích, không bị làm mờ. */
.article-prose blockquote p:not(:only-child):last-child {
    color: rgba(18, 26, 22, .7);
}

.article-prose table {
    width: 100%;
    margin: 24px 0;
    border-collapse: collapse;
}

.article-prose td,
.article-prose th {
    padding: 10px 12px;
    border: 1px solid rgba(18, 26, 22, .2);
}


/* ---------- Hàng thẻ và chia sẻ ---------- */

.article-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    margin-top: 33px;
    padding-top: 33px;
    border-top: 1px solid var(--ink);
}

.article-tags {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
}

.article-tags a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 156px;
    padding: 5px 18px;
    color: var(--green);
    background: var(--green-10);
    border-radius: var(--r-pill);
    font-size: var(--fs-base);
    line-height: 25px;
    font-weight: 700;
    letter-spacing: .03em;
    text-decoration: none;
    transition:
        background var(--dur) var(--ease),
        color var(--dur) var(--ease);
}

.article-tags a:hover {
    color: var(--smoke);
    background: var(--green);
}

.article-share {
    position: relative;
    display: flex;
    align-items: center;
    gap: 21px;
    color: var(--ink-50);
    font-size: var(--fs-base);
    line-height: 25px;
    font-weight: 700;
    letter-spacing: .03em;
}

/* Lời báo sau khi bấm sao chép. Nổi LÊN TRÊN nút chứ không chen vào hàng:
   chen vào thì cả hàng thẻ bên trái nhảy chỗ mỗi lần bấm. Luôn có mặt trong
   DOM (role="status") để trình đọc màn hình đọc được, chỉ mờ đi khi rảnh. */
.article-share__toast {
    position: absolute;
    right: 0;
    bottom: calc(100% + 10px);
    padding: 5px 11px;
    color: var(--smoke);
    background: var(--green);
    border-radius: var(--r-row);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    letter-spacing: normal;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur) var(--ease);
}

.article-share__toast.is-on {
    opacity: 1;
}

/* Vàng khi phải nhờ người dùng chép tay — khác hẳn màu xanh báo đã xong, để
   không ai tưởng là chép được rồi. */
.article-share__toast.is-warn {
    color: var(--green);
    background: var(--gold);
}

/* Đường lui cuối cùng: chiếm trọn một hàng riêng dưới hàng thẻ và chia sẻ. */
.article-share__manual {
    flex: 0 0 100%;
    margin-top: 4px;
}

.article-share__manual-label {
    display: block;
    margin-bottom: 6px;
    color: var(--ink-50);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    letter-spacing: normal;
}

.article-share__manual input {
    width: 100%;
    padding: 9px 13px;
    color: var(--ink);
    background: var(--white);
    border: 1px solid rgba(18, 26, 22, .3);
    border-radius: var(--r-row);
    font-family: inherit;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 400;
    letter-spacing: normal;
}

.article-share__buttons {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Figma cho hai nút hình chữ nhật bo 5, KHÔNG phải nút tròn như các khối
   khác trong site — giữ đúng vậy. */
.article-share a,
.article-share button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 35px;
    height: 31px;
    padding: 0;
    color: var(--green);
    cursor: pointer;
    background: var(--green-10);
    border: 0;
    border-radius: var(--r-row);
    font-size: var(--fs-base);
    text-decoration: none;
    transition:
        background var(--dur) var(--ease),
        color var(--dur) var(--ease);
}

.article-share a:hover,
.article-share button:hover,
.article-share button.is-copied {
    color: var(--smoke);
    background: var(--green);
}


/* ---------- Cột bài viết liên quan ---------- */

.article-related {
    min-width: 0;
}

/* Lại là border-bottom của chính tiêu đề thay cho một thẻ Line riêng. */
.article-related>h2 {
    margin: 0 0 11px;
    padding-bottom: 11px;
    color: var(--ink);
    font-size: var(--fs-sm);
    line-height: 25px;
    font-weight: 700;
    letter-spacing: .03em;
    border-bottom: 1px solid var(--ink);
}

.article-related-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid rgba(18, 26, 22, .3);
}

.article-related-item__number {
    flex: none;
    width: 32px;
    color: var(--gold);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 800;
    letter-spacing: .05em;
    text-align: center;
}

.article-related-item>div {
    min-width: 0;
}

/* Khác trang danh sách: ở cột phụ này Figma xếp TIÊU ĐỀ lên trước, dòng
   chuyên mục và ngày mới nằm dưới. */
.article-related-item h3 {
    margin: 0 0 4px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
}

.article-related-item h3 a {
    color: var(--ink);
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.article-related-item h3 a:hover {
    color: var(--green);
}

.article-related-item__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    color: var(--green);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
}

.article-related__empty {
    margin: 0;
    padding: 14px 0;
    color: var(--muted);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
}

.article-related__more {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 21px;
    color: var(--green);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 800;
    letter-spacing: .05em;
    text-decoration: none;
    transition: transform var(--dur) var(--ease);
}

.article-related__more:hover {
    transform: translateX(3px);
}


/* ============================================================
   C13h · RESPONSIVE

   Hero trang DANH SÁCH không có mặt ở đây: nó dùng .chero nên đã theo sẵn các
   ngưỡng 860px và 600px khai trong khối C12. Sửa nó thì sửa ở đó.
   ============================================================ */

@media (max-width: 767px) {

    /* ---------- Danh sách tin ---------- */

    /* Ảnh xuống dòng dưới chữ, nhưng thụt vào đúng 52px (bề ngang số thứ tự
       cộng khe 20) để mép trái ảnh thẳng hàng với mép trái tiêu đề. */
    .news-row {
        flex-direction: column;
        align-items: stretch;
        gap: 14px;
        min-height: 0;
        padding: 20px 0;
    }

    .news-row__main {
        max-width: none;
    }

    .news-row__thumbnail {
        width: auto;
        height: auto;
        margin-left: 52px;
        aspect-ratio: 16 / 8;
    }

    /* ---------- Trang chi tiết ---------- */

    .article-hero {
        min-height: 0;
    }

    /* Ngoại lệ DUY NHẤT với luật "hero mọi trang cùng cỡ chữ": tiêu đề bài
       viết dài hơn hẳn tiêu đề trang, để nguyên 48px trên màn điện thoại thì
       một cái tựa bình thường đã chiếm bảy dòng. Chỉ hạ ở ngưỡng này. */
    .article-hero__title {
        font-size: clamp(26px, 6.2vw, 40px);
        line-height: 1.24;
    }

    .article-grid {
        display: block;
    }

    .article-related {
        margin-top: 42px;
        padding-top: 25px;
        border-top: 1px solid rgba(18, 26, 22, .15);
    }

    .article-bottom {
        align-items: flex-start;
        flex-direction: column;
    }

}


@media (max-width: 480px) {

    .news-toolbar__count {
        display: none;
    }

    /* Số thứ tự bỏ đi ở màn hẹp nhất: nó chỉ là mốc đọc cho mắt, mà giữ lại
       thì tiêu đề chỉ còn chưa tới hai phần ba bề ngang. */
    .news-row__number {
        display: none;
    }

    .news-row__thumbnail {
        margin-left: 0;
    }

    .article-prose>p:first-child::first-letter {
        font-size: 38px;
        line-height: 34px;
    }

    .article-tags a {
        min-width: 0;
    }

}

/* #endregion */


/* =====================================================================
   #region C14 · TRANG TRA CỨU ĐIỂM THI — /tra-cuu-diem

   Bốn khối: hero (biến thể của C2), ba thẻ thủ khoa, thanh tra cứu + bảng
   điểm, và thanh phân trang.

   Không khai token riêng cho trang này: màu, cỡ chữ, bo góc, đổ bóng đều lấy
   từ bộ biến ở đầu file. Xem ghi chú mở đầu khối C13 để biết vì sao.
   ===================================================================== */


/* ============================================================
   C14a · HERO — biến thể của C2

   CHỮ, NÚT, MÀU và luật cao-100vh KHÔNG khai lại ở đây; hero mọi trang phải
   đọc lên như một. Khối này chỉ lo phần thật sự khác: hình LỤC GIÁC thay cho
   vòng tròn, vạch xanh dưới chân ảnh và bốn mảnh tam giác.

   Mọi selector ở đây có hai class (0-2-0) nên thắng bản gốc (0-1-0) kể cả
   trong @media — media query không cộng thêm độ đặc hiệu. Hệ quả: thuộc tính
   nào đã đè ở đây mà cần đổi theo bề ngang màn hình thì phải khai lại trong
   các @media của CHÍNH khối này.
   ============================================================ */

/* Thiết kế chừa một khoảng dưới chân ảnh cho vạch xanh thở. Đặt đệm lên .hero
   chứ không lên .hero-visual: đệm trên khung ảnh làm mọi mốc % của các phần tử
   absolute bên trong lệch theo. */
.hero--score {
    padding-bottom: 40px;
}

.hero--score .hero-grid {
    align-items: end;
}

/* Cùng lý do và cùng con số với .hero--award .hero-visual ở khối C7a: ảnh bị
   trần chiều cao kẹp nên không nở theo cột, còn lục giác (left 50%), vạch
   xanh (left 24%) và bốn mảnh tam giác đều bám % cột — cột rộng ra thì cụm
   trôi phải. Đo ở 1440x900: tâm cụm lệch phải 43px trên cột 681px; ở 1280
   lệch 38px — vẫn quanh 6%. */
@media (min-width: 1081px) {
    .hero--score .hero-visual {
        transform: translateX(-6%);
    }
}

/* Ảnh nhô ra hai bên khung lục giác đúng như bản xuất (ảnh rộng 533 so với
   lục giác 473). */
/* Kẹp theo chiều cao còn lại giống C2; tỉ lệ ảnh trang này là 1067/948 ≈ 1.1255. */
/* Cùng cách làm với .hero--award: quy bề ngang ảnh về một biến để lục giác
   và vạch xanh bám theo ẢNH chứ không theo cột. */
.hero--score .hero-visual {
    --photo-w: min(104%, calc((100vh - var(--header-h) + var(--nav-overlap) - 120px) * 1.1255));
}

.hero--score .hero-photo {
    width: var(--photo-w);
    margin-left: -2%;
}

/* Lục giác: tâm trùng tâm ảnh, đường kính bằng 89% bề ngang ảnh. Giữ nguyên
   tên .hero-ring vì app.js nhận diện phần tử parallax bằng class này. */
/* left theo TÂM ẢNH, không theo tâm cột. Mốc 50% cũ chỉ đúng khi vế 104%
   quyết định bề ngang ảnh (ảnh 104% lệch trái 2% thì tâm ảnh rơi đúng 50%
   cột). Khi màn thấp, vế trần chiều cao nhỏ hơn và quyết định thay: ảnh hẹp
   lại nhưng vẫn dính mốc -2% nên tâm ảnh tụt sang trái, còn lục giác đứng
   yên ở 50% — đo ở 1600x740 thấy người lệch hẳn về nửa trái lục giác. */
.hero--score .hero-ring {
    top: 47%;
    left: calc(-2% + var(--photo-w) / 2);
    width: 89%;
    max-width: 520px;
}

/* Nhịp thở của lục giác: PHÓNG TO — THU NHỎ, không xoay.

   Bản gốc `heroRingPulse` ở khối C2 vừa xoay ±5deg vừa đổi cỡ. Cách đó hợp với
   vòng TRÒN của trang chủ vì hình tròn xoay thì mắt không nhận ra, chỉ thấy nó
   thở. Lục giác có sáu cạnh nên xoay là thấy ngay nó lắc qua lắc lại.

   Biên độ cũng rộng hơn bản gốc (1 → 1.09 thay vì 0.98 → 1.03) để chuyển động
   đọc ra là "to lên" chứ không phải một rung động mơ hồ. Ở cỡ lớn nhất lục
   giác chiếm 97% bề ngang cột ảnh, vẫn nằm gọn trong khung nên không bị
   overflow:hidden của .hero cắt mất góc.

   Mọi khung hình PHẢI gói var(--scroll-transform): app.js ghi biến ấy khi cuộn
   trang, khung nào quên là mất luôn parallax ở đúng khung đó. */
@keyframes cepHexBreathe {
    from {
        transform: var(--scroll-transform, translate(-50%, -50%)) scale(1);
    }

    to {
        transform: var(--scroll-transform, translate(-50%, -50%)) scale(1.09);
    }
}

/* Cùng độ đặc hiệu (0-1-0) với .hero-ring gốc nên thắng được là nhờ đứng SAU
   trong file — khối C14 nằm cuối app.css. Đừng dời khối này lên trên.
   Luật @media (prefers-reduced-motion) ở C2 bắt theo .hero-ring, mà phần tử
   này mang cả hai class, nên vẫn tự tắt khi người dùng yêu cầu giảm chuyển động. */
.hero-ring--score {
    animation: cepHexBreathe 7s ease-in-out infinite alternate;
}

/* Vạch xanh nằm ngay dưới chân ảnh, không luồn ra sau. Tâm bám ảnh cùng lý
   do với .hero--score .hero-ring: mốc cũ 24% + 55%/2 = 51,5% cột, trùng tâm
   ảnh 50% ở khổ gốc, nhưng trôi khỏi chân ảnh khi trần chiều cao ăn. */
.score-line {
    position: absolute;
    z-index: 2;
    left: calc(-2% + var(--photo-w) / 2);
    bottom: 0%;
    width: 55%;
    transform: translateX(-50%);
    pointer-events: none;
}

/* Bốn mảnh tam giác. PHẢI trả các cạnh không dùng về auto: bản gốc ở C2 ghim
   bottom/right cho .deco-tgd và .deco-tgv, ghim cả bốn cạnh thì ảnh bị kéo
   giãn cho vừa khung và tam giác méo. */
.hero--score .deco-tgd {
    top: 8%;
    left: 6%;
    right: auto;
    bottom: auto;
    width: clamp(30px, 3.2vw, 46px);
}

.hero--score .deco-tgv {
    top: 32%;
    left: 86%;
    right: auto;
    bottom: auto;
    width: clamp(34px, 3.6vw, 52px);
}

.hero--score .deco-tgv2 {
    top: 82%;
    left: 1%;
    width: clamp(28px, 3vw, 44px);
}

/* Mảnh dưới bên phải nằm hẳn ngoài khung ảnh và xoay -52deg đúng ma trận
   transform trong bản xuất. Xoay bằng transform thì đè mất biến
   --scroll-transform của app.js, nên dùng thuộc tính rotate riêng — nó độc lập
   với transform nên hai hiệu ứng cộng dồn được, không cái nào đè cái nào.

   Neo theo mép PHẢI của khung ảnh chứ không theo left:%. Ở khổ Figma 1440 thì
   hai cách ra cùng một chỗ, nhưng .hero cắt phần tràn (overflow:hidden) nên
   ngay khi cửa sổ hẹp hơn — 1280px là gặp — mốc tính theo left đẩy mảnh này
   vượt mép màn hình và nó bị cắt mất một nửa. */
.hero--score .deco-tgd2 {
    top: 86%;
    left: auto;
    right: -3%;
    width: clamp(30px, 3.2vw, 48px);
    rotate: -52deg;
}


/* ============================================================
   C14b · BA THẺ THỦ KHOA
   ============================================================ */

/* padding-bottom bỏ hẳn (trước clamp(50px, 5.4vw, 72px)): section kế tiếp
   (.admitted) cùng nền --green và tự có padding-top riêng — cộng thêm đệm
   đáy ở đây thành hai khoảng trắng CÙNG MÀU chồng lên nhau, không có gì phân
   ranh giới nên mắt đọc thành một mảng trống bất thường giữa "ba thẻ thủ
   khoa" và "Trúng tuyển". Giữ nguyên padding-top vì đó là khoảng cách với
   nhãn "Điểm cao nhất" ngay phía trên, không liên quan tới section sau. */
.podium {
    padding: clamp(46px, 5vw, 67px) 0 0;
    color: var(--smoke);
    background: var(--green);
    overflow: hidden;
}

/* Nhãn nhỏ và hai vạch hai bên ăn theo color của section nên tự thành trắng —
   xem ghi chú "KHÔNG đặt màu ở đây" tại .section-eyebrow. */
.podium .section-head {
    margin-bottom: 32px;
}

.podium-scope {
    color: rgba(244, 247, 245, .75);
}

/* Ba cột khổ 220 / 280 / 220, co lại được trên màn hẹp.
   align-items:end để ba thẻ thẳng chân dù thẻ giữa cao hơn. */
.podium-list {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 220px));
    align-items: end;
    justify-content: center;
    gap: 16px;
}

/* Thẻ giữa 280 thay vì 220 của thẻ bên — chênh lệch ~27% giữ đúng nhịp bục
   vinh danh, vừa vặn không bị tràn ngang màn hình.
   Không phải khai thêm chiều cao: .podium-photo dùng aspect-ratio nên ảnh thẻ
   giữa tự cao theo bề ngang, kéo cả thẻ cao lên — và align-items:end ở khung
   bọc khiến phần cao thêm ấy nhô LÊN TRÊN, đúng dáng bục trao giải. */
.podium-list--full {
    grid-template-columns: minmax(0, 220px) minmax(0, 280px) minmax(0, 220px);
}

/* Hạng 1 ra giữa, hạng 2 sang trái. Chỉ đổi chỗ khi ĐỦ ba thẻ — thiếu người mà
   vẫn ghim grid-column cứng thì giữa hàng chừa ra những ô trống.
   DOM vẫn giữ thứ tự 1-2-3 cho trình đọc màn hình và cho bản điện thoại. */
.podium-list--full .podium-card--1 {
    grid-column: 2;
    grid-row: 1;
}

.podium-list--full .podium-card--2 {
    grid-column: 1;
    grid-row: 1;
}

.podium-list--full .podium-card--3 {
    grid-column: 3;
    grid-row: 1;
}

/* Chữ trong thẻ hạng 1 to hơn hai thẻ bên cạnh.
   Thẻ giữa rộng hơn 27% mà chữ vẫn y hệt thì phần thông tin nhìn loãng ra giữa
   một khung rộng; phóng chữ lên vừa lấp chỗ ấy vừa dồn ánh mắt vào đúng người
   đứng nhất. Điểm số phóng mạnh nhất vì nó là thứ người xem tìm.
   Chỉ áp khi ĐỦ ba thẻ và còn xếp hàng ngang — dưới 900px ba thẻ xếp chồng
   bằng nhau, lúc ấy phải trả chữ về cỡ chung (xem media query bên dưới). */
.podium-list--full .podium-card--1 .podium-info {
    gap: 15px;
    padding: 16px 10px;
}

.podium-list--full .podium-card--1 .podium-name {
    font-size: clamp(18px, 1.4vw, 21px);
}

.podium-list--full .podium-card--1 .podium-score {
    font-size: clamp(34px, 2.9vw, 44px);
    line-height: 1.15;
}

/* 24px con tem + 1px khe hở, đúng `gap: 1px` của khung bọc trong Figma. */
.podium-card {
    position: relative;
    padding-top: 25px;
    transition: transform var(--dur) var(--ease);
}

/* Nhấc CẢ THẺ BỌC chứ không nhấc riêng .podium-frame. Con tem hạng là phần tử
   absolute nằm trong .podium-card nhưng NGOÀI .podium-frame, nên nhấc cái
   frame thì tem đứng lại một chỗ và thẻ trượt ra khỏi nó.
   Cùng cách đã dùng cho thẻ giáo viên (.teacher), vốn có đúng bài toán này:
   ảnh chân dung nhô lên trên thân thẻ nên transform phải đặt ở thẻ bọc.
   -8px cũng lấy theo .teacher — sâu gấp đôi mức --lift 3px của các nút, vì
   đây là khối ảnh lớn, nhấc nhè nhẹ thì gần như không thấy gì. */
.podium-card:hover {
    transform: translateY(-8px);
}

/* Con tem hạng: 71x24, nền vàng chữ xanh, chữ 13px/600 — số đo lấy thẳng từ
   Frame 329 của bản xuất.

   CĂN GIỮA theo thẻ, vì khung bọc trong Figma là flex-column có
   `align-items: center`.

   Bo tròn BA góc, riêng góc DƯỚI-TRÁI để vuông. Chính chi tiết bất đối xứng ấy
   khiến Figma phải xuất con tem thành path tự vẽ ("Vector 7") thay vì một hình
   chữ nhật — và nó cũng nói rằng tem hiện TRỌN VẸN phía trên thẻ, chứ không
   nấp một phần ra sau: nấp thì đã chẳng ai đi tạo dáng cho hai góc dưới. */
.podium-badge {
    position: absolute;
    top: 1px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    min-width: 71px;
    margin: 0;
    /* 5 trên + 16 (line-height --lh-sm) + 3 dưới = đúng 24px của Frame 329;
       ngang 8px khớp chữ đặt ở left:8 trong khung rộng 71. */
    padding: 5px 8px 3px;
    /* color: var(--green); */
    background: var(--gold);
    border-radius: 50px 50px 0px 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    text-align: center;
}

/* overflow:hidden để ảnh bên trong bị bo góc theo thẻ. */
.podium-frame {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--smoke);
    border: 1px solid var(--gold);
    border-radius: var(--r-box);
    /* Không còn transition transform ở đây: việc di chuyển đã chuyển hẳn lên
       .podium-card để con tem đi theo. */
    transition: box-shadow var(--dur) var(--ease);
}

/* Bóng đổ đậm hơn hẳn lúc nghỉ (.28 → .38) vì thẻ nằm trên nền XANH ĐẬM —
   bóng đen trên nền tối vốn đã khó thấy, để nhạt như trên nền trắng thì hiệu
   ứng gần như biến mất. */
.podium-card:hover .podium-frame {
    box-shadow: 0 22px 40px rgba(0, 0, 0, .38);
}

/* aspect-ratio thay cho height cứng: thẻ giữa rộng hơn nên ảnh của nó tự cao
   hơn đúng tỉ lệ 274/244 của thiết kế, không phải khai riêng hai cỡ. */
.podium-photo {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 274 / 244;
    object-fit: cover;
    background: var(--green-10);
    transition: transform var(--dur) var(--ease);
}

/* Ảnh nhích to ra khi rê chuột, giống thẻ giáo viên. Khung có overflow:hidden
   nên phần thừa bị cắt gọn theo bo góc, ảnh không tràn ra ngoài thẻ. */
.podium-card:hover .podium-photo {
    transform: scale(1.06);
}

/* flex:1 để phần chữ của ba thẻ cao bằng nhau dù tên trường dài ngắn khác
   nhau — nhờ vậy ba dòng điểm luôn nằm ngang hàng. */
.podium-info {
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 15px;
    padding: 16px 10px;
    text-align: center;
}

.podium-id {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.podium-name {
    margin: 0;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--ink);
}

.podium-school {
    margin: 0;
    color: rgba(18, 26, 22, .7);
}

.podium-score {
    margin: 0;
    white-space: nowrap;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    letter-spacing: .02em;
    color: var(--green);
}

/* Cả ba hạng dùng CHUNG một gradient đỏ→vàng, không phân biệt màu theo thứ
   hạng nữa — chỉ hạng 1 to chữ hơn để vẫn nổi bật giữa ba thẻ. */
.podium-score__val {
    font-weight: 800;
    color: #DC2626;
    background: linear-gradient(135deg, #DC2626 0%, #EA580C 55%, var(--gold) 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.podium-card--1 .podium-score__val {
    font-size: 33px;
}

.podium-score .score-point__max {
    margin-left: 2px;
    font-size: var(--fs-sm);
    font-weight: 500;
    letter-spacing: 0;
    color: rgba(18, 26, 22, .45);
}

.podium-exam {
    margin: 0;
    font-weight: 700;
    color: rgba(18, 26, 22, .7);
}


/* ============================================================
   C14c · THANH TRA CỨU
   ============================================================ */

.score-board {
    padding: clamp(46px, 5vw, 72px) 0 clamp(50px, 5.4vw, 80px);
    background: var(--smoke);
}

/* .section-head gốc là space-between cho hàng có nút bên phải; ở đây chỉ có
   khối chữ nên trả về block.

   text-align: center đã BỎ ngày 21/09/2026 khi khách chốt canh trái toàn site.
   Nó vốn đã hết tác dụng lên chính tiêu đề từ lúc .section-title thành flex
   (text-align không canh được item của flex container), nhưng để lại là luật
   nói một đằng, trang hiện một nẻo.

   Luật màu .score-head .section-eyebrow cũng bỏ cùng lúc: nhãn nhỏ "Bảng điểm
   vinh danh" đã gỡ khỏi view, mà .score-head chỉ dùng đúng ở trang đó. */
.score-head {
    display: block;
    margin-bottom: 32px;
}

.score-filter {
    display: flex;
    align-items: center;
    gap: clamp(14px, 2.4vw, 35px);
    padding: clamp(18px, 2.2vw, 30px);
    background: var(--white);
    border-radius: var(--r-box);
    box-shadow: 4px 4px 4px rgba(18, 26, 22, .2);
}

.score-filter__field {
    position: relative;
    display: flex;
    align-items: center;
    margin: 0;
}

/* Ô tìm kiếm nuốt hết chỗ thừa, hai ô chọn giữ bề ngang của thiết kế. */
.score-filter__field--search {
    flex: 1;
    min-width: 0;
}

/* Nhãn chỉ dành cho trình đọc màn hình: thiết kế dùng placeholder làm nhãn,
   mà placeholder biến mất ngay khi người dùng gõ chữ đầu tiên. */
.score-filter__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.score-filter__field i {
    position: absolute;
    left: 15px;
    font-size: 15px;
    color: rgba(18, 26, 22, .7);
    pointer-events: none;
}

.score-filter input,
.score-filter select {
    width: 100%;
    height: 48px;
    padding: 5px 15px;
    font-family: inherit;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
    background: var(--white);
    border: .5px solid rgba(18, 26, 22, .5);
    border-radius: var(--r-row);
    transition:
        border-color var(--dur) var(--ease),
        box-shadow var(--dur) var(--ease);
}

.score-filter input {
    padding-left: 38px;
}

.score-filter input::placeholder {
    color: rgba(18, 26, 22, .7);
}

.score-filter input:focus,
.score-filter select:focus {
    outline: none;
    border-color: var(--green);
    box-shadow: 0 0 0 3px var(--green-15);
}

/* Mũi tên xổ xuống vẽ bằng SVG nội tuyến thay cho mũi tên mặc định của hệ điều
   hành — mỗi trình duyệt một kiểu, và không kiểu nào khớp thiết kế. */
.score-filter select {
    min-width: 185px;
    padding-right: 34px;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='10' viewBox='0 0 16 10' fill='none'%3E%3Cpath d='M1 1L8 8L15 1' stroke='rgba(18,26,22,0.7)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    cursor: pointer;
}

/* Nút gửi ẩn khỏi mắt nhưng vẫn nhận được tiêu điểm bàn phím — xem ghi chú
   trong table.php. display:none sẽ tước luôn khả năng bấm Enter để gửi form. */
.score-filter__submit {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    border: 0;
}

.score-filter__submit--visible {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    clip-path: none;
}

.score-count {
    margin: clamp(20px, 2.4vw, 30px) 0 12px;
    color: rgba(18, 26, 22, .7);
}

.score-count strong {
    color: var(--green);
}

.score-count a {
    margin-left: 6px;
    color: var(--green);
    font-weight: 600;
}


/* ============================================================
   C14d · BẢNG ĐIỂM
   ============================================================ */

/* overflow-x cho phép bảng tự trượt ngang ở khoảng giữa (900-1080px) thay vì
   ép cả trang trượt theo. Dưới 900px bảng đổi hẳn sang dạng thẻ, xem C14f. */
.score-table-wrap {
    overflow-x: auto;
    border-radius: var(--r-media);
    box-shadow: 0 6px 24px rgba(0, 0, 0, .12);
}

.score-table {
    width: 100%;
    min-width: 820px;
    border-collapse: collapse;
    background: var(--white);
    text-align: left;
}

/* <caption> phải có để trình đọc màn hình biết bảng này nói về cái gì, nhưng
   thiết kế không vẽ dòng ấy nên giấu khỏi mắt. */
.score-table__caption {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
}

.score-table th {
    padding: 14px 20px;
    color: var(--smoke);
    background: var(--green);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;
}

/* Bề ngang các cột theo thiết kế (51 / 457 / 163 / 235 / 45 trong khổ 1200),
   quy ra % để bảng co giãn được. */
.score-table th:nth-child(1) {
    width: 9%;
}

.score-table th:nth-child(2) {
    width: 41%;
}

.score-table th:nth-child(3) {
    width: 18%;
}

.score-table th:nth-child(4) {
    width: 22%;
}

.score-table th:nth-child(5) {
    width: 10%;
}

.score-table td {
    padding: 18px 20px;
    border-bottom: .3px solid rgba(18, 26, 22, .2);
    vertical-align: middle;
}

.score-table tbody tr {
    transition: background var(--dur) var(--ease);
}

.score-table tbody tr:hover {
    background: var(--green-10);
}

.score-table tbody tr:last-child td {
    border-bottom: 0;
}

/* Huy hiệu hạng: 30px tròn. Ba hạng đầu nền vàng, còn lại nền khói. */
.score-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    background: var(--smoke);
    border-radius: var(--r-pill);
    font-weight: 600;
}

.score-rank--top {
    background: var(--gold);
}

.score-name {
    display: block;
    font-weight: 600;
    color: var(--ink);
}

.score-school {
    display: block;
    color: rgba(18, 26, 22, .65);
}

.score-code {
    font-weight: 500;
    color: rgba(18, 26, 22, .7);
    /* Mã học viên là chuỗi kỹ thuật, tránh để nó xuống dòng giữa chừng. */
    white-space: nowrap;
}

.score-point {
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    letter-spacing: .05em;
    color: var(--green);
    white-space: nowrap;
}

/* Thang điểm bám sát con số nhưng phải nhẹ hẳn đi: nó là chú thích cho con số,
   không phải một con số thứ hai ngang hàng. Dùng ở cả bảng lẫn thẻ thủ khoa. */
.score-point__max {
    margin-left: 2px;
    font-size: var(--fs-sm);
    font-weight: 500;
    letter-spacing: 0;
    color: rgba(18, 26, 22, .45);
}

.score-note {
    max-width: 92ch;
    margin: 18px auto 0;
    color: rgba(18, 26, 22, .6);
    font-size: var(--fs-sm);
    line-height: 1.7;
    text-align: center;
}

.score-empty {
    padding: 70px 20px;
    color: var(--muted);
    text-align: center;
    background: var(--white);
    border-radius: var(--r-media);
    box-shadow: 0 6px 24px rgba(0, 0, 0, .08);
}

.score-empty i {
    font-size: 32px;
    color: var(--green-30);
}

.score-empty h3 {
    margin: 14px 0 6px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    color: var(--ink);
}

.score-empty p {
    max-width: 46ch;
    margin: 0 auto;
}


/* ============================================================
   C14e · PHÂN TRANG — dùng lại .pager của khối C5b

   KHÔNG khai dải nút riêng cho trang này. Trang Tra cứu điểm thi dùng
   thẳng `.pager .pager--light` giống danh sách khóa học và danh sách giáo
   viên, nên khối này không còn quy tắc nào.

   Bản cũ (.score-pagination) là một dải nút thứ ba gần giống hai dải kia
   nhưng lệch ở mọi số đo: nút 40px thay vì 36px, khe 15px thay vì 10px,
   ô số nền trong suốt còn hai mũi tên có viền — đứng riêng thì không sao,
   đặt cạnh trang giáo viên là thấy ngay hai trang không cùng một bộ.
   Cần đổi dáng phân trang thì sửa .pager ở C5b để mọi trang đổi theo.
   ============================================================ */


/* ============================================================
   C14f · RESPONSIVE
   ============================================================ */

@media (max-width: 1080px) {

    .hero--score .hero-photo {
        width: 100%;
        margin-left: 0;
    }

    .hero--score .hero-ring {
        top: 47%;
        left: 50%;
        width: 92%;
    }

    /* Ở ngưỡng này ảnh là 100% khung, lề trái 0 — tâm ảnh trùng 50% khung nên
       khai thẳng 50%, không dùng công thức theo --photo-w như bản rộng. */
    .score-line {
        left: 50%;
    }

    .hero--score .deco-tgv {
        left: 84%;
    }

    .podium-list,
    .podium-list--full {
        gap: 14px;
    }

    /* PHẢI chuyển sang fr trong đúng khoảng này, nếu không hạng 1 mất hẳn vẻ
       to hơn — lỗi âm thầm, chỉ lộ ra trên laptop 1024-1080px.
       Lý do: minmax(0, Npx) chỉ đặt TRẦN. Container ở ngưỡng này còn 760px,
       hẹp hơn tổng ba trần (834px), nên Grid nuôi đều cả ba track từ 0 lên —
       cả ba cùng chạm 231px trước khi track giữa kịp vượt lên. Kết quả là ba
       thẻ BẰNG NHAU CHÍNH XÁC, con tem "Hạng 1" thành thứ duy nhất phân biệt.

       Ghi chú cũ ở đây từng cấm dùng fr, nhưng nó nói về 1fr ĐỀU NHAU cho mọi
       ngưỡng — khai vậy ở mốc 1280px (container 1050) thì thẻ phình lên 318px,
       to hơn cả bản 1440px, đúng là ngược đời. Ở đây khác hai điểm: tỉ lệ
       1/1.28 GIỮ NGUYÊN chênh lệch của thiết kế, và chỉ áp cho container 760px
       nên ra 211/270 — vẫn nhỏ hơn 242/310 của màn rộng, không hề ngược đời. */
    .podium-list--full {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.28fr) minmax(0, 1fr);
    }
}

@media (max-width: 900px) {

    /* Hero mất luật một-màn-hình từ ngưỡng này (xem C2), cột ảnh về giữa. */
    .hero--score {
        padding-bottom: 28px;
    }

    /* Ba thẻ xếp chồng, hạng 1 lên đầu trở lại — lúc này DOM đã đúng thứ tự nên
       chỉ cần gỡ bỏ việc ghim cột. */
    .podium-list,
    .podium-list--full {
        grid-template-columns: minmax(0, 280px);
        justify-content: center;
        gap: 20px;
    }

    .podium-list--full .podium-card--1,
    .podium-list--full .podium-card--2,
    .podium-list--full .podium-card--3 {
        grid-column: auto;
        grid-row: auto;
    }

    /* Ba thẻ giờ rộng bằng nhau nên phải trả chữ hạng 1 về cỡ chung — để chữ
       to trong một thẻ cùng khổ với hai thẻ kia thì nhìn như lỗi cỡ chữ, chứ
       không ra ý nhấn mạnh. Con tem "Hạng 1" đã đủ nói ai đứng nhất. */
    .podium-list--full .podium-card--1 .podium-info {
        gap: 15px;
        padding: 16px 10px;
    }

    .podium-list--full .podium-card--1 .podium-name {
        font-size: var(--fs-md);
    }

    .podium-list--full .podium-card--1 .podium-score {
        font-size: var(--fs-lg);
    }

    .score-filter {
        flex-wrap: wrap;
        gap: 12px;
    }

    .score-filter__field--search {
        flex: 1 0 100%;
    }

    .score-filter__field:not(.score-filter__field--search) {
        flex: 1;
    }

    .score-filter select {
        min-width: 0;
    }

    /* Bảng đổi sang dạng THẺ: mỗi dòng thành một khối, tên cột lấy từ
       data-label của chính ô đó. Phải giấu <thead> bằng position thay vì
       display:none — display:none tước luôn quan hệ ô/cột mà trình đọc màn
       hình dựa vào. */
    .score-table-wrap {
        overflow-x: visible;
        box-shadow: none;
    }

    .score-table {
        min-width: 0;
    }

    .score-table thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
    }

    .score-table tbody tr {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        gap: 6px 14px;
        margin-bottom: 14px;
        padding: 16px;
        background: var(--white);
        border-radius: var(--r-media);
        box-shadow: 0 4px 16px rgba(0, 0, 0, .1);
    }

    .score-table td {
        display: flex;
        align-items: baseline;
        gap: 10px;
        padding: 0;
        border: 0;
    }

    /* 106px là bề ngang của nhãn dài nhất ("MÃ HỌC SINH:") ở cỡ 13px in hoa.
       Hẹp hơn là nó gãy làm hai dòng và cột giá trị bên cạnh so le hẳn đi. */
    .score-table td::before {
        content: attr(data-label) ":";
        flex: 0 0 106px;
        color: rgba(18, 26, 22, .6);
        font-size: var(--fs-sm);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .04em;
        white-space: nowrap;
    }

    /* Hạng và điểm là hai đầu của cùng một dòng tiêu đề thẻ, không cần nhãn. */
    .score-table td[data-label="Hạng"],
    .score-table td[data-label="Điểm"] {
        grid-row: 1;
    }

    .score-table td[data-label="Hạng"] {
        grid-column: 1;
    }

    .score-table td[data-label="Điểm"] {
        grid-column: 2;
        justify-content: flex-end;
    }

    .score-table td[data-label="Hạng"]::before,
    .score-table td[data-label="Điểm"]::before {
        content: none;
    }

    .score-table td[data-label="Họ và tên"] {
        grid-column: 1 / -1;
        flex-direction: column;
        gap: 2px;
    }

    .score-table td[data-label="Họ và tên"]::before {
        content: none;
    }

    .score-table td[data-label="Mã học sinh"],
    .score-table td[data-label="Đợt thi"] {
        grid-column: 1 / -1;
    }
}

@media (max-width: 600px) {

    .score-filter__field:not(.score-filter__field--search) {
        flex: 1 0 100%;
    }

    .podium-list,
    .podium-list--full {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Không thu nhỏ dải nút chuyển trang ở đây nữa: .pager là thành phần dùng
       chung, thu riêng cho trang này là lại lệch khỏi trang giáo viên đúng
       như cũ. 36px vẫn đạt ngưỡng vùng chạm tối thiểu nên không cần đụng. */
}

/* #endregion */

/* =====================================================================
   #region C15 · TRANG GIỎ HÀNG — /gio-hang

   Hai cột: cột trái là danh sách khóa đã chọn + link quay lại + hộp "Thông
   tin học viên"; cột phải là thẻ tóm tắt đơn, dính lại khi cuộn.

   Không khai token riêng cho trang này — màu, cỡ chữ, bo góc đều lấy từ bộ
   biến ở đầu file, giống C13/C14. Số của bản Figma là ở khung 1440: cột trái
   778 + khe 44 + cột phải 376 = 1198, vừa đúng --container 1200.
   ===================================================================== */

.cart-page {
    padding: clamp(32px, 3.4vw, 48px) 0 clamp(56px, 5.6vw, 90px);
    background: var(--white);
}


/* ============================================================
   C15a · ĐƯỜNG DẪN VÀ TIÊU ĐỀ
   ============================================================ */

.cart-crumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: clamp(18px, 1.9vw, 26px);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .8);
}

.cart-crumb a {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.cart-crumb a:hover {
    color: var(--green);
}

.cart-crumb__last {
    font-weight: 700;
    color: var(--ink);
}

.cart-heading {
    margin: 0 0 clamp(22px, 2.4vw, 34px);
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    color: var(--ink);
}


/* ============================================================
   C15b · KHUNG HAI CỘT

   align-items: start là bắt buộc — mặc định stretch sẽ kéo <aside> cao bằng
   cột trái, mà position: sticky bên trong một khối đã cao bằng cha thì không
   còn chỗ nào để trượt: thẻ tóm tắt sẽ đứng im như thường.
   ============================================================ */

.cart-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 376px;
    align-items: start;
    gap: 44px;
}

/* Trừ đi chiều cao thanh menu lúc đã dính, cộng một chút cho thẻ thở. */
.cart-aside {
    position: sticky;
    top: calc(var(--nav-stuck-h) + 20px);
}


/* ============================================================
   C15c · DÒNG KHÓA HỌC TRONG GIỎ
   ============================================================ */

.cart-list {
    display: flex;
    flex-direction: column;
    gap: 20px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.cart-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
    padding: 15px;
    background: var(--smoke);
    border-radius: var(--r-row);
}

/* min-width: 0 để tên khóa dài cắt được bên trong ô flex, không đẩy cụm giá
   tràn ra khỏi thẻ. */
.cart-item__lead {
    display: flex;
    align-items: center;
    gap: 19px;
    min-width: 0;
}

.cart-item__media {
    flex: none;
    width: 163px;
    overflow: hidden;
    border-radius: var(--r-row);
    line-height: 0;
}

/* height: auto KHÔNG được bỏ: thẻ img có thuộc tính height="105", mà thuộc
   tính ấy đè mất aspect-ratio và ảnh sẽ méo khi khung co lại ở màn hình nhỏ. */
.cart-item__thumb {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 163 / 105;
    object-fit: cover;
}

.cart-item__info {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}

/* Figma để khe 10px giữa tên và cụm lịch học, còn hai dòng lịch học cách nhau
   5px. Một flex-gap không kể được hai con số, nên khe 5px nằm ở
   .cart-item__info và 5px còn lại cộng thêm ở đây. */
.cart-item__name {
    margin: 0 0 5px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    color: var(--ink);
}

.cart-item__name a {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.cart-item__name a:hover {
    color: var(--green);
}

.cart-item__meta {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .7);
}

.cart-item__tail {
    display: flex;
    flex: none;
    align-items: center;
    gap: 14px;
}

.cart-item__price {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 3px;
    margin: 0;
}

.cart-item__price strong {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    color: var(--green);
}

.cart-item__price del {
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    letter-spacing: var(--track);
    color: var(--price-old);
}

/* "đ" của giá gốc là chữ nhỏ gạch chân, giống thẻ khóa học ngang ở C5b */
.cart-item__price sup {
    font-size: .7em;
    vertical-align: super;
    text-decoration: underline;
}

.cart-item__remove {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    font-size: 20px;
    color: rgba(18, 26, 22, .7);
    cursor: pointer;
    transition:
        color var(--dur) var(--ease),
        background-color var(--dur) var(--ease);
}

.cart-item__remove:hover {
    background: rgba(18, 26, 22, .07);
    color: var(--ink);
}


/* ============================================================
   C15d · GIỎ TRỐNG
   ============================================================ */

.cart-empty {
    padding: clamp(32px, 4vw, 56px) 24px;
    text-align: center;
    background: var(--smoke);
    border-radius: var(--r-media);
}

.cart-empty i {
    font-size: 40px;
    color: var(--green-30);
}

.cart-empty__title {
    margin: 16px 0 8px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--ink);
}

.cart-empty__desc {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .7);
}

.cart-empty__cta {
    display: inline-block;
    margin-top: 20px;
    padding: 11px 26px;
    border-radius: var(--r-pill);
    background: var(--green);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--smoke);
    text-decoration: none;
    transition: transform var(--dur) var(--ease);
}

.cart-empty__cta:hover {
    transform: translateY(var(--lift));
}


/* ============================================================
   C15e · LINK "TIẾP TỤC CHỌN KHÓA HỌC"
   ============================================================ */

.cart-back {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: 26px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 600;
    color: var(--green);
    text-decoration: none;
}

.cart-back i {
    font-size: 21px;
    transition: transform var(--dur) var(--ease);
}

.cart-back:hover i {
    transform: translateX(-4px);
}


/* ============================================================
   C15f · THẺ TÓM TẮT ĐƠN ĐĂNG KÝ
   ============================================================ */

.cart-summary {
    padding: 30px 24px 26px;
    background: var(--smoke);
    border: .5px solid rgba(18, 26, 22, .2);
    border-radius: var(--r-media);
    box-shadow: 4px 4px 4px rgba(0, 0, 0, .25);
}

.cart-summary__title {
    margin: 0 0 30px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--ink);
}

.cart-summary__rows {
    display: flex;
    flex-direction: column;
    gap: 20px;
    margin: 0;
}

.cart-summary__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
}

.cart-summary__row dt {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .7);
}

.cart-summary__row dd {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    color: #000;
}

.cart-summary__row del {
    font-weight: 400;
    color: rgba(0, 0, 0, .5);
}

.cart-summary__row--save dt {
    font-weight: 600;
}

.cart-summary__row--save dd {
    color: var(--green);
}

.cart-summary__line {
    margin: 30px 0;
    border: 0;
    border-top: 1px solid rgba(18, 26, 22, .2);
}

.cart-summary__total {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    margin: 0;
}

.cart-summary__total span {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    color: rgba(18, 26, 22, .7);
}

.cart-summary__total strong {
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 600;
    color: var(--green);
}

.cart-summary__submit {
    display: block;
    width: 100%;
    min-height: 41px;
    margin-top: 34px;
    padding: 10px;
    border: 0;
    border-radius: 20px;
    background: var(--green);
    font-family: var(--font);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    letter-spacing: var(--track);
    color: var(--smoke);
    cursor: pointer;
    transition:
        transform var(--dur) var(--ease),
        opacity var(--dur) var(--ease);
}

.cart-summary__submit:hover:not(:disabled) {
    transform: translateY(var(--lift-sm));
}

.cart-summary__submit:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.cart-summary__note {
    margin: 12px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    text-align: center;
    color: rgba(18, 26, 22, .7);
}


/* ============================================================
   C15g · HỘP "THÔNG TIN HỌC VIÊN"
   ============================================================ */

.cart-form {
    margin-top: 48px;
    padding: clamp(22px, 3.1vw, 44px);
    background: var(--white);
    border: 1px solid rgba(18, 26, 22, .3);
    border-radius: var(--r-media);
}

.cart-form__title {
    margin: 0 0 14px;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    color: var(--ink);
}

.cart-form__lead {
    margin: 0 0 40px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
}

.cart-field {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Khe giữa các nhóm trường. Viết bằng bộ chọn anh-em thay vì margin cứng trên
   .cart-field để nhóm ĐẦU TIÊN không đội thêm khoảng trắng dưới đoạn dẫn.

   Dấu > là bắt buộc: hai ô "Số điện thoại" và "Email" cũng là hai .cart-field
   đứng cạnh nhau — bên trong .cart-field-row. Thiếu dấu >, ô Email ăn luôn
   24px này và tụt xuống thấp hơn ô bên trái đúng chừng ấy. */
.cart-form>.cart-field+.cart-field,
.cart-form>.cart-field+.cart-field-row,
.cart-form>.cart-field-row+.cart-field {
    margin-top: 24px;
}

/* Hai class để đủ 0-3-0, bằng độ đặc hiệu của luật 24px ở trên và đứng sau
   nó trong file nên thắng. Viết .cart-field--pay trơn (0-1-0) là thua, khối
   "Phương thức thanh toán" sẽ vẫn cách 24px chứ không phải 32px. */
.cart-form>.cart-field.cart-field--pay {
    margin-top: 32px;
}

.cart-field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 25px;
}

.cart-label {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    color: var(--ink);
}

.cart-input {
    width: 100%;
    min-height: 42px;
    padding: 10px 15px;
    border: 1px solid rgba(18, 26, 22, .5);
    border-radius: var(--r-row);
    background: var(--white);
    font-family: var(--font);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--ink);
    transition:
        border-color var(--dur) var(--ease),
        box-shadow var(--dur) var(--ease);
}

.cart-input::placeholder {
    color: rgba(18, 26, 22, .7);
}

.cart-input:focus {
    outline: 0;
    border-color: var(--green);
    box-shadow: 0 0 0 3px var(--green-15);
}

/* Chỉ cho kéo dọc: kéo ngang được thì người dùng làm textarea rộng hơn hộp và
   cả bố cục hai cột bị đẩy lệch. */
.cart-input--area {
    min-height: 106px;
    resize: vertical;
}

.cart-error {
    margin: 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: #B3261E;
}


/* ---- Phương thức thanh toán ---- */

.cart-pay-group {
    margin: 0;
    padding: 0;
    border: 0;
}

.cart-pay {
    display: flex;
    align-items: center;
    gap: 15px;
    min-height: 73px;
    padding: 10px 15px;
    background: var(--green-10);
    border: 1px solid var(--green);
    border-radius: var(--r-row);
    cursor: pointer;
}

/* appearance: none tắt nút tròn mặc định của hệ điều hành để vẽ lại theo
   Figma: viền xanh 2px, chấm xanh ở giữa khi được chọn. */
.cart-pay__radio {
    flex: none;
    appearance: none;
    width: 19px;
    height: 19px;
    margin: 0;
    border: 2px solid var(--green);
    border-radius: 50%;
    background: var(--white);
    cursor: pointer;
}

.cart-pay__radio:checked {
    background:
        radial-gradient(circle,
            var(--green) 0 4.5px,
            var(--white) 4.5px);
}

.cart-pay__radio:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}

.cart-pay__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.cart-pay__text strong {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    color: rgba(18, 26, 22, .7);
}

.cart-pay__text span {
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: rgba(18, 26, 22, .7);
}


/* ============================================================
   C15h · CO THEO MÀN HÌNH
   ============================================================ */

/* Laptop: cột phải hẹp lại trước, khe hẹp theo — cột trái phải giữ đủ chỗ cho
   ảnh 163px cộng khối chữ. */
@media (max-width: 1150px) {
    .cart-grid {
        grid-template-columns: minmax(0, 1fr) 330px;
        gap: 28px;
    }

    .cart-item {
        gap: 24px;
    }
}

/* Tablet: xuống một cột. Thẻ tóm tắt đi xuống cuối — người dùng điền xong biểu
   mẫu thì gặp ngay tổng tiền và nút gửi, đúng thứ tự thao tác. Bỏ sticky vì
   một cột thì không còn gì để thẻ trượt dọc theo. */
@media (max-width: 1024px) {
    .cart-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 32px;
    }

    .cart-aside {
        position: static;
    }
}

/* Tablet dọc: dòng giỏ hàng xuống hai hàng — chữ ở trên, giá và nút xóa ở
   dưới, dàn hai đầu. */
@media (max-width: 820px) {
    .cart-item {
        flex-wrap: wrap;
        gap: 16px;
    }

    .cart-item__lead {
        flex: 1 1 100%;
    }

    .cart-item__tail {
        flex: 1 1 100%;
        justify-content: space-between;
    }

    .cart-item__price {
        align-items: flex-start;
    }
}

@media (max-width: 700px) {
    .cart-item__media {
        width: 120px;
    }

    .cart-item__lead {
        gap: 14px;
    }

    .cart-field-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 24px;
    }

    .cart-form {
        margin-top: 32px;
    }

    .cart-back {
        font-size: var(--fs-base);
        line-height: var(--lh-base);
    }
}

/* Mobile nhỏ: ảnh và chữ xếp dọc, ảnh trải hết bề ngang thẻ. */
@media (max-width: 480px) {
    .cart-item__lead {
        flex-direction: column;
        align-items: stretch;
    }

    .cart-item__media {
        width: 100%;
    }

    .cart-pay {
        align-items: flex-start;
        padding: 14px 15px;
    }

    .cart-pay__radio {
        margin-top: 2px;
    }
}

/* #endregion */


/* =====================================================================
   #region C16 · DẢI THÔNG BÁO TOÀN TRANG

   Hiện sau mỗi thao tác đổi dữ liệu có chuyển hướng (POST-Redirect-GET): thêm
   vào giỏ, xóa khỏi giỏ, và sau này là tạo đơn / thanh toán.

   position: fixed là cố ý. Đặt trong luồng thì khối này đẩy hero xuống, mà hero
   mọi trang đang kéo ngược lên bằng margin-top âm (--nav-overlap, khối C2) —
   hai thứ đá nhau, thanh menu sẽ đè lên dòng chữ. Cho nổi lên trên là không
   phải động gì đến bố cục của bất kỳ trang nào.
   ===================================================================== */

/* GÓC DƯỚI phải, không phải góc trên: ở đỉnh trang thanh menu chưa dính nên
   nó còn nằm thấp hơn 180px, mọi mốc top tính theo --nav-stuck-h đều rơi trúng
   khối Hotline / Email / Địa chỉ. Góc dưới thì không đụng gì ở bất kỳ vị trí
   cuộn nào. z-index 200 để nằm trên thanh menu dính (.nav-sticky dùng 100). */
.site-notice {
    position: fixed;
    bottom: 24px;
    right: 20px;
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: min(420px, calc(100vw - 40px));
    /* Không chặn chuột ở khung ngoài: sau khi thông báo mờ đi, khung rỗng vẫn
       nằm đó và sẽ ăn mất cú bấm vào nội dung ngay dưới. */
    pointer-events: none;
}

/* Hai lớp hoạt ảnh nối nhau: trượt vào 0.35s, đứng yên, rồi tự mờ đi từ giây
   thứ 5. 'forwards' giữ nguyên khung cuối nên nó biến hẳn, không hiện lại.
   Không cần một dòng JavaScript nào. */
.site-notice__item {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 12px 16px;
    border-radius: var(--r-media);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    animation:
        notice-in .35s var(--ease) both,
        notice-out .5s var(--ease) 5s forwards;
}

.site-notice__item i {
    flex: none;
    font-size: 18px;
}

.site-notice__item--ok {
    background: var(--green);
    color: var(--smoke);
}

.site-notice__item--error {
    background: #B3261E;
    color: var(--white);
}

@keyframes notice-in {
    from {
        opacity: 0;
        transform: translateY(12px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes notice-out {
    to {
        opacity: 0;
        transform: translateY(8px);
        visibility: hidden;
    }
}

/* Người dùng đã bật "giảm chuyển động": bỏ phần trượt vào, nhưng VẪN giữ
   phần tự ẩn — tắt nốt thì thông báo đứng mãi trên màn hình. */
@media (prefers-reduced-motion: reduce) {
    .site-notice__item {
        animation: notice-out .01s linear 5s forwards;
    }
}

@media (max-width: 700px) {
    .site-notice {
        bottom: 12px;
        right: 12px;
        left: 12px;
        max-width: none;
    }

    .site-notice__item {
        font-size: var(--fs-sm);
        line-height: var(--lh-sm);
    }
}

/* #endregion */
/* =====================================================================
   #region C17 · TRANG ĐƠN ĐĂNG KÝ — /don-hang/{code}

   Trang này CỐ Ý dùng lại khung của khối C15 (.cart-page, .cart-grid,
   .cart-list, .cart-item, .cart-summary): giỏ hàng và đơn đăng ký là hai bước
   liền nhau của cùng một luồng, người dùng vừa rời trang trước là sang trang
   này — hai bố cục khác nhau sẽ làm họ tưởng đi lạc.

   Khối này chỉ khai phần thật sự riêng: cụm tiêu đề, con tem trạng thái, bảng
   thông tin học viên và thẻ thanh toán.
   ===================================================================== */

.order-head {
    margin-bottom: clamp(22px, 2.4vw, 34px);
}

/* .cart-heading đã có margin-bottom cho trang giỏ; ở đây dưới nó còn ba dòng
   nữa nên phải thu lại, nếu không cụm tiêu đề rời rạc hẳn ra. */
.order-head .cart-heading {
    margin-bottom: 10px;
}

.order-head__meta {
    margin: 0 0 14px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .7);
}

/* Mã đơn là thứ người dùng phải chép sang nội dung chuyển khoản và đọc qua
   điện thoại — cho nó chữ đều nét để không nhầm ký tự nào với ký tự nào. */
.order-head__code {
    font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Consolas, monospace;
    font-size: 1.05em;
    letter-spacing: .04em;
    color: var(--ink);
}

.order-head__lead {
    max-width: 70ch;
    margin: 14px 0 0;
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    color: rgba(18, 26, 22, .8);
}

/* ---- Con tem trạng thái ---- */

.order-tag {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 6px 14px;
    border-radius: var(--r-pill);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    letter-spacing: var(--track);
}

.order-tag--is-waiting {
    background: var(--gold-10);
    color: #8A6104;
}

.order-tag--is-paid {
    background: var(--green-10);
    color: var(--green);
}

.order-tag--is-expired {
    background: rgba(179, 38, 30, .1);
    color: #B3261E;
}

/* ---- Bảng thông tin học viên ---- */

.order-panel {
    margin-top: 26px;
    padding: clamp(22px, 3.1vw, 36px);
    background: var(--white);
    border: 1px solid rgba(18, 26, 22, .3);
    border-radius: var(--r-media);
}

.order-panel__title {
    margin: 0 0 22px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--ink);
}

.order-info {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin: 0;
}

/* Hai cột cố định cho nhãn: các giá trị thẳng hàng nhau thì mắt quét dọc rất
   nhanh. minmax(0, 1fr) cho cột giá trị để email dài cắt được trong ô. */
.order-info__row {
    display: grid;
    grid-template-columns: 170px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

.order-info__row dt {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: rgba(18, 26, 22, .7);
}

.order-info__row dd {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    color: var(--ink);
    /* Email và ghi chú dài không có dấu cách sẽ đẩy vỡ lưới nếu không cho ngắt. */
    overflow-wrap: anywhere;
}

.order-info__row dd a {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}

.order-info__row dd a:hover {
    color: var(--green);
}

.order-info__row--note dd {
    font-weight: 400;
    line-height: var(--lh-loose);
}

.order-panel__hint {
    margin: 24px 0 0;
    padding-top: 20px;
    border-top: 1px solid rgba(18, 26, 22, .15);
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: rgba(18, 26, 22, .7);
}

.order-panel__hint a {
    color: var(--green);
    font-weight: 600;
    text-decoration: none;
}

/* ---- Thẻ thanh toán ---- */

/* Khối mã QR VietQR. Nền TRẮNG là bắt buộc, không phải trang trí: QrImage bỏ
   hẳn các ô trắng của mã để giảm kích thước, nên phần nền phải do CSS lo. Đặt
   mã lên nền màu là máy quét đọc sai tương phản và chịu thua. */
.order-pay {
    margin-top: 26px;
    padding: 18px 16px;
    border: 1px solid var(--green-30);
    border-radius: var(--r-row);
    background: var(--white);
    text-align: center;
}

/* Viền ĐỨT dành riêng cho trạng thái hỏng — quy ước quen thuộc cho "vùng này
   lẽ ra có nội dung mà chưa có". Không giả vờ là một nút bấm. */
.order-pay--todo {
    border-style: dashed;
}

/* Vùng lặng của mã đã nằm sẵn trong SVG (quietzoneSize 2) nên không cần đệm
   thêm. 200px là cỡ đủ để camera điện thoại bắt được ở khoảng cách cầm tay. */
.order-pay__qr {
    width: min(200px, 100%);
    margin: 14px auto 10px;
    line-height: 0;
}

.order-pay__qr svg {
    display: block;
    width: 100%;
    height: auto;
}

.order-pay__amount {
    margin: 0;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--green);
}

.order-pay__countdown {
    margin: 8px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: rgba(18, 26, 22, .7);
}

/* Sắp hết giờ thì đổi màu để lôi mắt về — app.js gắn class này. */
.order-pay__countdown.is-urgent {
    font-weight: 700;
    color: #B3261E;
}

/* ---- Chuyển khoản thủ công ---- */

.order-bank {
    margin-top: 14px;
    text-align: left;
}

.order-bank>summary {
    cursor: pointer;
    padding: 8px 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    color: var(--green);
}

.order-bank__list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 6px 0 0;
    padding: 12px 14px;
    border-radius: var(--r-row);
    background: var(--white);
}

.order-bank__list>div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.order-bank__list dt {
    flex: none;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: rgba(18, 26, 22, .7);
}

/* Số tài khoản và nội dung chuyển khoản phải gõ lại đúng từng ký tự, nên chữ
   đều nét — cùng lý do với mã đơn ở .order-head__code. */
.order-bank__list dd {
    margin: 0;
    font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Consolas, monospace;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    color: var(--ink);
    text-align: right;
    overflow-wrap: anywhere;
}

.order-bank__warn {
    display: flex;
    gap: 8px;
    margin: 10px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: #8A6104;
}

.order-bank__warn i {
    flex: none;
    margin-top: 2px;
}

.order-pay__title {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 0 0 6px;
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 700;
    color: var(--green);
}

.order-pay__desc {
    margin: 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: rgba(18, 26, 22, .7);
}

/* Dòng "đang chờ thanh toán" dưới thẻ. Chấm tròn chỉ nhấp nháy khi JavaScript
   đã thật sự bật vòng theo dõi (class is-watching) — không có JS thì chỉ còn
   dòng chữ tĩnh bảo người dùng tự tải lại trang, đúng như HTML in ra. */
.order-watch {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 14px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: rgba(18, 26, 22, .7);
    text-align: center;
}

.order-watch__dot {
    display: none;
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--green);
}

.order-watch.is-watching .order-watch__dot {
    display: block;
    animation: watch-pulse 1.4s var(--ease) infinite;
}

@keyframes watch-pulse {

    0%,
    100% {
        opacity: 1;
        transform: scale(1);
    }

    50% {
        opacity: .35;
        transform: scale(.7);
    }
}

/* Người dùng đã bật "giảm chuyển động": giữ chấm nhưng thôi nhấp nháy. */
@media (prefers-reduced-motion: reduce) {
    .order-watch.is-watching .order-watch__dot {
        animation: none;
    }
}

.order-pay__done {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 26px 0 0;
    padding: 14px;
    border-radius: var(--r-row);
    background: var(--green-10);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    font-weight: 600;
    color: var(--green);
}

/* .cart-summary__submit vốn là <button>; ở trang này nó có lúc là thẻ <a>, mà
   thẻ <a> không tự căn giữa chữ theo chiều dọc như button. */
a.cart-summary__submit {
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

@media (max-width: 700px) {
    .order-info__row {
        grid-template-columns: minmax(0, 1fr);
        gap: 4px;
    }

    .order-panel {
        margin-top: 20px;
    }
}

/* #endregion */


/* =====================================================================
   #region C18 · CỔNG HỌC VIÊN — /hoc-vien

   Khối này KHÔNG dùng lại gì của admin.css dù bố cục thanh bên trông na ná.
   Hai nơi có mục tiêu thiết kế ngược nhau: khu quản trị là màn làm việc cả
   ngày nên nén thông tin tối đa, còn đây là mặt khách hàng — cùng bảng màu,
   cùng bo góc, cùng nhịp giãn với phần công khai để học viên không thấy mình
   bị ném sang một website khác.

   Header và footer là của layouts/web.php dùng lại nguyên vẹn, nên khối này
   chỉ lo phần thân: thanh bên, dải số liệu, thẻ lớp và bảng đơn.

   Phần MÀN HÌNH HẸP nằm ở CUỐI khối, sau mọi quy tắc gốc — media query không
   tự cộng độ đặc hiệu, nên quy tắc gốc viết sau sẽ đè ngược lại nó. Cùng cái
   bẫy đã ghi ở đầu khối MÀN HÌNH HẸP bên admin.css.
   ===================================================================== */

.stu-main {
    /* Cùng nhịp với .cart-page: hai trang này đều không có hero, nên khoảng
       thở dưới thanh menu phải bằng nhau thì chuyển trang mới không giật. */
    padding: clamp(32px, 3.4vw, 48px) 0 clamp(56px, 5.6vw, 90px);
    background: var(--white);
}

.stu-shell {
    display: grid;
    grid-template-columns: 284px minmax(0, 1fr);
    align-items: start;
    gap: clamp(20px, 2.4vw, 36px);
}

/* minmax(0, 1fr) và .stu-body { min-width: 0 } là RÀO CHẮN, không phải thứ
   đang cứu một lỗi có thật — đo bằng scrollWidth ở 320-1320px thì bỏ chúng đi
   trang vẫn không tràn ngang. Lý do: ô lưới mặc định mang min-width:auto và
   KHÔNG co nhỏ hơn nội dung, nhưng .stu-tablewrap lại có overflow-x:auto, mà
   kích thước tối thiểu tự động của một khung cuộn vốn đã bằng 0 — nó tự lo
   được cho mình.

   Giữ lại vì thứ tự bảo vệ ấy chỉ đúng chừng nào nội dung còn là khung cuộn.
   Thêm vào .stu-body một khối KHÔNG cuộn mà rộng (bảng không bọc, khối <pre>,
   ảnh cỡ cố định) là bẫy min-width:auto quay lại ngay, và lúc ấy cả trang sinh
   thanh cuộn ngang chứ không phải riêng khối đó. Đúng cái bẫy đã ghi ở
   .adm-main bên admin.css. */


/* ---------------------------------------------------------------
   THANH BÊN
   --------------------------------------------------------------- */

.stu-side {
    position: sticky;
    /* --nav-stuck-h là chiều cao thanh menu KHI ĐÃ DÍNH (14 + 46). Thiếu nó
       thì mục menu trên cùng chui xuống dưới thanh ấy khi cuộn. */
    top: calc(var(--nav-stuck-h) + 16px);
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.stu-me {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 18px 20px;
    background: var(--smoke);
    border-radius: var(--r-box);
}

.stu-me-hi {
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
}

.stu-me-name {
    font-size: var(--fs-base);
    line-height: 1.35;
    font-weight: 700;
    color: var(--ink);
}

.stu-me-code {
    font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', Consolas, monospace;
    font-size: 12px;
    letter-spacing: .04em;
    color: var(--muted);
}

.stu-nav {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Dùng chung cho cả <a> (trang đã dựng) lẫn <span> (trang 'soon'), nên khai
   display:flex ở đây thay vì trông vào kiểu mặc định của từng thẻ. */
.stu-nav-link {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 11px 14px;
    border-radius: var(--r-media);
    font-size: var(--fs-base);
    line-height: 1.3;
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.stu-nav-link i {
    width: 18px;
    font-size: 15px;
    text-align: center;
    color: var(--green);
}

/* :not(.is-active) KHÔNG phải cho gọn — nó sửa một lỗi thật.
   Chữ `a` ở đầu vốn để loại <span class="is-soon"> khỏi hiệu ứng rê chuột,
   nhưng nó cũng đẩy điểm đặc hiệu lên (0,2,1), cao hơn `.stu-nav-link.is-active`
   ở (0,2,0) — mà độ đặc hiệu thắng bất kể thứ tự viết. Hậu quả: rê chuột lên
   chính mục đang xem thì nền xanh đậm bị thay bằng --green-10, trong khi
   `color: white` của quy tắc kia KHÔNG bị đè (hover không khai màu chữ) — ra
   chữ trắng trên nền xanh rất nhạt, gần như không đọc được.
   Loại thẳng mục đang xem ra là hết, và bộ chọn cũng nói đúng ý định. */
a.stu-nav-link:not(.is-active):hover {
    background: var(--green-10);
}

a.stu-nav-link:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}

.stu-nav-link.is-active {
    color: var(--white);
    background: var(--green);
}

.stu-nav-link.is-active i {
    color: var(--gold);
}

/* Trang chưa dựng. Không có :hover, không có con trỏ tay — nó là <span> nên
   vốn đã không bấm được; phần còn lại chỉ là nói điều đó ra bằng hình ảnh. */
.stu-nav-link.is-soon {
    color: var(--muted);
    cursor: default;
}

.stu-nav-link.is-soon i {
    color: rgba(18, 26, 22, .25);
}

.stu-soon {
    margin-left: auto;

    /* Không có dòng này thì "SẮP CÓ" tự ngắt thành hai dòng ngay trong con
       tem: nó là con út của một flex item đã hết chỗ, nên trình duyệt ngắt ở
       khoảng trắng giữa hai chữ trước khi chịu đẩy tên mục xuống dòng. Kết quả
       là cả tem lẫn tên mục đều vỡ. */
    white-space: nowrap;

    padding: 2px 8px;
    border-radius: var(--r-pill);
    background: var(--gold-10);
    font-size: 10.5px;
    font-style: normal;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--warn);
}

.stu-logout button {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    width: 100%;
    padding: 11px 14px;
    font-family: inherit;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    color: var(--danger);
    background: transparent;
    border: 1px solid rgba(190, 40, 40, .3);
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.stu-logout button:hover {
    background: rgba(190, 40, 40, .06);
    border-color: rgba(190, 40, 40, .5);
}

.stu-logout button:focus-visible {
    outline: 2px solid var(--danger);
    outline-offset: 2px;
}


/* ---------------------------------------------------------------
   THÂN TRANG
   --------------------------------------------------------------- */

.stu-body {
    min-width: 0;
}

.stu-title {
    margin: 0 0 6px;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 700;
    color: var(--ink);
}

.stu-hello {
    margin: 0 0 clamp(20px, 2.2vw, 30px);
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    color: rgba(18, 26, 22, .75);
}

.stu-sec {
    margin-top: clamp(28px, 3vw, 44px);
}

.stu-sec-title {
    margin: 0 0 14px;
    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--card-title);
}

.stu-empty {
    margin: 0;
    padding: 28px 24px;
    text-align: center;
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    color: var(--muted);
    background: var(--smoke);
    border-radius: var(--r-box);
}


/* ---- Dải bốn con số ---- */

.stu-stats {
    display: grid;
    /* auto-fit + minmax: số cột tự co theo bề ngang, không cần media query
       riêng cho từng mốc. */
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 14px;
}

.stu-stat {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 20px;
    background: var(--white);
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
    box-shadow: var(--shadow-card);
}

.stu-stat i {
    display: grid;
    place-items: center;
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--green-10);
    font-size: 17px;
    color: var(--green);
}

.stu-stat-num {
    display: block;
    font-size: var(--fs-md);
    line-height: 1.2;
    font-weight: 700;
    color: var(--ink);
}

.stu-stat-label {
    display: block;
    margin-top: 2px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
}


/* ---- Thẻ lớp học ---- */

.stu-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 16px;
}

.stu-card {
    /* Flex cột chỉ để có một thứ: margin-top:auto của .stu-card-acts đẩy được
       hàng nút xuống đáy thẻ. Các thẻ cùng hàng lưới cao bằng nhau (stretch)
       nhưng ruột dài ngắn khác nhau — lớp có ghi chú lịch học, lớp không — nên
       để mặc thì hàng nút mỗi thẻ nằm một độ cao.

       An toàn với bảng điều khiển (thẻ ở đó không có nút): mọi con đều là khối
       xếp dọc y như cũ. Flex không cho lề dọc của hai anh em chồng lên nhau
       (margin collapsing), nhưng khối này vốn không dựa vào cơ chế ấy — mọi
       con đều khai lề một phía. */
    display: flex;
    flex-direction: column;

    padding: 20px 22px;
    background: var(--white);
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
    box-shadow: var(--shadow-card);
}

.stu-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.stu-card-head h3 {
    margin: 0;
    font-size: var(--fs-base);
    line-height: 1.35;
    font-weight: 700;
    color: var(--card-title);
}

.stu-card-meta {
    margin: 0 0 14px;
    font-size: var(--fs-sm);
    line-height: 1.5;
}

.stu-card-meta > div {
    display: grid;
    /* 104px chứ không phải 92px như bản đầu: nhãn dài nhất giờ là "Ngày kết
       thúc" (thẻ ở /hoc-vien/khoa-hoc tách hai mốc thời gian thành hai dòng),
       92px là vừa đủ để nó xuống dòng trên máy có phông rộng hơn một chút. */
    grid-template-columns: 104px minmax(0, 1fr);
    gap: 10px;
    padding: 4px 0;
}

.stu-card-meta dt {
    color: var(--muted);
}

.stu-card-meta dd {
    margin: 0;
    color: var(--ink);
    /* Tên giáo viên hoặc ghi chú lịch học dài sẽ tràn ra khỏi thẻ nếu không
       cho phép ngắt — đây là chuỗi do admin nhập nên không đoán trước độ dài. */
    overflow-wrap: anywhere;
}

/* Thanh chuyên cần. Nền là máng, <span> bên trong là phần đã đi học. */
.stu-bar {
    height: 7px;
    border-radius: var(--r-pill);
    background: var(--green-10);
    overflow: hidden;
}

.stu-bar span {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--green);
}

.stu-card-foot {
    margin: 9px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
}


/* ---- Con tem trạng thái ----
   Một bộ dùng chung cho ba nhóm giá trị khác nhau (tình trạng học, tình trạng
   thanh toán, tình trạng đơn) vì chúng không bao giờ đứng cạnh nhau trong cùng
   một cột — mắt không phải phân biệt hai con tem cùng màu khác nghĩa. */

.stu-chip {
    display: inline-block;
    flex: none;
    padding: 4px 11px;
    border-radius: var(--r-pill);
    font-size: 11.5px;
    line-height: 1.45;
    font-weight: 700;
    letter-spacing: .02em;
    white-space: nowrap;
    background: rgba(18, 26, 22, .07);
    color: var(--muted);
}

/* Đang diễn ra / đã xong xuôi → xanh lá. */
.stu-chip--studying,
.stu-chip--finished,
.stu-chip--paid,
.stu-chip--approved,
.stu-chip--present {
    background: var(--green-10);
    color: var(--green);
}

/* Cần chú ý, chưa xong → vàng.
   'late' và 'absent_excused' vào đây chứ không vào nhóm đỏ: đi muộn vẫn được
   tính là có đi học (Attendance::ATTENDED), còn vắng có phép là đã báo trước.
   Bôi đỏ cả hai thì học viên mở trang ra thấy một bảng đỏ lòm trong khi chuyên
   cần vẫn đạt — con số nói một đằng, màu nói một nẻo. */
.stu-chip--unpaid,
.stu-chip--partially_paid,
.stu-chip--pending,
.stu-chip--late,
.stu-chip--absent_excused {
    background: var(--gold-10);
    color: var(--warn);
}

/* Đã dừng, không đi tiếp → đỏ. */
.stu-chip--dropped,
.stu-chip--cancelled,
.stu-chip--expired,
.stu-chip--refunded,
.stu-chip--overpaid,
.stu-chip--absent {
    background: var(--danger-10);
    color: var(--danger);
}


/* ---- Bảng đơn đăng ký ---- */

/* Bọc riêng để BẢNG cuộn ngang, không phải cả trang. Đây là lý do .stu-shell
   cần minmax(0, 1fr) — thiếu nó thì overflow này vô tác dụng. */
.stu-tablewrap {
    width: 100%;
    overflow-x: auto;
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
}

.stu-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-sm);
    line-height: 1.5;
}

.stu-table th,
.stu-table td {
    padding: 12px 14px;
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--green-10);
    white-space: nowrap;
}

.stu-table thead th {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--white);
    background: var(--green);
}

.stu-table tbody tr:last-child td {
    border-bottom: none;
}

.stu-table a {
    font-weight: 700;
    color: var(--green);
    text-decoration: none;
}

.stu-table a:hover {
    text-decoration: underline;
}

/* Cột khóa học ở bảng lịch sử thanh toán: tên khóa dài, cho phép xuống dòng
   thay vì ép cả bảng rộng ra. Các cột khác vẫn giữ white-space: nowrap. */
.stu-cell-wrap {
    white-space: normal;
    min-width: 180px;
    max-width: 320px;
}

/* Dòng "còn N đơn nữa" dưới bảng. Cỡ chữ nhỏ và màu mờ vì nó là chú thích cho
   bảng, không phải một mục nội dung ngang hàng. */
.stu-more {
    margin: 10px 2px 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
}

.stu-more a {
    font-weight: 700;
    color: var(--green);
}



/* ---------------------------------------------------------------
   THANH TAB — trang /hoc-vien/khoa-hoc
   --------------------------------------------------------------- */

/* Là các thẻ <a> tải lại trang chứ không phải nút JavaScript, nên phải TRÔNG
   như tab mà vẫn CƯ XỬ như liên kết: có :focus-visible, có aria-current, và
   đổi trạng thái bằng chính đường dẫn. Xem ghi chú trong student/courses.php. */
.stu-tabs {
    display: flex;

    /* Trang /hoc-vien/khoa-hoc chỉ có hai nhãn ngắn nên không bao giờ xuống
       hàng. Nhưng /hoc-vien/diem-danh dùng lại cụm này làm BỘ CHỌN LỚP, mà
       nhãn ở đó là tên lớp đầy đủ ("ĐGNL Toàn diện – K12 – Khai giảng 15/08")
       — ba lớp là tràn. Cho xuống hàng tốt hơn cuộn ngang: cuộn ngang thì lớp
       thứ ba nằm ngoài màn hình và không ai biết nó có ở đó. */
    flex-wrap: wrap;

    gap: 8px;
    margin-bottom: clamp(18px, 2vw, 26px);

    /* 3px đệm quanh các tab để vòng focus (outline-offset: 2px) không bị cắt
       cụt: ở màn hẹp cụm này thành khung cuộn ngang, mà overflow-x: auto kéo
       theo overflow-y: auto — cắt cả chiều dọc. Đệm nằm BÊN TRONG nên bề ngoài
       của cụm không đổi, đường kẻ dưới vẫn chạy hết bề ngang nội dung. */
    padding: 3px 3px 10px;

    /* Đường kẻ chạy hết bề ngang phía dưới cả cụm — cái neo thị giác nói rằng
       nội dung bên dưới thuộc về tab đang sáng, không phải một khối rời. */
    border-bottom: 1px solid var(--green-10);
}

.stu-tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border-radius: var(--r-pill);
    font-size: var(--fs-base);
    line-height: 1.3;
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    background: var(--smoke);
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

/* :not(.is-active) vì đúng lý do đã ghi ở a.stu-nav-link — nền hover sáng đè
   mất nền xanh đậm của tab đang xem trong khi màu chữ trắng vẫn giữ nguyên,
   ra chữ trắng trên nền nhạt. Loại thẳng tab đang xem ra là hết. */
.stu-tab:not(.is-active):hover {
    background: var(--green-10);
    color: var(--green);
}

.stu-tab:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}

.stu-tab.is-active {
    color: var(--white);
    background: var(--green);
}

/* Số lớp trong tab. Nền nửa trong suốt chứ không phải một màu cứng: cùng một
   quy tắc phải đọc được trên CẢ nền xám của tab thường LẪN nền xanh đậm của
   tab đang xem — màu cứng thì một trong hai nền sẽ nuốt mất nó. */
.stu-tab-num {
    min-width: 22px;
    padding: 1px 7px;
    border-radius: var(--r-pill);
    background: rgba(18, 26, 22, .09);
    font-size: 11.5px;
    font-weight: 700;
    text-align: center;
}

.stu-tab.is-active .stu-tab-num {
    background: rgba(255, 255, 255, .22);
}


/* ---- Nút tắt dưới thẻ lớp ---- */

/* margin-top: auto đẩy cụm nút xuống ĐÁY thẻ. Cần nó vì .stu-card là flex cột
   trong một lưới có align-items mặc định là stretch: các thẻ cùng hàng cao
   bằng nhau, nhưng phần thông tin bên trong dài ngắn khác nhau (lớp có ghi chú
   lịch học, lớp không). Thiếu dòng này thì hàng nút mỗi thẻ nằm một độ cao,
   trông như lỗi dựng trang. */
.stu-card-acts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: auto;
    padding-top: 14px;
}

.stu-act {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 14px;
    border-radius: var(--r-pill);
    border: 1px solid var(--green-10);
    font-size: var(--fs-sm);
    line-height: 1.3;
    font-weight: 700;
    color: var(--green);
    text-decoration: none;
    background: var(--white);
    transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
}

.stu-act i {
    font-size: 13px;
}

/* a. ở đầu để <span class="is-soon"> không dính hiệu ứng — nút chưa dùng được
   thì không được sáng lên khi rê chuột qua. */
a.stu-act:hover {
    color: var(--white);
    background: var(--green);
    border-color: var(--green);
}

a.stu-act:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}

/* Trang đích chưa dựng. Nó là <span> nên vốn đã không bấm được; phần này chỉ
   nói điều đó ra bằng hình ảnh — cùng quy ước với .stu-nav-link.is-soon. */
.stu-act.is-soon {
    color: var(--muted);
    background: var(--smoke);
    border-color: transparent;
    cursor: default;
}

.stu-act.is-soon i {
    color: rgba(18, 26, 22, .25);
}

/* Con tem "sắp có" dùng lại .stu-soon của thanh bên, nhưng ở đó nó có
   margin-left: auto để dạt về mép phải của một mục menu chiếm hết bề ngang.
   Nút tắt thì co theo nội dung nên không có khoảng trống nào để 'auto' ăn vào
   — vô hại, nhưng gỡ ra cho bộ chọn nói đúng ý định. */
.stu-act .stu-soon {
    margin-left: 0;
}


/* ---------------------------------------------------------------
   LỊCH SỬ ĐIỂM DANH — trang /hoc-vien/diem-danh
   --------------------------------------------------------------- */

/* Trang này dùng lại gần như toàn bộ khối trên: .stu-tabs làm bộ chọn lớp,
   .stu-cards + thẻ lớp làm tiêu đề, .stu-stats làm dải bốn con số,
   .stu-tablewrap + .stu-table làm bảng. Phần dưới đây chỉ là những chỗ bảng
   điểm danh khác bảng đơn hàng. */

/* Một thẻ lớp đứng một mình. .stu-cards là lưới auto-fit minmax(300px, 1fr)
   nên với một phần tử nó vốn đã chiếm hết bề ngang — khai lại 1 cột cho rõ ý
   "ở đây cố tình chỉ có một thẻ", và để thêm thẻ thứ hai vào sau này là thấy
   ngay mình đang phá vỡ giả định gì. */
.stu-cards--one {
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: clamp(6px, 1vw, 12px);
}

/* <caption> chỉ dành cho trình đọc màn hình. Bảng đã có <h2> "Chi tiết từng
   buổi" ngay trên đầu và thẻ lớp ngay trước đó, nên in caption ra là lặp lại
   thông tin bằng mắt. Nhưng khi nhảy giữa các bảng bằng phím tắt của trình đọc
   màn hình thì <h2> KHÔNG được đọc kèm — caption mới là thứ nói cho họ biết
   bảng này là bảng gì.

   Không dùng display:none hay visibility:hidden: cả hai đều gỡ phần tử khỏi
   cây trợ năng, tức là trình đọc màn hình cũng không thấy nốt. Cách duy nhất
   đúng là thu về 1px rồi cắt đi. */
.stu-table-cap {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Ô đầu mỗi dòng là <th scope="row">, không phải <td>. Trình duyệt mặc định in
   <th> đậm và căn giữa — trả nó về cùng dáng với các ô còn lại, chỉ giữ lại
   nét đậm vừa phải để mắt bám được cột số buổi khi cuộn. */
.stu-table tbody th.stu-sess-no {
    font-weight: 700;
    text-align: left;
    color: var(--card-title);
}

/* Giờ học đứng sau ngày, cùng ô. Nhỏ và mờ hơn vì nó là thông tin phụ — ngày
   mới là thứ học viên dò tìm. */
.stu-sess-time {
    margin-left: 6px;
    font-size: 11.5px;
    color: var(--muted);
}

/* Ô ghi chú của giáo viên.

   .stu-table đặt white-space: nowrap cho MỌI ô — đúng với bảng đơn hàng nơi
   mọi giá trị đều ngắn và cố định. Ghi chú thì ngược lại: chuỗi tự do, có thể
   là cả một câu. Không gỡ nowrap ở đây thì một ghi chú hai dòng kéo bảng rộng
   gấp ba và học viên phải cuộn ngang để đọc hết.

   min-width giữ cột đủ rộng để câu không bị bẻ thành từng chữ một; max-width
   chặn chiều ngược lại, cho ghi chú dài tự xuống dòng thay vì chiếm cả bảng. */
/* Cột "Thời gian tham gia" ở bảng điểm danh cá nhân — /hoc-vien/diem-danh.
   Số phút, giờ vào–ra và số lần vào/ra do phần mềm dạy trực tuyến ghi lại.

   .stu-table đặt white-space: nowrap cho MỌI ô nên ba mẩu thông tin này nằm
   đè lên một hàng. Ép lại thành cột dọc: mỗi mẩu một dòng, đọc từ trên xuống
   giống hệt cách nói "70 phút, từ 21:50 đến 23:02, ra vào 2 lần".
   tabular-nums để các chữ số thẳng cột giữa các buổi, mắt so được theo chiều
   dọc mà không phải đọc từng con số. */
.stu-att-detail {
    white-space: normal;
    font-variant-numeric: tabular-nums;
    line-height: 1.5;
}

.stu-att-detail .stu-sess-time {
    display: block;
}

/* Các chặng vào/ra thật, gấp trong <details>.

   Học viên rớt mạng bảy lần thì bảy dòng ấy là câu trả lời cho "vì sao con
   tôi bị ghi có mặt mà lại chỉ học được 20 phút". Nhưng bày sẵn thì hàng đó
   cao gấp năm hàng khác trong khi đa số buổi chẳng có gì để xem — nên gấp
   lại, ai cần thì mở. */
.stu-spans {
    margin-top: 2px;
}

.stu-spans > summary {
    cursor: pointer;
    font-size: .82rem;
    color: var(--muted, #696984);
}

.stu-spans > summary:hover {
    color: var(--green, #1B5E3F);
}

.stu-spans > summary:focus-visible {
    outline: 2px solid var(--green, #1B5E3F);
    outline-offset: 2px;
    border-radius: 3px;
}

.stu-spans-list {
    margin: 6px 0 0;
    padding-left: 18px;
    font-size: .82rem;
    line-height: 1.7;
    color: var(--muted, #696984);
    white-space: normal;
}

/* nowrap Ở TỪNG DÒNG, không ở cả danh sách.
   .stu-table đặt nowrap cho mọi ô nên danh sách phải gỡ ra (normal) mới xuống
   dòng được giữa các chặng — nhưng gỡ xong thì chính MỘT chặng cũng gãy đôi:
   "1. 21:29:17 →" rồi xuống dòng "21:33:57", đọc thành hai mốc rời rạc. Cấm
   xuống dòng ở <li> là mỗi chặng liền một mạch, còn các chặng vẫn xếp dọc. */
.stu-spans-list li {
    white-space: nowrap;
}

.stu-note-cell {
    white-space: normal;
    min-width: 200px;
    max-width: 420px;

    /* Giáo viên có thể dán vào một chuỗi không dấu cách (đường dẫn, mã bài).
       Thiếu dòng này thì chính chuỗi ấy phá vỡ cả max-width ở trên. */
    overflow-wrap: anywhere;
}

/* Buổi chưa diễn ra. Viền nét đứt, nền trong suốt — khác hẳn con tem đặc của
   các trạng thái đã chốt, để mắt tách ngay "lịch sắp tới" khỏi "kết quả đã
   có". Nếu để nó dùng nền xám mặc định của .stu-chip thì nó giống hệt con tem
   "Chưa điểm danh", mà hai thứ ấy mang hai nghĩa hoàn toàn khác nhau. */
.stu-chip--upcoming {
    background: transparent;
    border: 1px dashed rgba(18, 26, 22, .22);
    color: var(--muted);

    /* Bù lại 1px viền vừa thêm, để con tem này cao đúng bằng các con tem khác
       trên cùng một cột — lệch 2px là cả cột nhấp nhô. */
    padding: 3px 10px;
}


/* Gạch ngang thay cho ô trống. In "—" chứ không để trống hẳn vì ô trống trông
   như dữ liệu chưa tải xong, còn gạch ngang nói rõ "có xem, và không có gì". */
.stu-dash {
    color: rgba(18, 26, 22, .35);
}

/* Dòng của buổi đã hủy. Làm mờ cả dòng chứ không chỉ đổi con tem: buổi ấy
   không diễn ra nên mọi ô trên dòng đều là thông tin đã hết hiệu lực, và mắt
   phải lướt qua được nó mà không phải đọc.

   KHÔNG dùng text-decoration: line-through — gạch ngang chữ nghĩa là "sai/đã
   bỏ", trong khi ngày và số buổi ở đây vẫn đúng, chỉ là buổi không diễn ra. */
.stu-table tr.is-cancelled th,
.stu-table tr.is-cancelled td {
    color: var(--muted);
    background: rgba(18, 26, 22, .022);
}


/* ---------------------------------------------------------------
   BẢNG ĐIỂM CÁ NHÂN — trang /hoc-vien/bang-diem
   --------------------------------------------------------------- */

/* Lại dùng chung gần hết khối trên: .stu-tabs làm thanh lọc lớp, .stu-stats
   làm dải bốn con số, .stu-tablewrap + .stu-table làm bảng, .stu-bar làm thanh
   tỉ lệ. Dưới đây chỉ là những chỗ bảng điểm khác bảng điểm danh. */

/* Ô đầu mỗi dòng — tên bài kiểm tra, xếp ba tầng chữ.
   Phải tự gỡ white-space: nowrap mà .stu-table đặt cho mọi ô: tên bài và dòng
   điểm thành phần đều là chuỗi dài do admin nhập, để nowrap thì bảng rộng ra
   vô hạn. Cùng lý do đã ghi ở .stu-note-cell. */
.stu-exam-cell {
    white-space: normal;
    min-width: 240px;
    max-width: 460px;
    font-weight: 400;
    text-align: left;
    overflow-wrap: anywhere;
}

.stu-exam-name {
    display: block;
    font-weight: 700;
    color: var(--card-title);
}

/* Đợt thi và lớp. Nhỏ và mờ vì là thông tin định vị, không phải nội dung chính
   của dòng. */
.stu-exam-sub {
    display: block;
    margin-top: 2px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--muted);
}

/* Điểm thành phần: một dòng chữ nhỏ, các phần cách nhau bằng dấu chấm giữa.
   KHÔNG làm thành bảng con hay danh sách: với ba đến bốn phần thi thì một dòng
   đọc nhanh hơn, mà cũng không phá vỡ quan hệ hàng–cột của bảng — thứ trình
   đọc màn hình dựa vào để đọc đúng "Bài kiểm tra … Điểm … Xếp hạng". */
.stu-exam-parts {
    display: block;
    margin-top: 5px;
    font-size: 11.5px;
    line-height: 1.55;
    color: var(--muted);
}

.stu-exam-parts b {
    font-weight: 700;
    color: var(--ink);
}

/* Ô điểm. Điểm đạt in đậm cỡ lớn, thang điểm nhỏ và mờ đứng sau — mắt bắt số
   quan trọng trước, rồi mới đọc mẫu số nếu cần. */
.stu-score-cell b {
    font-size: 15px;
    font-weight: 800;
    color: var(--green);
}

.stu-score-max {
    margin-left: 3px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--muted);
}

/* Thanh tỉ lệ trong ô bảng: thanh và con số nằm ngang nhau. Cho thanh một bề
   ngang cố định thay vì để nó co theo cột — các dòng phải so sánh được với
   nhau bằng mắt, mà thanh mỗi dòng một độ dài thì so bằng gì. */
.stu-ratio {
    display: flex;
    align-items: center;
    gap: 9px;
}

.stu-ratio .stu-bar {
    width: 84px;
    flex: none;
}

.stu-ratio-num {
    font-size: 12px;
    font-weight: 700;
    color: var(--ink);
}

/* Mũi tên tiến bộ ở thẻ thứ tư của dải số liệu.
   Màu là thứ YẾU, không phải thứ duy nhất mang nghĩa: ngay cạnh con số đã có
   dấu +/− và icon mũi tên lên/xuống, nên người không phân biệt được màu vẫn
   đọc đúng. Đây là lý do không dùng riêng màu để phân biệt tăng và giảm. */
.stu-stat-num.is-up {
    color: var(--green);
}

.stu-stat-num.is-down {
    color: var(--danger);
}

/* ---------------------------------------------------------------
   TRANG HỒ SƠ — /hoc-vien/ho-so
   --------------------------------------------------------------- */

/* Khối chỉ-đọc ở đầu trang: mã học viên, SĐT, các mốc thời gian.
   <dl> chứ không phải bảng — đây là các cặp nhãn–giá trị của MỘT đối tượng,
   không phải nhiều hàng cùng cấu trúc. Mỗi cặp bọc trong một <div> để lưới
   xếp được chúng thành ô; đặt grid thẳng lên <dl> thì dt và dd rơi vào hai ô
   rời nhau và mất luôn quan hệ nhãn–giá trị khi màn hình đổi bề ngang. */
.stu-info {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 14px;
    margin: 0;
    padding: 20px 22px;
    background: var(--white);
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
    box-shadow: var(--shadow-card);
}

.stu-info dt {
    margin-bottom: 4px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    color: var(--muted);
}

.stu-info dd {
    margin: 0;
    font-size: var(--fs-base);
    line-height: 1.5;
    font-weight: 700;
    color: var(--ink);
}

/* "cũng là tên đăng nhập của bạn" — chú thích đi kèm giá trị, phải nhẹ hơn hẳn
   để không bị đọc nhầm thành một phần của chính số điện thoại. */
.stu-info-note {
    display: block;
    margin-top: 2px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 500;
    color: var(--muted);
}

/* Câu giải thích vì sao SĐT không sửa được. Nền vàng nhạt chứ không đỏ: đây là
   một lời dặn, không phải một lỗi. */
.stu-lock {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 12px 0 0;
    padding: 14px 16px;
    font-size: var(--fs-sm);
    line-height: var(--lh-loose);
    color: var(--warn);
    background: var(--gold-10);
    border: 1px solid var(--gold-30);
    border-radius: var(--r-box);
}

/* Biểu tượng không được co lại khi câu chữ dài ra và xuống dòng. */
.stu-lock i {
    flex: none;
    margin-top: 5px;
}

.stu-lock a {
    font-weight: 700;
    color: var(--warn);
    text-decoration: underline;
}

/* ---- Hai biểu mẫu ---- */

/* max-width chứ không để giãn hết cột: một ô nhập rộng 880px thì mắt phải đi
   hết chiều ngang màn hình mới soát lại được cái tên vừa gõ. Các bảng ở những
   trang khác thì ngược lại — chúng cần mọi milimet có được. */
.stu-form {
    max-width: 620px;
    padding: 22px 24px;
    background: var(--white);
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
    box-shadow: var(--shadow-card);
}

.stu-field + .stu-field {
    margin-top: 18px;
}

.stu-field label {
    display: block;
    margin-bottom: 6px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 700;
    color: var(--card-title);
}

/* Dấu sao bắt buộc. aria-hidden trong HTML vì thuộc tính required trên chính ô
   nhập mới là thứ trình đọc màn hình dùng — để cả hai thì nghe thành "sao, bắt
   buộc" ở mọi trường. */
.stu-req {
    color: var(--danger);
}

.stu-field input {
    width: 100%;
    padding: 12px 14px;
    font-family: var(--font);
    font-size: var(--fs-base);
    line-height: 1.4;
    color: var(--ink);
    background: var(--white);
    border: 1px solid var(--green-15);
    border-radius: var(--r-box);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.stu-field input::placeholder {
    color: rgba(105, 105, 132, .7);
}

/* :focus-visible chứ không :focus — bấm chuột vào ô nhập thì con trỏ nhấp nháy
   đã đủ nói ô nào đang nhận chữ, thêm một vòng sáng nữa là thừa. */
.stu-field input:focus-visible {
    outline: none;
    border-color: var(--green);
    box-shadow: 0 0 0 3px var(--green-10);
}

/* Ô vừa nhập sai. Viền đỏ chỉ là lớp phụ: câu lỗi bằng chữ ngay dưới mới là
   thứ mang nghĩa, nên người không phân biệt được màu vẫn hiểu chuyện gì. */
.stu-field input[aria-invalid="true"] {
    border-color: var(--danger);
    background: var(--danger-10);
}

.stu-field input[aria-invalid="true"]:focus-visible {
    box-shadow: 0 0 0 3px var(--danger-10);
}

/* Bọc ô mật khẩu và nút con mắt. position: relative để nút định vị tuyệt đối
   được bám vào đây chứ không bám ra cả trang. */
.stu-input-wrap {
    position: relative;
}

/* Chừa chỗ cho nút, nếu không thì mật khẩu dài chui xuống dưới biểu tượng. */
.stu-input-wrap input {
    padding-right: 48px;
}

/* Cùng khuôn với .auth-eye ở trang đăng nhập — chung một JavaScript
   ([data-pw-toggle]) thì cũng nên chung một dáng. 40px là mức tối thiểu bấm
   trúng bằng ngón tay; bản thân biểu tượng chỉ ~16px. */
.stu-eye {
    position: absolute;
    top: 50%;
    right: 4px;
    transform: translateY(-50%);

    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;

    padding: 0;
    background: none;
    border: 0;
    border-radius: var(--r-row);
    color: var(--muted);
    font-size: 15px;
    cursor: pointer;
    transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}

.stu-eye:hover {
    color: var(--green);
    background: var(--green-10);
}

.stu-eye:focus-visible {
    outline: none;
    color: var(--green);
    box-shadow: 0 0 0 3px var(--green-10);
}

/* Đang hiện mật khẩu: đổi màu để trạng thái nhìn thấy được, không chỉ dựa vào
   việc biểu tượng đổi từ con mắt sang con mắt gạch chéo (khác biệt khá nhỏ). */
.stu-eye[aria-pressed="true"] {
    color: var(--green);
}

.stu-err {
    margin: 6px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    color: var(--danger);
}

.stu-hint {
    margin: 6px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-loose);
    color: var(--muted);
}

/* Hàng cuối biểu mẫu. flex-wrap để trên màn hình hẹp câu chú thích xuống dòng
   nằm dưới nút, thay vì bóp nút lại thành hai dòng chữ. */
.stu-form-foot {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px 16px;
    margin-top: 22px;
}

/* flex: 1 1 200px — câu chú thích chiếm phần còn lại của hàng khi còn chỗ, và
   tự nhảy xuống dòng riêng khi phần còn lại hẹp hơn 200px. */
.stu-form-foot .stu-form-note {
    flex: 1 1 200px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
}


/* ---------------------------------------------------------------
   MÀN HÌNH HẸP — phải nằm CUỐI khối, xem ghi chú đầu #region
   --------------------------------------------------------------- */

/* Thanh bên hết chỗ đứng cạnh nội dung: đưa nó lên trên thành một dải ngang.
   KHÔNG làm ngăn kéo trượt như khu quản trị — ở đó menu có 13 mục chia bốn
   nhóm, còn đây chỉ sáu mục phẳng, một dải cuộn ngang là đủ mà không cần thêm
   một dòng JavaScript nào. */
@media (max-width: 1000px) {
    .stu-shell {
        grid-template-columns: minmax(0, 1fr);
    }

    .stu-side {
        position: static;
        gap: 14px;
    }

    /* KHÔNG cần min-width: 0 ở đây, dù .stu-side là ô lưới còn .stu-nav là
       flex item — hai chỗ mà bẫy min-width:auto hay xuất hiện. Chính dòng
       overflow-x: auto dưới đây gỡ bẫy: kích thước tối thiểu tự động của một
       phần tử có overflow khác 'visible' được tính bằng 0, nên dải menu tự co
       lại và cuộn trong lòng nó thay vì kéo giãn cả trang. Đã đo lại bằng
       scrollWidth ở 320/360/390px — bỏ hay thêm min-width đều không tràn. */
    .stu-nav {
        flex-direction: row;
        gap: 8px;
        overflow-x: auto;

        /* Chừa chỗ cho vòng focus khỏi bị khung cuộn cắt cụt. */
        padding: 3px;
        margin: -3px;
        scrollbar-width: none;
    }

    .stu-nav::-webkit-scrollbar {
        display: none;
    }

    .stu-nav-link {
        flex: none;
        white-space: nowrap;
    }

    /* Nhãn "sắp có" ăn chỗ của tên mục trên dải ngang, mà ở đây chữ mờ và
       không bấm được đã đủ nói lên điều đó rồi. */
    .stu-soon {
        display: none;
    }

    .stu-logout {
        display: flex;
        justify-content: flex-end;
    }

    .stu-logout button {
        width: auto;
        padding-inline: 20px;
    }
}

@media (max-width: 700px) {
    .stu-cards {
        grid-template-columns: minmax(0, 1fr);
    }

    .stu-stats {
        grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
        gap: 12px;
    }

    .stu-stat {
        gap: 12px;
        padding: 14px 15px;
    }

    .stu-stat i {
        width: 38px;
        height: 38px;
        font-size: 15px;
    }

    /* Vùng chạm: mọi đích bấm của cổng này trên điện thoại phải đạt 42px như
       mọi nút khác trong dự án — mục menu, nút đăng xuất, tab lọc lớp và nút
       tắt dưới thẻ. */
    .stu-nav-link,
    .stu-logout button,
    .stu-tab,
    .stu-act {
        min-height: 42px;
    }

    /* flex-wrap ở quy tắc gốc đã lo việc tràn, nên KHÔNG cần cuộn ngang ở đây.
       Chỉ chặn một thứ: nhãn dài hơn cả bề ngang màn hình thì chính thẻ pill
       phải co lại và cho chữ xuống dòng, thay vì đẩy cả trang rộng ra. */
    .stu-tab {
        max-width: 100%;
    }

    .stu-card {
        padding: 16px 17px;
    }

    /* Dưới ~430px cột nhãn 104px ép giá trị vào một dải quá hẹp: ngày tháng và
       tên giáo viên bắt đầu ngắt dòng giữa chừng. Cho nhãn lên trên. */
    .stu-card-meta > div {
        grid-template-columns: minmax(0, 1fr);
        gap: 1px;
    }
}

/* Người bật "giảm chuyển động" trong hệ điều hành thường là vì chuyển động gây
   chóng mặt. Ở khối này chỉ còn các hiệu ứng đổi nền khi rê chuột — mục menu,
   nút đăng xuất, tab lọc lớp, nút tắt dưới thẻ. Tắt đi thì chúng đổi tức thì,
   vẫn thấy rõ đang trỏ vào đâu. */
@media (prefers-reduced-motion: reduce) {

    .stu-nav-link,
    .stu-logout button,
    .stu-tab,
    .stu-act {
        transition: none;
    }
}

/* #endregion */


/* =====================================================================
   #region C19 · TRỢ LÝ TƯ VẤN NỔI — mọi trang công khai

   Gộp về đây từ file chatbot.css riêng. Lý do cũ ghi trên đầu file ấy là "để
   app.css khỏi phình thêm", nhưng dự án đã chốt MỘT file cho phần công khai:
   thêm một <link> nữa là thêm một lượt chờ tải chặn hiển thị trên mọi trang,
   và người sau đi tìm một class .cep-chat__* sẽ không đoán được nó nằm ở file
   nào. Chỉ news.css còn đứng riêng, vì nó chỉ nạp cho hai trang tin tức.

   Toàn khối tự cô lập trong .cep-chat: sáu biến --cb-* khai ngay trên chính
   phần tử gốc chứ không đụng vào :root, nên nó không kéo theo màu nào của
   trang và cũng không bị trang kéo ngược. Giữ nguyên như vậy khi sửa.

   Phần MÀN HÌNH HẸP nằm ở CUỐI khối — media query không tự cộng độ đặc hiệu
   nên quy tắc gốc viết sau sẽ đè ngược lại nó.
   ===================================================================== */

/* Chấm tròn báo tin mới được chatbot.js bật/tắt bằng thuộc tính hidden. Luật
   .cep-chat__badge ngay dưới đặt display:grid, mà display của tác giả luôn
   thắng display:none mặc định của [hidden] — thiếu dòng này thì gọi
   el.hidden = true xong chấm tròn vẫn nằm nguyên đó. */
.cep-chat__badge[hidden] { display: none; }

.cep-chat.is-disabled{display:none!important}
.cep-chat{--cb-green:#176747;--cb-green-dark:#0e5137;--cb-soft:#f5f8f6;--cb-line:#dde7e1;--cb-text:#26332d;--cb-muted:#708078;position:fixed;right:26px;bottom:24px;z-index:1200;font-family:'Montserrat',sans-serif;color:var(--cb-text)}
.cep-chat *{box-sizing:border-box}
.cep-chat .sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}
.cep-chat button,.cep-chat textarea{font:var(--font)}
/* 1.75rem, không phải 2rem như trước: nút mẹ vừa co từ 58px xuống 50px (để
   bằng đúng cỡ hai nút Zalo/Gọi điện nổi bên cạnh — xem #region C21), icon
   phải co theo cùng tỉ lệ (50/58) để không bị chật khung. */
.cep-chat button.cep-chat__launcher i {font-size: 1.75rem;}
.cep-chat button.cep-chat__launcher i.fa-comment {display: block}
.cep-chat button.cep-chat__launcher i.fa-x {display: none}
.cep-chat.is-open button.cep-chat__launcher i.fa-comment {display: none}
.cep-chat.is-open button.cep-chat__launcher i.fa-x {display: block}
/* 50px, không phải 58px như bản gốc — chỉnh để BẰNG ĐÚNG cỡ hai nút Zalo và
   Gọi điện nổi bên cạnh (.cep-float__btn, #region C21), theo yêu cầu của
   khách: ba nút đứng chồng thành một cụm thì phải cùng một cỡ mắt mới đọc ra
   là một bộ. ĐỔI SỐ NÀY THÌ PHẢI ĐỔI THEO Ở #region C21 (biến $cep-float
   dùng chính con số 50 này để tính khoảng cách xếp chồng) VÀ hai chỗ khác
   ngay dưới đây: .cep-chat__hint (right:72px → 64px) và .cep-chat__panel
   (bottom:74px → 66px) — cả hai đều neo theo đúng chiều cao nút này. */
.cep-chat__launcher{position:relative;width:50px;height:50px;border:0;border-radius:50%;background:var(--cb-green);color:#fff;display:grid;place-items:center;font-size:22px;cursor:pointer;box-shadow:0 12px 30px rgba(20,73,52,.22);transition:transform .2s ease,background .2s ease,box-shadow .2s ease}
.cep-chat__launcher:hover{background:var(--cb-green-dark);transform:translateY(-2px);box-shadow:0 16px 34px rgba(20,73,52,.28)}
.cep-chat__launcher:focus-visible,.cep-chat__close:focus-visible,.cep-chat__form button:focus-visible,.cep-chat__topic:focus-visible,.cep-chat__hint button:focus-visible{outline:3px solid rgba(23,103,71,.25);outline-offset:3px}
.cep-chat.is-open .cep-chat__launcher{transform:scale(.92)}
.cep-chat__badge{position:absolute;right:-6px;top:-6px;min-width:24px;height:24px;padding:0 4px;border-radius:99px;background:#f4a100;color:#fff;border:2px solid #fff;font-size:10px;font-weight:700;display:grid;place-items:center}
.cep-chat.is-open .cep-chat__badge{display:none}
/* right:64px = cỡ nút mới (50px) + khoảng thở (14px), giữ nguyên đúng khe hở
   14px đã có với bản 58px trước (58+14=72). */
.cep-chat__hint{position:absolute;right:64px;bottom:4px;width:264px;min-height:48px;padding:12px 34px 12px 15px;border:1px solid #edf1ef;background:#fff;border-radius:12px;color:#55645d;font-size:11px;font-weight:600;line-height:1.45;box-shadow:0 10px 30px rgba(32,53,44,.09);animation:cb-in .3s ease both}
.cep-chat__hint:after{content:"";position:absolute;right:-7px;bottom:17px;width:12px;height:12px;background:#fff;border-right:1px solid #edf1ef;border-top:1px solid #edf1ef;transform:rotate(45deg)}
.cep-chat__hint button{position:absolute;right:8px;top:7px;border:0;background:transparent;color:#8b9691;cursor:pointer;font-size:17px;line-height:1}
/* bottom:66px = cỡ nút mới (50px) + khoảng thở (16px), giữ nguyên đúng khe hở
   16px đã có với bản 58px trước (58+16=74) — thiếu bước này thì bảng chat mở
   ra để hở 24px phía trên nút thay vì 16px như thiết kế gốc. */
.cep-chat__panel{position:absolute;right:0;bottom:66px;width:min(380px,calc(100vw - 32px));height:min(610px,calc(100vh - 120px));background:#fff;border:1px solid #dce5e0;border-radius:18px;box-shadow:0 24px 70px rgba(24,55,41,.20);overflow:hidden;display:flex;flex-direction:column;opacity:0;visibility:hidden;transform:translateY(14px) scale(.98);transform-origin:right bottom;transition:opacity .2s ease,transform .2s ease,visibility .2s}
.cep-chat.is-open .cep-chat__panel{opacity:1;visibility:visible;transform:none}
.cep-chat__head{min-height:72px;background:var(--cb-green);color:#fff;padding:13px 14px;display:flex;align-items:center;gap:11px}
.cep-chat__bot-icon{width:38px;height:38px;border-radius:12px;background:rgba(255,255,255,.14);display:grid;place-items:center;font-size:16px}
.cep-chat__identity{min-width:0;display:flex;flex-direction:column;gap:3px;flex:1}
.cep-chat__identity strong{font-size:14px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cep-chat__identity>span{display:flex;align-items:center;gap:6px;color:rgba(255,255,255,.78);font-size:10.5px}
.cep-chat__identity i{width:6px;height:6px;background:#8ee5b5;border-radius:50%;box-shadow:0 0 0 3px rgba(142,229,181,.13)}
.cep-chat__close{width:34px;height:34px;border:0;border-radius:10px;background:rgba(255,255,255,.12);color:#fff;cursor:pointer;font-size:16px}
.cep-chat__close:hover{background:rgba(255,255,255,.2)}
.cep-chat__body{flex:1;min-height:0;overflow:auto;padding:17px 15px 14px;background:#f7f9f8;scroll-behavior:smooth}
.cep-chat__messages{display:flex;flex-direction:column;gap:10px}
.cep-chat__message{max-width:88%;padding:10px 12px;border-radius:13px;font-size:12px;line-height:1.55;white-space:pre-wrap;word-break:break-word;animation:cb-msg .2s ease both}
.cep-chat__message.is-bot{align-self:flex-start;background:#fff;border:1px solid #e3eae6;border-top-left-radius:5px; font-size: 13px; box-shadow:0 5px 14px rgba(37,62,50,.05)}
.cep-chat__message.is-user{align-self:flex-end;background:var(--cb-green);color:#fff;border-top-right-radius:5px}
.cep-chat__message.is-error{background:#fff7f5;border-color:#f1c8bd;color:#984a38}
.cep-chat__typing{align-self:flex-start;width:54px;height:34px;border-radius:12px;border-top-left-radius:5px;background:#fff;border:1px solid #e3eae6;display:flex;align-items:center;justify-content:center;gap:4px}
.cep-chat__typing i{width:5px;height:5px;border-radius:50%;background:#8da097;animation:cb-dot 1s infinite ease-in-out}
.cep-chat__typing i:nth-child(2){animation-delay:.13s}.cep-chat__typing i:nth-child(3){animation-delay:.26s}
/* =========================================================
   CHAT SUGGESTIONS
========================================================= */

.cep-chat__suggestions {
    margin-top: 15px;
    padding-top: 11px;
    border-top: 1px solid #e2e9e5;
}


/* Header nhỏ của khu vực gợi ý */

.cep-chat__suggestions-head {
    min-height: 28px;

    display: flex;
    align-items: center;
    justify-content: space-between;

    margin-bottom: 8px;
}

.cep-chat__suggestions-head > span {
    display: inline-flex;
    align-items: center;
    gap: 6px;

    color: #78867f;

    font-size: 9.5px;
    font-weight: 600;
}

.cep-chat__suggestions-head > span i {
    color: var(--cb-green);
    font-size: 10px;
}


/* Nút mũi tên thu gọn */

.cep-chat__suggestions-toggle {
    width: 27px;
    height: 27px;

    padding: 0;
    border: 0;
    border-radius: 8px;

    display: grid;
    place-items: center;

    background: transparent;
    color: #708078;

    cursor: pointer;

    transition:
        background .2s ease,
        color .2s ease,
        transform .2s ease;
}

.cep-chat__suggestions-toggle:hover {
    background: #eaf2ee;
    color: var(--cb-green);
}

.cep-chat__suggestions-toggle i {
    font-size: 10px;
}


/* =========================================================
   COLLAPSE ANIMATION
========================================================= */

.cep-chat__suggestions-content {
    max-height: 1000px;

    opacity: 1;
    overflow: hidden;

    transition:
        max-height .3s ease,
        opacity .2s ease;
}

.cep-chat__suggestions.is-collapsed
.cep-chat__suggestions-content {
    max-height: 0;
    opacity: 0;
}

.cep-chat__suggestions.is-collapsed
.cep-chat__suggestions-head {
    margin-bottom: 0;
}


/* =========================================================
   TOPICS
========================================================= */

.cep-chat__topics {
    display: flex;
    flex-direction: column;
    align-items: flex-end;

    gap: 8px;
}


/* Bubble giống ảnh mẫu */

.cep-chat__topic {
    width: fit-content;
    max-width: 88%;

    min-height: 34px;

    padding: 8px 10px;

    border: 1px solid #86aa98;
    border-radius: 9px;

    background: #fff;
    color: #344b40;

    display: inline-flex;
    align-items: center;
    gap: 6px;

    /* 13px — khách chốt trực tiếp con số này, không suy ra từ nơi khác. Trước
       đó đã thử khớp đúng .cep-chat__message (12px) nhưng khách vẫn thấy chữ
       hiện to như cũ, nhiều khả năng do trình duyệt đang bật "cỡ chữ tối
       thiểu" (mục cài đặt hỗ trợ tiếp cận) với sàn cao hơn 12px, nên cả 10.7px
       lẫn 12px đều bị đẩy lên cùng một mức — sửa số trong CSS không thấy gì
       đổi là vì trình duyệt đang ghi đè, không phải vì quy tắc chưa chạy. */
    font-size: 13px !important;
    font-weight: 500;
    line-height: 1.4;

    text-align: left;

    cursor: pointer;

    box-shadow:
        0 2px 5px rgba(24, 69, 49, .06);

    transition:
        border-color .18s ease,
        background .18s ease,
        box-shadow .18s ease,
        transform .18s ease;
}

.cep-chat__topic i {
    flex: 0 0 auto;

    color: var(--cb-green);
    font-size: 13px !important;
}

.cep-chat__topic:hover {
    border-color: var(--cb-green);

    background: #f8fbf9;

    transform: translateY(-1px);

    box-shadow:
        0 4px 10px rgba(24, 69, 49, .09);
}

.cep-chat__topic:active {
    transform: translateY(0);
}


/* =========================================================
   XEM TẤT CẢ
========================================================= */

.cep-chat__topics-more {
    align-self: flex-end;

    margin-top: 2px;
    padding: 3px 2px;

    border: 0;
    background: transparent;

    display: inline-flex;
    align-items: center;
    gap: 5px;

    color: #68756f;

    font-size: 9.5px;
    font-weight: 700;

    text-decoration: underline;
    text-underline-offset: 2px;

    cursor: pointer;

    transition: color .18s ease;
}

.cep-chat__topics-more:hover {
    color: var(--cb-green);
}

.cep-chat__topics-more span{
    font-size: 13px;
}
.cep-chat__topics-more i {
    font-size: 8px;
}
.cep-chat__foot{background:#fff;border-top:1px solid #e0e7e3;padding:9px 11px 10px}
.cep-chat__handoff{margin:0 0 8px;padding:8px 11px;border:1px solid #d4e2da;border-radius:10px;color:var(--cb-green);font-size:10.5px;font-weight:700;text-decoration:none;display:inline-flex;align-items:center;gap:7px}
.cep-chat__handoff[hidden]{display:none}
.cep-chat__handoff:hover{background:#f5faf7}
.cep-chat__form{display:flex;align-items:flex-end;gap:8px;border:1px solid #ccdcd4;border-radius:14px;background:#fbfcfb;padding:5px 5px 5px 12px;transition:border .2s,box-shadow .2s}
.cep-chat__form:focus-within{border-color:var(--cb-green);box-shadow:0 0 0 3px rgba(23,103,71,.08)}
.cep-chat__form textarea{flex:1;min-height:34px;max-height:88px;padding:8px 0;border:0;outline:0;background:transparent;resize:none;color:var(--cb-text);font-size:11.5px;line-height:1.4}
.cep-chat__form textarea::placeholder{color:#9ba7a1}
.cep-chat__form button{flex:0 0 38px;height:38px;border:0;border-radius:11px;background:var(--cb-green);color:#fff;cursor:pointer;display:grid;place-items:center;transition:.18s ease}
.cep-chat__form button:hover{background:var(--cb-green-dark)}
.cep-chat__form button:disabled{opacity:.5;cursor:not-allowed}
.cep-chat__note{margin:7px 3px 0;color:#98a39e;font-size:8.8px;line-height:1.35;text-align:center}
@keyframes cb-in{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
@keyframes cb-msg{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@keyframes cb-dot{0%,70%,100%{transform:translateY(0);opacity:.45}35%{transform:translateY(-3px);opacity:1}}
/* Ba số 44/60/72 cùng đổi theo một nhịp với nút, đúng công thức đã ghi ở
   .cep-chat__launcher: launcher 54→44px (bằng .cep-float__btn mobile);
   .cep-chat__hint bottom 70→60px (= bottom .cep-chat mobile 16 + launcher 44,
   khớp thẳng đỉnh với launcher như bản gốc: 16+54=70 trước đây);
   .cep-chat__panel bottom 82→72px (giữ nguyên phần đệm +12px đã có so với
   công thức launcher+16: 44+16+12=72, đúng như 54+16+12=82 trước đây). */
@media(max-width:640px){.cep-chat{right:15px;bottom:16px}.cep-chat__hint{right:0;bottom:60px;width:min(290px,calc(100vw - 30px))}.cep-chat__hint:after{right:20px;bottom:-7px;transform:rotate(135deg)}.cep-chat__launcher{width:44px;height:44px}.cep-chat__panel{position:fixed;left:10px;right:10px;bottom:72px;width:auto;height:min(620px,calc(100dvh - 100px));border-radius:16px;transform-origin:center bottom}.cep-chat__head{min-height:68px}.cep-chat__message{max-width:92%}}
@media(prefers-reduced-motion:reduce){.cep-chat *{scroll-behavior:auto!important;animation:none!important;transition:none!important}}

/* #endregion */


/* =====================================================================
   #region C20 · NHÓM TRANG CHÍNH SÁCH — /dieu-khoan-giao-dich và các trang
   cùng loại ở chân trang

   KHÔNG CÓ HERO, cùng lối với /gio-hang: đây là trang người ta mở ra để TÌM
   một câu cụ thể, thường là đang có việc cần hỏi. Một tấm ảnh lớn chiếm trọn
   màn hình đầu chỉ đẩy thứ họ cần xuống dưới. Vì thế .legal dùng đúng nhịp
   padding của .cart-page để chuyển qua lại giữa hai trang không giật.

   BỐ CỤC MỘT CỘT CÓ TRẦN BỀ NGANG, không phải hai cột với mục lục dính bên
   trái: văn bản pháp lý đọc theo dòng dài, mà dòng dài quá khoảng 75 ký tự
   thì mắt nhảy dòng sai chỗ. Mục lục nằm gọn thành một khối trên đầu — đủ
   việc cho một trang 12 mục, và không cần một dòng JavaScript nào.

   KHÔNG khai scroll-margin-top cho tiêu đề mục: bấm một mục trong mục lục thì
   trình duyệt cuộn tiêu đề lên sát mép trên, chỗ đang bị thanh menu dính che.
   Nhưng html đã có sẵn scroll-padding-top: calc(var(--nav-stuck-h) + 12px)
   (khối biến ở đầu file) lo đúng việc ấy cho MỌI neo trong website — thêm
   một lần nữa ở đây là hai chỗ cùng bù một khoảng, đổi thanh menu thì phải
   nhớ sửa cả hai.

   Phần MÀN HÌNH HẸP nằm ở CUỐI khối, sau mọi quy tắc gốc — media query không
   tự cộng độ đặc hiệu nên quy tắc gốc viết sau sẽ đè ngược lại nó.
   ===================================================================== */

.legal {
    padding: clamp(32px, 3.4vw, 48px) 0 clamp(56px, 5.6vw, 90px);
    background: var(--white);
}

/* Trần bề ngang đặt trên chính các khối chữ chứ không trên .container: nhờ vậy
   trang này vẫn canh theo đúng lưới chung với mọi trang khác, chỉ có phần chữ
   là hẹp lại.

   margin-inline: auto thêm ngày 2026-09-17, cùng lúc với việc nới khung lên
   1600px cho mọi trang. Trước đây khung 1360px nên cột chữ 860px dán mép
   trái chỉ chừa ~500px bên phải, còn chấp nhận được; với khung 1600px thì
   chừa tới ~740px — nhìn ra một trang bị lệch hẳn sang trái chứ không ra
   chủ đích. Canh giữa lại thì hai bên cân nhau, đọc như một văn bản dài
   bình thường. 860px giữ nguyên vì đó là khổ đọc, không phải khổ lưới. */
.legal-crumb,
.legal-head,
.legal-toc,
.legal-body {
    max-width: 860px;
    margin-inline: auto;
}


/* ---- Đường dẫn và tiêu đề ---- */

.legal-crumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 18px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--muted);
}

.legal-crumb a {
    color: var(--muted);
}

.legal-crumb a:hover {
    color: var(--green);
}

.legal-crumb__last {
    font-weight: 700;
    color: var(--ink);
}

.legal-head {
    margin-bottom: clamp(22px, 2.4vw, 32px);
}

.legal-title {
    margin: 0 0 8px;
    font-size: var(--fs-lg);
    line-height: var(--lh-lg);
    font-weight: 800;
    color: var(--ink);
}

.legal-sub {
    margin: 0;
    font-size: var(--fs-base);
    line-height: 1.6;
    color: var(--muted);
}

.legal-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 0 0;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    color: var(--green);
}


/* ---- Mục lục ---- */

.legal-toc {
    padding: 20px 22px;
    margin-bottom: clamp(26px, 2.8vw, 40px);
    background: var(--smoke);
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
}

.legal-toc__title {
    margin: 0 0 12px;
    font-size: var(--fs-base);
    line-height: 1.3;
    font-weight: 700;
    color: var(--card-title);
}

/* Hai cột khi còn chỗ: 12 mục xếp một hàng dọc sẽ đẩy nội dung chính xuống
   quá sâu. Dùng columns chứ không grid vì thứ tự đọc phải là DỌC theo từng
   cột — mục 1 nằm trên mục 2 — còn grid sẽ rải 1 và 2 nằm ngang cạnh nhau,
   tức là đọc theo hàng, sai với một mục lục đánh số. */
.legal-toc__list {
    columns: 2;
    column-gap: 28px;
    margin: 0;
    padding-left: 20px;
    font-size: var(--fs-sm);
    line-height: 1.9;
    color: var(--muted);
}

/* Không để một mục bị cắt đôi giữa hai cột. */
.legal-toc__list li {
    break-inside: avoid;
}

.legal-toc__list a {
    color: var(--green);
    font-weight: 600;
}

.legal-toc__list a:hover {
    text-decoration: underline;
}


/* ---- Thân văn bản ---- */

.legal-body {
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    color: rgba(18, 26, 22, .85);

    /* Cùng cách căn với .article-prose ở trang Tin tức: đây cũng là văn bản
       chạy dài nhiều dòng (định nghĩa thuật ngữ, điều khoản, các bước) chứ
       không phải nhãn ngắn — căn đều hai lề cho mép phải thẳng hàng thay vì
       răng cưa. */
    text-align: justify;
}

.legal-body p {
    margin: 0 0 14px;
}

.legal-body ul,
.legal-body ol {
    margin: 0 0 16px;
    padding-left: 22px;
}

.legal-body li {
    margin-bottom: 8px;
}

/* Chặn "chữ mồ côi" cuối đoạn/cuối định nghĩa/cuối gạch đầu dòng — cùng lý do
   và cùng cách làm với .article-prose p ở trang Tin tức. dd và li cũng cần vì
   .legal-terms (định nghĩa thuật ngữ) và các <ul>/<ol> trong trang đều là câu
   hoàn chỉnh có thể xuống hai dòng, không phải nhãn một dòng. */
.legal-body p,
.legal-body dd,
.legal-body li {
    text-wrap: pretty;
}

/* Danh sách lồng, ví dụ các mốc hoàn tiền trong mục 7. */
.legal-body li > ul {
    margin: 8px 0 0;
}

.legal-body a {
    color: var(--green);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.legal-h2 {
    margin: clamp(28px, 3vw, 40px) 0 14px;
    padding-top: clamp(18px, 2vw, 26px);
    border-top: 1px solid var(--green-10);

    font-size: var(--fs-md);
    line-height: var(--lh-md);
    font-weight: 700;
    color: var(--card-title);
}

/* Mục đầu tiên bỏ vạch ngăn: ngay phía trên nó là khối mục lục, vốn đã có
   viền riêng — hai đường kẻ sát nhau trông như lỗi dựng trang. */
.legal-h2:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

/* Số thứ tự tách khỏi tên mục bằng MÀU, không bằng cỡ chữ: cùng cỡ thì cả
   hàng chữ vẫn nằm trên một đường cơ sở. */
.legal-no {
    color: var(--green);
}

.legal-h3 {
    margin: 22px 0 10px;
    font-size: var(--fs-base);
    line-height: 1.4;
    font-weight: 700;
    color: var(--ink);
}

.legal-lead {
    font-weight: 600;
    color: var(--ink);
}


/* ---- Khối thông tin chủ sở hữu (mục 1) ---- */

/* <dl> chứ không <table>: đây là các cặp nhãn–giá trị của MỘT pháp nhân, không
   phải nhiều hàng cùng cấu trúc. Mỗi cặp bọc trong một <div> để lưới xếp được
   thành ô — đặt grid thẳng lên <dl> thì dt và dd rơi vào hai ô rời nhau và mất
   quan hệ nhãn–giá trị. Cùng cách làm với .stu-info ở khối C18. */
.legal-info {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 16px;
    margin: 0 0 18px;
    padding: 20px 22px;
    background: var(--white);
    border: 1px solid var(--green-10);
    border-radius: var(--r-box);
    box-shadow: var(--shadow-card);
}

.legal-info dt {
    margin-bottom: 4px;
    font-size: var(--fs-sm);
    line-height: var(--lh-sm);
    font-weight: 600;
    color: var(--muted);
}

.legal-info dd {
    margin: 0;
    font-size: var(--fs-base);
    line-height: 1.5;
    font-weight: 700;
    color: var(--ink);
}


/* ---- Bảng thuật ngữ (mục 2) ---- */

/* Ở đây thì KHÔNG bọc <div>: danh sách thuật ngữ đọc tuần tự từ trên xuống,
   mỗi thuật ngữ một dòng — không có lưới nào để xếp, nên dt/dd đứng thẳng
   trong <dl> là đúng nhất. */
.legal-terms {
    margin: 0 0 16px;
}

.legal-terms dt {
    margin-top: 14px;
    font-weight: 700;
    color: var(--ink);
}

.legal-terms dt:first-child {
    margin-top: 0;
}

.legal-terms dd {
    margin: 2px 0 0;
    padding-left: 16px;
    border-left: 2px solid var(--green-15);
}


/* ---- Các bước trong mục 4 ---- */

/* Số bước tự sinh bằng counter thay vì để <ol> tự đánh: cần đặt con số vào
   một viên tròn có nền, mà ::marker thì không nhận padding hay background. */
.legal-steps {
    counter-reset: legal-step;
    list-style: none;
    padding-left: 0;
}

.legal-steps > li {
    counter-increment: legal-step;
    position: relative;
    padding-left: 40px;
    margin-bottom: 12px;
}

.legal-steps > li::before {
    content: counter(legal-step);
    position: absolute;
    left: 0;
    top: 2px;

    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;

    background: var(--green);
    color: var(--white);
    border-radius: 50%;
    font-size: var(--fs-sm);
    font-weight: 700;
    line-height: 1;
}


/* ---- Lối ra cuối trang ---- */

.legal-contact {
    margin: clamp(28px, 3vw, 40px) 0 0;
    padding: 16px 18px;
    background: var(--green-10);
    border-radius: var(--r-box);
    font-size: var(--fs-sm);
    line-height: var(--lh-loose);
    color: var(--ink);
}


/* ---------------------------------------------------------------
   MÀN HÌNH HẸP — phải nằm CUỐI khối, xem ghi chú đầu #region
   --------------------------------------------------------------- */

@media (max-width: 640px) {
    /* Một cột: hai cột mục lục trên điện thoại thì mỗi cột chỉ còn chỗ cho
       vài chữ, tên mục nào cũng phải xuống ba dòng. */
    .legal-toc__list {
        columns: 1;
        line-height: 1.8;
    }

    .legal-toc,
    .legal-info {
        padding: 16px 18px;
    }
}

/* #endregion */


/* =====================================================================
   #region C21 · HAI NÚT LIÊN HỆ NHANH NỔI — Zalo và Gọi điện, mọi trang công khai

   Đứng NGAY PHÍA TRÊN nút mở trợ lý tư vấn (#region C19), cùng cạnh phải.
   Toạ độ dưới đây KHÔNG phải số chọn cho đẹp mắt — chúng cộng trực tiếp từ
   kích thước thật của .cep-chat__launcher:

     đáy chồng lên đỉnh nút trợ lý = bottom của .cep-chat (24px)
                                     + cao nút trợ lý (50px)
                                     + một khoảng thở (16px)
                                   = 90px

   Nút trợ lý vừa được thu về đúng 50px — bằng cỡ hai nút Zalo/Gọi điện ở đây
   (.cep-float__btn) theo yêu cầu của khách, thay cho 58px ban đầu. Con số
   90px dưới đây (và 76px ở phần màn hình hẹp) đã tính lại theo đúng công
   thức trên. Đổi kích thước hay vị trí nút trợ lý ở #region C19 lần nữa thì
   PHẢI sửa lại hai con số này theo đúng công thức, nếu không hai khối nổi sẽ
   đè lên nhau.

   z-index THẤP HƠN .cep-chat (1200): khi bấm mở trợ lý, bảng chat (.cep-chat__
   panel) trải rộng đúng lên vùng hai nút này đang đứng. Để z-index thấp hơn là
   bảng chat che khuất chúng — đúng ý, vì lúc đó màn hình đã đủ chật với cửa sổ
   chat đang mở, hai nút bấm nhanh không cần hiện ra chồng lên trên nó.

   BÓNG ĐỔ VÀ HIỆU ỨNG HOVER LẤY Y HỆT SỐ CỦA .cep-chat__launcher (0 12px 30px
   lúc nghỉ, 0 16px 34px lúc rê chuột, cùng translateY(-2px)) — cố ý, không
   phải trùng hợp. Ba nút đứng chồng thành MỘT cụm, nên phải cùng một "ngôn
   ngữ độ nổi" thì mắt mới đọc ra chúng là một nhóm, thay vì ba nút rời rạc
   ngẫu nhiên đứng cạnh nhau. Đổi số ở .cep-chat__launcher thì nhớ đổi theo ở
   đây.

   Phần MÀN HÌNH HẸP nằm ở CUỐI khối — media query không tự cộng độ đặc hiệu
   nên quy tắc gốc viết sau sẽ đè ngược lại nó, cùng bẫy đã ghi ở #region C19.
   ===================================================================== */

.cep-float {
    position: fixed;
    right: 26px;
    bottom: 90px;
    z-index: 1100;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.cep-float__btn {
    /* relative để ::before (vòng nhấp nháy) định vị tuyệt đối theo đúng nút
       cha, và KHÔNG đặt overflow:hidden ở đây — vòng nhấp nháy cần tràn ra
       ngoài khung mới nhìn thấy được. Phần bo tròn + cắt viền của riêng icon
       Zalo nằm ở .cep-float__icon (span con), một tầng tách biệt. */
    position: relative;

    width: 50px;
    height: 50px;
    display: grid;
    place-items: center;

    border-radius: 50%;
    box-shadow: 0 12px 30px rgba(20, 73, 52, .22);
    transition: transform .2s ease, box-shadow .2s ease;

    /* Hiệu ứng XUẤT HIỆN khi tải trang — xem @keyframes cqaIn bên dưới. Đặt
       tên riêng (không dùng lại @keyframes cepFloatIn của trang Tin tức) dù
       hiệu ứng gần giống nhau, để không ai đọc nhầm hai thứ là một, và sửa
       một bên không âm thầm kéo bên kia đổi theo. */
    animation: cqaIn .6s var(--ease) both;
}

.cep-float__btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 16px 34px rgba(20, 73, 52, .28);
}

.cep-float__btn:focus-visible {
    outline: 3px solid var(--green-30);
    outline-offset: 3px;
}

/* Lệch giờ xuất hiện: Zalo hiện trước, Điện thoại hiện sau 0.15s — một nhịp
   "rơi xuống theo tầng" thay vì cả cụm bật ra cùng lúc như một khối cứng. */
.cep-float__btn--zalo {
    animation-delay: .05s;
}

/* Nút gọi tô VÀNG (--gold), không phải xanh lá: xanh lá đã là màu của nút mở
   trợ lý tư vấn đứng ngay dưới nó, hai khối xanh giống hệt nhau chồng liền
   kề đọc như MỘT nút bị lặp chứ không phải hai chức năng khác nhau. Vàng là
   màu thứ hai (duy nhất, cùng xanh lá) trong bảng màu thương hiệu — không
   phải một màu tự chọn ngoài palette.

   color: var(--ink) chứ KHÔNG phải trắng: nền vàng #E3A21B quá sáng, biểu
   tượng trắng trên nó chỉ đạt tỉ lệ tương phản ~2.2:1, dưới ngưỡng 3:1 mà
   WCAG đòi cho biểu tượng đồ hoạ. .btn-gold ở khối C1 cũng xử lý y hệt vậy
   — chữ tối trên nền vàng — nên đây không phải lựa chọn riêng cho nút này. */
.cep-float__btn--phone {
    text-decoration: none;
    animation-delay: .2s;
    background: var(--gold);
    color: var(--ink);
    font-size: 20px;
    box-shadow: 0 12px 30px rgba(227, 162, 27, .35);
}

/* Đậm hơn một nấc khi rê chuột, cùng sắc vàng với .btn-gold:hover — để cả
   trang chỉ có một "giọng vàng" duy nhất, không phải mỗi nơi một sắc. */
.cep-float__btn--phone:hover {
    background: #f4b327;
    box-shadow: 0 16px 34px rgba(227, 162, 27, .42);
}

/* Vòng tròn nhấp nháy lan ra rồi mờ dần — quy ước thị giác quen thuộc cho
   "đây là nút liên hệ, có thể bấm được", hay gặp ở các nút Zalo/gọi nổi trên
   website Việt Nam. --cqa-ring đặt trên từng biến thể để vòng mang đúng màu
   thương hiệu của nút đó (Zalo xanh dương #0068FF, gọi điện vàng --gold).

   pointer-events: none bắt buộc: vòng phồng to hơn nút thật, thiếu dòng này
   thì có những khung hình chuột bấm trúng vòng (đang vô hình) mà chệch mất
   nút bên dưới. */
.cep-float__btn::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid var(--cqa-ring, var(--green));
    opacity: 0;
    pointer-events: none;
    animation: cqaPulse 2.6s ease-out infinite;
}

.cep-float__btn--zalo::before {
    --cqa-ring: #0068FF;
    animation-delay: 1.2s;
}

/* --cqa-ring đổi theo nền: nút gọi giờ nền vàng nên vòng cũng phải vàng,
   nếu không vòng nhấp nháy vẫn xanh lá trong khi cả nút đã đổi màu — hai chi
   tiết của cùng một nút nói hai ngôn ngữ màu khác nhau. */
.cep-float__btn--phone::before {
    --cqa-ring: var(--gold);
    animation-delay: 0s;
}

@keyframes cqaIn {
    from {
        opacity: 0;
        transform: translateY(14px) scale(.9);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes cqaPulse {
    0% {
        transform: scale(1);
        opacity: .55;
    }

    70%,
    100% {
        transform: scale(1.45);
        opacity: 0;
    }
}

/* Người dùng đã bật "giảm chuyển động": bỏ hết hiệu ứng xuất hiện, vòng nhấp
   nháy và cú nảy lên khi rê chuột — chỉ giữ lại đổ bóng tĩnh, cùng nguyên tắc
   với .order-watch__dot và .cep-chat ở hai khối khác trong file này. */
@media (prefers-reduced-motion: reduce) {
    .cep-float__btn {
        animation: none;
        transition: none;
    }

    .cep-float__btn::before {
        animation: none;
        opacity: 0;
    }

    .cep-float__btn:hover {
        transform: none;
    }
}

/* KHÔNG đặt nền cho chính nút Zalo — span con .cep-float__icon mới là nơi tô
   màu, xem ghi chú tại component. */
.cep-float__btn--zalo {
    background: transparent;
}

/* Lớp bọc RIÊNG cho icon Zalo: bo tròn, cắt viền, và tô nền CÙNG MÀU XANH
   thương hiệu (#0068FF) với chính path nền trong SVG — không phải nền trắng
   như bản trước. Nhờ vậy nếu đường cong bo góc của path không khít tuyệt đối
   bốn cạnh khung vuông 50×50, khe hở (nếu có) LỘ RA CŨNG LÀ MÀU XANH ĐÓ chứ
   không lộ ra thành một viền trắng chênh lệch với icon — đúng lỗi trong ảnh
   chụp trước. overflow:hidden nằm ở TẦNG NÀY, tách khỏi .cep-float__btn cha,
   để không cắt mất vòng nhấp nháy ::before (nó cần tràn ra ngoài mới thấy). */
.cep-float__icon {
    width: 100%;
    height: 100%;
    display: grid;
    place-items: center;
    border-radius: 50%;
    overflow: hidden;
    background: #0068FF;
}

.cep-float__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}


/* ---------------------------------------------------------------
   MÀN HÌNH HẸP — phải nằm CUỐI khối, xem ghi chú đầu #region
   --------------------------------------------------------------- */

@media (max-width: 640px) {
    /* Cùng công thức như trên, tính lại theo kích thước nút trợ lý ở màn hình
       hẹp — vừa co từ 54px xuống 44px (bằng cỡ .cep-float__btn mobile):
       bottom(16) + cao(44) + thở(16) = 76px. */
    .cep-float {
        right: 15px;
        bottom: 76px;
        gap: 10px;
    }

    .cep-float__btn {
        width: 44px;
        height: 44px;
    }

    .cep-float__btn--phone {
        font-size: 17px;
    }
}

/* #endregion */

/* Tooltip cho nút Chatbot AI */
.cep-chat__tooltip {
    position: absolute;
    right: calc(100% + 14px);
    top: 50%;
    transform: translateY(-50%) translateX(10px);
    padding: 6px 12px;
    background: #55645d;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    border-radius: 8px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: all 0.2s ease;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.cep-chat__tooltip::after {
    content: "";
    position: absolute;
    top: 50%;
    right: -5px;
    transform: translateY(-50%);
    border-width: 5px 0 5px 6px;
    border-style: solid;
    border-color: transparent transparent transparent #55645d;
}

.cep-chat__launcher:hover .cep-chat__tooltip {
    opacity: 1;
    visibility: visible;
    transform: translateY(-50%) translateX(0);
}

.cep-chat.is-open .cep-chat__tooltip {
    display: none !important;
}
@media (max-width: 640px) { .cep-chat__tooltip { display: none !important; } }

/* ============================================================
   #region C22 · CẢM NHẬN HỌC VIÊN — BẢN THẺ NHỎ XẾP NGANG, 2 HÀNG (.tmrow)

   Component dùng lại được, KHÔNG thay thế khối .testimonial cũ (bản hai cột,
   ảnh lớn, mỗi lần một người — trang Thành tích vẫn dùng). Hai bản sống song
   song; xem app/Views/components/testimonial-row.php.

   Dùng chung băng trượt initCarousel với .teachers và .featured — engine đó
   đo "mỗi trang có bao nhiêu thẻ" bằng cách đếm số thẻ có mép trái nằm trong
   bề rộng track (xem computePerPage trong app.js), KHÔNG quan tâm thẻ nằm
   một hàng hay nhiều hàng. Nhờ vậy đổi track từ flex 1 hàng sang GRID 2 hàng
   (grid-auto-flow: column) mà KHÔNG cần sửa dòng JS nào: hai thẻ cùng một
   cột (xếp trên-dưới) có mép trái TRÙNG NHAU, nên engine tự đếm ra đúng "số
   cột lọt trong track × 2" cho mỗi trang — coi 6 thẻ (3 cột x 2 hàng) như
   trước đây coi 3 thẻ một hàng, mọi phép tính trang/chấm tròn/nhân bản giữ
   nguyên logic.

   ĐIỀU KIỆN BẮT BUỘC để mẹo trên đúng: card phải liệt kê trong HTML theo
   đúng thứ tự "hết một cột (đủ 2 hàng) mới sang cột kế" — chính là thứ tự
   DOM phẳng, liên tục mà testimonial-row.php đang render qua foreach, vì
   grid-auto-flow: column tự xếp đúng thứ tự đó. KHÔNG được nhóm thẻ theo
   "trang" trong HTML (ví dụ bọc mỗi 6 thẻ trong 1 div) — làm vậy sẽ phá đúng
   giả định 1 thẻ = 1 đơn vị đo của initCarousel.
   ============================================================ */
.tmrow {
    padding: var(--sec-y) 0 var(--sec-y-end);
    color: var(--ink);
    background: var(--smoke);
}

.tmrow-track {
    /* Khe giữa các thẻ khai thành biến vì công thức bề rộng thẻ ở dưới phải
       trừ đúng số khe — gõ lại số ở hai chỗ là sớm muộn lệch nhau. Dùng
       chung một biến cho cả khe ngang (giữa các cột) lẫn khe dọc (giữa 2
       hàng trong một cột) — gap ở grid áp cho cả hai chiều.

       Khe RỘNG HƠN bản gốc (16-24px lên 22-32px) là cách DUY NHẤT được dùng
       để thẻ hẹp lại — TUYỆT ĐỐI không nhân thêm hệ số < 1 vào công thức
       bề rộng cột bên dưới (từng thử .94 để "hé" thẻ kế tiếp, gây lỗi nặng:
       computePerPage trong app.js đếm SỐ THẺ có mép trái nằm trong track,
       không kiểm tra thẻ có lọt TRỌN hay không — hễ còn dư khoảng trống
       trong vùng 3-cột thì cột thứ 4 cũng lọt tiêu chí đó, JS tính nhầm
       thành 8 thẻ/trang thay vì 6, kéo theo mọi mốc trang lệch, hiện tượng
       nhìn thấy là mép thẻ trang bên cạnh lòi vào lấn trang đang xem. Khe
       rộng hơn thì 3 cột + 2 khe vẫn cộng ĐÚNG 100% track — không dư khoảng
       trống nào để cột thứ 4 chen mép trái vào, trang luôn sạch đúng 6 thẻ). */
    --tmrow-gap: clamp(22px, 3vw, 42px);

    /* 3 cột hiển thị ở màn rộng nhất, trừ đúng 2 khe giữa — CHIA HẾT 100%,
       không còn khoảng dư nào để lộ mép thẻ trang kế. */
    --tmrow-col: calc((100% - 2 * var(--tmrow-gap)) / 3);

    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(2, auto);
    grid-auto-columns: var(--tmrow-col);
    gap: var(--tmrow-gap);

    /* CHỪA CHỖ CHO BÓNG ĐỔ, RỒI TRỪ LẠI BẰNG MARGIN ÂM.
       overflow-x: auto biến đây thành khung cuộn, mà CSS không cho một trục
       auto còn trục kia visible — trục dọc tự thành auto theo, nên bóng của
       thẻ bị xén cụt ngay mép dưới track. Đó là vệt cắt ngang nhìn thấy dưới
       đáy mỗi thẻ.

       Vùng cắt là HỘP PADDING, nên padding chính là chỗ cho bóng trổ ra.
       Lượng cần tính từ chính hai cái bóng đang dùng — bóng toả xuống
       offsetY + blur/2, toả lên blur/2 − offsetY:
         nghỉ      0 18.83px 47.08px  ->  lên  4.7px, xuống 42.4px
         rê chuột  0 22px    44px     ->  lên  3.0px, xuống 41.0px (đã trừ
                                          3px thẻ nhấc lên theo --lift)
       Lấy trần: 6px trên, 44px dưới. Đổi bóng thì tính lại hai số này.

       margin âm bằng đúng padding nên vị trí nhìn thấy của track không nhích
       một pixel nào — chỉ vùng cắt rộng ra. KHÔNG thêm padding ngang: padding
       ngang trên khung cuộn làm lệch mốc snap và lệch cả phép đo
       getBoundingClientRect trong initCarousel. .featured-track cũng chỉ
       padding dọc, cùng lý do. */
    padding-block: 6px 44px;
    margin-block: -6px -44px;

    /* CÙNG PHÉP ẤY CHO HAI BÊN. Bóng toả sang ngang blur/2 = 23.5px, và mép
       trái thẻ đầu với mép phải thẻ cuối bị khung cuộn xén y như mép dưới.

       KHÔNG để 24px cứng: track thò ra ngoài khung chứa đúng bằng lượng này,
       mà trên điện thoại khung đã tràn viền rồi — chỉ còn --pad-x (12-14px)
       tính từ mép nội dung tới mép màn hình. Thò quá là cả TRANG có thanh
       cuộn ngang. min() tự kẹp: màn rộng được 20px, điện thoại rút về đúng
       12-14px, không bao giờ vượt.

       Đổi lại: màn rộng chừa 20px trong khi bóng cần 23.5px, tức 3.5px ngoài
       cùng vẫn bị cắt. Chỗ ấy là phần đuôi của dải mờ, alpha đã gần 0 nên
       không nhìn ra.

       scroll-padding-inline là thứ KHÔNG ĐƯỢC QUÊN: mốc neo của scroll-snap
       tính theo hộp viền, nên thiếu dòng này thì thẻ bị neo lệch sang trái
       đúng bằng lượng đệm. Bên JS, initCarousel cũng đã trừ đệm ra khỏi ba
       phép đo hình học vì cùng một lý do. */
    --tmrow-bleed: min(24px, var(--pad-x));

    padding-inline: var(--tmrow-bleed);
    margin-inline: calc(-1 * var(--tmrow-bleed));
    scroll-padding-inline: var(--tmrow-bleed);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.tmrow-track::-webkit-scrollbar {
    display: none;
}

/* Bề rộng KHÔNG khai ở đây nữa — track (grid-auto-columns) quyết định bề
   rộng mọi cột, thẻ chỉ cần lấp đầy đúng ô của mình (mặc định của grid item
   là stretch, không cần width: 100%). display: flex ở đây là bố cục BÊN
   TRONG một thẻ (sao, chữ, người — xếp dọc), không liên quan gì tới việc
   thẻ xếp thành lưới ngoài track. */
.tmrow-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin: 0;
    padding: clamp(20px, 1.7vw, 26px);
    overflow: hidden;
    background: var(--white);
    border: 1px solid rgba(18, 26, 22, .08);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-card);
    scroll-snap-align: start;
    transition:
        transform var(--dur) var(--ease),
        background-color var(--dur) var(--ease),
        box-shadow var(--dur) var(--ease),
        border-color var(--dur) var(--ease);
}

/* Dấu nháy chìm ở góc trên phải, làm nền chứ không làm nội dung. Đặt ở ĐÂY
   thay vì ngay trên dòng chữ để không tranh chỗ với hàng sao — hai thứ cùng
   nằm trên đầu thẻ thì nhìn rối, mà hàng sao mới là thứ người ta liếc trước.

   Vàng pha rất loãng (--gold-30 qua mask) nên nó chỉ gợi chất trích dẫn, đọc
   chữ vẫn không vướng. z-index/isolation không cần: các phần tử con đều đứng
   sau trong luồng nên tự nằm trên. overflow:hidden ở thẻ cắt gọn phần dấu
   nháy thò khỏi góc bo — chỉ ẩn trong THẺ, không ảnh hưởng băng trượt. */
.tmrow-card::before {
    content: "";
    position: absolute;
    /* 42x30 chứ không to hơn: đáy dấu nháy phải dừng TRÊN dòng chữ đầu tiên.
       Tính ở trường hợp xấu nhất — padding nhỏ nhất (20px, màn hẹp) và hàng
       sao thấp nhất (16px) — thì chữ bắt đầu ở y = 20 + 16 + 14(khe) = 50.
       Dấu nháy 16 + 30 = 46, hở 4px.

       Giữ đúng tỉ lệ 28:20 của viewBox (42/30 = 1.4) để mask-size:contain
       không chừa viền thừa. Đổi padding thẻ, cỡ hàng sao hay khe 14px thì
       tính lại — thử trên một cỡ màn là không đủ, bản 46x33 trước đó nhìn
       sạch ở màn rộng nhưng đè chữ ở màn hẹp. */
    top: 16px;
    right: 20px;
    width: 42px;
    height: 30px;
    background-color: var(--gold-30);
    -webkit-mask-image: var(--quote-mark);
    mask-image: var(--quote-mark);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    pointer-events: none;
}

/* Nhấc nhẹ khi rê chuột, cùng biên độ --lift với mọi thẻ khác trong trang.
   Viền đậm lên một chút để thẻ tách hẳn khỏi nền --smoke lúc đang trỏ vào. */
/* Nền đổi sang một lớp VÀNG rất nhạt khi rê chuột.

   Chọn tông ẤM chứ không phải xanh, dù xanh mới là màu chính: nền section là
   --smoke #F4F7F5, một sắc xám ngả xanh. Tô thẻ bằng xanh nhạt thì hai thứ
   cùng tông, mắt phải so độ sáng mới thấy khác; tô vàng thì lệch hẳn tông
   nên nhận ra ngay dù độ chênh sáng y hệt. Vàng cũng đúng họ với sao, dấu
   nháy và dòng thành tích vốn đã vàng sẵn trong thẻ.

   Độ mờ .18 là mức ĐẬM NHẤT còn giữ được chữ trích dẫn đạt chuẩn: --muted
   #696984 trên #FAEED6 cho 4.62:1, qua ngưỡng 4.5:1 của chữ thường. Lên .22
   là tụt xuống 4.50 và .26 còn 4.35 — đậm hơn thì nền nổi hơn thật, nhưng
   đánh đổi bằng chính phần chữ người ta đang đọc.

   Không dùng --gold-10 có sẵn: mức .10 chỉ chênh nền trắng 1.08 lần, rê chuột
   vào gần như không thấy gì đổi.

   background-color đã thêm vào danh sách transition ở rule gốc, nếu không thì
   nền nhảy màu đột ngột trong khi thẻ vẫn nhấc lên mượt. */
.tmrow-card:hover {
    transform: translateY(var(--lift));
    background-color: rgba(227, 162, 27, .18);
    border-color: var(--green-30);
    box-shadow: 0 22px 44px rgba(18, 26, 22, .13);
}

@media (prefers-reduced-motion: reduce) {
    .tmrow-card {
        transition: none;
    }

    .tmrow-card:hover {
        transform: none;
    }
}

.tmrow-stars {
    display: flex;
    gap: 4px;
    font-size: 14px;
    color: var(--gold);
}

/* Ba thứ cùng lo một việc: giữ khối chữ của mọi thẻ CAO NGANG NHAU.

   1. margin-bottom:auto đẩy cụm ảnh + tên xuống đáy thẻ, nên đường kẻ và
      gương mặt luôn thẳng hàng giữa ba thẻ dù trích dẫn dài ngắn khác nhau.

   2. min-height 3 dòng. Thiếu nó thì một cảm nhận ngắn ("Nhận xét ...") để
      lại mảng trống lớn giữa chữ và đường kẻ — lỗi nhìn thấy rõ nhất ở bản
      đầu. Viết bằng em nên tự đi theo cỡ chữ, khỏi tính lại khi đổi font-size.

   3. line-clamp 6 dòng chặn chiều ngược lại: một cảm nhận dài bất thường sẽ
      kéo CẢ HÀNG cao theo nó, vì flex cho các thẻ bằng chiều cao thẻ cao
      nhất. Sáu dòng là rộng rãi — cảm nhận thường chỉ 2-3 dòng — nên gần như
      không bao giờ cắt thật; nó là cái phanh, không phải khuôn. Nếu khách cần
      đăng cảm nhận dài thì nới số này chứ đừng bỏ hẳn. */
.tmrow-quote {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 6;
    overflow: hidden;
    min-height: calc(var(--lh-loose) * 3em);
    margin: 0 0 auto;
    /* 16px, bằng cỡ chữ nền của trang. Bản đầu để 13px rồi 14px đều bị đánh
       giá nhỏ — đây là phần nội dung chính của thẻ, không phải chú thích.
       min-height ở trên viết bằng em nên tự đi theo, khỏi tính lại. */
    font-size: var(--fs-base);
    line-height: var(--lh-loose);
    color: var(--muted);
}

.tmrow-person {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-top: 14px;
    border-top: 1px solid rgba(18, 26, 22, .08);
}

/* flex:none để ảnh không bị bóp méo khi tên dài; object-fit cắt gọn ảnh không
   vuông thay vì kéo giãn mặt người. */
.tmrow-avatar {
    flex: none;
    width: 44px;
    height: 44px;
    object-fit: cover;
    border-radius: var(--r-pill);
}

.tmrow-who {
    display: flex;
    min-width: 0;
    flex-direction: column;
    gap: 2px;
}

/* 17px chứ không 16px: trích dẫn vừa lên đúng 16px, để tên bằng y hệt thì
   mất thứ bậc giữa lời kể và người kể. Chênh một bậc là đủ, vì tên còn đậm
   700 và màu --ink đậm hơn hẳn màu --muted của trích dẫn. */
.tmrow-name {
    font-size: 17px;
    line-height: 1.3;
    font-weight: 700;
    color: var(--ink);
}

/* Vàng ĐẬM chứ không phải --gold. Dòng này chỉ 12px: --gold trên nền trắng
   đạt 2.22:1, ở cỡ chữ nhỏ là không đọc nổi, còn --gold-ink đạt 5.48:1. Tiêu
   đề section thì ngược lại, cố ý giữ --gold vì chữ ở đó to gấp gần ba lần —
   xem chú thích ở .section-title em. */
.tmrow-role {
    font-size: 13px;
    line-height: 1.3;
    font-weight: 600;
    color: var(--gold-ink);
}

.tmrow-dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-top: clamp(20px, 2.2vw, 30px);
}

/* Nền sáng nên chấm mờ phải là màu TỐI pha loãng. Không dùng lại .teacher-dot
   được: chấm đó là trắng pha loãng, dựng cho nền xanh đậm, đặt lên nền smoke
   thì gần như tàng hình. */
.tmrow-dot {
    width: 10px;
    height: 10px;
    padding: 0;
    background: rgba(18, 26, 22, .2);
    border: none;
    border-radius: var(--r-pill);
    cursor: pointer;
    transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}

.tmrow-dot.is-active {
    width: 28px;
    background: var(--gold);
}

/* Hai cột một trang (x 2 hàng = 4 thẻ/trang) — trừ 1 khe, chia hết 100%.
   KHÔNG nhân hệ số < 1 ở đây — lý do xem chú thích dài ở --tmrow-gap phía
   trên: dư khoảng trống trong track làm computePerPage (app.js) đếm lố
   sang cột kế, trang không còn dừng sạch ở đúng 4 thẻ. */
@media (max-width: 1024px) {
    .tmrow-track {
        grid-auto-columns: calc((100% - var(--tmrow-gap)) / 2);
    }
}

/* Một cột một trang (x 2 hàng = 2 thẻ/trang), không còn khe nào để trừ,
   100% tròn — cùng lý do trên. */
@media (max-width: 720px) {
    .tmrow-track {
        grid-auto-columns: 100%;
    }
}

/* #endregion C22 */
