/* Phong cách gốc Canuc80k: lớp token đặt SAU portal.css (site-kit).
   Mọi wiki dùng chung nền, chữ, khoảng cách, thành phần; mỗi wiki chỉ đổi vài núm:
     --hue      sắc màu nhấn (0–360, OKLCH). AI = 40 (đất nung, màu gốc).
     --chroma   độ đậm màu nhấn (1 = như gốc; < 1 cho sắc dễ tràn gam như vàng, gỗ).
     --rk       hệ số bo góc (1 = như gốc; .5 vuông hơn, 1.5 tròn hơn). prep.mjs đổi mọi border-radius của portal.css thành calc(N * --rk).
     --motion   hệ số thời gian chuyển động (1 = như gốc, 0 = tắt). prep.mjs đổi mọi transition của portal.css theo hệ số này.
   Biến màu nhấn tính lại ở mọi phần tử có lớp .themed (đặt --hue riêng cho một khối, ví dụ thẻ wiki trên trang cổng).
   Màu nhấn tính bằng OKLCH với độ sáng cố định nên đổi --hue không làm hỏng độ tương phản chữ (đã đo: chữ nhấn ≥ 5,1 : 1 trên nền sáng, ≥ 6,7 : 1 trên nền tối). */
:root {
  --hue: 40;
  --chroma: 1;
  --rk: 1;
  --motion: 1;
}
:root, .themed {
  --accent: oklch(.600 calc(.135 * var(--chroma)) var(--hue));
  --accent-strong: oklch(.531 calc(.123 * var(--chroma)) var(--hue));
  --accent-ink: oklch(.496 calc(.122 * var(--chroma)) var(--hue));
  --accent-soft: oklch(.934 calc(.020 * var(--chroma)) calc(var(--hue) + 13));
  --t-k: var(--accent-ink);

  --radius: calc(10px * var(--rk));
  --r-xs: calc(4px * var(--rk));
  --r-sm: calc(8px * var(--rk));
  --r-md: calc(10px * var(--rk));
  --r-lg: calc(14px * var(--rk));
  --r-pill: 999px;

  --dur-1: calc(120ms * var(--motion));
  --dur-2: calc(220ms * var(--motion));
  --dur-3: calc(420ms * var(--motion));
  --ease: cubic-bezier(.2, .7, .2, 1);

  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px; --sp-7: 48px;
  --fs-xs: 12px; --fs-sm: 13px; --fs-md: 15px; --fs-lg: 17px; --fs-xl: 22px; --fs-2xl: 28px; --fs-3xl: 34px;

  /* Tô màu code (Shiki, theme css-variables) theo bảng màu của trang. */
  --astro-code-foreground: var(--code-text);
  --astro-code-background: var(--code-bg);
  --astro-code-token-keyword: var(--t-k);
  --astro-code-token-string: var(--t-s);
  --astro-code-token-string-expression: var(--t-s);
  --astro-code-token-constant: var(--t-n);
  --astro-code-token-comment: var(--t-c);
  --astro-code-token-function: var(--code-text);
  --astro-code-token-parameter: var(--code-text);
  --astro-code-token-punctuation: var(--code-text);
  --astro-code-token-link: var(--accent-ink);
}
:root[data-theme="dark"], :root[data-theme="dark"] .themed {
  --accent: oklch(.672 calc(.131 * var(--chroma)) var(--hue));
  --accent-strong: oklch(.725 calc(.118 * var(--chroma)) var(--hue));
  --accent-ink: oklch(.761 calc(.105 * var(--chroma)) var(--hue));
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
  --t-k: var(--accent-ink);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]), :root:not([data-theme="light"]) .themed {
    --accent: oklch(.672 calc(.131 * var(--chroma)) var(--hue));
    --accent-strong: oklch(.725 calc(.118 * var(--chroma)) var(--hue));
    --accent-ink: oklch(.761 calc(.105 * var(--chroma)) var(--hue));
    --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
  --t-k: var(--accent-ink);
  }
}
@media (prefers-reduced-motion: reduce) { :root { --motion: 0 !important; } }

/* Khối code Shiki trong khung .t-code của site-kit. */
.t-code pre.astro-code { margin: 0; padding: 14px 16px; background: var(--code-bg) !important; font: 13.5px/1.6 var(--mono); tab-size: 4; }
.t-code pre.astro-code code { font: inherit; background: none; padding: 0; }

/* ---------- thành phần dùng chung của nền tảng (cổng + mọi wiki) ---------- */
/* Nút tài khoản trên thanh trên: chữ "Đăng nhập", hoặc ảnh/chữ cái đầu + tên khi đã đăng nhập. */
.acct { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; margin-inline-start: 4px; border: 1px solid var(--line); border-radius: calc(9px * var(--rk)); font-size: 13px; font-weight: 500; color: var(--text-2); white-space: nowrap; transition: background var(--dur-1) var(--ease); }
.acct:hover { background: var(--hover); color: var(--text); }
.acct-av { width: 20px; height: 20px; flex: none; border-radius: 50%; display: grid; place-items: center; background: var(--accent); color: #fff; font-size: 11px; font-weight: 600; overflow: hidden; }
.acct-av img { width: 100%; height: 100%; object-fit: cover; }
.acct.is-in { padding: 0 10px 0 6px; }
@media (max-width: 920px) { .acct-name { display: none; } .acct.is-in { padding: 0 5px; } }
/* Chân trang wiki: hết chỗ (điện thoại) thì xuống dòng thay vì tràn ngang. */
.foot { flex-wrap: wrap; row-gap: 8px; }
.foot nav { flex-wrap: wrap; gap: 8px 18px; }
/* Kết quả tìm: nhóm "Bài học" / "Bài tập", dòng phụ (chương, mã bài tập) nhỏ dưới tên. */
.hit-group { margin: 0; padding: 8px 10px 4px; font-size: 12px; font-weight: 500; color: var(--muted); }
.hit-group:not(:first-child) { margin-top: 4px; border-top: 1px solid var(--line); padding-top: 10px; }
.hit-t { min-width: 0; }
.hit-t small { display: block; margin-top: 2px; font-size: 12px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Thanh trên của wiki trên điện thoại: ô tìm co theo chỗ trống (ô nhập bỏ bề rộng tự nhiên ~240px),
   để còn chỗ cho nút tài khoản và không cuộn ngang ở khổ 320–414px. */
@media (max-width: 640px) {
  .top-tools, .search { min-width: 0; }
  .search-box input { width: 0; }
  .acct { padding: 0 10px; }
  /* Khung kết quả tìm bám hai mép màn hình (cách 16px) ngay dưới thanh trên, không theo vị trí ô tìm
     (site-kit cũ dịch -60px, lệch khỏi mép trái khi thanh trên có thêm nút tài khoản). */
  .search-pop { position: fixed; top: calc(var(--top-h) + 6px); left: 16px; right: 16px; width: auto; }
}
/* Logo cá nục Gameboy cạnh tên trang, 1,5px mỗi ô pixel; không làm cao thêm dòng. */
.wordmark { white-space: nowrap; }
.wordmark .brand-mark { flex: none; align-self: center; width: 33px; height: 28.5px; margin: -4px 0; }
/* Menu ngôn ngữ: nút quả địa cầu cạnh nút sáng/tối, bảng nhỏ ngay dưới nút. */
.lang { position: relative; }
.lang-pop { position: absolute; inset-inline-end: 0; top: calc(100% + 6px); z-index: 50; min-width: 180px; max-height: calc(100vh - 80px); max-height: calc(100dvh - 80px); overflow-y: auto; overscroll-behavior: contain; padding: 6px; background: var(--surface); border: 1px solid var(--line); border-radius: calc(12px * var(--rk)); box-shadow: var(--shadow); }
.lang-pop[hidden] { display: none; }
.lang-pop a { display: flex; align-items: center; justify-content: space-between; gap: 12px; height: 34px; padding: 0 10px; border-radius: calc(8px * var(--rk)); font-size: 14px; color: var(--text-2); transition: background var(--dur-1) var(--ease); }
.lang-pop a:hover { background: var(--hover); color: var(--text); }
.lang-pop a[aria-current] { color: var(--text); font-weight: 500; }
.lang-pop .i { width: 16px; height: 16px; color: var(--accent-ink); }

/* ---------- quảng cáo (shared/components/Ads.astro, AdCard.astro; dữ liệu shared/lib/ads.mjs) ---------- */
/* Thẻ kiểu Gameboy, như logo cá pixel: góc bo bậc thang 4 nấc (4-2-1-1 ô pixel --P), viền và bóng là ô pixel, không nghiêng.
   .rank-face (nền; mép trong nổi khối của nền tối là 2 lớp giả bậc 3-1-1) cắt theo --rank-clip; .rank-frame (cha của nó) vẽ viền bằng 4 drop-shadow ôm đúng bậc thang, thêm 1 drop-shadow
   lệch --d ô làm bóng. Rê chuột: nhấc lên, bóng sâu thêm một ô; bấm: ấn xuống như nút. Số thứ tự phông pixel Silkscreen (chỉ "#" và
   0–9, 3 KB, OFL). Mỗi thẻ một màu của trang (AdCard gắn .themed + --hue). Nền sáng: viền mực, bóng màu, nền ngả nhẹ.
   Nền tối: ô gạch nổi khối 8-bit (viền gần đen, mép trong sáng/tối cùng màu thẻ, bóng sẫm cùng màu). */
@font-face { font-family: "Silkscreen"; src: url("fonts/silkscreen-digits.woff2") format("woff2"); font-weight: 700; unicode-range: U+23, U+30-39; font-display: swap; }
/* Ô pixel và hai đường bo góc bậc thang (ngoài 4-2-1-1, trong 3-1-1) dùng chung cho thẻ và khung cảm ơn. */
:root {
  --P: 2px;
  --rank-clip: polygon(0 calc(var(--P) * 4), var(--P) calc(var(--P) * 4), var(--P) calc(var(--P) * 2), calc(var(--P) * 2) calc(var(--P) * 2), calc(var(--P) * 2) var(--P), calc(var(--P) * 4) var(--P), calc(var(--P) * 4) 0, calc(100% - var(--P) * 4) 0, calc(100% - var(--P) * 4) var(--P), calc(100% - var(--P) * 2) var(--P), calc(100% - var(--P) * 2) calc(var(--P) * 2), calc(100% - var(--P)) calc(var(--P) * 2), calc(100% - var(--P)) calc(var(--P) * 4), 100% calc(var(--P) * 4), 100% calc(100% - var(--P) * 4), calc(100% - var(--P)) calc(100% - var(--P) * 4), calc(100% - var(--P)) calc(100% - var(--P) * 2), calc(100% - var(--P) * 2) calc(100% - var(--P) * 2), calc(100% - var(--P) * 2) calc(100% - var(--P)), calc(100% - var(--P) * 4) calc(100% - var(--P)), calc(100% - var(--P) * 4) 100%, calc(var(--P) * 4) 100%, calc(var(--P) * 4) calc(100% - var(--P)), calc(var(--P) * 2) calc(100% - var(--P)), calc(var(--P) * 2) calc(100% - var(--P) * 2), var(--P) calc(100% - var(--P) * 2), var(--P) calc(100% - var(--P) * 4), 0 calc(100% - var(--P) * 4));
  --rank-clip-in: polygon(0 calc(var(--P) * 3), var(--P) calc(var(--P) * 3), var(--P) var(--P), calc(var(--P) * 3) var(--P), calc(var(--P) * 3) 0, calc(100% - var(--P) * 3) 0, calc(100% - var(--P) * 3) var(--P), calc(100% - var(--P)) var(--P), calc(100% - var(--P)) calc(var(--P) * 3), 100% calc(var(--P) * 3), 100% calc(100% - var(--P) * 3), calc(100% - var(--P)) calc(100% - var(--P) * 3), calc(100% - var(--P)) calc(100% - var(--P)), calc(100% - var(--P) * 3) calc(100% - var(--P)), calc(100% - var(--P) * 3) 100%, calc(var(--P) * 3) 100%, calc(var(--P) * 3) calc(100% - var(--P)), var(--P) calc(100% - var(--P)), var(--P) calc(100% - var(--P) * 3), 0 calc(100% - var(--P) * 3));
}
.rank-card {
  --P: 2px; --d: 1; --rank-b: var(--text); --rank-s: var(--text); --rank-bg: var(--surface);
  position: relative; isolation: isolate; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; min-height: 120px; padding: 26px 12px 12px;
  border: 0; border-radius: 0; background: none; color: var(--text); text-align: center; text-decoration: none;
  transform: translate(calc(var(--P) * (1 - var(--d))), calc(var(--P) * (1 - var(--d))));
  transition: transform calc(90ms * var(--motion)) steps(2);
}
.rank-frame { position: absolute; inset: 0; z-index: -1; pointer-events: none;
  filter: drop-shadow(var(--P) 0 0 var(--rank-b)) drop-shadow(calc(-1 * var(--P)) 0 0 var(--rank-b)) drop-shadow(0 var(--P) 0 var(--rank-b)) drop-shadow(0 calc(-1 * var(--P)) 0 var(--rank-b))
    drop-shadow(calc(var(--P) * var(--d)) calc(var(--P) * var(--d)) 0 var(--rank-s));
  transition: filter calc(90ms * var(--motion)) steps(2); }
.rank-face { position: absolute; inset: 0; background: var(--rank-hi, var(--rank-bg)); clip-path: var(--rank-clip); }
.rank-face::before, .rank-face::after { content: ""; position: absolute; inset: 0; }
.rank-face::before { background: var(--rank-lo, transparent); clip-path: var(--rank-clip); transform: translate(var(--P), var(--P)); }
.rank-face::after { inset: var(--P); background: var(--rank-bg); clip-path: var(--rank-clip-in); }
@media (hover: hover) { .rank-card:hover { --d: 2; } }
.rank-card:active { --d: 0; }
.rank-card:focus-visible { outline: 2px dashed var(--accent); outline-offset: 6px; }
.rank-card.themed { --rank-s: var(--accent); --rank-bg: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
.rank-card.themed .rank-no { color: var(--accent-ink); }
/* Nền tối: ô gạch nổi khối 8-bit — viền ngoài gần đen (như nét mực của nền sáng), mép trong trên-trái sáng, dưới-phải tối
   cùng màu thẻ, bóng pixel sẫm cùng màu, nền ngả màu sâu 10% (đã so 5 phương án, chọn bản này). */
:root[data-theme="dark"] .rank-card.themed { --rank-b: #141413; --rank-s: color-mix(in oklab, var(--accent) 45%, #000); --rank-bg: color-mix(in oklab, var(--accent) 10%, var(--surface));
  --rank-hi: color-mix(in oklab, var(--accent) 55%, var(--surface)); --rank-lo: color-mix(in oklab, var(--accent) 30%, #000); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .rank-card.themed { --rank-b: #141413; --rank-s: color-mix(in oklab, var(--accent) 45%, #000); --rank-bg: color-mix(in oklab, var(--accent) 10%, var(--surface));
  --rank-hi: color-mix(in oklab, var(--accent) 55%, var(--surface)); --rank-lo: color-mix(in oklab, var(--accent) 30%, #000); } }
/* Đặt trong vùng bài (.prose) cũng không nhận kiểu link của bài. */
.prose a.rank-card, a.rank-card { color: var(--text); text-decoration: none; }
/* Silkscreen chỉ nét khi cỡ là bội của 8px (16px = mỗi ô chữ 2px, khớp ô pixel của viền). */
.rank-no { position: absolute; top: 5px; inset-inline-start: 10px; font: 700 16px/1 "Silkscreen", var(--mono); letter-spacing: 0; color: var(--text); white-space: nowrap; }
.rank-tag { position: absolute; top: 10px; inset-inline-end: 10px; font: 700 8.5px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase; color: var(--faint); white-space: nowrap; }
/* Logo: ô vuông khía góc cùng kiểu viền thẻ (ô pixel 2px). */
.rank-logo { --lb: var(--rank-b); display: inline-grid; place-items: center; flex: none; width: 32px; height: 32px; overflow: hidden; border-radius: 0; background: var(--accent); color: #fff; font: 700 15px/1 var(--sans);
  box-shadow: 0 -2px 0 0 var(--lb), 0 2px 0 0 var(--lb), -2px 0 0 0 var(--lb), 2px 0 0 0 var(--lb); }
.rank-logo img { width: 100%; height: 100%; object-fit: contain; background: var(--surface); }
/* Logo ảnh thật: nền trắng, đệm mỏng để logo không chạm viền (cả nền tối). */
.rank-logo--img { background: #fff; }
.rank-logo--img img { padding: 2px; background: #fff; }
.rank-copy { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; max-width: 100%; }
.rank-copy strong { font: 650 14px/1.15 var(--sans); overflow-wrap: anywhere; text-wrap: balance; }
.rank-copy span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font: 10px/1.4 var(--mono); color: var(--muted); text-wrap: balance; }
/* Chữ không phải Latin (Ả Rập, Ba Tư, Thái, CJK) không có trong phông mono: dùng phông thường cho khỏi thưa, vỡ nét. */
:root:is(:lang(ar), :lang(fa), :lang(th), :lang(ja), :lang(ko), :lang(zh-Hans), :lang(zh-Hant)) .rank-copy span { font-family: var(--sans); }
:root:is(:lang(ar), :lang(fa), :lang(th), :lang(ja), :lang(ko), :lang(zh-Hans), :lang(zh-Hant)) .rank-tag { font: 600 10px/1 var(--sans); letter-spacing: 0; }
/* Ô còn trống: viền pixel mờ, không bóng, dấu cộng pixel trên ô vuông khía góc màu nhấn. */
/* Nền ô trống bằng màu nền trang (không để trong suốt: viền vẽ bằng drop-shadow của lớp nền). */
.rank-card--open { --rank-b: var(--faint); --rank-s: transparent; --rank-bg: var(--bg); }
:root[data-theme="dark"] .rank-card--open { --rank-b: var(--line-strong); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .rank-card--open { --rank-b: var(--line-strong); } }
@media (hover: hover) { .rank-card--open:hover { --rank-b: var(--muted); } }
.rank-plus { display: grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: 0; background: var(--accent); color: #fff;
  box-shadow: 0 -2px 0 0 var(--accent), 0 2px 0 0 var(--accent), -2px 0 0 0 var(--accent), 2px 0 0 0 var(--accent); }
.rank-plus svg { width: 14px; height: 14px; fill: currentColor; shape-rendering: crispEdges; }
/* Ô quảng cáo wiki điền trên máy người đọc (shared/scripts/rank.js): ẩn nhưng vẫn giữ chỗ tới khi điền xong (không nháy quảng cáo
   dựng sẵn rồi đổi); quá 1,2 giây (mạng chậm, tắt JS) thì hiện quảng cáo dựng sẵn. */
.rank-card[data-slot]:not(.is-set) { visibility: hidden; animation: rank-show 0s 1.2s forwards; }
@keyframes rank-show { to { visibility: visible; } }
/* Panel to giữa bài (wiki). Không có banner: bên trái là "màn hình" kiểu Gameboy (nền màu thẻ chấm pixel, viền mực) đặt logo thật to;
   bên phải: số thứ tự · Tài trợ, tên, dòng giới thiệu (màu thẻ), mô tả, tên miền và nút "Ghé thăm" (ô pixel màu nhấn viền mực).
   Có banner (ảnh 4:1 của nhà quảng cáo, trường banner): banner trải hết bề ngang trong màn hình, dưới là một dòng số thứ tự, tên, nút.
   Màn hẹp: màn hình lên trên, nút trải ngang. */
.rank-panel { margin: 2.4em 0; }
.rank-card--panel { flex-direction: row; align-items: stretch; justify-content: flex-start; gap: 0; min-height: 0; padding: 14px; text-align: start; }
.rank-shot { position: relative; isolation: isolate; flex: none; display: grid; place-items: center; width: 176px; min-height: 164px; margin: 2px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  box-shadow: 0 -2px 0 0 var(--rank-b), 0 2px 0 0 var(--rank-b), -2px 0 0 0 var(--rank-b), 2px 0 0 0 var(--rank-b); }
/* Chấm pixel 2px cách 6px, cùng màu thẻ. */
.rank-shot::before { content: ""; position: absolute; inset: 0; z-index: -1; background: color-mix(in srgb, var(--accent) 30%, transparent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6'%3E%3Crect width='2' height='2'/%3E%3C/svg%3E") 0 0 / 6px 6px; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6'%3E%3Crect width='2' height='2'/%3E%3C/svg%3E") 0 0 / 6px 6px; }
.rank-card--panel .rank-logo { width: 108px; height: 108px; font-size: 46px; }
.rank-card--panel .rank-logo--img img { padding: 8px; }
.rank-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; padding: 6px 8px 2px 24px; }
.rank-meta { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.rank-card--panel .rank-no, .rank-card--panel .rank-tag { position: static; }
.rank-card--panel .rank-tag { font-size: 9.5px; }
.rank-card--panel .rank-copy { align-items: flex-start; gap: 4px; }
.rank-card--panel .rank-copy strong { font-size: 24px; line-height: 1.15; }
.rank-card--panel .rank-copy span { -webkit-line-clamp: 1; font: 600 12.5px/1.45 var(--mono); color: var(--accent-ink); }
.rank-desc { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font: 14.5px/1.55 var(--sans); color: var(--text-2); }
.rank-desc[hidden] { display: none; }
.rank-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: auto; padding-top: 8px; }
.rank-host { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 12px/1.2 var(--mono); color: var(--faint); }
.rank-go { flex: none; display: inline-flex; align-items: center; gap: 10px; height: 38px; padding: 0 16px; background: var(--accent-strong); color: #fff; font: 700 13.5px/1 var(--sans); white-space: nowrap;
  box-shadow: 0 -2px 0 0 var(--rank-b), 0 2px 0 0 var(--rank-b), -2px 0 0 0 var(--rank-b), 2px 0 0 0 var(--rank-b); }
.rank-go svg { width: 14px; height: 14px; fill: currentColor; shape-rendering: crispEdges; transition: transform calc(90ms * var(--motion)) steps(2); }
@media (hover: hover) { .rank-card--panel:hover .rank-go svg { transform: translateX(2px); } }
:root[data-theme="dark"] .rank-go { background: var(--accent); color: #141413; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .rank-go { background: var(--accent); color: #141413; } }
/* Có banner: ảnh 4:1 trải ngang, dưới là số thứ tự, tên và nút trên một dòng. */
.rank-card--banner { flex-direction: column; }
.rank-card--banner .rank-shot { width: auto; min-height: 0; aspect-ratio: 4 / 1; overflow: hidden; background: var(--surface); }
.rank-card--banner .rank-shot::before { display: none; }
.prose .rank-banner, .rank-banner { display: block; width: 100%; height: 100%; margin: 0; border: 0; border-radius: 0; object-fit: cover; }
.rank-card--banner .rank-body { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px 16px; padding: 14px 4px 2px; }
.rank-card--banner .rank-copy { flex: 1; min-width: 0; }
.rank-card--banner .rank-copy strong { font-size: 18px; }
.rank-card--banner .rank-meta { justify-content: flex-start; }
.rank-card--banner :is(.rank-copy span, .rank-desc, .rank-host) { display: none; }
.rank-card--banner .rank-foot { margin: 0; padding: 0; }
@media (max-width: 640px) {
  .rank-card--panel { flex-direction: column; padding: 12px; }
  .rank-card--panel:not(.rank-card--banner) .rank-shot { width: auto; min-height: 132px; }
  .rank-card--panel .rank-logo { width: 88px; height: 88px; font-size: 38px; }
  .rank-body { padding: 14px 4px 2px; }
  .rank-card--panel .rank-copy strong { font-size: 21px; }
  .rank-desc { -webkit-line-clamp: 3; }
  .rank-foot { flex-wrap: wrap; }
  .rank-go { width: 100%; justify-content: center; }
}
/* Thẻ nằm ngang (trong trang): số thứ tự và chữ Sponsor trên một dải, logo + chữ một hàng. */
.rank-card--compact { flex-direction: row; justify-content: flex-start; gap: 10px; min-height: 0; padding: 26px 12px 10px; text-align: start; }
.rank-card--compact .rank-logo { width: 30px; height: 30px; font-size: 13px; }
.rank-card--compact .rank-plus { width: 28px; height: 28px; }
.rank-card--compact .rank-copy { align-items: flex-start; }
.rank-card--compact .rank-copy span { -webkit-line-clamp: 2; }
.rank-card--compact .rank-copy strong { font-size: 13.5px; }
.rank-card--compact .rank-no { top: 5px; }
.rank-card--compact .rank-tag { top: 10px; }
/* Máy tính rộng (≥1240px): hai cột quảng cáo ở hai bên, bắt đầu ngang tiêu đề, cuộn theo trang. Cột nằm đè vùng trống hai bên
   (không đẩy chân trang xuống; chân trang ở cột giữa nên không chồng nhau). Màn hẹp hơn: thẻ ngang dưới nội dung, hai cột;
   điện thoại một cột, giữ dòng giới thiệu. */
.rank-rail { display: none; }
.rank-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: var(--sp-7); }
.rank-list > .rank-card:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (min-width: 1240px) {
  .rank-layout { position: relative; }
  .rank-list { display: none; }
  .rank-rail { position: absolute; top: var(--sp-7); z-index: 1; display: flex; flex-direction: column; gap: 12px; width: 200px; }
  .rank-rail--start { inset-inline-start: 16px; }
  .rank-rail--end { inset-inline-end: 16px; }
  /* 4 thẻ mỗi bên lấp từ ngang tiêu đề (112px) tới gần đáy màn hình (chừa 40px cho thẻ có tên hai dòng); chữ, logo lớn dần
     theo chiều cao. Màn thấp: logo, lề nhỏ hơn để giới thiệu vẫn được 2 dòng. */
  .rank-rail { --rank-gap: 12px; gap: var(--rank-gap); }
  .rank-rail .rank-card { gap: 5px; padding: 24px 12px 10px; }
  .rank-rail .rank-logo { width: 28px; height: 28px; font-size: 13px; }
  .rank-rail .rank-plus { width: 28px; height: 28px; }
  .rank-rail .rank-card { min-height: clamp(120px, calc((100vh - 152px - 3 * var(--rank-gap)) / 4), 200px); min-height: clamp(120px, calc((100dvh - 152px - 3 * var(--rank-gap)) / 4), 200px); }
}
@media (min-width: 1240px) and (min-height: 760px) {
  .rank-rail { --rank-gap: 14px; width: 210px; }
  .rank-rail .rank-card { gap: 8px; padding: 30px 14px 14px; }
  .rank-rail .rank-logo { width: 36px; height: 36px; font-size: 16px; }
  .rank-rail .rank-plus { width: 34px; height: 34px; }
  .rank-rail .rank-copy strong { font-size: 14.5px; }
  .rank-rail .rank-copy span { font-size: 10.5px; -webkit-line-clamp: 2; }
  .rank-rail .rank-no { top: 6px; inset-inline-start: 12px; }
  .rank-rail .rank-tag { top: 11px; inset-inline-end: 12px; font-size: 9px; }
}
@media (min-width: 1240px) and (min-height: 880px) {
  .rank-rail { --rank-gap: 16px; width: 220px; }
  .rank-rail .rank-card { gap: 10px; padding: 34px 16px 18px; }
  .rank-rail .rank-logo { width: 40px; height: 40px; font-size: 17px; }
  .rank-rail .rank-plus { width: 36px; height: 36px; }
  .rank-rail .rank-plus svg { width: 18px; height: 18px; }
  .rank-rail .rank-copy { gap: 4px; }
  .rank-rail .rank-copy strong { font-size: 15px; }
  .rank-rail .rank-copy span { font-size: 11px; line-height: 1.45; -webkit-line-clamp: 3; }
  .rank-rail .rank-no { top: 7px; }
  .rank-rail .rank-tag { top: 12px; font-size: 9px; }
}
/* Màn to (≥1600×960): cột rộng hơn, thẻ cao tới 240px, chữ và logo to hơn. */
@media (min-width: 1600px) and (min-height: 960px) {
  .rank-rail { --rank-gap: 18px; width: 260px; }
  .rank-rail .rank-card { gap: 10px; padding: 38px 18px 20px; min-height: clamp(120px, calc((100vh - 152px - 3 * var(--rank-gap)) / 4), 240px); min-height: clamp(120px, calc((100dvh - 152px - 3 * var(--rank-gap)) / 4), 240px); }
  .rank-rail .rank-logo { width: 46px; height: 46px; font-size: 19px; }
  .rank-rail .rank-plus { width: 42px; height: 42px; }
  .rank-rail .rank-plus svg { width: 20px; height: 20px; }
  .rank-rail .rank-copy strong { font-size: 16.5px; }
  .rank-rail .rank-copy span { font-size: 12px; }
  .rank-rail .rank-no { top: 9px; inset-inline-start: 14px; }
  .rank-rail .rank-tag { top: 14px; inset-inline-end: 14px; font-size: 10px; }
}
@media (max-width: 480px) { .rank-list { grid-template-columns: minmax(0, 1fr); gap: 10px; } }
/* Wiki: bên trái là thanh điều hướng nên quảng cáo chỉ ở bên phải. Trang chủ wiki, trang chương: .rank-wiki chia hai cột (≥1240px),
   nội dung bên trái, cột 4 thẻ (#1–#3, ô trống #8) ngang tiêu đề, cỡ thẻ theo chiều cao màn hình như trang cổng; hẹp hơn: 4 thẻ
   ngang cuối trang (.rank-list). Trang bài: cột phải .learn-side (LearnSide.astro, dính theo khi cuộn) gồm mục lục thu gọn thành
   một dòng (<details>, bấm mở thì đẩy thẻ xuống) và 3 thẻ (.rank-side) chia đều chiều cao màn hình; cuối bài là khung
   cảm ơn nhà tài trợ (.rank-thanks). */
/* Cột phải hiện khi nội dung bên trái còn ≥ ~500px: có thanh bên trái thì từ 1024px, thanh bên gập (máy tính bảng) thì 768–920px.
   Từ 1240px cỡ thẻ theo chiều cao màn hình như trang cổng (.rank-rail ở trên); hẹp hơn: thẻ cỡ thường, cột 200px. */
@media (min-width: 768px) and (max-width: 920px), (min-width: 1024px) {
  .rank-wiki { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
  .rank-wiki .rank-list { display: none; }
  .rank-rail--wiki { position: static; margin-block-start: 56px; margin-inline-end: 24px; }
  .page-home + .rank-rail--wiki { margin-block-start: 72px; }
}
@media (min-width: 768px) and (max-width: 920px), (min-width: 1024px) and (max-width: 1239px) {
  .rank-rail--wiki { display: flex; flex-direction: column; gap: 12px; width: 200px; }
}
/* Cuối bài: khung "Cảm ơn các nhà tài trợ" (Thanks.astro), viền và bóng pixel như thẻ, màu theo wiki; lưới logo mỗi ô một màu,
   bóng pixel lệch, rê chuột nhấc lên; ô cuối "Còn trống" để đặt chỗ. Lưới dựng lại từ /ads.json (rank.js): ẩn tới khi xong như ô quảng cáo. */
.rank-thanks { --d: 1; --rank-b: var(--text); --rank-s: var(--accent); --rank-bg: color-mix(in srgb, var(--accent) 6%, var(--surface));
  position: relative; isolation: isolate; margin-top: var(--sp-7); padding: 24px 26px 26px; }
:root[data-theme="dark"] .rank-thanks { --rank-b: #141413; --rank-s: color-mix(in oklab, var(--accent) 45%, #000); --rank-bg: color-mix(in oklab, var(--accent) 8%, var(--surface));
  --rank-hi: color-mix(in oklab, var(--accent) 45%, var(--surface)); --rank-lo: color-mix(in oklab, var(--accent) 30%, #000); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .rank-thanks { --rank-b: #141413; --rank-s: color-mix(in oklab, var(--accent) 45%, #000); --rank-bg: color-mix(in oklab, var(--accent) 8%, var(--surface));
  --rank-hi: color-mix(in oklab, var(--accent) 45%, var(--surface)); --rank-lo: color-mix(in oklab, var(--accent) 30%, #000); } }
.rank-thanks-head { display: flex; align-items: center; gap: 10px; margin: 0; font: 700 17px/1.3 var(--sans); color: var(--text); }
.rank-thanks-head svg { width: 16px; height: 14px; flex: none; fill: var(--accent); shape-rendering: crispEdges; }
.rank-thanks-note { margin: 6px 0 20px; font-size: 14px; line-height: 1.5; color: var(--muted); }
.rank-wall { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 18px 10px; }
.rank-wall[data-wall]:not(.is-set) { visibility: hidden; animation: rank-show 0s 1.2s forwards; }
.rank-tile { display: flex; flex-direction: column; align-items: center; gap: 10px; min-width: 0; padding: 2px; color: var(--text); text-align: center; text-decoration: none; }
.rank-tile .rank-logo { --lb: var(--rank-b); width: 60px; height: 60px; font-size: 26px;
  box-shadow: 0 -2px 0 0 var(--lb), 0 2px 0 0 var(--lb), -2px 0 0 0 var(--lb), 2px 0 0 0 var(--lb), 4px 4px 0 0 var(--accent);
  transition: transform calc(90ms * var(--motion)) steps(2), box-shadow calc(90ms * var(--motion)) steps(2); }
.rank-tile .rank-logo--img img { padding: 5px; }
.rank-tile-name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; max-width: 100%; font: 600 12.5px/1.3 var(--sans); }
@media (hover: hover) {
  .rank-tile:hover .rank-logo { transform: translate(-2px, -2px); box-shadow: 0 -2px 0 0 var(--lb), 0 2px 0 0 var(--lb), -2px 0 0 0 var(--lb), 2px 0 0 0 var(--lb), 6px 6px 0 0 var(--accent); }
  .rank-tile:hover .rank-tile-name { color: var(--accent-ink); }
}
.rank-tile:focus-visible { outline: 2px dashed var(--accent); outline-offset: 4px; }
.rank-tile--open .rank-plus { width: 60px; height: 60px; }
.rank-tile--open .rank-plus svg { width: 22px; height: 22px; }
.rank-tile--open .rank-tile-name { color: var(--muted); font-weight: 500; }
@media (max-width: 640px) { .rank-thanks { padding: 20px 16px 22px; } .rank-wall { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 6px; } .rank-tile-name { -webkit-line-clamp: 3; } }
.toc-box > summary { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 0 6px 12px; border-left: 1px solid var(--line);
  font-size: 13px; font-weight: 500; color: var(--text-2); list-style: none; cursor: pointer; user-select: none; }
.toc-box > summary::-webkit-details-marker { display: none; }
.toc-box > summary:hover { color: var(--text); }
.toc-box > summary .i { width: 14px; height: 14px; color: var(--faint); transition: transform var(--dur-1) var(--ease); }
.toc-box[open] > summary { margin-bottom: 4px; }
.toc-box[open] > summary .i { transform: rotate(90deg); }
@media (min-width: 1101px) {
  .learn-side { position: sticky; top: calc(var(--top-h) + 76px); display: flex; flex-direction: column; gap: 20px; }
  /* Mục lục mở: như bản gốc (100vh − 100px) trừ dòng "Mục lục"; thẻ bị đẩy xuống dưới. */
  .learn-side .toc { position: static; max-height: calc(100vh - var(--top-h) - 150px); max-height: calc(100dvh - var(--top-h) - 150px); }
  /* Mục lục thu gọn: 3 thẻ lấp từ dòng "Mục lục" (cao ~30px, cách 20px) tới cách đáy màn hình 24px, mỗi thẻ 120–240px. */
  .rank-side { --rank-gap: 14px; display: flex; flex-direction: column; gap: var(--rank-gap); }
  .rank-side .rank-card { min-height: clamp(120px, calc((100vh - var(--top-h) - 76px - 74px - 2 * var(--rank-gap)) / 3), 240px);
    min-height: clamp(120px, calc((100dvh - var(--top-h) - 76px - 74px - 2 * var(--rank-gap)) / 3), 240px); }
}
/* Màn cao: thẻ cao 200–240px, logo và chữ to lên như cột quảng cáo trang cổng. */
@media (min-width: 1101px) and (min-height: 880px) {
  .rank-side .rank-card { gap: 10px; padding: 34px 16px 18px; }
  .rank-side .rank-logo { width: 40px; height: 40px; font-size: 17px; }
  .rank-side .rank-copy { gap: 4px; }
  .rank-side .rank-copy strong { font-size: 15px; }
  .rank-side .rank-copy span { font-size: 11px; line-height: 1.45; -webkit-line-clamp: 3; }
  .rank-side .rank-no { top: 7px; }
  .rank-side .rank-tag { top: 12px; font-size: 9px; }
}
@media (max-width: 1100px) { .learn-side { display: none; } }

/* ---------- thứ tiếng khác (16 thứ tiếng của cổng, shared/lib/i18n.mjs) ---------- */
/* Chữ Nga (Kirin) của Lora, Inter: tệp riêng, trình duyệt chỉ tải khi trang có chữ Kirin (Fontsource 5.3.0, OFL). */
@font-face { font-family: "Lora"; src: url("fonts/lora-cyrillic.woff2") format("woff2"); font-weight: 400 700; font-style: normal; font-display: swap; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1; }
@font-face { font-family: "Inter"; src: url("fonts/inter-cyrillic.woff2") format("woff2"); font-weight: 400 700; font-style: normal; font-display: swap; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1; }
/* Trung, Nhật, Hàn, Thái, Ả Rập, Ba Tư: phông có sẵn trong máy (không tải thêm); Lora, Inter vẫn đứng đầu cho chữ Latin. */
:root:lang(zh-Hans) { --cjk: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", "Noto Sans CJK SC", "Source Han Sans SC"; }
:root:lang(zh-Hant) { --cjk: "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", "Noto Sans CJK TC", "Source Han Sans TC"; }
:root:lang(ja) { --cjk: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic UI", "Meiryo", "Noto Sans JP", "Noto Sans CJK JP"; }
:root:lang(ko) { --cjk: "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", "Noto Sans CJK KR"; }
:root:lang(th) { --cjk: "Leelawadee UI", "Thonburi", "Sukhumvit Set", "Noto Sans Thai"; }
:root:lang(ar), :root:lang(fa) { --cjk: "Segoe UI", "Geeza Pro", "Noto Sans Arabic", "Noto Naskh Arabic", "Tahoma"; }
:root:is(:lang(zh-Hans), :lang(zh-Hant), :lang(ja), :lang(ko), :lang(th), :lang(ar), :lang(fa)) {
  --serif: "Lora", var(--cjk), sans-serif;
  --sans: "Inter", var(--cjk), system-ui, sans-serif;
}
/* Chữ Ả Rập, Ba Tư viết liền nét: không giãn/khít chữ; mũi tên trỏ theo chiều đọc. */
[dir="rtl"] :is(.pt-head h1, .page-home .phase-title, .course-head) { letter-spacing: 0; }
[dir="rtl"] .page-home .phase > .i { transform: scaleX(-1); }
