/* Sửa lỗi đo được trong bản export Framer 05/09/2026.
 *
 * Vì sao là CSS + lớp do JS gắn, chứ không phải CSS thuần: mọi tên lớp trong
 * bản export đều mang hash của Framer (framer-6aip5y, framer-15xcfhk…) và đổi
 * sau mỗi lần xuất lại. Bám vào chúng là hẹn một lần build vỡ. Nên register.js
 * tìm phần tử theo ĐẶC ĐIỂM ĐO ĐƯỢC (cỡ chữ, nét bị cắt) rồi gắn lớp ở đây.
 *
 * Tệp này nằm trong <head> nên sống sót qua hydrate của React. */

/* Dấu tiếng Việt bị xén vì giãn dòng đặt đúng bằng cỡ chữ.
 *
 * Bản thiết kế đặt line-height = font-size ở 8 chỗ: ba số hero (34px/34px),
 * "Plan your visit", hai dòng giờ mở cửa, và ba bước "Chọn hoạt động / Gửi
 * thông tin / Nhận xác nhận" (đều 40px/40px). Với chữ Latin trần thì vừa khít;
 * với tiếng Việt thì không, vì ế ọ ữ ộ cần thêm chỗ cả trên lẫn dưới. Đo được:
 * nét chữ cao 42px trong hộp dòng 34px, thừa 4px, bị khung overflow:hidden xén
 * mất chân.
 *
 * 1.5 chứ không phải 1.35. Đo lại trên trang: cụm "Chọn hoạt động" ở cỡ 28.5px
 * có nét chữ cao 38px — tỉ lệ 1,33 — nên hộp dòng 1.35 (31.9px) vẫn để nét
 * tràn lên trên 4px và bị xén. Playfair có phần trên cao, cộng dấu chồng tiếng
 * Việt thì cần rộng hơn hẳn mức thường dùng cho chữ Latin.
 *
 * register.js chỉ gắn lớp này khi giãn dòng CHẬT HƠN 1.15 lần cỡ chữ — xem chú
 * thích ở đó về lần sửa đầu đã bóp nhầm 5 chỗ vốn đã rộng sẵn.
 *
 * GIỮ #main Ở ĐẦU BỘ CHỌN. Lớp tái dòng mobile trước đây đặt line-height cho
 * "#main h2 *" — có một #id nên nó THẮNG ".tt-net-bi-cat" dù cả hai đều
 * !important và dù nạp sau; phải thêm #main để cân lại (1,1,0) > (1,0,2). Lớp
 * đó nay đã gỡ (mobile là trang riêng, xem mobile.js), nhưng giữ nguyên bộ
 * chọn này: nó không hại gì và là hàng rào sẵn cho lần sau có ai đó viết một
 * luật mang #id vào cùng chỗ. */
#main .tt-net-bi-cat,
.tt-net-bi-cat {
  line-height: 1.5 !important;
}

/* Chữ nhỏ tới mức không đọc được.
 *
 * Chỉ dùng cho những cỡ dưới 9px — hiện có đúng hai chỗ: ghi chú giờ Café 6px
 * và dòng "Sat 05:09 09:00" 7px. Các nhãn 9–11px là nhãn chữ hoa giãn rộng,
 * cố ý nhỏ, nên không đụng.
 *
 * LƯU Ý: đây chỉ chữa phần desktop. Bản export khai khung nhìn cố định 1440px
 * và không có media query nào, nên trên máy 390px cả trang bị thu còn 27% —
 * nhãn 11px hoá ra ~3px. Chỗ đó phải dựng breakpoint trong Framer rồi xuất
 * lại, CSS ở đây không với tới được. */
.tt-chu-qua-nho {
  font-size: 11px !important;
  line-height: 1.45 !important;
}

/* Khối bị gỡ lời mời bấm (xem boMoiBamGia trong register.js): con trỏ tay của
   bản export nằm trên cả khối lẫn từng dòng chữ bên trong, nên phải quét cả
   cây con — đặt mỗi trên khối cha thì chữ bên trong vẫn hiện bàn tay. */
#main [data-tt-cam],
#main [data-tt-cam] * {
  cursor: default !important;
}

/* Hạng thành viên đang chọn: NỀN DO CSS QUYẾT, không do kiểu nội tuyến.
 *
 * Bản đầu tôi ghi thẳng background-color vào style của khối. Đo trên bản thật
 * thì thấy hai khối mang nền KHÔNG PHẢI của tôi:
 *     TeeTee Member  rgba(95, 122, 138, 0.62)
 *     Blue           rgba(75, 96, 108, 0.38)
 * Mã của tôi chỉ ghi rgb(121, 155, 175) hoặc transparent — hai màu mờ kia là
 * của Framer: bản export tự chạy hiệu ứng rê chuột và tự ghi kiểu nội tuyến
 * đè lên. Con trỏ quét ngang cột hạng một lượt là nền đọng lại sai chỗ.
 *
 * Tệ hơn: MutationObserver của register.js không nghe thuộc tính, nên Framer
 * ghi đè xong thì không có gì gọi lượt vẽ lại để sửa. Khách nhìn thấy hạng
 * này sáng còn thẻ bên cạnh hiện nội dung hạng khác — và vì màu chữ vẫn là
 * của tôi nên ra hai cặp lệch nhau: chữ tối trên nền tối ở khối bỏ chọn,
 * chữ trắng trên nền nhạt ở khối đang chọn (gần như tàng hình).
 *
 * Đấu kiểu nội tuyến bằng kiểu nội tuyến là đấu lại chính vòng đời của
 * Framer. Quy tắc CSS mang !important thì thắng mọi khai báo nội tuyến không
 * !important, nên nguồn sự thật chuyển hẳn về aria-pressed — thuộc tính mà
 * chỉ mã của tôi đặt. Chưa được đánh dấu thì không quy tắc nào khớp, khối giữ
 * nguyên dáng của bản export. */
#main [data-tt-hang-tv][aria-pressed="true"] {
  background-color: rgb(121, 155, 175) !important;
}

#main [data-tt-hang-tv][aria-pressed="false"] {
  background-color: transparent !important;
}

/* Màu chữ đi kèm nền, cùng một quy tắc, để không bao giờ lệch cặp nữa.
   Bỏ chọn phải ĐẶT THẲNG màu tối: mặc định của Framer cho chip này là chữ
   TRẮNG (nó là chip được chọn sẵn trong bản export), trắng trên nền kem là
   tàng hình. Đo được 11,52:1 với màu tối này. */
/* CHỮ TỐI, không phải chữ trắng. Trắng trên #799BAF chỉ được 2,95:1, mà chữ
   ở đây 15px — chữ thường, ngưỡng 4.5. Mực thân của site #2E3028 cho 4,54:1.
   Lưu ý mực #2A3B45 quen dùng ở chỗ khác chỉ được 3,93:1, không đủ. */
#main [data-tt-hang-tv][aria-pressed="true"] p {
  color: rgb(46, 48, 40) !important;
}

#main [data-tt-hang-tv][aria-pressed="false"] p {
  color: rgb(42, 59, 69) !important;
}

/* Chip lọc đang chọn: CHỮ TỐI, và phải với tới THẺ CHỮ BÊN TRONG.
 *
 * chipLoc() đặt `e.style.color` lên khối bọc, nhưng chữ thật nằm trong một
 * <p class="framer-text"> có màu riêng — Framer đặt biến --framer-text-color
 * nội tuyến ngay trên thẻ đó, nên nó KHÔNG thừa hưởng màu của khối bọc. Đo
 * được: khối bọc 4,54:1 mà thẻ chữ vẫn kem 2,93:1, và ảnh phóng to cho thấy
 * chữ trắng y như cũ. Đổi màu ở khối bọc là đổi vào chỗ không ai nhìn.
 *
 * Quét cả cây con (`*`) và dùng !important để thắng khai báo dựng từ biến nội
 * tuyến của Framer. Cùng lối đã dùng cho chip hạng ngay bên trên. */
/* 01/10 (anh Long: "ấn chuyển bị nhảy màu chữ đen trắng loạn lên"). Quy tắc
 * trên đòi chữ TỐI, còn latMucTrenXanh() của register.js thấy chip nằm trên
 * nền xanh nên ghi chữ KEM nội tuyến !important — nội tuyến thắng, khách thấy
 * kem. Nhưng Framer vẽ lại kiểu của thẻ chữ mỗi lần rê chuột / bấm, xoá mất
 * dòng nội tuyến: chữ về tối theo quy tắc này, rồi 60-400ms sau lượt lật lại
 * ghi kem. Hai nguồn sự thật giành nhau = chữ nháy đen trắng.
 *
 * Nay chip lọc chỉ còn MỘT nguồn: CSS theo aria-pressed, cả nền lẫn chữ (như
 * chip hạng ở trên); latMucTrenXanh() bỏ qua mọi thứ trong chip. Chữ đang chọn
 * là KEM — đúng thứ khách vẫn thấy từ trước tới giờ và đúng tài liệu 17/09
 * ("Nền xanh → Chữ trắng"); chữ bỏ chọn là mực thân của site. */
#main [data-tt-chip="1"][aria-pressed="true"] {
  background-color: rgb(121, 155, 175) !important;
}
#main [data-tt-chip="1"][aria-pressed="false"] {
  background-color: transparent !important;
}
#main [data-tt-chip="1"][aria-pressed="true"],
#main [data-tt-chip="1"][aria-pressed="true"] * {
  color: rgb(255, 255, 243) !important;
}
#main [data-tt-chip="1"][aria-pressed="false"],
#main [data-tt-chip="1"][aria-pressed="false"] * {
  color: rgb(46, 48, 40) !important;
}
/* Viền chip do Framer vẽ bằng ::after theo biến --border-color nội tuyến: chip vừa
   được chọn vẫn giữ viền 1px bên trong nền xanh ("viền nhảy ra bên trong nút",
   anh Long 01/10). Ghim theo aria-pressed như nền và chữ; bỏ vòng tiêu điểm khi bấm chuột. */
#main [data-tt-chip="1"][aria-pressed="true"]::after { border-color: transparent !important; }
#main [data-tt-chip="1"][aria-pressed="false"]::after { border-color: rgba(46, 48, 40, 0.18) !important; }
#main [data-tt-chip="1"]:focus:not(:focus-visible) { outline: none !important; }
#main [data-tt-chip="1"] { -webkit-tap-highlight-color: transparent; }

/* Nhãn "DỰ KIẾN" trên tem ngày của thẻ: BỎ GIÃN CHỮ, nếu không nó tràn ra
 * ngoài cột ngày.
 *
 * Nhãn này thay chỗ dòng tháng ("OCT.") nên thừa hưởng kiểu của dòng tháng —
 * trong đó có letter-spacing 1,26px, hợp với bốn ký tự nhưng không hợp với
 * bảy. Đo được trên bản thật:
 *     cột ngày   72px, x 51 -> 123
 *     "DỰ KIẾN"  48px, x 77 -> 125     tràn 2px, chữ N chạm đường kẻ dọc
 * Bỏ giãn chữ: còn 39px, mép phải 116, hở 7px. Giữ nguyên cỡ 9px để không
 * nhỏ hơn dòng tháng nó vừa thay.
 *
 * Chỗ này chỉ bắt được bằng ẢNH PHÓNG TO. Phép quét trùng lặp theo phần tử
 * báo "không đè vào gì" — đúng, vì đường kẻ là border của khung cha chứ không
 * phải một phần tử riêng để mà đè. */
/* Nhãn "DỰ KIẾN" dưới số ngày trên thẻ buổi.
 *
 * MÀU: mực nhãn olive #6D705D của chính trang (5.05:1), không phải xanh nhấn.
 * Đo trên cùng MỘT thẻ thì mọi nhãn nhỏ khác đều là mực hoặc olive —
 * "Pilates & Yoga Classes" #2E3028, "TeeTee&Co. Wellness" và "PRIORITY
 * REGISTRATION OPEN" đều #6D705D — chỉ mỗi "DỰ KIẾN" là xanh, lạc lõng ngay
 * tại chỗ nó đứng. Xanh nhấn #799BAF ở 9px chỉ được 2.93:1, mà đây là nhãn nói
 * cho khách biết ngày chưa chốt.
 *
 * Đây là nhãn MÌNH thêm vào (ngayDuKienLenThe), không phải của bản xuất — nên
 * đổi nó không đụng gì tới thiết kế gốc. Xanh nhấn của bản xuất giữ nguyên.
 *
 * letter-spacing: bản xuất giãn chữ cho ô tháng viết tắt, mà "DỰ KIẾN" dài hơn
 * nên giãn thêm là tràn.
 */
#main [data-tt-gan="1"] [data-tt-nhan-dk="1"] {
  letter-spacing: 0 !important;
  color: rgb(109, 112, 93) !important;
}

/* Gạch chân mục đang xem trên thanh menu.
 *
 * Vẽ bằng ::after của chính liên kết, không phải một thanh trượt chèn thêm:
 * chèn phần tử vào DOM của React là việc đã gây trắng trang một lần, còn ::after
 * thì trình duyệt tự dựng, React không biết và không đụng tới.
 *
 * transform: scaleX chứ không phải width — scale chạy trên luồng hợp thành, không
 * bắt trình duyệt tính lại bố cục ở mỗi khung hình.
 */
#main a[data-tt-nav="1"] {
  position: relative;
}

#main a[data-tt-nav="1"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  transition: transform 0.36s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.36s ease;
  pointer-events: none;
}

#main a[data-tt-nav="1"][data-tt-hien="1"]::after {
  transform: scaleX(1);
  opacity: 1;
}

/* Rê chuột thì hiện mờ: cho biết chữ này bấm được, mà không tranh với mục đang
   xem. Chỉ ở máy có chuột thật — trên cảm ứng, :hover dính lại sau khi chạm. */
@media (hover: hover) and (pointer: fine) {
  #main a[data-tt-nav="1"]:hover::after {
    transform: scaleX(1);
    opacity: 0.42;
  }
  #main a[data-tt-nav="1"][data-tt-hien="1"]:hover::after { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  #main a[data-tt-nav="1"]::after { transition: none; }
}

/* =====================================================  hiệu ứng  ========= */

/* KHÔNG CÒN HIỆU ỨNG TRANG TRÍ NÀO Ở ĐÂY — đã gỡ hết ngày 12/09.
 *
 * Gỡ đợt một: "hiện dần khi cuộn tới". Nó NHÁY, và đây là số đo (đặt thẳng
 * `currentTime` lên chính hoạt ảnh đang chạy, không cần khung hình nào):
 *
 *   fill: "none" + delay 270ms  →  t=0: độ mờ 1 · t=260: vẫn 1 · t=280: 0.062
 *
 * `fill: "none"` nghĩa là trong lúc còn trễ, hoạt ảnh KHÔNG có tác dụng gì —
 * phần tử hiện nguyên vẹn. Hết trễ thì khung hình đầu mới áp vào và nó tắt
 * phụt, rồi mờ dần trở lại trong 720ms. Tức là: hiện ra → biến mất → hiện lại.
 * Ba trong bốn nhịp so le (90/180/270ms) đều có trễ nên 3/4 số phần tử nháy.
 * Bài học: `fill: "none"` + `delay` khác 0 là một cặp sai.
 *
 * Gỡ đợt hai: nhấc thẻ và phóng ảnh khi rê chuột. Lượt trước giữ lại với lý lẽ
 * "khác loại — phản hồi trực tiếp cho thao tác của khách". Anh Long bảo bỏ nốt,
 * và nhìn lại thì lý lẽ ấy không cứu được chúng: `translateY(-5px)` làm cả thẻ
 * nhích lên khỏi hàng, còn `scale(1.045)` phóng ảnh trong một khung
 * `overflow: hidden` — cùng một họ với cái vừa gỡ, chỉ khác cò bấm.
 *
 * Trang này bán những buổi ngồi yên một chỗ để làm một việc tử tế. Nó không
 * cần nhúc nhích để tỏ ra sống động.
 *
 * Chuyển động còn lại trên trang đều CÓ VIỆC, không phải trang trí:
 *   - gạch chân mục đang xem trên thanh menu — cho biết đang ở mục nào;
 *   - thanh tiến độ ở mép dưới thanh menu — cho biết đã lướt tới đâu;
 *   - hộp đặt chỗ trượt lên khi mở — cho biết nó vừa hiện ra từ đâu.
 */

/* Ba dòng chữ trong thẻ nổi trên ảnh bìa: đẩy vào cho có lề.
 *
 * Chúng là con ĐỊNH VỊ TUYỆT ĐỐI ở left:0, mà con tuyệt đối neo vào mép hộp
 * đệm — thêm padding cho thẻ không đẩy được chúng một pixel nào. Dịch bằng
 * transform: không đụng bố cục nên không có nguy cơ hộp con hẹp lại.
 *
 * !important vì Framer ghi thẳng `transform: none` vào style nội tuyến của
 * từng dòng ở mỗi lượt dựng lại.
 *
 * Bề ngang thẻ và giá trị --tt-le-the do theNoiOmChu() trong register.js đo và
 * đặt; xem khối chú thích ở đó cho phần vì sao.
 */
#main [data-tt-the-noi="1"] > * {
  transform: translateX(var(--tt-le-the, 0px)) !important;
}

/* Thanh cho biết đang lướt tới đâu trong trang.
 *
 * Vẽ bằng ::after của chính thanh menu, không chèn phần tử: chèn vào DOM của
 * React là việc đã gây trắng trang một lần, còn ::after thì trình duyệt tự
 * dựng và React không biết nó tồn tại.
 *
 * Nằm ở MÉP DƯỚI thanh menu chứ không ở mép trên khung nhìn. Thanh menu là
 * khối nền đặc #799BAF duy nhất luôn ở đó, nên nét mực #2E3028 (4.54:1) đọc
 * được ở mọi vị trí cuộn — đặt ở mép trên thì nền phía sau đổi liên tục theo
 * từng mục và có đoạn chạy qua ảnh.
 *
 * Đo được thanh menu: position: sticky, top: 0, overflow: clip — vừa là khối
 * chứa cho con định vị tuyệt đối, vừa tự cắt gọn nét thừa. Không có ::after
 * nào sẵn để mà đè lên.
 *
 * transform: scaleX chứ không phải width — chạy trên luồng hợp thành, không
 * bắt tính lại bố cục ở mỗi khung hình khi cuộn. Không đặt transition: giá trị
 * đã đi theo ngón tay khách rồi, thêm một nhịp trễ nữa là thanh chạy đuổi theo
 * trang.
 *
 * Giá trị --tt-tien-do do veTienDo() trong register.js đặt trên thẻ <html>.
 */
/* Đệm thanh menu lệch 19/21, không phải 20/20 — cùng một lý do với thanh đầu
 * bản điện thoại, xem chú thích ở .mb-dau trong mobile.css.
 *
 * Thanh tiến độ 2px ngay dưới đây nằm ở mép dưới thanh menu, nên dải xanh mắt
 * nhìn thấy là 78px chứ không phải 80px. `align-items: center` căn cả ba vật
 * (logo, nhóm liên kết, nút CTA) vào giữa hộp đệm — với 20/20 thì tâm hộp đệm
 * là 40, thấp hơn tâm dải thấy được (39) đúng 1px.
 *
 * GIỮ NGUYÊN TỔNG ĐỆM 40px. Bản xuất đặt `height: min-content` cho thanh này —
 * 80px là do 20 + 40 (nút CTA, vật cao nhất) + 20, chứ không phải số neo cứng.
 * Thêm đệm đáy mà không bớt đệm đỉnh là thanh cao lên 82px và đẩy cả trang
 * xuống, kéo theo mọi mốc cuộn. Chia lại 19/21 thì hộp đệm thành 19..59, tâm
 * 39, mà thanh vẫn đúng 80px.
 *
 * Không có style nội tuyến trên thẻ nav nên `#main nav` (1 id) thắng quy tắc
 * lớp của Framer, không cần !important.
 */
#main nav {
  padding-top: 19px;
  padding-bottom: 21px;
}

#main nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: rgb(46, 48, 40);
  transform: scaleX(var(--tt-tien-do, 0));
  transform-origin: left center;
  pointer-events: none;
}

/* Ảnh mục Partners: thêm lớp phủ tối mờ ở đáy, cho hai dòng chữ đè lên đọc ra.
 *
 * ĐO ĐƯỢC NGÀY 18/09: "Selected with intention" là chữ 9px màu #AADAE8 đặt
 * thẳng lên ảnh, mà đúng chỗ nó nằm thì ảnh là chiếc váy sáng màu — tỉ lệ
 * tương phản khoảng 2:1, gần như không đọc được. Dòng "Shared with our
 * community." ngay dưới cũng chung cảnh, chỉ đỡ hơn nhờ cỡ chữ 42px.
 *
 * Bản xuất KHÔNG có lớp phủ nào: ba khối (ảnh, nhãn, tiêu đề) là anh em ruột,
 * cùng position:absolute, z-index:auto. Chữ đọc được hay không hoàn toàn phụ
 * thuộc vào chỗ sáng tối của tấm ảnh — tức là may rủi, và đổi ảnh là đổi luôn.
 *
 * PHỦ CHỨ KHÔNG ĐỔI MÀU CHỮ. Đổi #AADAE8 sang kem thì vẫn là chữ 9px trên váy
 * sáng, chỉ nhích lên chút. Lớp phủ chữa được CẢ HAI dòng, không đụng vào một
 * màu thương hiệu nào, và chịu được cả khi sau này thay ảnh khác.
 *
 * Số đo sau khi phủ: nhãn 7.35:1, tiêu đề 9.43:1 (trước đó ~2:1).
 *
 * CHÉP ĐÚNG DẢI CỦA THẺ BUỔI BẢN ĐIỆN THOẠI (.mb-the trong mobile.css): cùng
 * màu rgba(42,59,69), cùng dáng dốc. Trang này đã có sẵn một ngôn ngữ "chữ đè
 * lên ảnh" rồi, không đặt thêm cái thứ hai.
 *
 * ::after CỦA KHỐI BỌC ẢNH, không phải của khối cha. Ba khối là anh em và đều
 * z-index:auto, nên thứ tự vẽ là thứ tự cây: ::after của khối bọc ảnh nằm TRÊN
 * ảnh mà vẫn DƯỚI hai khối chữ. Đặt ở khối cha thì nó phủ lên cả chữ.
 *
 * Neo bằng :has(> img) trong #partner chứ không bằng tên lớp framer-*: tên lớp
 * đổi mỗi lần xuất lại, còn "khối bọc ảnh trong mục Partners" thì không. Đã
 * kiểm: khớp đúng MỘT phần tử. Trình duyệt không hiểu :has() thì quy tắc bị bỏ
 * qua và trang trở về đúng trạng thái hôm nay, không vỡ gì.
 *
 * Chỉ desktop: dưới 1200px thì #main tắt hẳn, mục Partners do mobile.js dựng
 * và chữ ở đó nằm trên nền phẳng chứ không đè lên ảnh.
 */
#main #partner div:has(> img)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 46%;
  background: linear-gradient(
    to top,
    rgba(42, 59, 69, 0.92) 6%,
    rgba(42, 59, 69, 0.68) 40%,
    rgba(42, 59, 69, 0.1) 78%,
    rgba(42, 59, 69, 0) 100%
  );
  pointer-events: none;
}

/* ------------------------------------------------------------------ ảnh dọc
 * trong ô ngang: Running Club
 *
 * Ảnh sBtSkFy1… đứng ở ba chỗ, và ba chỗ ấy muốn hai khung khác hẳn nhau:
 *
 *   · hero bản điện thoại  — ô DỌC, `height: 100svh` (mobile.css)
 *   · "Opening Image"      — ô NGANG, bản desktop
 *   · thẻ Running Club     — ô NGANG, bản desktop
 *
 * Ngày 19/09 ảnh này được thay bằng ảnh anh Long gửi: hai người chạy bên hồ
 * Gươm, ảnh DỌC 1086×1448. Chọn giữ nguyên tỉ lệ dọc chứ không cắt về 16:9, vì
 * điện thoại là 97,5% lượt xem và ô hero bên đó là ô dọc — cắt về ngang là tối
 * ưu cho thiểu số.
 *
 * Đổi lại, hai ô bên desktop phải tự lo.
 *
 * ĐỪNG TIN THUỘC TÍNH width/height CỦA THẺ. Nó khai 2752×1536, đọc ra 16:9 —
 * và đó là số của ảnh CŨ, bộ xuất Framer ghi một lần rồi không ai cập nhật.
 * Thẻ lại nằm trong khung phủ kín (`position:absolute; inset:0`) nên hai con số
 * ấy không quyết định gì về hình dạng ô cả. Đo trên bản thật ở 1440px ngày
 * 19/09, hai ô rộng cao thế này:
 *
 *   "Opening Image"    631 × 700  → 0,90  (gần vuông)
 *   thẻ Running Club   691 × 518  → 1,33  (4:3)
 *
 * Với ảnh 0,75 thì `cover` giữ lại 83% chiều cao ở ô thứ nhất và 56% ở ô thứ
 * hai. Điểm neo mặc định `center` đẩy khung xuống giữa, mà đỉnh đầu người nam
 * nằm ở khoảng 21% — ô 4:3 cắt đúng ngang cằm anh ta (đã dựng ảnh thử để xem).
 *
 * 30% kéo khung lên: ô thứ nhất thành 5%–88%, ô thứ hai thành 13%–69%. Cả hai
 * đều đủ hai gương mặt và còn giữ được Tháp Rùa ở mép phải — đã xem lại trên
 * bản thật sau khi đẩy. Số này đo từ ẢNH CỤ THỂ và Ô CỤ THỂ: thay ảnh khác,
 * hoặc đổi bố cục hai khối này, thì phải đo lại.
 *
 * #main là khung của bản desktop; dưới 1200px nó tắt hẳn nên luật này không
 * với tới hero điện thoại. `!important` là bắt buộc: Framer ghi
 * `object-position:center` thẳng vào thuộc tính style của thẻ. */
/* Hai tấm cùng một buổi chạy, cùng tỉ lệ dọc, nên cùng một điểm neo:
   sBtSkFy1… ở ô mở đầu, tt-running-club ở thẻ Running Club. */
#main img[src*="sBtSkFy1UYTWvfDi2xCzk39D0vM"],
#main img[src*="tt-running-club"] {
  object-position: center 30% !important;
}

/* 25/09 — HIỆN TRANG SAU LƯỢT SỬA ĐẦU (anh Long: "load lại bị nhảy màu chữ
 * và khung hình"). register.js sửa màu/cỡ/vị trí bằng JS; script defer không
 * chặn lần vẽ đầu nên khách từng thấy bản gốc rồi mới thấy bản sửa. Giữ #main
 * trong suốt (vẫn chiếm chỗ, vẫn đọc được cho máy tìm kiếm) tới khi <html> có
 * data-tt-sua="1" — xem moManHinh() trong register.js. Lưới an toàn: 1,2 giây
 * JS chưa chạy thì CSS tự hiện. Dưới 1200px #main vốn ẩn (mobile.css). */
@keyframes tt-hien-trang { to { opacity: 1; } }
html:not([data-tt-sua="1"]) #main {
  opacity: 0;
  animation: tt-hien-trang 0.15s ease 1.2s forwards;
}
html[data-tt-sua="1"] #main {
  opacity: 1;
  transition: opacity 0.18s ease;
}
@media (prefers-reduced-motion: reduce) {
  html[data-tt-sua="1"] #main { transition: none; }
}

/* 25/09 — HÀNG BA BƯỚC 01/02/03 LỆCH KHUNG (anh Long gửi ảnh góc "03": "lỗi
 * thiết kế"). Ba ô chia nhau bằng đường kẻ, nhưng bản xuất cho ô 01 và 02 cao
 * 224px còn ô 03 cao 264px, rồi căn GIỮA theo chiều dọc: ô 03 thò lên trên và
 * xuống dưới 20px, đường kẻ của nó không nối với đường kẻ của hai ô kia — góc
 * trên của "03" thành bậc thang. Đo lại ở 1280 và 1440: kéo cả ba ô về cùng
 * chiều cao (stretch), khung cao theo nội dung với lề 32px trên dưới như ô 03
 * vốn có. Sau sửa: ba ô cùng 264px, cùng y=32, khung 328px (trước 327px) —
 * khối bên dưới gần như không xê dịch.
 *
 * Neo theo lớp Framer (framer-hxkg6f) vì khối này không có id; xuất lại
 * Framer thì phải đo lại. Dưới 1200px #main tắt nên luật không với tới. */
#main .framer-hxkg6f {
  align-items: stretch !important;
  height: auto !important;
  padding-top: 32px !important;
  padding-bottom: 32px !important;
}
#main .framer-hxkg6f > * {
  height: auto !important;
}

/* 30/09: nửa giây sau khi bấm chip lọc, thẻ không nhận chuột — thẻ vừa trượt
   vào dưới con trỏ không bật hiệu ứng hover (phóng ảnh) giữa lúc lưới đổi.
   Lớp tt-dang-loc do register.js (emKhiLoc) gắn rồi tự gỡ. Chip không mang
   data-tt-gan nên vẫn bấm được. */
html.tt-dang-loc #chon-hoat-dong [data-tt-gan="1"] { pointer-events: none; }
