/* ============================================================
   Vinpack — page-vechungtoi.css
   CSS RIÊNG CỦA trang "Về chúng tôi". Chỉ nạp khi
   is_page_template( 'page-templates/ve-chung-toi.php' ).

   NẠP SAU global.css VÀ layout.css — inc/enqueue.php khai vinpack-global và
   vinpack-layout làm dependency của vinpack-vechungtoi (style), đúng khuôn
   page-nangluc.css.

   BA LUẬT CỦA FILE NÀY — cùng ba luật page-nangluc.css:
   1. KHÔNG khai custom property nào. Token thuộc về theme.json/global.css.
   2. KHÔNG dùng !important.
   3. KHÔNG khai `outline` ở bất kỳ đâu.

   VỀ `.crumb`: page-nangluc.css đã tự cảnh báo trước — style `.crumb` ở đó
   CHỈ nạp trên trang Năng lực doanh nghiệp, "một trang sau dùng lại breadcrumb
   sẽ cần chuyển khối đó sang layout.css hoặc chép một bản — quyết định đó
   thuộc về task đó". Đây là trang đó. banner.php (Task 1) gọi
   vinpack_breadcrumb() y hệt nangluc, nên file này TỰ CHÉP một bản `.crumb`
   riêng (mục 1) thay vì phụ thuộc ngầm vào một stylesheet KHÔNG được nạp trên
   trang này. Màu lấy đúng mockup trang này (#A9C4FF — TRÙNG token
   --on-navy-accent có sẵn, không phải --on-navy-text mà nl-banner dùng).

   VỀ NỀN TRÊN bg-alt: `.vmv` là `<section class="vmv wrap">` mang
   `background:var(--bg-alt)`, SỐNG TRỰC TIẾP trên nền đó — mọi chữ vốn
   --text-muted trong mockup (section-head p, vmv-tab nghỉ, vmv-body p,
   vmv-vtext p) chỉ đạt 4.24:1 trên --bg-alt (đo trong global.css mục 1.4.11),
   trượt AA cho chữ thường. Đổi hết sang --text (15.25:1) hoặc --cobalt-ink
   (4.70:1) cho chữ có màu nhấn — cùng bài học đã ghim ở `.nl-head p`/
   `.cm-toggle` của page-nangluc.css. --cobalt trơn (2.72:1 trên bg-alt) CHỈ
   còn dùng cho hình trang trí aria-hidden (SVG icon), không bao giờ cho chữ.

   VỀ `.org-role-title`: mockup dùng `color:var(--cobalt)` cho nhãn 12px chữ
   hoa đậm trên NỀN TRẮNG (.org không đặt bg-alt) — 3.10:1 trên trắng, trượt
   AA cho chữ 12px (không đạt ngưỡng "chữ lớn" 14pt/18.66px đậm). Đổi sang
   --cobalt-ink (contrast cao hơn nhiều trên nền trắng, cùng token đã dùng ở
   `.pc-text .label` của page-nangluc.css cho đúng kiểu nhãn hoa 13px).

   VỀ `.tl-year`/`.tl-body::before` CỦA MOCKUP: xem cảnh báo đầy đủ trong
   docblock template-parts/vechungtoi/timeline.php — mockup đặt `.tl-item`
   với `opacity:0` mặc định, CHỈ hiện khi JS cuộn thêm class `.show` (không có
   ở đây). File này bỏ hẳn cơ chế đó: `.tl-item` LUÔN `opacity:1`. Hệ quả kéo
   theo hai chi tiết KHÁC của mockup cũng phụ thuộc `.show`/`:hover`:
     - `.tl-year` mặc định `color:transparent` + viền chữ (`-webkit-text-
       stroke`), chỉ tô đặc màu khi `.show`/`:hover` — vì `.show` không bao
       giờ xuất hiện, con số năm sẽ mãi mãi chỉ là NÉT VIỀN MỜ, đọc gần như
       không được (một dạng khác của cùng cái bẫy "không JS thì vô hình" mà
       mockup gây ra). File này bỏ trạng thái viền-rỗng, tô ĐẶC var(--navy)
       ngay từ đầu.
     - `.tl-body::before` (vạch nhấn dọc) mặc định `transform:scaleY(0)`, chỉ
       hiện khi `.show`. Đây THUẦN trang trí (không phải nội dung), giữ luôn
       ở trạng thái hiện (`scaleY(1)`) cho nhất quán — nửa-vời (vạch ẩn vĩnh
       viễn cạnh nội dung luôn hiện) trông như lỗi hiển thị hơn là một quyết
       định có chủ đích.
   KHÔNG viết JS cuộn-hiện ở task này (xem báo cáo cuối) — coi hiệu ứng đó là
   tăng cường TUỲ CHỌN cho một task sau, không phải điều kiện để đọc được nội
   dung, đúng yêu cầu của docblock timeline.php.

   CẬP NHẬT — FEEDBACK ĐỢT 1, STT 16 ("hiện dần lần lượt từng năm khi cuộn
   tới"): ĐÂY LÀ "task sau" đã nói ở trên. Ba bất biến phía trên (opacity:1
   mặc định, `.tl-year` tô đặc ngay từ đầu, `.tl-body::before` luôn hiện)
   GIỮ NGUYÊN KHÔNG ĐỔI — hiệu ứng mới KHÔNG được phép quay lại bẫy "không JS
   thì vô hình" mà mockup mắc phải.

   CẬP NHẬT LẦN 2 (01/09/2026, khách yêu cầu dùng GSAP toàn site): cơ chế
   gate-class `.js-tl-anim` lên `<html>` + `.show` mô tả ở trên đã BỊ THAY —
   xem assets/js/motion.js (GSAP + ScrollTrigger dùng chung toàn site). Giờ
   KHÔNG còn class trung gian nào trên `<html>` nữa: motion.js tự set trạng
   thái ẩn của `.tl-item` bằng `gsap.set()` (inline style — autoAlpha:0,
   y:22) CHỈ KHI đã tải được GSAP và KHÔNG bật prefers-reduced-motion, rồi
   tween thẳng khi ScrollTrigger báo `.tl-wrap` cuộn vào khung nhìn — so le
   bằng tuỳ chọn `stagger` của GSAP, không phải setTimeout tay. Bất biến
   "không JS/giảm chuyển động thì `.tl-item` giữ opacity:1 mặc định, không
   khung nào biến mất" GIỮ NGUYÊN — chỉ đổi CƠ CHẾ, không đổi HỢP ĐỒNG.

   VỀ `.vmv-panel[hidden]`: dựa vào UA mặc định `[hidden]{display:none}`. File
   này KHÔNG đặt `display` vô điều kiện lên `.vmv-panel` — animation vào của
   panel chỉ áp cho `.vmv-panel:not([hidden])`.

   VỀ SECTION NỀN MÀU RIÊNG: `.vmv.wrap`, `.org.wrap`, `.contact-cta.wrap` đều
   là `<section class="X wrap">` mang `background` riêng (bg-alt/trắng/trắng)
   — cùng lỗi mockup mà home.css mục 1 đã sửa (section CÓ nền phải rộng hết
   trang, chỉ NỘI DUNG bị giới hạn --wrap-max). `.fields.wrap` KHÔNG có
   background riêng trong mockup nên GIỮ NGUYÊN `section.wrap` mặc định của
   global.css, không cần sửa. `.page-hero`/`.timeline` không mang class
   `wrap` trên section (banner.php/timeline.php đã ghi rõ trong docblock) nên
   vốn đã rộng hết `<main>`, không cần luật này.

   VỀ TOKEN KHOẢNG CÁCH/BO GÓC: số không khớp thang --sp-* hoặc --r-* giữ literal
   (đường kính icon, offset ảnh so le, cỡ chữ) — cùng tiền lệ page-nangluc.css.
   `.timeline{padding-block:...}` mockup ghi 96px — KHỚP đúng --sp-8, dùng
   token. `.contact-cta-box{border-radius:24px}` mockup — 22-24px KHÔNG có
   bậc nào trong thang (--r-xl là bậc cuối, 20px), giữ literal đúng như đã ghi
   trong docblock page-nangluc.css cho trường hợp này.
   ============================================================ */

/* ============================================================
   1. Breadcrumb — bản chép riêng, xem giải thích ở đầu file.
   ============================================================ */
/*
 * SỬA (28/08/2026, khách yêu cầu "làm layout banner, breadcrumb vs title
 * giống trang product cat"): breadcrumb rời khỏi nền navy (từng đọc màu
 * --on-navy-accent) sang nền TRẮNG của `.page-hero-info` — đổi bảng màu +
 * canh trái, cùng khuôn `.cat-hero-info .crumb` của taxonomy-danhmuc.css.
 * Xem mục 2 ngay dưới để rõ vì sao cấu trúc `.page-hero` đổi hẳn.
 */
.page-hero-info .crumb{ font-size:13px; color:var(--text-muted); margin-bottom:var(--sp-4); text-align:left; }
.page-hero-info .crumb a{ color:var(--text-muted); }
.page-hero-info .crumb a:hover{ color:var(--navy); }

/* ============================================================
   2. Banner (.page-hero)
   ============================================================ */
/*
 * SỬA (28/08/2026, cùng yêu cầu ở mục 1) — bỏ hẳn khối MỘT PHẦN nền navy
 * gradient bọc breadcrumb+H1+đoạn dẫn (padding 64/72px, `.page-hero p`),
 * đổi sang khuôn HAI PHẦN của `.cat-hero`/`.cat-hero-img`/`.cat-hero-info`
 * (taxonomy-vp_product_cat.php + assets/css/taxonomy-danhmuc.css) — dải
 * ảnh 2640×500 (fallback gradient navy khi field `banner_image` trống) rồi
 * xuống khối info NỀN TRẮNG. `.page-hero` (section ngoài cùng) không còn
 * cần nền/màu/padding riêng — hai khối con tự lo layout của mình.
 */
.page-hero{ padding:0; }
/*
 * SỬA 05/09/2026 (khách chốt kích thước ảnh banner): desktop 1920x425
 * (aspect-ratio 1920/425 ~ 4.52:1, cao hơn mốc 2640/500 = 5.28:1 chốt
 * 27/08/2026), điện thoại 430x150 (~2.87:1) để ảnh không mỏng như một vệt khi
 * bề ngang chỉ còn ~430px. Mốc 600px là breakpoint điện thoại các file này đang
 * dùng. Ảnh vẫn `object-fit:cover` nên ảnh gốc cỡ nào cũng lấp đúng khung.
 */
.page-hero-img{
  width:100%;
  aspect-ratio:1920/425;
  overflow:hidden;
  background:linear-gradient(160deg, var(--navy) 0%, var(--navy-dark) 100%);
}
.page-hero-img-el{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
.page-hero-info{
  padding:var(--sp-6) var(--wrap-x) var(--sp-5);
  text-align:center;
}
/*
 * SỬA (28/08/2026, khách chụp /gioi-thieu/ve-chung-toi/ khoanh mũi tên vào
 * breadcrumb, báo "check lại cái breadcrumb và đồng bộ lại tất cả cùng 1
 * style"): BỎ HẲN `.page-hero .wrap{max-width:820px}` — đây chính là gốc
 * lỗi khách thấy. `.page-hero-info` vừa mang class `wrap` (mặc định
 * max-width:var(--wrap-max), tức 1180px, xem global.css) vừa bị đè xuống
 * 820px RIÊNG cho khối banner — cột 820px này CANH GIỮA trang, nên breadcrumb
 * dù đã `text-align:left` vẫn có cạnh trái lùi vào ~180px so với mép trái
 * thật của `.wrap` 1180px chuẩn mà MỌI khối khác của trang (kể cả
 * `.cat-hero-info` bên danh mục sản phẩm) đang dùng — nhìn như breadcrumb
 * "trôi" giữa trang thay vì thẳng hàng với nội dung bên dưới. Bỏ override
 * này để `.page-hero-info` dùng ĐÚNG `.wrap` 1180px mặc định, khớp hoàn
 * toàn `.cat-hero-info`/`.nl-banner-info` (không có override tương tự).
 */
.page-hero-info h1{ color:var(--navy); font-size:38px; line-height:1.15; margin-bottom:var(--sp-4); }

/* ============================================================
   3. Section nền màu riêng phải tràn hết chiều ngang — xem giải thích đầu
   file. Cùng công thức home.css mục 1.
   ============================================================ */
.vmv.wrap,
.org.wrap,
.contact-cta.wrap{
  max-width:none;
  padding-block:var(--sp-8);
  padding-inline:max( var(--wrap-x), calc( (100% - var(--wrap-max) + var(--wrap-x) * 2) / 2 ) );
}
.vmv.wrap{ background:var(--bg-alt); }
.org.wrap{ background:var(--white); }
.contact-cta.wrap{ background:var(--white); }

/* ============================================================
   4. Giới thiệu Vinpack (.intro-grid)
   ============================================================ */
.intro-grid{ display:grid; grid-template-columns:1fr 1fr; gap:56px; align-items:center; }

.intro-copy .kicker{
  display:inline-block;
  font-size:12px;
  font-weight:700;
  color:var(--cobalt-ink);
  letter-spacing:2px;
  text-transform:uppercase;
  margin-bottom:var(--sp-4);
}
.intro-copy h2{ font-size:32px; line-height:1.22; margin-bottom:var(--sp-4); }
.intro-copy p{ color:var(--text-muted); font-size:15px; line-height:1.8; margin-bottom:var(--sp-4); }

.intro-stats{
  display:grid;
  grid-template-columns:repeat(2, 1fr);
  gap:var(--sp-5) var(--sp-4);
  margin-top:var(--sp-6);
  padding-top:var(--sp-6);
  border-top:1px solid var(--border);
}
.intro-stat .num{ font-family:var(--font-head); font-weight:800; font-size:34px; color:var(--navy); line-height:1; }
.intro-stat .num span{ color:var(--cobalt-ink); }
.intro-stat .lb{ font-size:13.5px; color:var(--text-muted); margin-top:6px; }

.intro-visual{ position:relative; min-height:440px; }
.intro-shape{
  position:absolute;
  border-radius:var(--r-xl);
  overflow:hidden;
  background:var(--img-bg);
  display:flex;
  align-items:center;
  justify-content:center;
}
.intro-shape.big{
  top:0; right:0; width:76%; height:340px;
  box-shadow:var(--sh-4);
}
.intro-shape.small{
  bottom:0; left:0; width:54%; height:220px;
  border:6px solid var(--white);
  box-shadow:var(--sh-3);
}
.intro-shape.big img{ width:100%; height:100%; object-fit:cover; }
.intro-shape.small svg{ width:56px; height:56px; opacity:.5; color:var(--navy); }


.intro-badge{
  position:absolute;
  left:8%;
  top:44%;
  z-index:3;
  background:var(--white);
  border-radius:var(--r-card-lg);
  padding:var(--sp-4) 22px;
  box-shadow:var(--sh-3);
  display:flex;
  align-items:center;
  gap:var(--sp-3);
}
.intro-badge .ib-num{ font-family:var(--font-head); font-weight:800; font-size:26px; color:var(--navy); }
.intro-badge .ib-lb{ font-size:12px; color:var(--text-muted); line-height:1.3; max-width:96px; }

/* ============================================================
   5. Tầm nhìn – Sứ mệnh – Giá trị cốt lõi (.vmv-tabs / .vmv-panel)
   ============================================================ */
.vmv .section-head{ text-align:center; max-width:1240px; margin-inline:auto; }
/* --text-muted mặc định của .section-head (global.css) trượt AA trên bg-alt
   — xem giải thích đầu file. */
.vmv .section-head p{ color:var(--text); }

.vmv-tabs{
  display:flex;
  gap:var(--sp-2);
  justify-content:center;
  flex-wrap:wrap;
  border-bottom:1px solid var(--border);
  margin-bottom:52px;
}
.vmv-tab{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--sp-3);
  padding:6px 34px 20px;
  position:relative;
  background:transparent;
  border:0;
  cursor:pointer;
  font-family:var(--font-head);
  font-weight:700;
  font-size:16px;
  /* --text trên bg-alt, KHÔNG --text-muted — xem giải thích đầu file. */
  color:var(--text);
  transition:color var(--dur-state) ease;
}
.vmv-tab .vmv-ico{
  width:44px;
  height:44px;
  display:flex;
  align-items:center;
  justify-content:center;
  color:var(--text);
  transition:color var(--dur-state) ease, transform var(--dur-state) ease;
}
.vmv-tab .vmv-ico svg{ width:30px; height:30px; }
.vmv-tab::after{
  content:'';
  position:absolute;
  left:0;
  right:0;
  bottom:-1px;
  height:3px;
  background:var(--navy);
  border-radius:3px 3px 0 0;
  transform:scaleX(0);
  transition:transform var(--dur-state) cubic-bezier(.4, 0, .2, 1);
}
.vmv-tab.active{ color:var(--navy); }
.vmv-tab.active .vmv-ico{ color:var(--navy); transform:translateY(-2px); }
.vmv-tab.active::after{ transform:scaleX(1); }
/* --cobalt-ink, KHÔNG --cobalt — chữ/icon hover cần đủ 4.5:1 trên bg-alt,
   xem giải thích đầu file. */
.vmv-tab:not(.active):hover{ color:var(--cobalt-ink); }
.vmv-tab:not(.active):hover .vmv-ico{ color:var(--cobalt-ink); }

@keyframes vpVmvFade{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }
.vmv-panel:not([hidden]){ animation:vpVmvFade .45s ease; }

.vmv-layout{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:56px;
  align-items:center;
  max-width:1080px;
  margin-inline:auto;
}
.vmv-media{
  border-radius:var(--r-xl);
  overflow:hidden;
  aspect-ratio:4 / 3;
  background:var(--img-bg);
  display:flex;
  align-items:center;
  justify-content:center;
  box-shadow:var(--sh-3);
}
.vmv-media svg{ width:60px; height:60px; opacity:.45; color:var(--navy); }
.vmv-body h3{ font-size:30px; line-height:1.2; margin-bottom:var(--sp-4); color:var(--navy); }
/* --text trên bg-alt, KHÔNG --text-muted — xem giải thích đầu file. */
.vmv-body > p{ color:var(--text); font-size:16px; line-height:1.85; }

.vmv-vlist{ display:flex; flex-direction:column; gap:22px; }
.vmv-vitem{ display:flex; gap:18px; align-items:flex-start; }
.vmv-vnum{
  flex-shrink:0;
  width:40px;
  height:40px;
  border-radius:11px;
  background:var(--white);
  color:var(--navy);
  font-family:var(--font-head);
  font-weight:800;
  font-size:16px;
  display:flex;
  align-items:center;
  justify-content:center;
  transition:background var(--dur-state) ease, color var(--dur-state) ease;
}
.vmv-vitem:hover .vmv-vnum{ background:var(--navy); color:var(--white); }
.vmv-vtext h4{ font-size:17px; margin-bottom:5px; color:var(--navy); }
/* --text trên bg-alt, KHÔNG --text-muted — xem giải thích đầu file. */
.vmv-vtext p{ color:var(--text); font-size:14px; line-height:1.65; }
.vmv-body.is-values h3{ margin-bottom:26px; }

/* ============================================================
   6. Ban lãnh đạo (.org-ceo / .org-row / .org-card)
   ============================================================ */
.org .section-head{ text-align:center; max-width:1240px; margin-inline:auto; }

.org-ceo{ display:flex; justify-content:center; }
.org-connector{ width:1px; height:44px; background:var(--border); margin-inline:auto; }
/* BÀI HỌC FEEDBACK ĐỢT 1, STT 15 — "chia 3 shape trên 3 shape dưới":
   TIỀN ĐỀ CŨ: `.org-row` chỉ có `flex-wrap:wrap` KHÔNG giới hạn max-width —
   với thẻ rộng cố định 236px + gap 28px, container thật (~1136px, .org.wrap
   trừ padding) vừa đúng 4 thẻ/hàng (4*236+3*28=1028 < 1136, 5 thẻ thì
   1180+112=1292 > 1136 nên bật hàng mới). Với dữ liệu demo 6 thành viên, kết
   quả là 4 thẻ hàng trên + 2 thẻ hàng dưới — LỆCH so với "3 trên 3 dưới"
   khách yêu cầu, dù đúng "chịu được 1..n" của Phase H (không vỡ, không ô
   rỗng, chỉ SAI SỐ CỘT MONG MUỐN).
   VÌ SAO SỬA BẰNG max-width CHỨ KHÔNG PHẢI grid-template-columns CỐ ĐỊNH:
   CSS Grid với `repeat(3, Npx)` tạo đủ 3 track CỐ ĐỊNH bất kể có bao nhiêu
   thẻ — hàng cuối THIẾU thẻ (n không chia hết 3, ví dụ 5 hoặc 7 thành viên)
   sẽ để trống track cuối, thẻ vẫn dồn về TRÁI, không tự căn giữa (giới hạn
   đã biết của CSS Grid: `justify-content` trên container chỉ căn giữa TOÀN
   BỘ tập track đã tạo, không căn giữa riêng từng hàng). Flexbox wrap thì
   NGƯỢC LẠI: mỗi "dòng" (flex line) tự có `justify-content` riêng — dòng nào
   thiếu thẻ vẫn tự căn giữa đúng dòng đó, không phụ thuộc dòng trước.
   BẤT BIẾN MỚI: `.org-row` giới hạn `max-width:764px` (= 3×236px thẻ +
   2×28px gap, đúng khổ MỘT hàng 3 thẻ) rồi `margin-inline:auto` để tự căn
   giữa trong `.org.wrap`. `flex-wrap` bật đúng hàng mới sau thẻ thứ 3 (thẻ
   thứ 4 không còn chỗ trong 764px), và `justify-content:center` cũ vẫn giữ
   nguyên nên căn giữa ĐÚNG cho MỌI n — n=6 (dữ liệu demo) ra đúng 3+3, n=5
   ra 3+2 (hàng 2 tự căn giữa, KHÔNG dồn trái), n=7 ra 3+3+1. KHÔNG hard-code
   "6" — đúng ràng buộc "chịu được số thành viên KHÁC 6" của feedback đợt 1. */
.org-row{ display:flex; justify-content:center; gap:28px; flex-wrap:wrap; max-width:764px; margin-inline:auto; margin-top:28px; }

.org-card{
  width:236px;
  background:var(--white);
  border:1px solid var(--border);
  border-radius:var(--r-card);
  overflow:hidden;
  transition:box-shadow var(--dur-state) ease, transform var(--dur-state) ease, border-color var(--dur-state) ease;
}
.org-card:hover{ transform:translateY(-4px); box-shadow:var(--sh-3); border-color:transparent; }
.org-photo{
  width:100%;
  aspect-ratio:4 / 3;
  background:var(--img-bg);
  display:flex;
  align-items:flex-end;
  justify-content:center;
  overflow:hidden;
}
.org-photo svg{ width:78px; height:78px; color:var(--icon-muted); margin-bottom:-4px; }
.org-photo img{ width:100%; height:100%; object-fit:cover; }
.org-info{ padding:18px 20px 20px; }
.org-name{ font-family:var(--font-head); font-weight:800; font-size:17px; color:var(--navy); margin-bottom:6px; }
/* --cobalt-ink, KHÔNG --cobalt — nhãn 12px đậm trên nền trắng cần đủ 4.5:1,
   xem giải thích đầu file. */
.org-role-title{ display:block; font-size:12px; font-weight:700; color:var(--cobalt-ink); text-transform:uppercase; letter-spacing:.6px; margin-bottom:3px; }
.org-role-sub{ font-size:13.5px; color:var(--text-muted); line-height:1.4; }

.org-card.lead{ width:280px; }
.org-card.lead .org-photo{ aspect-ratio:16 / 11; }
.org-card.lead .org-photo svg{ width:92px; height:92px; }
.org-card.lead .org-info{ padding:22px 24px 24px; border-top:3px solid var(--navy); }
.org-card.lead .org-name{ font-size:20px; }
.org-card.lead .org-role-title{ color:var(--navy); }

/* ============================================================
   7. Cột mốc phát triển (.timeline) — full-bleed, KHÔNG .wrap
   ============================================================ */
.timeline{
  background:var(--bg-alt);
  padding-block:var(--sp-8);
}
.timeline .section-head{ text-align:center; max-width:1240px; margin-inline:auto; padding-inline:var(--wrap-x); }
.tl-wrap{ max-width:860px; margin-inline:auto; padding-inline:var(--wrap-x); }

.tl-item{
  position:relative;
  padding:38px 0;
  border-bottom:1px solid var(--border);
  display:grid;
  grid-template-columns:220px 1fr;
  gap:40px;
  align-items:center;
  /* LUÔN hiện MẶC ĐỊNH — xem cảnh báo đầy đủ ở đầu file và docblock
     timeline.php. Hiệu ứng "hiện lần lượt khi cuộn tới" đã CHUYỂN sang GSAP
     + ScrollTrigger dùng chung toàn site (assets/js/motion.js) — không còn
     gate-class .js-tl-anim/.show nữa: GSAP tự set trạng thái ẩn bằng
     gsap.set() (inline style), CHỈ KHI đã tải được GSAP + KHÔNG bật
     prefers-reduced-motion, cùng đúng hợp đồng suy giảm êm như trước. */
  opacity:1;
}
.tl-item:last-child{ border-bottom:none; }
.tl-year{
  font-family:var(--font-head);
  font-weight:800;
  font-size:76px;
  line-height:.9;
  /* Tô đặc ngay từ đầu — KHÔNG viền-rỗng chờ .show, xem giải thích đầu file. */
  color:var(--navy);
  letter-spacing:-1px;
}
.tl-body{ position:relative; }
.tl-body::before{
  content:'';
  position:absolute;
  left:-40px;
  top:6px;
  bottom:6px;
  width:3px;
  border-radius:3px;
  background:linear-gradient(180deg, var(--navy), var(--cobalt));
  /* LUÔN hiện — xem giải thích đầu file. */
  transform:scaleY(1);
}
.tl-body p{ color:var(--text); font-size:15px; line-height:1.75; }

/* ============================================================
   8. Lĩnh vực kinh doanh (.fields-row) — không nền riêng, dùng
   section.wrap mặc định của global.css.
   ============================================================ */
.fields .section-head{ text-align:center; max-width:1240px; margin-inline:auto; }

/* BÀI HỌC FEEDBACK ĐỢT 1, STT 17 — "căn giữa cụm Lĩnh vực kinh doanh trên cả
   desktop lẫn mobile":
   TIỀN ĐỀ CŨ: CSS Grid `repeat(6, 1fr)` LUÔN tạo đủ 6 track dù có bao nhiêu
   ô — dữ liệu THẬT hôm nay chỉ có 5 danh mục cấp một (đo trực tiếp trên
   trang sống: 5 phần tử `.field-col`, xem báo cáo), nên track thứ 6 luôn
   trống nhưng vẫn giữ 1/6 bề rộng ở BÊN PHẢI, đẩy cả cụm 5 ô nhìn lệch trái
   trong khung `.fields-row` đã căn giữa — hộp NGOÀI thì giữa trang, nhưng
   NỘI DUNG bên trong lại lệch, đúng như khách phản ánh. Cùng loại giới hạn
   CSS Grid đã ghi ở docblock `.org-row` (STT 15) — track cố định không tự
   co khi thiếu ô.
   BẤT BIẾN MỚI: đổi sang Flexbox (`flex-wrap` + `justify-content:center`)
   với `flex-basis` theo PHẦN TRĂM (không phải px cố định) khớp đúng số cột
   mong muốn mỗi khổ màn hình (16.6667% = 1/6 desktop, 33.3333% = 1/3 tablet,
   50% = 1/2 mobile — xem 2 khai báo `.field-col` ở khối responsive bên
   dưới). Flexbox tự căn giữa TỪNG DÒNG độc lập (khác CSS Grid), nên hàng
   cuối thiếu ô (n không chia hết cho số cột) vẫn tự căn giữa đúng — n=5 hôm
   nay ra một hàng CĂN GIỮA (5×16.6667%=83.33% được đặt giữa 100%), n=6 ra
   đủ một hàng khớp thiết kế mockup (không đổi), n=8 ra 6+2 với hàng 2 tự
   căn giữa. KHÔNG hard-code "6" — đúng nguyên tắc "1..n" đã ghi sẵn trong
   docblock fields.php. */
.fields-row{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  max-width:1080px;
  margin-inline:auto;
}
.field-col{
  flex:0 1 16.6667%;
  text-align:center;
  padding:8px var(--sp-5);
  position:relative;
  text-decoration:none;
}
/* Vách ngăn dọc mảnh giữa các cột liền kề — không phụ thuộc số ô cố định. */
.field-col + .field-col::before{
  content:'';
  position:absolute;
  left:0;
  top:14%;
  bottom:14%;
  width:1px;
  background:var(--border);
}
.field-ic{
  width:52px;
  height:52px;
  margin:0 auto var(--sp-4);
  color:var(--navy);
  display:flex;
  align-items:center;
  justify-content:center;
  transition:color var(--dur-state) ease, transform var(--dur-state) ease;
}
/* svg dựng sẵn và img khách tải lên cùng lấp đầy ô 52px — xem cat-slider.css. */
.field-ic svg,
.field-ic img{ width:100%; height:100%; }
.field-ic img{ object-fit:contain; }
.field-col:hover .field-ic{ color:var(--cobalt); transform:translateY(-3px); }
.field-col h3{ font-size:15px; color:var(--navy); margin-bottom:var(--sp-2); font-family:var(--font-head); font-weight:800; }
.field-col p{ font-size:12.5px; color:var(--text-muted); line-height:1.55; }

/* ============================================================
   9. Liên hệ (.contact-cta-box)
   ============================================================ */
.contact-cta-box{
  background:linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  border-radius:var(--r-xl);
  padding:var(--sp-7);
  text-align:center;
  color:var(--white);
  position:relative;
  overflow:hidden;
}
/* Vòng sáng góc trái dưới — phần khuôn chung, trước đây chỉ 3/6 khối có. */
.contact-cta-box::after{
  content:"";
  position:absolute;
  left:-60px;
  bottom:-60px;
  width:260px;
  height:260px;
  border-radius:var(--r-full);
  background:radial-gradient(circle, rgba(92,144,245,.25), transparent 70%);
}
.contact-cta-box > *{ position:relative; z-index:1; }
/*
 * BỎ font-size GHI CỨNG (07/09/2026, đợt đồng bộ CTA — lượt kiểm điện thoại).
 * Đo tại 375px: tiêu đề khối này 32px trong khi `.cta-box` của trang chủ/dịch
 * vụ/dự án/tuyển dụng chỉ 25px, vì `.cta-box h2` KHÔNG khai cỡ chữ nên co theo
 * `h2{font-size:25px}` của global.css ở mốc ≤900px, còn khối này khai đè nên
 * đứng nguyên 32px trên hộp chỉ rộng 279px. Bỏ khai đi thì cả sáu khối cùng
 * một cỡ ở cả hai đầu: 32px desktop, 25px điện thoại.
 */
.contact-cta-box h2{ color:var(--white); margin-bottom:var(--sp-4); text-wrap:balance; }
.contact-cta-box p{ color:var(--on-navy-text); font-size:16px; line-height:1.7; margin-bottom:var(--sp-6); max-width:600px; margin-inline:auto; }
.contact-cta-actions{ display:flex; gap:var(--sp-4); justify-content:center; flex-wrap:wrap; }
/*
 * SỬA (27/08/2026, khách yêu cầu "đồng bộ lại các trang với nhau về style
 * nút") — bỏ `.cta-btn-primary`/`.cta-btn-ghost` riêng của trang này, đổi
 * markup sang dùng `.btn.btn-primary`/`.btn.btn-outline-light` chung — ĐÚNG
 * kiểu nút đã dùng ở trang chủ/dịch vụ/dự án (chọn làm chuẩn vì đã có ở 3/4
 * nơi). `.btn-outline-light` dùng nguyên từ global.css, không cần override
 * (viền/chữ trắng vốn đã hợp nền navy). `.btn-primary` thì cần, cùng lý lẽ
 * đúng từng chữ như `.cta-box .btn-primary` của home.css/page-dichvu.css/
 * page-duan.css: `.contact-cta-box` KHÔNG mang `.on-navy` nên rule của
 * global.css không với tới, và nền --navy của `.btn-primary` chỉ 1.23:1 so
 * với hộp navy — nút tàng hình.
 */
/*
 * ĐÍCH ĐỔI 03/09/2026 (khách gửi ảnh chụp nút chìm vào nền navy ở khối
 * "Vẫn còn nhiều dự án khác", /du-an-tieu-bieu/): --cobalt-ink trên nền hộp
 * navy chỉ tách bạch 2.13:1 — đỡ hơn nút TÀNG HÌNH (1.23:1) mà comment ở
 * trên nói tới, nhưng vẫn mờ. `.cta-box .btn-primary` (home.css/page-
 * dichvu.css/page-duan.css) — khối mà rule NÀY tự nhận là "khuôn" để theo —
 * đã đổi sang trắng/navy, đạt 11.41:1. Đổi tại đây cho khớp lại đúng cái
 * khuôn nó tự nhận.
 */
.contact-cta-box .btn-primary,
.contact-cta-box .btn-primary:hover{ background:var(--white); color:var(--navy); border-color:var(--white); }

/* ============================================================
   10. Responsive
   ============================================================ */
@media (max-width:1180px){
  .intro-grid{ grid-template-columns:1fr; gap:36px; }
  .intro-visual{ min-height:360px; }
  .vmv-layout{ grid-template-columns:1fr; gap:32px; }
  .vmv-media{ aspect-ratio:16 / 10; }
  .vmv-body h3{ font-size:24px; }
  .fields-row{ gap:36px 0; }
  .field-col{ flex-basis:33.3333%; }
  .field-col:nth-child(3n+1)::before{ display:none; }
  .field-col + .field-col::before{ top:0; bottom:0; }
  /* max-width:none — huỷ giới hạn 764px (khổ hàng 3 thẻ) của desktop. Ở khổ
     này `.org-card` đã đổi sang width PHẦN TRĂM (50%) nên tự chia đúng 2
     thẻ/hàng bất kể .org-row rộng bao nhiêu — không cần giới hạn max-width
     kiểu desktop nữa, xem docblock đầy đủ ở khai báo .org-row mặc định. */
  .org-row{ gap:20px; max-width:none; }
  .org-card{ width:calc(50% - 12px); max-width:236px; }
  .org-card.lead{ width:280px; }
}

@media (max-width:900px){
  .vmv.wrap,
  .org.wrap,
  .contact-cta.wrap,
  .timeline{ padding-block:var(--sp-6); }
}

@media (max-width:680px){
  .tl-item{ grid-template-columns:1fr; gap:10px; padding:28px 0; }
  .tl-year{ font-size:54px; }
  .tl-body::before{ display:none; }
}

@media (max-width:600px){
	/* Banner điện thoại 430x150 — xem ghi chú .page-hero-img. */
	.page-hero-img{ aspect-ratio:430/150; }

  .intro-stats{ grid-template-columns:1fr 1fr; }
  .field-col{ flex-basis:50%; }
  .field-col:nth-child(3n+1)::before{ display:block; }
  .field-col:nth-child(2n+1)::before{ display:none; }
  .vmv-tab{ padding:6px 18px 16px; font-size:14px; }
  .vmv-tab .vmv-ico{ width:34px; height:34px; }
  .vmv-tab .vmv-ico svg{ width:24px; height:24px; }
  .org-card,
  .org-card.lead{ width:100%; max-width:280px; }
  .contact-cta-box{ padding:var(--sp-6) var(--sp-5); }
}
/*
 * KHUÔN CTA CHUẨN TRÊN ĐIỆN THOẠI (07/09/2026) — khai cuối file để chắc chắn
 * đứng SAU rule chính của hộp (bài học từ page-tacgia.css: rule điện thoại nằm
 * TRƯỚC rule chính thì thua thứ tự nguồn, khai đúng mà không hiệu lực nào —
 * hộp đó đo ra đệm 36px trong khi năm hộp kia 32/24).
 *
 * NÚT FULL-WIDTH: đo tại 375px, nút co theo độ dài chữ nên hai nút trong cùng
 * một khối lệch nhau (dự án 187px và 155px, năng lực 199px và 171px) và mỗi
 * trang một bề ngang. Kéo bằng bề ngang hộp thì cột nút thẳng nhau ở mọi
 * trang, và vùng chạm cũng rộng hơn hẳn.
 */
@media (max-width:600px){
  .contact-cta-box .btn{ width:100%; }
}
/*
 * THANG CỠ TIÊU ĐỀ BANNER CHUẨN (07/09/2026): 38px desktop, 30px từ 900px,
 * 28px từ 600px. Trước đợt này mỗi banner tự chọn mốc và cỡ riêng nên ở 800px
 * màn hình có ba cỡ tiêu đề khác nhau cùng lúc — xem docblock đầy đủ trong
 * scratchpad/banner-dong-bo.py và các khối tương ứng ở tám file banner khác.
 */
@media (max-width:900px){
  .page-hero-info h1{ font-size:30px; }
}

@media (max-width:600px){
  .page-hero-info h1{ font-size:28px; }
}
