/* ============================================================
   SAVINA · NỀN CHUNG CHO MÀN HÌNH ĐIỆN THOẠI
   ------------------------------------------------------------
   Tệp này sửa hai nguyên nhân gốc làm vỡ bố cục khi người đọc mở
   trang từ trong Zalo, Facebook, Messenger, Instagram, TikTok —
   những trình duyệt nằm BÊN TRONG ứng dụng, không phải Safari hay
   Chrome thật.

   NGUYÊN NHÂN 1 · 100vh không bằng chiều cao nhìn thấy
   Trong trình duyệt của ứng dụng luôn có thanh công cụ riêng ở
   trên và dưới, ăn mất 100–180px. Nhưng 100vh vẫn tính theo chiều
   cao màn hình KHI KHÔNG CÓ các thanh đó. Hậu quả: khối đặt
   min-height:100vh cao hơn chỗ thật sự nhìn thấy nên nội dung bị
   đẩy xuống dưới mép; khối đặt max-height:calc(100vh - 110px) thì
   tràn qua đáy, phần cuối không ai cuộn tới được. Chrome trên máy
   tính không bao giờ lộ lỗi này, nên nó hay lọt lưới.

   Cách chữa: dùng --vh thay cho 100vh.
     · Máy đời mới hiểu đơn vị dvh — luôn đúng chiều cao nhìn thấy.
     · Máy cũ hơn thì savina-mobile.js đo window.innerHeight và cập
       nhật mỗi khi thanh công cụ hiện ra hay thu lại.
     · Không có JavaScript thì rơi về 100vh như cũ, tức là không tệ
       hơn hiện tại.

   NGUYÊN NHÂN 2 · viewport-fit=cover mà không chừa vùng an toàn
   Mọi trang đều khai báo viewport-fit=cover để nền tràn sát mép
   máy. Nhưng không trang nào chừa chỗ cho tai thỏ ở trên và vạch
   home ở dưới. Trên iPhone, thanh điều hướng dính đáy nằm ở
   bottom:12px — nghĩa là nằm ĐÈ lên vạch home, bấm thì máy hiểu
   nhầm thành vuốt thoát ứng dụng. Thanh trên cùng cũng chui vào
   dưới tai thỏ.

   Cách chữa: cộng thêm env(safe-area-inset-*) vào các khối dính
   mép. Máy không có tai thỏ trả về 0px nên bố cục giữ nguyên y cũ.
   ============================================================ */

/* ---------- Chiều cao thật của khung nhìn ---------- */
:root { --vh: 100vh; }
@supports (height: 100dvh) { :root { --vh: 100dvh; } }
/* savina-mobile.js chỉ ghi đè --vh khi máy KHÔNG hiểu dvh */

/* ---------- Vùng an toàn của máy ---------- */
:root {
  --sa-top:    env(safe-area-inset-top, 0px);
  --sa-bottom: env(safe-area-inset-bottom, 0px);
  --sa-left:   env(safe-area-inset-left, 0px);
  --sa-right:  env(safe-area-inset-right, 0px);
}

/* KHÔNG đụng vào thanh trên cùng. Tôi đã thử nới nó xuống dưới tai thỏ,
   nhưng 17 trang đang bù khoảng trống đầu trang bằng con số cố định
   (padding-top:76px, 74px, 68px tuỳ trang). Nới thanh ra là nội dung đầu
   mỗi trang chui vào dưới nó — chữa một chỗ, vỡ mười bảy chỗ.

   Thêm nữa, trong trình duyệt của Zalo và Facebook thì thanh công cụ của
   chính ứng dụng đã chiếm phần tai thỏ, nên nội dung web bắt đầu bên
   dưới nó: safe-area-inset-top bằng 0 và không có gì phải chừa. Việc nới
   thanh chỉ cần cho Safari mở trực tiếp — một việc riêng, làm cùng lúc
   với việc dời các con số cố định kia vào một biến chung. */

/* Thanh điều hướng dính đáy và các nút nổi: nâng lên khỏi vạch home */
.savina-support-nav, #savinaSupportNav {
  bottom: calc(12px + var(--sa-bottom)) !important;
}
.ai-fab, #ai-fab { bottom: calc(24px + var(--sa-bottom)); }

/* Khoảng trống cuối trang để thanh dính đáy không che mất dòng cuối */
body { padding-bottom: calc(var(--sa-bottom)); }

/* Lề trái phải khi máy xoay ngang, lúc đó tai thỏ nằm ở cạnh bên */
@media (orientation: landscape) {
  body { padding-left: var(--sa-left); padding-right: var(--sa-right); }
}

/* ---------- Vài nếp giữ cho chắc ----------
   Ảnh và khung nhúng không chịu co theo khung cha là nguyên nhân
   phổ biến thứ ba làm trang trượt ngang trên máy hẹp. */
img, video, iframe, svg, table { max-width: 100%; }
img, video { height: auto; }

/* Chữ dài không ngắt được (địa chỉ web, mã hợp đồng) đẩy rộng khối
   chứa nó. Cho phép ngắt ở mọi vị trí khi không còn cách nào khác. */
body { overflow-wrap: break-word; }

/* Trình duyệt trong ứng dụng hay tự phóng to cỡ chữ theo cách riêng,
   làm chữ nhảy cỡ lung tung giữa các khối. Khoá lại. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* iOS phóng to cả trang khi chạm vào ô nhập có cỡ chữ dưới 16px.
   Người đọc gõ xong thì trang đứng ở mức phóng to, nhìn như vỡ. */
@media (max-width: 900px) {
  input, select, textarea { font-size: max(16px, 1em); }
}

/* ---------- Bảng giá trên máy rất hẹp ----------
   Bảng bốn cột với đệm 10px mỗi bên vừa đủ tràn khung ở máy 360px, cắt
   mất một khúc cột cuối. Tiếng Anh dễ vỡ hơn tiếng Việt vì tiêu đề cột
   dài hơn ("LOCALITY" so với "Địa phương"). Thu đệm lại thay vì cho
   bảng cuộn ngang — người đọc không nhìn thấy thanh cuộn trong bảng,
   nên họ tưởng là trang bị lỗi chứ không biết có thể kéo. */
@media (max-width: 400px) {
  .detail-table th, .detail-table td,
  .price-table th, .price-table td,
  .reference-table th, .reference-table td { padding-left: 7px; padding-right: 7px; }
  /* Tiêu đề cột tiếng Anh viết hoa ("LOCALITY") vẫn rộng hơn chỗ có.
     Cho phép ngắt dòng trong ô tiêu đề thay vì đẩy bảng tràn ra. */
  .detail-table th, .price-table th, .reference-table th {
    white-space: normal; word-break: break-word; hyphens: auto;
  }
}

/* ---------- Nội dung đầu trang chui xuống dưới thanh cố định ----------
   Khối đầu trang chủ căn giữa theo chiều dọc (align-items:center) trong một
   khung cao tối thiểu 680px. Trên màn hình hẹp, chữ xuống dòng nhiều nên
   nội dung CAO HƠN khung; lúc đó căn giữa đẩy nó tràn đều ra hai đầu, và
   đầu trên chui vào dưới thanh điều hướng cố định. Kết quả: dòng đầu tiên
   bị cắt ngang — đúng 8px ở mọi cỡ máy điện thoại, trong khi máy tính thì
   không sao vì chữ ít dòng hơn.

   'safe center' là cách chữa đúng gốc: vẫn căn giữa khi còn chỗ, nhưng khi
   nội dung cao hơn khung thì bám mép trên thay vì tràn lên. Nhờ vậy dù bạn
   sửa chữ trong Admin cho dài thêm, dòng đầu cũng không bao giờ bị che nữa
   — khác với cách nới thêm khoảng trống, chỉ đúng với độ dài chữ hiện tại.

   Trình duyệt quá cũ không hiểu 'safe' thì rơi về flex-start: chữ bám mép
   trên, vẫn đọc được trọn vẹn. */
@media (max-width: 900px) {
  .hero {
    align-items: flex-start;
    align-items: safe center;
    padding-top: 92px;          /* thanh cao 70px + khoảng thở 22px */
  }
}

/* ============================================================
   CHẠM VÀ BẤM
   ------------------------------------------------------------
   Mặc định trình duyệt di động tô một ô vuông xanh lên thứ vừa
   được chạm. Nó vuông, lệch khỏi hình dạng nút, và hiện cả ở chỗ
   không phải nút. Tắt nó đi rồi tự làm phản hồi: thu nhẹ và tối
   nhẹ ngay lúc ngón tay còn đặt, nhả ra thì bật lại.

   Thu 2–4% là đủ để ngón tay cảm thấy "ăn", mà không làm chữ
   nhảy. Nút lớn thu ít hơn nút nhỏ, vì cùng một tỷ lệ thì nút
   lớn trông như bị giật.

   Ai đã bật "giảm chuyển động" trong cài đặt máy thì bỏ hết
   hiệu ứng — với một số người, chuyển động gây chóng mặt thật.
   ============================================================ */
a, button, [role="button"], input, select, textarea, label, summary,
.btn, .pill, .chip, .card, .term, .ssMuc, .pcTab, .phTab {
  -webkit-tap-highlight-color: transparent;
}

a, button, [role="button"], summary, .btn, .pill, .chip, .pcTab, .phTab {
  transition: transform .13s cubic-bezier(.22, .61, .36, 1),
              background-color .16s ease, border-color .16s ease, opacity .16s ease;
  -webkit-touch-callout: none;
}
button:active, [role="button"]:active, .btn:active, .pill:active,
.chip:active, .pcTab:active, .phTab:active, summary:active { transform: scale(.96); }

/* Thẻ và ô danh sách: lún xuống một chút thay vì thu lại, vì thu cả
   thẻ lớn trông như trang bị rung. */
.card:active, .term:active, .ssMuc:active, .analysisCard:active,
.knowledge-card:active, .region-card:active {
  transform: translateY(1px);
  transition: transform .13s cubic-bezier(.22,.61,.36,1), background-color .16s ease;
}

/* Liên kết trong bài đọc: không thu, chỉ đổi màu — chữ nhúc nhích
   giữa đoạn văn làm người đọc mất dòng. */
p a:active, li a:active, td a:active { transform: none; opacity: .62; }

/* Vùng chạm tối thiểu 44px cho nút nhỏ trên điện thoại: ngón tay
   người lớn không bấm trúng ô 28px, bấm hụt vài lần là người ta bỏ đi. */
@media (max-width: 900px) and (pointer: coarse) {
  button, [role="button"], .pill, .chip { min-height: 40px; }
}

/* Viền chỉ hiện khi đi bằng bàn phím, không hiện khi chạm tay */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--green, #123126);
  outline-offset: 2px; border-radius: 6px;
}

@media (prefers-reduced-motion: reduce) {
  a, button, [role="button"], summary, .btn, .pill, .chip, .pcTab, .phTab,
  .card, .term, .ssMuc { transition: none !important; }
  button:active, [role="button"]:active, .btn:active, .pill:active, .chip:active,
  .pcTab:active, .phTab:active, .card:active, .term:active, .ssMuc:active { transform: none !important; }
}

/* ---------- Ô trong lưới phải co được ----------
   Lưới đặt cột là '1fr' thì mức co nhỏ nhất của cột mặc định bằng bề
   rộng tối thiểu của NỘI DUNG bên trong. Một thuật ngữ dài không ngắt
   được là cột phình ra rộng hơn khung chứa, kéo cả trang trượt ngang.
   Thấy rõ nhất khi người đọc phóng to chữ: chỗ hẹp đi mà chữ thì dài ra.

   min-width:0 cho phép cột co theo khung, còn chữ thì ngắt xuống dòng.
   Đây là cách chữa đúng gốc cho mọi lưới, không phải chỉnh riêng trang
   từ điển. */
.grid > *, .cards > *, .list > *, .term, .card { min-width: 0; }
.term, .card, .grid > * { overflow-wrap: anywhere; }

/* ---------- Khung chứa chữ không được khoá chiều cao ----------
   Khi người đọc để cỡ chữ lớn trong cài đặt máy, hệ điều hành phóng to
   CHỮ nhưng không phóng khung chứa nó. Mọi khung đặt height cố định sẽ
   cắt mất phần chữ dôi ra. Đo ở cỡ chữ gấp đôi: thẻ chuỗi sản xuất mất
   110–172px chữ, thanh điều hướng đáy mất 7–14px — tức là mất hẳn dòng
   nhãn dưới biểu tượng.

   Đổi height thành min-height: ở cỡ chữ thường trông y như cũ, còn khi
   chữ to lên thì khung cao theo. */
/* ĐÃ GỠ phần chỉnh thẻ chuỗi sản xuất (.step).
   Tôi từng ép thẻ xuống một cột trên máy hẹp để chữ có đủ bề ngang khi
   người đọc phóng to cỡ chữ. Hậu quả: cột ẢNH bị bóp về 0px — ảnh vẫn
   nằm đó nhưng không còn bề ngang nào để hiện, nên thẻ trông trống trơn.
   Mất ảnh là cái giá quá đắt cho một lỗi chỉ xảy ra ở cỡ chữ gấp rưỡi
   trở lên. Trả .step về đúng như cũ, không đụng tới nữa. */

.savina-support-nav, #savinaSupportNav {
  bottom: calc(12px + var(--sa-bottom)) !important;
}
.ai-fab, #ai-fab { bottom: calc(24px + var(--sa-bottom)); }

/* Khoảng trống cuối trang để thanh dính đáy không che mất dòng cuối */
body { padding-bottom: calc(var(--sa-bottom)); }

/* Lề trái phải khi máy xoay ngang, lúc đó tai thỏ nằm ở cạnh bên */
@media (orientation: landscape) {
  body { padding-left: var(--sa-left); padding-right: var(--sa-right); }
}

/* ---------- Vài nếp giữ cho chắc ----------
   Ảnh và khung nhúng không chịu co theo khung cha là nguyên nhân
   phổ biến thứ ba làm trang trượt ngang trên máy hẹp. */
img, video, iframe, svg, table { max-width: 100%; }
img, video { height: auto; }

/* Chữ dài không ngắt được (địa chỉ web, mã hợp đồng) đẩy rộng khối
   chứa nó. Cho phép ngắt ở mọi vị trí khi không còn cách nào khác. */
body { overflow-wrap: break-word; }

/* Trình duyệt trong ứng dụng hay tự phóng to cỡ chữ theo cách riêng,
   làm chữ nhảy cỡ lung tung giữa các khối. Khoá lại. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* iOS phóng to cả trang khi chạm vào ô nhập có cỡ chữ dưới 16px.
   Người đọc gõ xong thì trang đứng ở mức phóng to, nhìn như vỡ. */
@media (max-width: 900px) {
  input, select, textarea { font-size: max(16px, 1em); }
}

/* ---------- Bảng giá trên máy rất hẹp ----------
   Bảng bốn cột với đệm 10px mỗi bên vừa đủ tràn khung ở máy 360px, cắt
   mất một khúc cột cuối. Tiếng Anh dễ vỡ hơn tiếng Việt vì tiêu đề cột
   dài hơn ("LOCALITY" so với "Địa phương"). Thu đệm lại thay vì cho
   bảng cuộn ngang — người đọc không nhìn thấy thanh cuộn trong bảng,
   nên họ tưởng là trang bị lỗi chứ không biết có thể kéo. */
@media (max-width: 400px) {
  .detail-table th, .detail-table td,
  .price-table th, .price-table td,
  .reference-table th, .reference-table td { padding-left: 7px; padding-right: 7px; }
  /* Tiêu đề cột tiếng Anh viết hoa ("LOCALITY") vẫn rộng hơn chỗ có.
     Cho phép ngắt dòng trong ô tiêu đề thay vì đẩy bảng tràn ra. */
  .detail-table th, .price-table th, .reference-table th {
    white-space: normal; word-break: break-word; hyphens: auto;
  }
}

/* ---------- Nội dung đầu trang chui xuống dưới thanh cố định ----------
   Khối đầu trang chủ căn giữa theo chiều dọc (align-items:center) trong một
   khung cao tối thiểu 680px. Trên màn hình hẹp, chữ xuống dòng nhiều nên
   nội dung CAO HƠN khung; lúc đó căn giữa đẩy nó tràn đều ra hai đầu, và
   đầu trên chui vào dưới thanh điều hướng cố định. Kết quả: dòng đầu tiên
   bị cắt ngang — đúng 8px ở mọi cỡ máy điện thoại, trong khi máy tính thì
   không sao vì chữ ít dòng hơn.

   'safe center' là cách chữa đúng gốc: vẫn căn giữa khi còn chỗ, nhưng khi
   nội dung cao hơn khung thì bám mép trên thay vì tràn lên. Nhờ vậy dù bạn
   sửa chữ trong Admin cho dài thêm, dòng đầu cũng không bao giờ bị che nữa
   — khác với cách nới thêm khoảng trống, chỉ đúng với độ dài chữ hiện tại.

   Trình duyệt quá cũ không hiểu 'safe' thì rơi về flex-start: chữ bám mép
   trên, vẫn đọc được trọn vẹn. */
@media (max-width: 900px) {
  .hero {
    align-items: flex-start;
    align-items: safe center;
    padding-top: 92px;          /* thanh cao 70px + khoảng thở 22px */
  }
}

/* ============================================================
   CHẠM VÀ BẤM
   ------------------------------------------------------------
   Mặc định trình duyệt di động tô một ô vuông xanh lên thứ vừa
   được chạm. Nó vuông, lệch khỏi hình dạng nút, và hiện cả ở chỗ
   không phải nút. Tắt nó đi rồi tự làm phản hồi: thu nhẹ và tối
   nhẹ ngay lúc ngón tay còn đặt, nhả ra thì bật lại.

   Thu 2–4% là đủ để ngón tay cảm thấy "ăn", mà không làm chữ
   nhảy. Nút lớn thu ít hơn nút nhỏ, vì cùng một tỷ lệ thì nút
   lớn trông như bị giật.

   Ai đã bật "giảm chuyển động" trong cài đặt máy thì bỏ hết
   hiệu ứng — với một số người, chuyển động gây chóng mặt thật.
   ============================================================ */
a, button, [role="button"], input, select, textarea, label, summary,
.btn, .pill, .chip, .card, .term, .ssMuc, .pcTab, .phTab {
  -webkit-tap-highlight-color: transparent;
}

a, button, [role="button"], summary, .btn, .pill, .chip, .pcTab, .phTab {
  transition: transform .13s cubic-bezier(.22, .61, .36, 1),
              background-color .16s ease, border-color .16s ease, opacity .16s ease;
  -webkit-touch-callout: none;
}
button:active, [role="button"]:active, .btn:active, .pill:active,
.chip:active, .pcTab:active, .phTab:active, summary:active { transform: scale(.96); }

/* Thẻ và ô danh sách: lún xuống một chút thay vì thu lại, vì thu cả
   thẻ lớn trông như trang bị rung. */
.card:active, .term:active, .ssMuc:active, .analysisCard:active,
.knowledge-card:active, .region-card:active {
  transform: translateY(1px);
  transition: transform .13s cubic-bezier(.22,.61,.36,1), background-color .16s ease;
}

/* Liên kết trong bài đọc: không thu, chỉ đổi màu — chữ nhúc nhích
   giữa đoạn văn làm người đọc mất dòng. */
p a:active, li a:active, td a:active { transform: none; opacity: .62; }

/* Vùng chạm tối thiểu 44px cho nút nhỏ trên điện thoại: ngón tay
   người lớn không bấm trúng ô 28px, bấm hụt vài lần là người ta bỏ đi. */
@media (max-width: 900px) and (pointer: coarse) {
  button, [role="button"], .pill, .chip { min-height: 40px; }
}

/* Viền chỉ hiện khi đi bằng bàn phím, không hiện khi chạm tay */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--green, #123126);
  outline-offset: 2px; border-radius: 6px;
}

@media (prefers-reduced-motion: reduce) {
  a, button, [role="button"], summary, .btn, .pill, .chip, .pcTab, .phTab,
  .card, .term, .ssMuc { transition: none !important; }
  button:active, [role="button"]:active, .btn:active, .pill:active, .chip:active,
  .pcTab:active, .phTab:active, .card:active, .term:active, .ssMuc:active { transform: none !important; }
}

/* ---------- Ô trong lưới phải co được ----------
   Lưới đặt cột là '1fr' thì mức co nhỏ nhất của cột mặc định bằng bề
   rộng tối thiểu của NỘI DUNG bên trong. Một thuật ngữ dài không ngắt
   được là cột phình ra rộng hơn khung chứa, kéo cả trang trượt ngang.
   Thấy rõ nhất khi người đọc phóng to chữ: chỗ hẹp đi mà chữ thì dài ra.

   min-width:0 cho phép cột co theo khung, còn chữ thì ngắt xuống dòng.
   Đây là cách chữa đúng gốc cho mọi lưới, không phải chỉnh riêng trang
   từ điển. */
.grid > *, .cards > *, .list > *, .term, .card { min-width: 0; }
.term, .card, .grid > * { overflow-wrap: anywhere; }

/* ---------- Khung chứa chữ không được khoá chiều cao ----------
   Khi người đọc để cỡ chữ lớn trong cài đặt máy, hệ điều hành phóng to
   CHỮ nhưng không phóng khung chứa nó. Mọi khung đặt height cố định sẽ
   cắt mất phần chữ dôi ra. Đo ở cỡ chữ gấp đôi: thẻ chuỗi sản xuất mất
   110–172px chữ, thanh điều hướng đáy mất 7–14px — tức là mất hẳn dòng
   nhãn dưới biểu tượng.

   Đổi height thành min-height: ở cỡ chữ thường trông y như cũ, còn khi
   chữ to lên thì khung cao theo. */

.savina-support-nav, #savinaSupportNav {
  height: auto !important;
  min-height: 66px !important;
  padding-top: 7px !important;
  padding-bottom: 7px !important;
}
.savina-support-nav a, #savinaSupportNav a { height: auto !important; }

/* Thẻ chuỗi sản xuất chia hai cột cố định 44%/56%; chữ to lên thì cột chữ
   quá hẹp. Trên máy hẹp cho ảnh và chữ xếp dọc để chữ có đủ bề ngang. */


/* ---------- Thanh trên cùng cao theo cỡ chữ ----------
   Ở cỡ chữ gấp đôi, tên trang và các nút trong thanh cần 218px nhưng
   thanh bị khoá ở 76px nên cắt mất. Cho thanh cao theo nội dung, rồi
   khối đầu trang chừa đúng bằng chiều cao THẬT của thanh (savina-mobile.js
   đo và ghi vào --nav-h) thay vì bằng một con số cố định. */
nav.nav, header.nav, .nav { height: auto; min-height: 76px; }
@media (max-width: 900px) { nav.nav, header.nav, .nav { min-height: 68px; } }

/* Bên trong thanh cũng khoá cứng chiều cao: khung 70px, các nút 44px.
   Chữ to lên thì chúng tràn ra ngoài thanh và đè xuống nội dung bên
   dưới. Đổi hết sang min-height để thanh nở ra thay vì để chữ lòi ra. */
.nav .container { height: auto; min-height: 70px; }
.nav .actions, .nav .icon, .nav .langpill, .nav .pill {
  height: auto; min-height: 44px; display: inline-flex;
  align-items: center; justify-content: center;
}
.nav .actions { flex-wrap: wrap; gap: 8px; }

@media (max-width: 900px) {
  .hero { padding-top: calc(var(--nav-h, 70px) + 22px); }
}
