/* ─────────────────────────── tinvan — bộ giao diện đọc dùng chung ───────────────────────────
   Tiền tố tt-. Ra đời ở Thinktanks, nay dùng chung cho Tin tức, Báo cáo ngày, Trợ lý AI; nạp qua
   templates/_tt_head.html. Phần riêng của từng trang để ở file CSS riêng của trang đó, đừng nhồi
   vào đây. Viết CSS riêng thay vì class Tailwind: app.css là bản build subset, class mới không có
   hiệu lực.

   Ý đồ: MỘT font cho toàn site — Be Vietnam Pro (xem --tt-sans); chữ đọc dài theo thang
   --tt-read-fs / --tt-read-lh. Màu nhấn chỉ dùng cho hành động chính và
   dấu hiệu "đang chọn" của thanh trượt; lựa chọn trong bộ lọc tô bằng màu mực. */

/* Font dự phòng CHỈNH SỐ ĐO cho Be Vietnam Pro. Google Fonts nạp với display=swap: trang vẽ trước bằng
   font dự phòng rồi đổi sang Be Vietnam Pro — rộng hơn Arial 3–7% và dòng cao hơn — nên chữ xuống dòng
   khác đi và cả khối phía dưới nhảy (đo 30/09/2026: /admin/bao-cao-mau CLS 0,066 khi cho tải font,
   0 khi chặn font). Mặt chữ dưới đây là Arial phóng theo đúng tỉ lệ đo được từng độ đậm (canvas
   measureText trên câu tiếng Việt), ascent/descent quy về 1,00/0,27 em như font thật → lúc đổi font
   chữ gần như không dịch chuyển. Đo lại nếu đổi font chính. */
@font-face { font-family: "Be Vietnam Pro Fallback"; font-weight: 100 449; src: local("Arial"), local("ArialMT"), local("Helvetica"), local("Roboto");
  size-adjust: 106.8%; ascent-override: 93.6%; descent-override: 25.3%; line-gap-override: 0%; }
@font-face { font-family: "Be Vietnam Pro Fallback"; font-weight: 450 549; src: local("Arial"), local("ArialMT"), local("Helvetica"), local("Roboto");
  size-adjust: 105.3%; ascent-override: 95%; descent-override: 25.6%; line-gap-override: 0%; }
@font-face { font-family: "Be Vietnam Pro Fallback"; font-weight: 550 649; src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Bold"), local("Roboto Bold");
  size-adjust: 103%; ascent-override: 97.1%; descent-override: 26.2%; line-gap-override: 0%; }
@font-face { font-family: "Be Vietnam Pro Fallback"; font-weight: 650 900; src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Bold"), local("Roboto Bold");
  size-adjust: 104.1%; ascent-override: 96.1%; descent-override: 25.9%; line-gap-override: 0%; }

/* Token đặt ở :root (không chỉ .tt): khung trang base.html bọc MỌI trang, kể cả trang admin không có
   lớp .tt. Đây là nơi DUY NHẤT định nghĩa màu — tt-shell.css và các file trang chỉ dùng lại. */
:root {
  /* Báo cho trình duyệt biết đang sáng hay tối để thanh cuộn, hộp chọn ngày và menu <select>
     của HỆ ĐIỀU HÀNH đổi theo — CSS không vẽ được những thứ đó. Thiếu dòng này, bản tối vẫn
     hiện thanh cuộn trắng và lịch chọn ngày nền trắng. */
  color-scheme: light;
  --tt-ground: #f3f4f6;
  --tt-paper: #ffffff;
  --tt-sunk: #f4f6f5;
  --tt-ink: #17211d;
  --tt-ink-2: #36413c;
  --tt-muted: #65706b;
  --tt-rule: #e2e7e4;
  --tt-accent: #0b7a57;
  --tt-accent-strong: #075e43;
  --tt-accent-soft: #e5f3ec;
  --tt-on-accent: #ffffff;
  /* Hổ phách đậm hơn bản cũ #a8660b: bản cũ chỉ đạt 4.18:1 trên --tt-ground và 3.96:1 trên nền
     hổ phách nhạt — dưới chuẩn AA cho chữ nhỏ. #94580a đạt 5.2:1 và 4.85:1. */
  --tt-amber: #b45309;
  --tt-danger: #c92a2a;
  /* Màu trạng thái (đã đo tương phản trên --tt-paper, --tt-ground và trên chính nền -soft của nó,
     đều ≥ 4.5:1). Dùng cho chấm tình trạng, thông báo, huy hiệu — KHÔNG dùng làm màu nhấn. */
  --tt-success: #15803d;
  --tt-warning: var(--tt-amber);
  --tt-info: #2c5fdb;
  --tt-success-soft: color-mix(in srgb, var(--tt-success) 11%, transparent);
  --tt-warning-soft: color-mix(in srgb, var(--tt-warning) 12%, transparent);
  --tt-info-soft: color-mix(in srgb, var(--tt-info) 10%, transparent);
  --tt-danger-soft: color-mix(in srgb, var(--tt-danger) 9%, transparent);
  --tt-danger-rule: color-mix(in srgb, var(--tt-danger) 40%, var(--tt-rule));
  /* Mức nguy hiểm (CVSS của FIRST). Chuyển từ tt-cyber.css lên đây để trang khác (Tổng quan,
     cảnh báo) dùng cùng một thang. "Trung bình" đậm hơn bản cũ (#8a6d0b chỉ vừa chạm 4.5:1). */
  --tt-sev-critical: #c92a2a;  --tt-sev-critical-bg: #fdeaea;
  --tt-sev-high: #c2410c;      --tt-sev-high-bg: #fff0e5;
  --tt-sev-medium: #a16207;    --tt-sev-medium-bg: #fcf6e1;
  --tt-sev-low: #15803d;       --tt-sev-low-bg: #e6f7ec;
  /* Vòng focus bàn phím: màu nhấn (5.3:1 trên nền trắng). Bản cũ #10B981 chỉ 2.5:1. */
  --tt-focus: var(--tt-accent);
  --tt-backdrop: rgba(8, 15, 12, .42);
  --tt-lift: 0 18px 50px -20px rgba(15, 30, 24, .35);
  --tt-shadow-sm: 0 1px 2px rgba(0, 0, 0, .08), 0 2px 6px -2px rgba(0, 0, 0, .1);
  /* Bóng thẻ mềm: thẻ "nổi" nhẹ trên nền thay vì chỉ là khung viền phẳng. */
  --tt-shadow-card: 0 1px 2px rgba(15, 23, 42, .04), 0 6px 20px -8px rgba(15, 23, 42, .10);
  --tt-shadow-hover: 0 2px 4px rgba(15, 23, 42, .05), 0 14px 30px -12px rgba(15, 23, 42, .18);
  /* Thang bo góc theo cấp: control < thẻ < hộp thoại. Trước đây có 21 giá trị rải rác. */
  --tt-r-xs: .35rem;   /* chip, kbd, mã */
  --tt-r-sm: .6rem;    /* nút nhỏ, mục menu */
  --tt-r-md: .75rem;   /* nút, ô nhập */
  --tt-r-lg: 1.25rem;  /* thẻ, bảng, danh sách */
  --tt-r-xl: 1.5rem;   /* hộp thoại, tấm trượt */
  --tt-r-pill: 999px;
  /* MỘT font cho toàn site (14/10/2026, người dùng chốt): Be Vietnam Pro — dựng cho tiếng Việt, đủ dấu,
     đủ độ đậm. Literata (serif) cho thân bài đã bỏ: cạnh giao diện không chân nó trông như một trang
     khác, và to hơn hẳn ở cùng cỡ chữ. Giữ tên --tt-serif để CSS cũ không phải sửa từng chỗ. */
  --tt-serif: var(--tt-sans);
  /* Thang cỡ chữ ĐỌC dùng chung (khung đọc tin, trang bài, báo cáo, Trợ lý AI): 16px là sàn chuẩn của
     chữ thân bài, giãn dòng 1,7 nằm trong khoảng 1,5–1,75 dễ đọc. */
  --tt-read-fs: 1rem;
  --tt-read-lh: 1.7;
  /* THANG CHỮ TIÊU ĐỀ — một nguồn cho mọi trang (15/10/2026). Mốc là tiêu đề trang (người dùng đã yêu
     cầu thu nhỏ 26/09); không tiêu đề mục/thẻ nào được to hơn mốc, trang đọc chỉ nhỉnh hơn một nấc.
     Trước đó mỗi tệp CSS tự đặt cỡ: trang đọc báo cáo 32px, mục admin 21px, trong khi tiêu đề trang 19px.
     Đo lại bằng tools/ui_qa/typo.py. */
  --tt-fs-page: clamp(1.05rem, 1rem + .3vw, 1.2rem);           /* h1 tiêu đề trang (19px máy tính) */
  --tt-fs-headline: clamp(1.15rem, 1.05rem + .45vw, 1.375rem); /* h1 bài / báo cáo đang đọc (22px) */
  --tt-fs-section: 1.0625rem;                                  /* h2 mục trong trang, tiêu đề thẻ (17px) */
  --tt-fs-item: 1rem;                                          /* tiêu đề khung nhỏ, thẻ gọn (16px) */
  --tt-fs-label: .9375rem;                                     /* nhãn khối, tiêu đề hộp admin (15px) */
  --tt-fs-stat: 1.5rem;                                        /* số KPI (24px) — số liệu, không phải tiêu đề */
  --tt-sans: "Be Vietnam Pro", "Be Vietnam Pro Fallback", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --tt-display: "Be Vietnam Pro", "Be Vietnam Pro Fallback", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --tt-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --tt-ease: cubic-bezier(.22, .8, .24, 1);
  --tt-ease-in: cubic-bezier(.4, 0, 1, 1);
  /* Vùng chạm tối thiểu cho mọi thứ bấm được (WCAG 2.5.8 khuyên ≥ 24px, ta lấy 40px cho tay). */
  --tt-hit: 2.5rem;
  /* Khung trang trải HẾT bề ngang (26/09/2026) — trần 90rem cũ để lại hai dải trắng lớn ở màn rộng.
     --tt-gutter là lề hai bên, dùng chung cho thanh điều hướng, nội dung, chân trang → mép thẳng hàng. */
  --tt-max: none;
  --tt-gutter: clamp(1rem, 2.2vw, 2.5rem);
}
.tt {
  color: var(--tt-ink);
  max-width: none;
  margin: 0 auto;
  padding-bottom: 3rem;
  /* Thuộc tính này DI TRUYỀN: đặt một lần ở đây là mọi vùng cuộn bên trong (dải lỗ hổng,
     dải tab, thân hộp lọc) đều có thanh cuộn mảnh cùng tông, thay vì thanh xám mặc định
     của hệ điều hành đè lên nền giấy. */
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--tt-ink) 20%, transparent) transparent;
}
html.dark {
  color-scheme: dark;
  --tt-ground: #111827;
  --tt-paper: #1b2431;
  --tt-sunk: #151d28;
  --tt-ink: #edf2ef;
  --tt-ink-2: #c9d2ce;
  --tt-muted: #97a39e;
  --tt-rule: #2e3a48;
  --tt-accent: #5fc79c;
  --tt-accent-strong: #8fd6b8;
  --tt-accent-soft: rgba(95, 199, 156, .11);
  --tt-on-accent: #05291b;
  --tt-amber: #f2bd5c;
  --tt-danger: #e8a4a1;
  --tt-success: #4ade80;
  --tt-info: #93c5fd;
  --tt-sev-critical: #ff9a92;  --tt-sev-critical-bg: #3a1614;
  --tt-sev-high: #f5bd7c;      --tt-sev-high-bg: #372213;
  --tt-sev-medium: #e8d48a;    --tt-sev-medium-bg: #322b12;
  --tt-sev-low: #9fd5bc;       --tt-sev-low-bg: #14291f;
  --tt-backdrop: rgba(0, 0, 0, .55);
  --tt-lift: 0 18px 50px -18px rgba(0, 0, 0, .7);
  --tt-shadow-sm: 0 1px 2px rgba(0, 0, 0, .35), 0 2px 6px -2px rgba(0, 0, 0, .4);
  --tt-shadow-card: 0 1px 2px rgba(0, 0, 0, .3), 0 8px 24px -12px rgba(0, 0, 0, .55);
  --tt-shadow-hover: 0 2px 4px rgba(0, 0, 0, .35), 0 16px 34px -14px rgba(0, 0, 0, .7);
}

/* ─────────────────────────── Lớp màu (25/09/2026) ───────────────────────────
   Người dùng muốn web MÀU MÈ, bắt mắt — không phải nền xám đơn điệu. Lớp này thêm màu mà không
   hy sinh độ đọc: mọi màu chữ đã đo ≥ 4.5:1 trên --tt-paper VÀ trên chính nền -soft của nó.

   Tám sắc độ dùng để PHÂN BIỆT (chuyên mục, loại báo cáo, nhóm số liệu) — không dùng làm màu hành
   động. Gắn bằng lớp .tt-hue-1…8 lên một khối, rồi thành phần bên trong dùng var(--h)/var(--h-soft). */
:root {
  /* Hai tầng mỗi sắc độ (26/09/2026): --tt-hue-N = màu CHỮ (tông sạch, đủ đậm để đọc);
     --tt-hue-N-v = màu TƯƠI cho nền nhạt, chấm, vạch, thanh — để màu trong chứ không "tệt". */
  --tt-hue-1: #047857;  --tt-hue-1-v: #10b981;  /* lục bảo — màu nhận diện */
  --tt-hue-2: #0e7490;  --tt-hue-2-v: #06b6d4;  /* xanh ngọc */
  --tt-hue-3: #2c5fdb;  --tt-hue-3-v: #3b82f6;  /* xanh dương */
  --tt-hue-4: #4f46e5;  --tt-hue-4-v: #6366f1;  /* chàm */
  --tt-hue-5: #7c3aed;  --tt-hue-5-v: #8b5cf6;  /* tím */
  --tt-hue-6: #cc1f47;  --tt-hue-6-v: #f43f5e;  /* hồng */
  --tt-hue-7: #c2410c;  --tt-hue-7-v: #f97316;  /* cam */
  --tt-hue-8: #b45309;  --tt-hue-8-v: #f59e0b;  /* hổ phách */
  /* Gradient nhận diện: cả ba điểm dừng đều cho chữ trắng ≥ 5.3:1. */
  /* Dịu lại 26/09/2026 (người dùng thấy chói): hai tông lục bảo → ngọc gần nhau thay cho ba tông
     tới chàm; chữ trắng vẫn ≥ 5.3:1 ở mọi điểm. */
  --tt-grad-brand: linear-gradient(135deg, #0b7a57 0%, #0f6f80 100%);
  --tt-grad-soft: linear-gradient(135deg, color-mix(in srgb, #10b981 10%, var(--tt-paper)), color-mix(in srgb, #0e7490 8%, var(--tt-paper)));
  /* Điểm dừng của gradient trang trí (logo, vạch cầu vồng) — logo SVG trong base.html dùng lại. */
  --tt-grad-c1: #10b981; --tt-grad-c2: #06b6d4; --tt-grad-c3: #6366f1; --tt-grad-c4: #ec4899;
  --tt-grad-line: linear-gradient(90deg, var(--tt-grad-c1), var(--tt-grad-c2) 35%, var(--tt-grad-c3) 65%, var(--tt-grad-c4));
  /* Quầng màu phía sau trang — nhạt, cố định, để nền không còn là mảng xám phẳng. */
  /* Sáng sủa hơn (26/09/2026): nền gần trắng, quầng màu tươi nhưng rất nhạt. */
  --tt-glow-a: rgba(16, 185, 129, .10);
  --tt-glow-b: rgba(59, 130, 246, .08);
  --tt-glow-c: rgba(236, 72, 153, .05);
  --tt-ground: #f7f9fc;
  /* Chữ trên nền gradient nhận diện / nền đỏ nguy hiểm. */
  --tt-on-grad: #ffffff;
  --tt-on-danger: #ffffff;
  --tt-grad-shadow: transparent;
  /* Toast nền MỰC (đảo màu): chấm trạng thái phải lấy tông của chế độ NGƯỢC lại mới nổi. */
  --tt-inv-success: #4ade80; --tt-inv-danger: #fca5a5; --tt-inv-warning: #f2bd5c; --tt-inv-info: #93c5fd;
}
html.dark {
  --tt-hue-1: #86cfb0;
  --tt-hue-2: #86c9d6;
  --tt-hue-3: #9fbbe3;
  --tt-hue-4: #adb3e0;
  --tt-hue-5: #bcaee0;
  --tt-hue-6: #e2a4ad;
  --tt-hue-7: #e0b08c;
  --tt-hue-8: #dcc285;
  --tt-hue-1-v: var(--tt-hue-1); --tt-hue-2-v: var(--tt-hue-2); --tt-hue-3-v: var(--tt-hue-3); --tt-hue-4-v: var(--tt-hue-4);
  --tt-hue-5-v: var(--tt-hue-5); --tt-hue-6-v: var(--tt-hue-6); --tt-hue-7-v: var(--tt-hue-7); --tt-hue-8-v: var(--tt-hue-8);
  --tt-grad-brand: linear-gradient(135deg, #5fbf9c 0%, #62aebf 100%);
  --tt-grad-soft: linear-gradient(135deg, color-mix(in srgb, #10b981 10%, var(--tt-paper)), color-mix(in srgb, #0e7490 10%, var(--tt-paper)));
  --tt-glow-a: rgba(16, 185, 129, .06);
  --tt-glow-b: rgba(99, 102, 241, .07);
  --tt-glow-c: rgba(236, 72, 153, .03);
  --tt-ground: #0f1623;
  --tt-on-grad: var(--tt-on-accent);
  --tt-on-danger: #2a0909;
  --tt-inv-success: #15803d; --tt-inv-danger: #c92a2a; --tt-inv-warning: #b45309; --tt-inv-info: #2c5fdb;
}
.tt-hue-1 { --h: var(--tt-hue-1); --h-v: var(--tt-hue-1-v); } .tt-hue-2 { --h: var(--tt-hue-2); --h-v: var(--tt-hue-2-v); }
.tt-hue-3 { --h: var(--tt-hue-3); --h-v: var(--tt-hue-3-v); } .tt-hue-4 { --h: var(--tt-hue-4); --h-v: var(--tt-hue-4-v); }
.tt-hue-5 { --h: var(--tt-hue-5); --h-v: var(--tt-hue-5-v); } .tt-hue-6 { --h: var(--tt-hue-6); --h-v: var(--tt-hue-6-v); }
.tt-hue-7 { --h: var(--tt-hue-7); --h-v: var(--tt-hue-7-v); } .tt-hue-8 { --h: var(--tt-hue-8); --h-v: var(--tt-hue-8-v); }
[class*="tt-hue-"] { --h-soft: color-mix(in srgb, var(--h-v) 12%, var(--tt-paper)); --h-rule: color-mix(in srgb, var(--h-v) 40%, var(--tt-rule)); }
html.dark [class*="tt-hue-"] { --h-soft: color-mix(in srgb, var(--h) 14%, var(--tt-paper)); }

/* Nền trang: màu nền + ba quầng màu cố định. background-attachment: fixed để cuộn dài không lặp. */
body {
  background-color: var(--tt-ground) !important;
  background-image:
    radial-gradient(60rem 36rem at -10% -10%, var(--tt-glow-a), transparent 60%),
    radial-gradient(52rem 34rem at 110% 0%, var(--tt-glow-b), transparent 62%),
    radial-gradient(48rem 30rem at 50% 115%, var(--tt-glow-c), transparent 60%);
  background-attachment: fixed;
  color: var(--tt-ink);
  /* Gán thẳng ở body: trang nào không tự khai font (khung Tailwind, trang admin) cũng ra Be Vietnam Pro
     thay vì font hệ thống. */
  font-family: var(--tt-sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Chip màu theo sắc độ (chuyên mục, loại, nhóm) */
.tt-chip { display: inline-flex; align-items: center; gap: .35rem; height: 1.6rem; padding: 0 .6rem; border-radius: var(--tt-r-pill); font-size: .75rem; font-weight: 650; white-space: nowrap; color: var(--h, var(--tt-accent-strong)); background: var(--h-soft, var(--tt-accent-soft)); }
.tt-chip::before { content: ""; width: .45rem; height: .45rem; border-radius: 50%; background: var(--h-v, currentColor); }

/* Ô biểu tượng có màu (đầu thẻ, ô số liệu, mục điều hướng) */
.tt-tile { width: 2.5rem; height: 2.5rem; flex: none; display: grid; place-items: center; border-radius: var(--tt-r-md); color: var(--h, var(--tt-accent-strong)); background: var(--h-soft, var(--tt-accent-soft)); }
.tt-tile .tt-ic, .tt-tile svg { width: 1.25rem; height: 1.25rem; }

/* Thẻ có vạch màu ở đầu — phân biệt khối bằng màu mà vẫn nền giấy dễ đọc. */
.tt-card--hue { position: relative; overflow: hidden; }
.tt-card--hue::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: color-mix(in srgb, var(--h-v, var(--tt-accent)) 75%, var(--tt-paper)); }
.tt-card--brand::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: var(--tt-grad-line); opacity: .5; }
.tt-card--brand { position: relative; overflow: hidden; }
.tt-stat-value.is-hue { color: var(--h); }

.tt-ic { width: 1.05em; height: 1.05em; flex: none; }
.tt-vh { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ── Nút ── */
.tt-btn {
  font-family: var(--tt-sans);
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 2.5rem; padding: 0 .95rem; border-radius: .7rem;
  font-size: .875rem; font-weight: 600; white-space: nowrap;
  color: var(--tt-ink-2); background: var(--tt-paper); border: 1px solid var(--tt-rule);
  transition: background-color .2s, border-color .2s, color .2s, transform .15s var(--tt-ease);
  -webkit-tap-highlight-color: transparent;
}
.tt-btn:hover { color: var(--tt-accent-strong); border-color: color-mix(in srgb, var(--tt-accent) 45%, var(--tt-rule)); }
.tt-btn:active { transform: scale(.97); }
.tt-btn--primary { background: var(--tt-accent); border-color: var(--tt-accent); color: var(--tt-on-accent); }
.tt-btn--primary:hover { background: var(--tt-accent-strong); border-color: var(--tt-accent-strong); color: var(--tt-on-accent); }
.tt-btn--quiet { background: transparent; border-color: transparent; color: var(--tt-muted); }
.tt-btn--quiet:hover { background: var(--tt-sunk); border-color: transparent; }
.tt-btn[disabled] { opacity: .4; pointer-events: none; }

/* ── Đầu trang ── */
.tt-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .4rem .75rem; margin: 0 0 .6rem; }
/* Nút trong đầu trang là thao tác phụ → cỡ nhỏ, không chiếm thêm chiều cao. */
.tt-head-aside .tt-btn { min-height: 2.25rem; padding: 0 .75rem; font-size: .8125rem; border-radius: var(--tt-r-sm); }
.tt-head-aside .tt-badge { min-width: 1.1rem; height: 1.1rem; font-size: .68rem; }
/* Cỡ tiêu đề trang thu nhỏ 26/09/2026 theo yêu cầu (bản đầu 1.9–2.6rem, rồi 1.3–1.6rem vẫn to). */
.tt-title { font-family: var(--tt-display); font-weight: 600; font-size: var(--tt-fs-page); line-height: 1.25; letter-spacing: -.01em; color: var(--tt-ink); }
.tt-lede { margin-top: 0; max-width: 62ch; font-size: .8125rem; line-height: 1.5; color: var(--tt-muted); }
.tt-head-aside { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }
.tt-head-main { display: flex; align-items: center; gap: .5rem; min-width: 0; }
/* Tiêu đề và dòng phụ (số tin, giờ…) chung một hàng — đầu trang chỉ cao một dòng, nhường chỗ cho dữ liệu. */
.tt-head-main > div { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 .75rem; min-width: 0; }
/* Điện thoại: dòng phụ LUÔN xuống hàng thứ hai. Để tự xuống dòng thì chiều cao đầu trang đổi theo
   độ dài chữ — font web tải xong (chữ rộng hơn font dự phòng) hoặc JS điền số liệu ("54 tin · 3 khu
   vực…") là cả trang bị đẩy xuống 15px (CLS 0,12–0,15 đo ở Tổng quan, Bản đồ 30/09/2026). */
@media (max-width: 639px) { .tt-head-main > div:has(> .tt-lede) { flex-direction: column; align-items: flex-start; } }
.tt-head-main .tt-tile { width: 1.65rem; height: 1.65rem; border-radius: var(--tt-r-sm); }
.tt-head-main .tt-tile .tt-ic { width: .9rem; height: .9rem; }
/* Lề trên của khung nội dung: Tailwind sm:mt-8 (32px) để trống cả dải dưới thanh điều hướng. */
#app-main.container { margin-top: .85rem; }
.tt-empty .tt-empty-ic { margin: 0 auto 1rem; width: 3rem; height: 3rem; border-radius: var(--tt-r-lg); }
.tt-pending { display: inline-flex; align-items: center; gap: .5rem; font-size: .8125rem; color: var(--tt-amber); font-variant-numeric: tabular-nums; }
.tt-pending::before { content: ""; width: .5rem; height: .5rem; border-radius: 50%; background: currentColor; animation: tt-pulse 1.8s ease-in-out infinite; }

/* ── Thanh tìm kiếm dính ── */
.tt-sentinel { height: 1px; margin-bottom: -1px; }
.tt-bar-wrap {
  position: sticky; top: var(--tt-nav, 56px); z-index: 30;
  margin: 0 -1rem; padding: .6rem 1rem;
  background: color-mix(in srgb, var(--tt-ground) 86%, transparent);
  -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
  transition: box-shadow .3s;
}
.tt-bar-wrap.is-stuck { box-shadow: 0 1px 0 var(--tt-rule); }
.tt-bar { display: flex; gap: .5rem; align-items: center; }
/* Số bài + thanh sắp xếp nằm CÙNG hàng với ô tìm và nút Bộ lọc (26/09/2026) — thêm một dòng riêng
   chỉ để ghi "N bài" là phí chỗ. Màn hẹp: tự xuống hàng thứ hai, vẫn trong khối dính. */
.tt-meta-inline { flex: none; display: flex; align-items: center; gap: .6rem; margin: 0; }
/* Cùng độ ưu tiên với .tt-meta-row đứng SAU trong tệp → phải nâng độ ưu tiên mới thắng được. */
.tt-bar .tt-meta-inline, .tt-rp-bar .tt-meta-inline { margin: 0; flex-wrap: nowrap; gap: .6rem; }
/* Khối đếm từng là thứ chèn khoảng cách giữa thanh tìm và danh sách; dời vào thanh rồi thì danh sách
   phải tự có khoảng cách, không thì dính sát chip lọc. */
form + .tt-list, .tt-active + .tt-list, form + .tt-empty, .tt-active + .tt-empty { margin-top: .9rem; }
.tt-meta-inline .tt-count { white-space: nowrap; }
.tt-meta-inline .tt-seg { width: auto; }
@media (max-width: 899px) {
  .tt-bar, .tt-rp-bar { flex-wrap: wrap; }
  .tt-bar .tt-search, .tt-rp-bar .tt-search { flex: 1 1 12rem; }
  .tt-meta-inline { order: 3; width: 100%; justify-content: space-between; }
  .tt-meta-inline .tt-seg { flex: 0 1 auto; width: auto; }
}
.tt-search { position: relative; flex: 1; min-width: 0; }
.tt-search > .tt-ic { position: absolute; left: .9rem; top: 50%; transform: translateY(-50%); color: var(--tt-muted); pointer-events: none; }
.tt-field, .tt-select {
  width: 100%; height: 2.75rem; border-radius: .8rem; border: 1px solid var(--tt-rule);
  background-color: var(--tt-paper); color: var(--tt-ink); font-size: 1rem;
  transition: border-color .2s, box-shadow .2s;
}
.tt-search .tt-field { padding: 0 2.6rem 0 2.55rem; }
.tt-field::placeholder { color: var(--tt-muted); opacity: .85; }
.tt-field:focus, .tt-select:focus { outline: none; border-color: var(--tt-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--tt-accent) 30%, transparent); }
.tt-field::-webkit-search-cancel-button { display: none; }
.tt-kbd { position: absolute; right: .7rem; top: 50%; transform: translateY(-50%); min-width: 1.4rem; height: 1.4rem; display: grid; place-items: center; border: 1px solid var(--tt-rule); border-radius: .35rem; font-size: .75rem; color: var(--tt-muted); pointer-events: none; transition: opacity .2s; }
.tt-field:focus ~ .tt-kbd, .tt-field:not(:placeholder-shown) ~ .tt-kbd { opacity: 0; }
@media (hover: none), (max-width: 639px) { .tt-kbd { display: none; } }
.tt-search-clear { position: absolute; right: .15rem; top: 50%; transform: translateY(-50%); width: var(--tt-hit); height: var(--tt-hit); display: grid; place-items: center; border-radius: .6rem; color: var(--tt-muted); }
.tt-search-clear:hover { background: var(--tt-sunk); color: var(--tt-ink); }
.tt-filter-btn { height: 2.75rem; border-radius: .8rem; padding: 0 1rem; }
.tt-badge { min-width: 1.25rem; height: 1.25rem; padding: 0 .35rem; display: inline-grid; place-items: center; border-radius: 999px; background: var(--tt-accent); color: var(--tt-on-accent); font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* Base.html ép input/select sang nền xám trong chế độ tối bằng !important. */
.dark .tt .tt-field, .dark .tt .tt-select { background-color: var(--tt-paper) !important; border-color: var(--tt-rule) !important; color: var(--tt-ink) !important; }
.dark .tt .tt-panel .tt-field, .dark .tt .tt-panel .tt-select { background-color: var(--tt-sunk) !important; }
/* Dòng trên ép viền về --tt-rule bằng !important nên nuốt luôn viền nhấn lúc focus: ở nền tối ô
   đang gõ trông y hệt ô bên cạnh. Trạng thái focus/lỗi phải thắng lại bằng cùng mức !important. */
.dark .tt .tt-field:focus, .dark .tt .tt-select:focus { border-color: var(--tt-accent) !important; }
.dark .tt .lg-input.is-bad .tt-field { border-color: var(--tt-danger) !important; }

/* ── Bộ lọc đang bật ── */
.tt-active { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-top: .75rem; }
.tt-pill {
  display: inline-flex; align-items: center; gap: .3rem; max-width: 100%;
  height: 2rem; padding: 0 .3rem 0 .8rem; border-radius: 999px;
  background: var(--tt-accent-soft); color: var(--tt-accent-strong);
  font-size: .8125rem; font-weight: 550;
  animation: tt-pop .35s var(--tt-ease) both;
  transition: opacity .2s, transform .2s;
}
.tt-pill span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-pill .tt-ic { width: 1.4rem; height: 1.4rem; padding: .3rem; border-radius: 50%; transition: background-color .2s; }
.tt-pill:hover .tt-ic { background: color-mix(in srgb, var(--tt-accent) 22%, transparent); }
.tt-pill.is-leaving { opacity: 0; transform: scale(.9); }
.tt-clear-all { padding: 0 .4rem; font-size: .8125rem; color: var(--tt-muted); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--tt-rule); }
.tt-clear-all:hover { color: var(--tt-ink); text-decoration-color: currentColor; }

/* ── Dòng đếm + thanh trượt sắp xếp ── */
.tt-meta-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .6rem .75rem; margin: 1rem 0 .75rem; }
.tt-count { font-size: .8125rem; color: var(--tt-muted); font-variant-numeric: tabular-nums; }
.tt-count b { color: var(--tt-ink); font-weight: 650; }

/* Tấm trượt trắng rộng đúng MỘT ô, nên nó phải biết thanh có mấy lựa chọn. Đếm bằng :has()
   để trang nào thêm hay bớt lựa chọn cũng không phải sửa lại chỗ này. `minmax(0, 1fr)` giữ
   các ô bằng nhau cả khi thanh bị ép hẹp — `1fr` trần thì ô có chữ dài sẽ nở ra, tấm trượt
   lệch khỏi lựa chọn đang chọn. */
.tt-seg {
  --tt-seg-n: 2;
  position: relative; display: inline-grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  max-width: 100%; padding: 3px; border-radius: .75rem;
  background: color-mix(in srgb, var(--tt-ink) 7%, transparent);
}
.tt-seg:has(> :nth-child(3)) { --tt-seg-n: 3; }
.tt-seg:has(> :nth-child(4)) { --tt-seg-n: 4; }
.tt-seg:has(> :nth-child(5)) { --tt-seg-n: 5; }
.tt-seg:has(> :nth-child(6)) { --tt-seg-n: 6; }
.tt-seg::before {
  content: ""; position: absolute; top: 3px; bottom: 3px; left: 3px;
  width: calc((100% - 6px) / var(--tt-seg-n));
  border-radius: .6rem; background: var(--tt-paper);
  box-shadow: var(--tt-shadow-sm);
  transform: translateX(calc(var(--tt-seg-i, 0) * 100%));
  transition: transform .4s var(--tt-ease);
}
.tt-seg a, .tt-seg button { position: relative; z-index: 1; padding: .4rem .9rem; border-radius: .6rem; text-align: center; font-size: .8125rem; font-weight: 600; color: var(--tt-muted); transition: color .25s; white-space: nowrap; }
.tt-seg a:hover, .tt-seg a[aria-current], .tt-seg button:hover, .tt-seg button[aria-selected="true"], .tt-seg button[aria-pressed="true"] { color: var(--tt-ink); }
.tt-seg :focus-visible { outline: 2px solid var(--tt-accent); outline-offset: 2px; border-radius: .6rem; }

/* Điện thoại: dòng đếm xuống hàng, thanh chọn ăn trọn một hàng. Bốn lựa chọn thì chữ dài
   phải xuống dòng chứ không được tràn khỏi ô — các ô cao bằng nhau nên tấm trượt vẫn khít. */
@media (max-width: 639px) {
  .tt-seg { width: 100%; }
  .tt-seg a, .tt-seg button {
    display: grid; align-content: center; min-height: 2.25rem;
    padding: .35rem .45rem; line-height: 1.3; white-space: normal; text-wrap: balance;
  }
}

/* Nhãn tab hai bản: đầy đủ (máy bàn) và rút gọn (điện thoại) — để thanh chọn không xuống hai dòng.
   Bản rút gọn aria-hidden; trình đọc màn hình luôn nghe bản đầy đủ (ẩn kiểu .tt-vh, không display:none). */
.tt-seg-short { display: none; }

/* ── Điện thoại: đầu trang + thanh tìm/bộ lọc GỌN (03/10/2026) ──
   Người dùng: phần đầu chiếm quá nhiều màn hình, đẩy nội dung chính xuống. Nên ở ≤639px:
   • ô tìm + nút Bộ lọc thấp còn 40px (cỡ chữ ô tìm giữ 16px — nhỏ hơn là iOS tự phóng to khi gõ);
   • bỏ dòng "N bài, trang x/y" (số trang đã có ở thanh phân trang cuối danh sách);
   • thanh sắp xếp ăn trọn bề ngang, chữ MỘT dòng;
   • các khoảng đệm dọc thu lại. */
@media (max-width: 639px) {
  #app-main.container { margin-top: .5rem; }
  .tt-head { margin-bottom: .4rem; gap: .35rem .5rem; }
  .tt-bar-wrap { padding: .35rem 1rem; }
  .tt-bar, .tt-rp-bar { gap: .4rem; }
  .tt-search .tt-field { height: 2.5rem; padding-left: 2.3rem; border-radius: .7rem; }
  .tt-search > .tt-ic { left: .75rem; }
  .tt-filter-btn { height: 2.5rem; padding: 0 .75rem; border-radius: .7rem; }
  .tt-meta-inline .tt-count { display: none; }
  .tt-meta-inline:not(:has(.tt-seg)) { display: none; }
  .tt-meta-inline .tt-seg { flex: 1 1 100%; width: 100%; }
  .tt-seg a, .tt-seg button { min-height: 2rem; padding: .25rem .3rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tt-seg:has(> :nth-child(4)) a, .tt-seg:has(> :nth-child(4)) button { font-size: .75rem; padding: .25rem .15rem; }
  .tt-seg-short { display: inline; }
  .tt-seg-full { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .tt-active { margin-top: .45rem; }
  form + .tt-list, .tt-active + .tt-list, form + .tt-empty, .tt-active + .tt-empty { margin-top: .5rem; }
}

/* ── Danh sách bài ── */
.tt-list { background: var(--tt-paper); border: 1px solid var(--tt-rule); border-radius: 1.1rem; overflow: hidden; transition: opacity .3s, filter .3s; }
html.tt-busy .tt-list { opacity: .5; filter: saturate(.6); }
.tt-entry {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: .45rem;
  padding: 1.15rem 1rem 1.25rem;
  animation: tt-rise .6s var(--tt-ease) both; animation-delay: calc(var(--i, 0) * 45ms);
  transition: background-color .25s;
}
.tt-entry + .tt-entry { border-top: 1px solid var(--tt-rule); }
.tt-entry:hover { background: color-mix(in srgb, var(--tt-sunk) 70%, transparent); }
@media (min-width: 768px) {
  .tt-entry { grid-template-columns: 11rem minmax(0, 1fr); column-gap: 2rem; padding: 1.45rem 1.75rem 1.5rem; }
}
.tt-card-src { display: flex; flex-wrap: wrap; align-items: center; gap: .2rem .7rem; font-size: .8125rem; color: var(--tt-muted); font-variant-numeric: tabular-nums; }
.tt-src-name { font-weight: 650; color: var(--tt-accent-strong); }
@media (min-width: 768px) {
  .tt-card-src { flex-direction: column; align-items: flex-start; gap: .3rem; padding-top: .3rem; }
  .tt-card-src .tt-src-name { font-size: .875rem; line-height: 1.3; }
  .tt-card-src .tt-score { margin-top: .3rem; }
}
.tt-card-main { min-width: 0; }
.tt-entry-title { font-family: var(--tt-display); font-weight: 600; font-size: var(--tt-fs-section); line-height: 1.38; letter-spacing: -.006em; color: var(--tt-ink); text-wrap: pretty; }
.tt-entry-title a {
  background-image: linear-gradient(currentColor, currentColor); background-repeat: no-repeat;
  background-position: 0 100%; background-size: 0 1px;
  transition: background-size .45s var(--tt-ease), color .2s;
}
.tt-entry-title a::after { content: ""; position: absolute; inset: 0; }
.tt-entry:hover .tt-entry-title a { color: var(--tt-accent-strong); background-size: 100% 1px; }
.tt-entry-title a:focus-visible { outline: none; }
.tt-entry:has(.tt-entry-title a:focus-visible) { box-shadow: inset 0 0 0 2px var(--tt-accent); }
.tt-orig { margin-top: .2rem; font-size: .8125rem; line-height: 1.45; color: var(--tt-muted); font-style: italic; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-sum { max-width: none; margin-top: .5rem; font-size: .9375rem; line-height: 1.68; color: var(--tt-ink-2); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.tt-tags { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; margin-top: .7rem; font-size: .78rem; color: var(--tt-muted); }
.tt-tag { display: inline-flex; align-items: center; gap: .35rem; }
.tt-tag + .tt-tag::before { content: ""; width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: .5; margin-right: .15rem; }
.tt-kind { display: inline-flex; align-items: center; height: 1.35rem; padding: 0 .5rem; border-radius: .35rem; border: 1px solid var(--tt-rule); font-size: .72rem; font-weight: 600; color: var(--tt-ink-2); }

/* Điểm liên quan 0–100 dạng vạch: đọc được bằng mắt nhanh hơn một con số. */
.tt-score { display: inline-flex; align-items: center; gap: .45rem; font-size: .75rem; color: var(--tt-muted); font-variant-numeric: tabular-nums; }
.tt-score-bar { position: relative; width: 2.75rem; height: 4px; border-radius: 2px; overflow: hidden; background: color-mix(in srgb, var(--tt-ink) 11%, transparent); }
.tt-score-bar::before { content: ""; position: absolute; inset: 0 auto 0 0; width: calc(var(--v, 0) * 1%); border-radius: inherit; background: var(--tt-muted); transform-origin: 0 50%; animation: tt-grow .9s var(--tt-ease) both; animation-delay: inherit; }
.tt-score.is-high { color: var(--tt-amber); font-weight: 600; }
.tt-score.is-high .tt-score-bar::before { background: var(--tt-amber); }

/* ── Phân trang ── */
.tt-pager { display: flex; align-items: center; justify-content: center; gap: .3rem; margin-top: 1.5rem; }
.tt-page { min-width: 2.5rem; height: 2.5rem; padding: 0 .65rem; display: inline-flex; align-items: center; justify-content: center; gap: .35rem; border-radius: .7rem; font-size: .875rem; font-weight: 600; color: var(--tt-ink-2); font-variant-numeric: tabular-nums; transition: background-color .2s, color .2s; }
a.tt-page:hover { background: var(--tt-paper); color: var(--tt-accent-strong); }
.tt-page[aria-current] { background: var(--tt-ink); color: var(--tt-paper); }
.tt-page--gap { color: var(--tt-muted); min-width: 1.5rem; padding: 0; }
.tt-page--of { display: none; }
@media (max-width: 639px) {
  .tt-pager { justify-content: space-between; }
  .tt-page--num, .tt-page--gap { display: none; }
  .tt-page--of { display: inline-flex; color: var(--tt-muted); font-weight: 500; }
  .tt-page--step { border: 1px solid var(--tt-rule); background: var(--tt-paper); padding: 0 1rem; }
}
.tt-page--step[aria-disabled] { opacity: .35; pointer-events: none; }

/* ── Trạng thái trống ── */
.tt-empty { padding: 3.5rem 1.5rem; text-align: center; background: var(--tt-paper); border: 1px dashed var(--tt-rule); border-radius: 1.1rem; color: var(--tt-muted); animation: tt-rise .5s var(--tt-ease) both; }
.tt-empty h2 { font-family: var(--tt-display); font-size: var(--tt-fs-section); font-weight: 600; color: var(--tt-ink); margin-bottom: .45rem; }
.tt-empty p { font-size: .9375rem; line-height: 1.6; max-width: 46ch; margin: 0 auto; }
.tt-empty .tt-btn { margin-top: 1.25rem; }
.tt-empty code { font-size: .85em; padding: .1em .35em; border-radius: .3rem; background: var(--tt-sunk); }

/* ── Ngăn bộ lọc: tấm trượt từ đáy (điện thoại) / ngăn kéo bên phải (máy bàn) ── */
.tt-sheet { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: transparent; color: var(--tt-ink); overflow: hidden; }
.tt-sheet::backdrop { background: var(--tt-backdrop); -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px); animation: tt-fade .35s ease both; }
.tt-sheet.is-closing::backdrop { animation: tt-fade-out .28s ease both; }
/* Giữ chỗ thanh cuộn khi khoá cuộn, không thì cả trang giật sang phải lúc mở ngăn lọc. */
html:has(.tt-sheet[open]) { overflow: hidden; scrollbar-gutter: stable; }
.tt-panel {
  position: absolute; left: 0; right: 0; bottom: 0; max-height: min(88dvh, 46rem);
  display: flex; flex-direction: column;
  background: var(--tt-paper); border-radius: 1.4rem 1.4rem 0 0; box-shadow: var(--tt-lift);
  padding-bottom: env(safe-area-inset-bottom);
  animation: tt-sheet-up .5s var(--tt-ease) both;
  will-change: transform;
}
.tt-sheet.is-closing .tt-panel { animation: tt-sheet-down .28s var(--tt-ease-in) both; }
/* is-settled gỡ animation sau khi trượt lên xong. Nếu chỉ tắt animation lúc kéo rồi bật lại,
   trình duyệt chạy lại animation từ đầu và tấm lọc trượt lên lần nữa sau mỗi cú chạm. */
.tt-panel.is-settled { animation: none; }
.tt-panel.is-dragging { transition: none; }
.tt-grab { display: flex; justify-content: center; padding: .6rem 0 .15rem; touch-action: none; cursor: grab; }
.tt-grab::before { content: ""; width: 2.5rem; height: 4px; border-radius: 2px; background: var(--tt-rule); }
@media (min-width: 768px) {
  .tt-panel { left: auto; top: 0; width: 27rem; max-height: none; border-radius: 1.4rem 0 0 1.4rem; animation-name: tt-drawer-in; }
  .tt-sheet.is-closing .tt-panel { animation-name: tt-drawer-out; }
  .tt-grab { display: none; }
}
.tt-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .35rem 1rem .8rem 1.35rem; border-bottom: 1px solid var(--tt-rule); touch-action: none; }
@media (min-width: 768px) { .tt-panel-head { padding: 1.1rem 1rem 1rem 1.5rem; } }
.tt-panel-title { font-family: var(--tt-display); font-size: var(--tt-fs-page); font-weight: 600; }
.tt-icon-btn { width: 2.5rem; height: 2.5rem; display: grid; place-items: center; border-radius: .75rem; color: var(--tt-muted); transition: background-color .2s, color .2s, transform .15s; }
.tt-icon-btn:hover { background: var(--tt-sunk); color: var(--tt-ink); }
.tt-icon-btn:active { transform: scale(.94); }
.tt-panel-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 1.1rem 1.35rem 1.5rem; display: grid; align-content: start; gap: 1.6rem; }
@media (min-width: 768px) { .tt-panel-body { padding: 1.35rem 1.5rem 1.75rem; } }
.tt-panel-body > * { animation: tt-rise .5s var(--tt-ease) both; }
.tt-panel-body > :nth-child(2) { animation-delay: 50ms; }
.tt-panel-body > :nth-child(3) { animation-delay: 100ms; }
.tt-panel-body > :nth-child(4) { animation-delay: 150ms; }
.tt-panel-foot { display: flex; gap: .6rem; padding: .85rem 1.35rem; border-top: 1px solid var(--tt-rule); background: var(--tt-paper); }
.tt-panel-foot .tt-btn { min-height: 2.9rem; }
.tt-panel-foot .tt-btn--primary { flex: 1; }
.tt-fs { border: 0; margin: 0; padding: 0; min-width: 0; }
.tt-fs-title { display: block; margin-bottom: .7rem; font-size: .875rem; font-weight: 650; color: var(--tt-ink); }
.tt-fs-hint { font-weight: 400; color: var(--tt-muted); }
.tt-opts { display: flex; flex-wrap: wrap; gap: .45rem; }
.tt-opt { position: relative; display: inline-flex; }
.tt-opt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.tt-opt span {
  display: inline-flex; align-items: center; gap: .4rem; min-height: 2.3rem; padding: 0 .9rem;
  border-radius: 999px; border: 1px solid var(--tt-rule); background: var(--tt-paper);
  font-size: .875rem; color: var(--tt-ink-2);
  transition: background-color .22s, border-color .22s, color .22s, transform .15s var(--tt-ease);
}
.tt-opt:hover span { border-color: color-mix(in srgb, var(--tt-ink) 35%, var(--tt-rule)); }
.tt-opt input:checked + span { background: var(--tt-ink); border-color: var(--tt-ink); color: var(--tt-paper); }
.tt-opt input:focus-visible + span { outline: 2px solid var(--tt-accent); outline-offset: 2px; }
.tt-opt input:active + span { transform: scale(.95); }
.tt-opt small { font-size: .72rem; opacity: .6; font-variant-numeric: tabular-nums; }
.tt-select { appearance: none; -webkit-appearance: none; padding: 0 2.4rem 0 .9rem; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2365706b' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .8rem center; background-size: 1rem; text-overflow: ellipsis; }
.tt-panel .tt-field { padding: 0 .8rem; }
.tt-stack { display: grid; gap: .55rem; }
.tt-range { display: none; grid-template-columns: 1fr 1fr; gap: .5rem; margin-top: .7rem; }
.tt-range label { display: grid; gap: .3rem; font-size: .75rem; color: var(--tt-muted); }
.tt-fs:has(input[value="custom"]:checked) .tt-range { display: grid; animation: tt-rise .35s var(--tt-ease) both; }

/* Thanh chạy báo đang tải trang mới sau khi bấm lọc. */
.tt-loadbar { position: fixed; left: 0; right: 0; top: var(--tt-nav, 56px); height: 2px; overflow: hidden; z-index: 60; pointer-events: none; opacity: 0; transition: opacity .2s; }
.tt-loadbar::before { content: ""; position: absolute; top: 0; bottom: 0; width: 35%; background: var(--tt-accent); animation: tt-load 1.1s ease-in-out infinite; }
html.tt-busy .tt-loadbar { opacity: 1; }
html:not(.tt-busy) .tt-loadbar::before { animation: none; }

/* ─────────────────────────── Trang đọc bài ─────────────────────────── */
/* Trang đọc chi tiết trải hết bề ngang như mọi trang (26/09/2026, người dùng yêu cầu đồng nhất). Dòng
   dài trên màn rộng được bù bằng cỡ chữ tăng theo bề ngang (xem --tt-fs ở .tt-doc). */
.tt-read { max-width: none; }
.tt-read-top { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin: 0 0 .9rem; }
.tt-back { display: inline-flex; align-items: center; gap: .5rem; min-height: var(--tt-hit); padding: 0 .15rem; font-size: .875rem; font-weight: 600; color: var(--tt-muted); transition: color .2s; }
.tt-back .tt-ic { transition: transform .3s var(--tt-ease); }
.tt-back:hover { color: var(--tt-accent-strong); }
.tt-back:hover .tt-ic { transform: translateX(-3px); }
.tt-actions { display: flex; align-items: center; gap: .5rem; }
@media (max-width: 639px) { .tt-read-top .tt-actions { display: none; } }
.tt-size { display: inline-flex; align-items: center; border: 1px solid var(--tt-rule); border-radius: .7rem; background: var(--tt-paper); overflow: hidden; }
.tt-size button { width: var(--tt-hit); height: var(--tt-hit); display: grid; place-items: center; font-family: var(--tt-display); font-weight: 600; color: var(--tt-ink-2); transition: background-color .2s, color .2s, opacity .2s; }
.tt-size button:first-child { font-size: .8rem; }
.tt-size button:last-child { font-size: 1.05rem; border-left: 1px solid var(--tt-rule); }
.tt-size button:hover { background: var(--tt-sunk); color: var(--tt-accent-strong); }
.tt-size button[disabled] { opacity: .35; pointer-events: none; }

.tt-doc {
  --tt-fs: var(--tt-read-fs);
  position: relative; background: var(--tt-paper); border: 1px solid var(--tt-rule); border-radius: 1.3rem;
  padding: 1.6rem 1.15rem 2rem;
  animation: tt-rise .6s var(--tt-ease) both;
}
@media (min-width: 640px) { .tt-doc { padding: 2.75rem 3.25rem 3rem; } }
/* Màn rộng: chữ nhích lên một nấc để dòng dài vẫn dễ đọc. */
@media (min-width: 1600px) { .tt-doc { --tt-fs: 1.0625rem; } }
@media (min-width: 2200px) { .tt-doc { --tt-fs: 1.125rem; } }
/* Điện thoại: tờ giấy tràn sát mép màn hình để cột chữ lấy lại ~30px bề rộng. */
@media (max-width: 639px) { .tt-doc { margin: 0 -1rem; border-radius: 0; border-left: 0; border-right: 0; padding: 1.6rem 1.25rem 2rem; } }
.tt-doc[data-size="s"] { --tt-fs: .9375rem; }
.tt-doc[data-size="l"] { --tt-fs: 1.125rem; }
.tt-kicker { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .6rem; font-size: .875rem; color: var(--tt-muted); }
.tt-kicker .tt-src-name { font-size: .9375rem; }
.tt-h1 { margin-top: .7rem; font-family: var(--tt-display); font-weight: 600; font-size: var(--tt-fs-headline); line-height: 1.3; letter-spacing: -.018em; color: var(--tt-ink); text-wrap: pretty; }
.tt-h1-orig { margin-top: .7rem; font-family: var(--tt-serif); font-style: italic; font-size: 1rem; line-height: 1.5; color: var(--tt-muted); }
.tt-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); gap: .9rem 1.25rem; margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--tt-rule); }
@media (max-width: 639px) { .tt-facts { grid-template-columns: 1fr 1fr; } }
.tt-fact { display: grid; gap: .2rem; align-content: start; font-size: .75rem; color: var(--tt-muted); }
.tt-fact > dd {font-size: .875rem; font-weight: 600; color: var(--tt-ink-2); line-height: 1.45; }
.tt-fact--wide { grid-column: 1 / -1; }
.tt-flag { margin-top: 1rem; padding: .7rem .9rem; border-radius: .7rem; font-size: .8125rem; line-height: 1.5; color: var(--tt-amber); background: color-mix(in srgb, var(--tt-amber) 11%, transparent); }

.tt-prose { margin-top: 2.1rem; font-family: var(--tt-serif); font-size: var(--tt-fs); line-height: var(--tt-read-lh); color: var(--tt-ink-2); transition: font-size .3s var(--tt-ease); }
.tt-prose > * + * { margin-top: 2.2em; }
.tt-sec-title { display: flex; align-items: center; gap: .6rem; margin-bottom: .75rem; font-family: var(--tt-sans); font-size: var(--tt-fs-label); font-weight: 700; letter-spacing: -.005em; color: var(--tt-ink); }
.tt-sec-title::after { content: ""; flex: 1; height: 1px; background: var(--tt-rule); }
.tt-lead { font-size: 1.06em; color: var(--tt-ink); text-wrap: pretty; }
.tt-lens { font-family: var(--tt-sans); font-size: .9375rem; line-height: 1.6; color: var(--tt-ink-2); padding: .9rem 1.05rem; border-radius: .8rem; background: var(--tt-sunk); }
.tt-lens b { display: block; font-size: .8125rem; font-weight: 650; color: var(--tt-muted); margin-bottom: .2rem; }
.tt-points { display: grid; gap: .8em; }
.tt-points li { position: relative; padding-left: 1.5em; text-wrap: pretty; }
.tt-points li::before { content: ""; position: absolute; left: .15em; top: .72em; width: .42em; height: .42em; background: var(--tt-accent); transform: rotate(45deg); border-radius: 1px; }
.tt-points--rec li::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--tt-accent); }
.tt-vn { position: relative; padding: 1.2em 1.3em 1.3em 1.5em; border-radius: .9rem; background: var(--tt-accent-soft); }
.tt-vn::before { content: ""; position: absolute; left: 0; top: 1em; bottom: 1em; width: 3px; border-radius: 0 3px 3px 0; background: var(--tt-accent); }
.tt-vn .tt-sec-title { color: var(--tt-accent-strong); }
.tt-vn .tt-sec-title::after { background: color-mix(in srgb, var(--tt-accent) 25%, transparent); }
.tt-vn p { color: var(--tt-ink); }
.tt-note { font-family: var(--tt-sans); font-size: .8125rem; line-height: 1.6; color: var(--tt-muted); padding-top: 1.3rem; border-top: 1px solid var(--tt-rule); }

.tt-original { margin-top: 1.75rem; border: 1px solid var(--tt-rule); border-radius: .95rem; }
.tt-original summary { list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 1.1rem; border-radius: .95rem; cursor: pointer; font-size: .9375rem; font-weight: 600; color: var(--tt-ink); transition: background-color .2s; scroll-margin-top: calc(var(--tt-nav, 56px) + 1rem); }
.tt-original summary::-webkit-details-marker { display: none; }
.tt-original summary:hover { background: var(--tt-sunk); }
.tt-original summary small { display: block; margin-top: .1rem; font-size: .8125rem; font-weight: 400; color: var(--tt-muted); }
.tt-original[open] summary { border-radius: .95rem .95rem 0 0; }
.tt-original .tt-chev { width: 1.25rem; height: 1.25rem; color: var(--tt-muted); transition: transform .4s var(--tt-ease); }
.tt-original[open] .tt-chev { transform: rotate(180deg); }
.tt-original-clip { overflow: hidden; }
.tt-original-body { padding: .5rem 1.1rem 1.4rem; border-top: 1px solid var(--tt-rule); font-family: var(--tt-serif); font-size: calc(var(--tt-fs) * .94); line-height: var(--tt-read-lh); color: var(--tt-ink-2); overflow-wrap: anywhere; }
.tt-original-body img { max-width: 100%; height: auto; border-radius: .5rem; }
.tt-original-body table { display: block; overflow-x: auto; }
.tt-original-body a { color: var(--tt-accent-strong); }

.tt-progress { position: fixed; left: 0; right: 0; top: var(--tt-nav, 56px); height: 3px; z-index: 45; pointer-events: none; }
.tt-progress span { display: block; height: 100%; background: var(--tt-accent); transform-origin: 0 50%; transform: scaleX(var(--p, 0)); }

/* Thanh hành động nổi dưới đáy màn hình điện thoại — tầm ngón cái. Ẩn khi cuộn xuống đọc,
   hiện lại khi cuộn lên. */
.tt-dock {
  position: fixed; left: .75rem; right: .75rem; bottom: calc(.75rem + env(safe-area-inset-bottom)); z-index: 40;
  display: flex; align-items: center; gap: .4rem; padding: .4rem;
  border-radius: 1.1rem; border: 1px solid var(--tt-rule);
  background: color-mix(in srgb, var(--tt-paper) 86%, transparent);
  -webkit-backdrop-filter: blur(16px) saturate(1.5); backdrop-filter: blur(16px) saturate(1.5);
  box-shadow: var(--tt-lift);
  transition: transform .45s var(--tt-ease), opacity .3s;
  animation: tt-dock-in .6s var(--tt-ease) .25s both;
}
.tt-dock.is-hidden { transform: translateY(calc(100% + 1.5rem)); opacity: 0; }
.tt-dock .tt-btn { flex: 1; min-height: 2.75rem; padding: 0 .6rem; border-radius: .8rem; }
.tt-dock .tt-size { border: 0; background: transparent; flex: none; }
.tt-dock .tt-size button { height: 2.75rem; }
@media (min-width: 640px) { .tt-dock { display: none; } }
@media (max-width: 639px) { .tt-read { padding-bottom: 6rem; } }

/* ─────────────────────────── Danh mục nguồn ─────────────────────────── */
.tt-src-tools { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-bottom: .9rem; }
.tt-src-tools .tt-search { flex: 1 1 16rem; }
.tt-src-tools .tt-search .tt-field { padding-right: .9rem; }
.tt-states { display: flex; gap: .4rem; overflow-x: auto; scrollbar-width: none; margin: 0 -1rem; padding: .1rem 1rem; }
.tt-states::-webkit-scrollbar { display: none; }
@media (min-width: 640px) { .tt-states { margin: 0; padding: .1rem 0; flex-wrap: wrap; } }
.tt-state-btn { flex: none; display: inline-flex; align-items: center; gap: .45rem; height: var(--tt-hit); padding: 0 .8rem; border-radius: 999px; border: 1px solid var(--tt-rule); background: var(--tt-paper); font-size: .8125rem; color: var(--tt-ink-2); transition: background-color .2s, color .2s, border-color .2s; }
.tt-state-btn small { font-size: .75rem; color: var(--tt-muted); font-variant-numeric: tabular-nums; }
.tt-state-btn[aria-pressed="true"] { background: var(--tt-ink); border-color: var(--tt-ink); color: var(--tt-paper); }
.tt-state-btn[aria-pressed="true"] small { color: inherit; opacity: .7; }
.tt-dot { width: .5rem; height: .5rem; border-radius: 50%; flex: none; background: var(--tt-muted); }
.tt-dot--ok { background: var(--tt-success); }
.tt-dot--warn { background: var(--tt-warning); }
.tt-dot--bad { background: var(--tt-danger); }
.tt-dot--wait { background: var(--tt-info); }
.tt-dot--off { background: color-mix(in srgb, var(--tt-muted) 55%, transparent); }
.tt-table-wrap { background: var(--tt-paper); border: 1px solid var(--tt-rule); border-radius: 1.1rem; overflow-x: auto; }
.tt-table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.tt-table th { padding: .8rem 1rem; text-align: left; font-size: .75rem; font-weight: 600; color: var(--tt-muted); border-bottom: 1px solid var(--tt-rule); white-space: nowrap; }
.tt-table td { padding: .85rem 1rem; vertical-align: top; color: var(--tt-ink-2); border-bottom: 1px solid var(--tt-rule); }
.tt-table tbody tr { transition: background-color .2s; }
.tt-table tbody tr:hover { background: color-mix(in srgb, var(--tt-sunk) 70%, transparent); }
.tt-table tbody tr:last-child td { border-bottom: 0; }
.tt-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.tt-src-link { font-weight: 600; color: var(--tt-ink); }
a.tt-src-link:hover { color: var(--tt-accent-strong); }
.tt-sub { margin-top: .15rem; font-size: .75rem; color: var(--tt-muted); }
.tt-err { margin-top: .35rem; font-size: .75rem; line-height: 1.45; color: var(--tt-muted); overflow-wrap: anywhere; max-width: 36ch; }
.tt-state { display: inline-flex; align-items: center; gap: .45rem; font-size: .8125rem; font-weight: 550; color: var(--tt-ink-2); white-space: nowrap; }
.tt-none { padding: 2.5rem 1rem; text-align: center; font-size: .9375rem; color: var(--tt-muted); }
@media (max-width: 767px) {
  .tt-table thead { display: none; }
  .tt-table, .tt-table tbody { display: block; }
  .tt-table tbody tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .35rem 1rem; padding: .95rem 1rem; border-bottom: 1px solid var(--tt-rule); }
  .tt-table tbody tr:last-child { border-bottom: 0; }
  .tt-table td { display: block; padding: 0; border: 0; }
  .tt-table td.c-name { grid-column: 1; }
  .tt-table td.c-posts { grid-column: 2; grid-row: 1; text-align: right; }
  .tt-table td.c-posts::after { content: " bài"; color: var(--tt-muted); font-size: .75rem; }
  /* 3 hàng: tên | số bài — nhóm | cách lấy — tình trạng | lần chạy tốt. */
  .tt-table td.c-group, .tt-table td.c-mode, .tt-table td.c-last { font-size: .75rem; color: var(--tt-muted); }
  .tt-table td.c-group { grid-column: 1; grid-row: 2; }
  .tt-table td.c-mode { grid-column: 2; grid-row: 2; text-align: right; }
  .tt-table td.c-state { grid-column: 1; grid-row: 3; }
  .tt-table td.c-last { grid-column: 2; grid-row: 3; text-align: right; white-space: nowrap; padding-top: .1rem; }
  .tt-table td.c-mode .tt-err { text-align: left; }
  .tt-err { max-width: none; }
}

/* ── Sao chép tóm tắt ── */
.tt-share { font-family: var(--tt-sans); }
.tt-share + .tt-note { margin-top: 1.5rem; }
.tt-btn .tt-ic-done { display: none; }
.tt-btn.is-done { color: var(--tt-accent-strong); border-color: color-mix(in srgb, var(--tt-accent) 45%, var(--tt-rule)); }
.tt-btn.is-done .tt-ic-copy { display: none; }
.tt-btn.is-done .tt-ic-done { display: block; animation: tt-pop .35s var(--tt-ease) both; }

/* ── In / lưu PDF trang bài: chỉ giữ nội dung, luôn nền trắng chữ đen kể cả khi đang bật chế độ tối ── */
@media print {
  nav, footer, .tt-read-top, .tt-dock, .tt-progress, .tt-loadbar, .tt-share,
  .tt-new-pill, .tt-live-toast { display: none !important; }
  body { background: #fff !important; }
  #app-main { margin: 0 !important; padding: 0 !important; max-width: none !important; }
  .tt, .dark .tt {
    --tt-paper: #fff; --tt-sunk: #f3f5f4; --tt-ink: #000; --tt-ink-2: #1c1c1c; --tt-muted: #555;
    --tt-rule: #cfd5d2; --tt-accent: #0b7a57; --tt-accent-strong: #075e43; --tt-accent-soft: #eef6f2; --tt-amber: #8a5300;
    max-width: none; padding: 0;
  }
  .tt-doc { border: 0; margin: 0; padding: 0; animation: none; --tt-fs: 11.5pt; }
  .tt-doc[data-size] { --tt-fs: 11.5pt; }
  .tt-original:not([open]) { display: none; }
  .tt-lens, .tt-vn, .tt-points li { break-inside: avoid; }
  .tt-sec-title { break-after: avoid; }
  .tt-read { padding-bottom: 0; }
}

/* ── Bài mới về khi trang đang mở (Thinktanks, An ninh mạng, Báo cáo ngày) ──
   Cùng ngôn ngữ với Tin tức (.news-new-pill trong tt-news.css): nút nổi giữa đỉnh khi người dùng
   đã cuộn xuống, thẻ vừa chèn sáng nhẹ rồi tự nhạt đi. Đặt ở đây vì ba trang cùng dùng. */
.tt-new-pill {
  position: fixed; top: calc(var(--tt-nav, 56px) + 1.25rem); left: 50%; z-index: 55;
  display: inline-flex; align-items: center; gap: .5rem; padding: .55rem 1.05rem; border-radius: 999px;
  background: var(--tt-accent); color: var(--tt-on-accent); font-size: .85rem; font-weight: 650;
  box-shadow: var(--tt-lift);
  opacity: 0; transform: translate(-50%, -12px); pointer-events: none;
  /* visibility (không phải chỉ opacity) để nút đang ẩn KHÔNG nhận được phím Tab: người dùng bàn
     phím trước đây vẫn tab trúng một nút vô hình rồi bấm nhầm. Vẫn giữ được hiệu ứng hiện/ẩn vì
     visibility đổi theo bước, đặt cùng thời lượng với opacity. */
  visibility: hidden;
  transition: opacity .3s, transform .35s var(--tt-ease), visibility .3s;
}
.tt-new-pill.is-visible { opacity: 1; visibility: visible; transform: translate(-50%, 0); pointer-events: auto; }
.tt-new-pill:active { transform: translate(-50%, 0) scale(.95); }
.tt-np-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; animation: tt-pulse 1.8s ease-in-out infinite; }
/* Tên KHÁC .tt-toast của tt-report.css (thông báo nổi ở ĐÁY trang Báo cáo ngày, lớp .is-on):
   hai thứ khác chỗ, khác cách bật, trùng tên là trang nào nạp cả hai file sẽ đá nhau. */
.tt-live-toast {
  position: fixed; top: calc(var(--tt-nav, 56px) + 1.25rem); left: 50%; z-index: 56; pointer-events: none;
  padding: .55rem 1.05rem; border-radius: 999px; background: var(--tt-ink); color: var(--tt-paper);
  font-size: .82rem; font-weight: 600; box-shadow: var(--tt-lift);
  opacity: 0; transform: translate(-50%, -12px); transition: opacity .35s, transform .35s var(--tt-ease);
}
.tt-live-toast.is-visible { opacity: 1; transform: translate(-50%, 0); }
/* Thẻ vừa chèn: trượt từ trên xuống, nền nhấn rồi nhạt dần (JS gỡ lớp sau ~3 giây). */
.tt-entry--new { animation: tt-drop-in .55s var(--tt-ease) both; background: var(--tt-accent-soft); }
.tt-entry--new.is-settled { background-color: transparent; transition: background-color 1.6s ease 1s; }
/* Người bật "giảm chuyển động" trong hệ điều hành: bỏ mọi hiệu ứng trang trí. Chấm nhấp nháy
   báo "đang chờ AI" chạy vô hạn nên càng phải tắt. KHÔNG đụng tới tấm lọc trượt lên/xuống —
   tt-list.js chờ `animationend` của nó để đóng, tắt đi thì hộp kẹt lại. */
@media (prefers-reduced-motion: reduce) {
  .tt-entry, .tt-entry--new, .tt-empty, .tt-doc, .tt-pill,
  .tt-panel-body > *, .tt-dock, .tt-score-bar::before { animation: none; }
  .tt-pending::before, .tt-np-dot { animation: none; }
  .tt-seg::before { transition: none; }
}

/* ─────────────────────────── Thành phần dùng chung (nền móng 09/2026) ───────────────────────────
   Thay cho bộ component của thư viện React trong bản yêu cầu gốc: cùng vai trò, viết bằng CSS thuần
   để template Jinja dùng thẳng. Hàm JS đi kèm ở static/js/tt-core.js (TT.toast, TT.confirm…).
   Chuẩn dùng: xem docs/ui-audit/PROGRESS.md mục "Quyết định thiết kế". */

/* Nút — biến thể theo NGỮ NGHĨA: --primary chỉ một nút mỗi vùng; --danger cho hành động không
   hoàn tác được; --quiet (ghost) cho thao tác phụ; --link cho hành động dạng chữ. */
.tt-btn:focus-visible, .tt-icon-btn:focus-visible, .tt-iconbtn:focus-visible { outline: 2px solid var(--tt-focus); outline-offset: 2px; }
.tt-btn--danger { background: var(--tt-danger); border-color: var(--tt-danger); color: var(--tt-on-danger); }
.tt-btn--danger:hover { background: color-mix(in srgb, var(--tt-danger) 85%, var(--tt-ink)); border-color: transparent; color: var(--tt-on-danger); }
.tt-btn--link { min-height: auto; padding: 0; border: 0; background: none; color: var(--tt-accent-strong); text-decoration: underline; text-underline-offset: 3px; }
.tt-btn--link:hover { color: var(--tt-ink); }
.tt-btn--sm { min-height: 2.25rem; padding: 0 .75rem; font-size: .8125rem; border-radius: var(--tt-r-sm); }
.tt-btn--block { width: 100%; }
.tt-btn[aria-busy="true"] { position: relative; color: transparent !important; pointer-events: none; }
.tt-btn[aria-busy="true"]::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 1.05rem; height: 1.05rem; border-radius: 50%;
  border: 2px solid var(--tt-muted); border-right-color: transparent;
  animation: tt-spin .7s linear infinite;
}
.tt-btn--primary[aria-busy="true"]::after, .tt-btn--danger[aria-busy="true"]::after { border-color: var(--tt-on-accent); border-right-color: transparent; }
.tt-icon-btn { width: var(--tt-hit); height: var(--tt-hit); }
.tt-icon-btn.is-danger:hover { color: var(--tt-danger); background: var(--tt-danger-soft); }

/* Thẻ nội dung (thay div bg-white rounded shadow tự chế ở các trang cũ). */
.tt-card { background: var(--tt-paper); border: 1px solid var(--tt-rule); border-radius: var(--tt-r-lg); padding: 1.25rem; }
@media (min-width: 640px) { .tt-card { padding: 1.5rem; } }
.tt-card + .tt-card { margin-top: 1rem; }
.tt-card-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: .5rem 1rem; margin-bottom: 1rem; }
.tt-card-title { font-size: var(--tt-fs-section); font-weight: 650; letter-spacing: -.01em; color: var(--tt-ink); }
.tt-card-desc { margin-top: .2rem; font-size: .875rem; line-height: 1.5; color: var(--tt-muted); }
.tt-card-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .5rem; margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--tt-rule); }
.tt-grid { display: grid; gap: 1rem; }
.tt-grid > .tt-card + .tt-card { margin-top: 0; }
@media (min-width: 768px) {
  .tt-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tt-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Số liệu KPI */
.tt-stat { display: grid; gap: .25rem; }
.tt-stat-label { font-size: .8125rem; color: var(--tt-muted); }
.tt-stat-value { font-size: var(--tt-fs-stat); font-weight: 700; letter-spacing: -.02em; line-height: 1.1; color: var(--tt-ink); font-variant-numeric: tabular-nums; }

/* Thông báo nằm trong trang (khác toast nổi): luôn có chữ, màu chỉ để nhấn. */
.tt-alert { display: flex; gap: .7rem; align-items: flex-start; padding: .8rem 1rem; border-radius: var(--tt-r-md); border: 1px solid var(--tt-rule); background: var(--tt-sunk); font-size: .875rem; line-height: 1.55; color: var(--tt-ink-2); }
.tt-alert > .tt-ic { margin-top: .15rem; }
.tt-alert b { color: var(--tt-ink); }
.tt-alert--ok { background: var(--tt-success-soft); border-color: color-mix(in srgb, var(--tt-success) 30%, var(--tt-rule)); }
.tt-alert--ok > .tt-ic { color: var(--tt-success); }
.tt-alert--warn { background: var(--tt-warning-soft); border-color: color-mix(in srgb, var(--tt-warning) 35%, var(--tt-rule)); }
.tt-alert--warn > .tt-ic { color: var(--tt-warning); }
.tt-alert--info { background: var(--tt-info-soft); border-color: color-mix(in srgb, var(--tt-info) 30%, var(--tt-rule)); }
.tt-alert--info > .tt-ic { color: var(--tt-info); }
.tt-alert--err { background: var(--tt-danger-soft); border-color: var(--tt-danger-rule); }
.tt-alert--err > .tt-ic { color: var(--tt-danger); }

/* Huy hiệu trạng thái: chữ + nền nhạt cùng tông (đều ≥ 4.5:1). */
.tt-tagc { display: inline-flex; align-items: center; gap: .3rem; height: 1.5rem; padding: 0 .55rem; border-radius: var(--tt-r-pill); font-size: .75rem; font-weight: 600; white-space: nowrap; background: var(--tt-sunk); color: var(--tt-ink-2); font-variant-numeric: tabular-nums; }
.tt-tagc--ok { background: var(--tt-success-soft); color: var(--tt-success); }
.tt-tagc--warn { background: var(--tt-warning-soft); color: var(--tt-warning); }
.tt-tagc--info { background: var(--tt-info-soft); color: var(--tt-info); }
.tt-tagc--err { background: var(--tt-danger-soft); color: var(--tt-danger); }
.tt-tagc--accent { background: var(--tt-accent-soft); color: var(--tt-accent-strong); }

/* Form: nhãn LUÔN hiện, gắn for/id; lỗi đứng dưới ô, nối qua aria-describedby. */
.tt-form { display: grid; gap: 1.1rem; }
.tt-fg { display: grid; gap: .4rem; }
.tt-label { font-size: .875rem; font-weight: 600; color: var(--tt-ink); }
.tt-label .tt-req { color: var(--tt-danger); margin-left: .15rem; }
.tt-help { font-size: .8125rem; line-height: 1.5; color: var(--tt-muted); }
.tt-ferr { font-size: .8125rem; line-height: 1.45; color: var(--tt-danger); }
.tt-ferr:empty { display: none; }
.tt-fg .tt-field { padding: 0 .9rem; }
.tt-fg textarea.tt-field, textarea.tt-field { height: auto; min-height: 6rem; padding: .7rem .9rem; line-height: 1.55; resize: vertical; }
.tt-field[aria-invalid="true"] { border-color: var(--tt-danger); }
.dark .tt .tt-field[aria-invalid="true"] { border-color: var(--tt-danger) !important; }
.tt-field[readonly], .tt-field:disabled { background-color: var(--tt-sunk); color: var(--tt-muted); cursor: not-allowed; }
/* Nền tối: dòng .dark .tt .tt-field ép nền giấy bằng !important nên ô chỉ-đọc trông như ô sửa được. */
.dark .tt .tt-field[readonly], .dark .tt .tt-field:disabled { background-color: var(--tt-sunk) !important; color: var(--tt-muted) !important; border-style: dashed !important; }
.tt-input-wrap { position: relative; }
.tt-input-wrap .tt-field { padding-right: 3rem; }
.tt-input-wrap .tt-icon-btn { position: absolute; right: .15rem; top: 50%; transform: translateY(-50%); }
.tt-check { display: inline-flex; align-items: center; gap: .6rem; min-height: var(--tt-hit); font-size: .9rem; color: var(--tt-ink-2); cursor: pointer; }
.tt-check input { width: 1.1rem; height: 1.1rem; accent-color: var(--tt-accent); }

/* Khung xương khi tải: đúng kích thước nội dung thật để không nhảy bố cục. */
.tt-sk { display: block; border-radius: var(--tt-r-sm); background: linear-gradient(90deg, var(--tt-sunk) 0%, color-mix(in srgb, var(--tt-rule) 70%, var(--tt-sunk)) 50%, var(--tt-sunk) 100%) 0 0 / 200% 100%; animation: tt-shimmer 1.4s ease-in-out infinite; }
.tt-sk--line { height: .85rem; margin: .45rem 0; }
.tt-sk--title { height: 1.3rem; width: 70%; margin: .2rem 0 .7rem; }
.tt-sk--block { height: 8rem; }

/* Toast nổi — MỘT vùng duy nhất cho cả site (TT.toast). */
.tt-toasts { position: fixed; z-index: 90; left: 50%; bottom: calc(1.25rem + env(safe-area-inset-bottom)); transform: translateX(-50%); display: grid; gap: .5rem; width: min(26rem, calc(100vw - 2rem)); pointer-events: none; }
.tt-toast2 { display: flex; align-items: flex-start; gap: .6rem; padding: .75rem .6rem .75rem .95rem; border-radius: var(--tt-r-md); background: var(--tt-ink); color: var(--tt-paper); font-size: .875rem; line-height: 1.5; box-shadow: var(--tt-lift); pointer-events: auto; animation: tt-toast-in .35s var(--tt-ease) both; }
.tt-toast2.is-leaving { animation: tt-toast-out .25s ease both; }
.tt-toast-dot { width: .55rem; height: .55rem; margin-top: .45rem; border-radius: 50%; flex: none; background: var(--tt-success); }
.tt-toast2--err .tt-toast-dot { background: var(--tt-danger); }
.tt-toast2--warn .tt-toast-dot { background: var(--tt-warning); }
.tt-toast2--info .tt-toast-dot { background: var(--tt-info); }
/* Toast là nền MỰC (đảo màu): chấm màu phải lấy tông của chế độ ngược lại mới nổi. */
.tt-toast2 { --tt-success: var(--tt-inv-success); --tt-danger: var(--tt-inv-danger); --tt-warning: var(--tt-inv-warning); --tt-info: var(--tt-inv-info); }
.tt-toast2-msg { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.tt-toast2-x { width: 2rem; height: 2rem; margin: -.3rem 0; display: grid; place-items: center; border-radius: var(--tt-r-sm); color: inherit; opacity: .7; flex: none; }
.tt-toast2-x:hover { opacity: 1; background: color-mix(in srgb, var(--tt-paper) 15%, transparent); }

/* Hộp thoại (TT.confirm / TT.modal) dựng trên <dialog>: nền sau tự `inert`, Esc do JS bắt. */
.tt-dlg { width: min(28rem, calc(100vw - 2rem)); max-width: none; max-height: calc(100dvh - 2rem); margin: auto; padding: 0; border: 1px solid var(--tt-rule); border-radius: var(--tt-r-xl); background: var(--tt-paper); color: var(--tt-ink); box-shadow: var(--tt-lift); animation: tt-dlg-in .28s var(--tt-ease) both; }
.tt-dlg--wide { width: min(40rem, calc(100vw - 2rem)); }
.tt-dlg::backdrop { background: var(--tt-backdrop); animation: tt-fade .25s ease both; }
.tt-dlg-body { padding: 1.4rem 1.4rem 1.1rem; }
.tt-dlg-title { font-size: 1.125rem; font-weight: 700; letter-spacing: -.01em; color: var(--tt-ink); }
.tt-dlg-text { margin-top: .5rem; font-size: .9375rem; line-height: 1.6; color: var(--tt-ink-2); overflow-wrap: anywhere; }
.tt-dlg-text b { color: var(--tt-ink); }
.tt-dlg-foot { display: flex; flex-wrap: wrap-reverse; justify-content: flex-end; gap: .5rem; padding: .9rem 1.4rem 1.2rem; }
@media (max-width: 479px) { .tt-dlg-foot .tt-btn { flex: 1 1 auto; } }
html:has(.tt-dlg[open]) { overflow: hidden; scrollbar-gutter: stable; }

/* Trang lỗi 403/404/500 (templates/errors/_error.html) */
.tt-errpage { max-width: 34rem; margin: clamp(2rem, 8vh, 5rem) auto 3rem; padding: 2.5rem 1.5rem; text-align: center; background: var(--tt-paper); border: 1px solid var(--tt-rule); border-radius: var(--tt-r-xl); box-shadow: var(--tt-lift); position: relative; overflow: hidden; }
.tt-errpage::before { content: ""; position: absolute; inset: 0 0 auto; height: 4px; background: var(--tt-grad-line); }
.tt-errpage-ic { margin: 0 auto 1rem; width: 3.25rem; height: 3.25rem; border-radius: var(--tt-r-lg); }
.tt-errpage-code { font-family: var(--tt-display); font-size: clamp(3.5rem, 2.5rem + 5vw, 5rem); font-weight: 700; line-height: 1; letter-spacing: -.03em; background: var(--tt-grad-brand); -webkit-background-clip: text; background-clip: text; color: transparent; }
.tt-errpage-title { margin-top: .75rem; font-size: var(--tt-fs-headline); font-weight: 700; letter-spacing: -.01em; color: var(--tt-ink); }
.tt-errpage-text { margin: .6rem auto 0; max-width: 40ch; font-size: .9375rem; line-height: 1.6; color: var(--tt-muted); }
.tt-errpage-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem; margin-top: 1.6rem; }

/* Đầu trang nhỏ hơn cho trang công cụ (tài khoản, admin) — dùng cùng .tt-head/.tt-title. */
.tt-title--sm { font-size: var(--tt-fs-page); }   /* giữ lớp cho tương thích; cùng cỡ với mọi trang */

@media (prefers-reduced-motion: reduce) {
  .tt-sk, .tt-btn[aria-busy="true"]::after { animation: none; }
  .tt-toast2, .tt-dlg { animation: none; }
}

/* ── Lớp màu: ghi đè thành phần (đặt SAU định nghĩa gốc của .tt-btn--primary, .tt-title… để thắng
   theo thứ tự; token màu nằm ở khối "Lớp màu" đầu tệp). ── */
/* Nút chính: gradient nhận diện thay cho mảng xanh phẳng. */
.tt-btn--primary { background: var(--tt-grad-brand); border-color: transparent; background-origin: border-box; box-shadow: 0 6px 16px -8px var(--tt-grad-shadow); }
.tt-btn--primary:hover { background: var(--tt-grad-brand); filter: brightness(1.08) saturate(1.1); border-color: transparent; }
html.dark .tt-btn--primary, html.dark .tt-btn--primary:hover { color: var(--tt-on-accent); }
/* Lựa chọn đang bật (trang hiện tại, bộ lọc, huy hiệu đếm) cũng mang gradient thay cho khối mực. */
.tt-page[aria-current], .tt-badge, .tt-opt input:checked + span, .tt-state-btn[aria-pressed="true"] { background: var(--tt-grad-brand); border-color: transparent; color: var(--tt-on-grad); }
html.dark .tt-page[aria-current], html.dark .tt-badge, html.dark .tt-opt input:checked + span, html.dark .tt-state-btn[aria-pressed="true"] { color: var(--tt-on-accent); }
/* Thẻ bài: vạch màu bên trái hiện khi rê chuột/focus — dẫn mắt vào thẻ đang chọn. */
.tt-entry::before { content: ""; position: absolute; left: 0; top: .9rem; bottom: .9rem; width: 3px; border-radius: 0 3px 3px 0; background: var(--tt-grad-brand); opacity: 0; transform: scaleY(.4); transition: opacity .25s, transform .35s var(--tt-ease); }
.tt-entry:hover::before, .tt-entry:focus-within::before { opacity: 1; transform: none; }
/* Thanh tìm dính: nền trong hơn để quầng màu phía sau vẫn thấy, không thành một dải xám. */
.tt-bar-wrap { background: color-mix(in srgb, var(--tt-ground) 72%, transparent); }
/* Chưa dính (đầu trang) thì trong suốt — tránh một dải nền lệch lề quanh ô tìm; chỉ có nền mờ khi đang dính. */
.tt-bar-wrap:not(.is-stuck) { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }

/* Tiêu đề trang: chữ tô gradient (mọi điểm dừng đều đạt tương phản trên nền sáng/tối). */
.tt-title { background: var(--tt-grad-brand); -webkit-background-clip: text; background-clip: text; color: transparent; }
@media (forced-colors: active) { .tt-title { background: none; color: CanvasText; } }

/* ── Làm mới 26/09/2026: hiện đại, sáng, có sức sống ── */
body { font-family: var(--tt-sans); -webkit-font-smoothing: antialiased; }
.tt-title, .tt-entry-title, .tt-h1, .tt-panel-title, .tt-card-title { letter-spacing: -.015em; }
.tt-title { font-weight: 700; }
.tt-entry-title { font-weight: 650; }
/* Thẻ, danh sách, bảng, tờ đọc: bóng mềm + viền nhạt hơn — "nổi" trên nền sáng. */
.tt-card, .tt-list, .tt-table-wrap, .tt-doc, .tt-empty { box-shadow: var(--tt-shadow-card); border-color: color-mix(in srgb, var(--tt-rule) 75%, transparent); }
.tt-empty { border-style: solid; }
/* Thẻ bấm được: nhấc nhẹ khi rê chuột. */
a.tt-card, .tt-card--link { transition: transform .25s var(--tt-ease), box-shadow .25s; }
a.tt-card:hover, .tt-card--link:hover { transform: translateY(-2px); box-shadow: var(--tt-shadow-hover); }
/* Nút: nhấc 1px khi rê, nút chính sáng lên nhẹ. */
.tt-btn { font-weight: 600; }
.tt-btn:hover { transform: translateY(-1px); }
.tt-btn:active { transform: translateY(0) scale(.98); }
/* Điều hướng chính: mục đang xem có nền nhấn bo tròn (kiểu ứng dụng hiện đại), rê chuột có nền nhạt. */
.tt-link { isolation: isolate; }
.tt-link::before { content: ""; position: absolute; inset: .6rem .1rem; z-index: -1; border-radius: var(--tt-r-sm); background: transparent; transition: background-color .2s; }
.tt-link:hover::before { background: var(--tt-sunk); }
.tt-nav .tt-link[aria-current="page"] { color: var(--tt-accent-strong); font-weight: 650; }
.tt-link[aria-current="page"]::before { background: var(--tt-accent-soft); }
.tt-top { background: color-mix(in srgb, var(--tt-paper) 82%, transparent) !important; }
/* Font mới rộng hơn font hệ thống: tên tài khoản dài làm thanh tràn 9px ở 1280px — giới hạn nút. */
.tt-nav .tt-user-btn { max-width: 11.5rem; }
@media (prefers-reduced-motion: reduce) {
  .tt-btn:hover, a.tt-card:hover, .tt-card--link:hover { transform: none; }
}

/* Khung trang: trải hết bề ngang, cùng một lề --tt-gutter cho thanh điều hướng, nội dung, chân trang. */
#app-main.container { max-width: none; padding-left: var(--tt-gutter); padding-right: var(--tt-gutter); }
.tt-top .tt-nav, .tt-foot .tt-foot-in { max-width: none; padding-left: var(--tt-gutter); padding-right: var(--tt-gutter); }
/* Thanh tìm dính kéo sát mép theo đúng lề trang mới. */
.tt-bar-wrap { margin: 0 calc(-1 * var(--tt-gutter)); padding-left: var(--tt-gutter); padding-right: var(--tt-gutter); }

/* Màn rộng: danh sách chia HAI CỘT để hiện nhiều tin hơn (Thinktanks, An ninh mạng, Báo cáo ngày,
   Hồ sơ). Mỗi ô vẫn đủ rộng để đọc; vạch ngăn dọc/ngang thay cho vạch ngang liên tục. */
@media (min-width: 1600px) {
  .tt-list, .tt-rp-list, .tt-hs-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tt-list > .tt-entry + .tt-entry, .tt-rp-list > .tt-rp-item + .tt-rp-item, .tt-hs-list > .tt-hs-card + .tt-hs-card { border-top: 0; }
  .tt-list > .tt-entry:nth-child(n+3), .tt-rp-list > .tt-rp-item:nth-child(n+3), .tt-hs-list > .tt-hs-card:nth-child(n+3) { border-top: 1px solid var(--tt-rule); }
  .tt-list > .tt-entry:nth-child(odd), .tt-rp-list > .tt-rp-item:nth-child(odd), .tt-hs-list > .tt-hs-card:nth-child(odd) { border-right: 1px solid var(--tt-rule); }
  .tt-entry { grid-template-columns: 9.5rem minmax(0, 1fr); }
}

/* Vạch cầu vồng mảnh dưới thanh điều hướng và trên chân trang. */
.tt-top { border-bottom: 0 !important; box-shadow: 0 1px 0 var(--tt-rule); }
.tt-top::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--tt-grad-line); opacity: .4; }
.tt-foot { position: relative; }
.tt-foot::before { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--tt-grad-line); opacity: .3; }
.tt-link::after { background: var(--tt-grad-line) !important; }
.tt-brand svg { color: transparent; stroke: url(#tt-brand-grad); }

/* ── Chuyển động ── */
@keyframes tt-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes tt-drop-in { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
@keyframes tt-pop { from { opacity: 0; transform: scale(.85); } to { opacity: 1; transform: none; } }
@keyframes tt-fade { from { opacity: 0; } }
@keyframes tt-fade-out { to { opacity: 0; } }
@keyframes tt-sheet-up { from { transform: translateY(100%); } }
@keyframes tt-sheet-down { to { transform: translateY(100%); } }
@keyframes tt-drawer-in { from { transform: translateX(100%); } }
@keyframes tt-drawer-out { to { transform: translateX(100%); } }
@keyframes tt-grow { from { transform: scaleX(0); } }
@keyframes tt-pulse { 50% { opacity: .3; } }
@keyframes tt-load { from { transform: translateX(-100%); } to { transform: translateX(300%); } }
@keyframes tt-dock-in { from { transform: translateY(calc(100% + 1.5rem)); opacity: 0; } }
@keyframes tt-spin { to { transform: rotate(360deg); } }
@keyframes tt-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@keyframes tt-toast-in { from { opacity: 0; transform: translateY(10px) scale(.98); } }
@keyframes tt-toast-out { to { opacity: 0; transform: translateY(6px); } }
@keyframes tt-dlg-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }

/* ── Chip chọn một phương án (.tt-pk) — /admin/bao-cao và Báo cáo › Dư luận ──
   Thay mọi <select> cũ bằng chip chọn: phương án ít (≤ 8) thì bày hết ra, mỗi phương án mang
   MỘT sắc độ riêng (lớp .tt-hue-N trên nhãn) — nhìn màu là nhận ra địa bàn/loại sự kiện, giống
   chấm màu ở danh sách hồ sơ. Ô radio phủ kín chip, trong suốt: vẫn nhận Tab + phím mũi tên. */
.tt-pick { display: flex; flex-wrap: wrap; gap: .4rem; }
.tt-pk { position: relative; display: inline-flex; }
.tt-pk input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.tt-pk span {
  display: inline-flex; align-items: center; gap: .45rem; min-height: 2.25rem; padding: 0 .85rem 0 .7rem;
  border: 1px solid var(--tt-rule); border-radius: 999px; background: var(--tt-paper);
  font-size: .8125rem; font-weight: 600; color: var(--tt-ink-2); white-space: nowrap;
  transition: background-color .18s, border-color .18s, color .18s, box-shadow .18s;
}
.tt-pk span::before {
  content: ""; width: .6rem; height: .6rem; flex: none; border-radius: 50%;
  background: var(--h-v, var(--tt-accent)); transition: box-shadow .18s;
}
.tt-pk:hover span { border-color: var(--h-rule, var(--tt-rule)); color: var(--tt-ink); }
.tt-pk input:checked + span {
  background: var(--h-soft, var(--tt-accent-soft)); border-color: var(--h, var(--tt-accent));
  color: var(--h, var(--tt-accent-strong)); font-weight: 650;
  box-shadow: 0 2px 10px -6px var(--h-v, var(--tt-accent));
}
.tt-pk input:checked + span::before { box-shadow: 0 0 0 3px color-mix(in srgb, var(--h-v, var(--tt-accent)) 28%, transparent); }
.tt-pk input:focus-visible + span { outline: 2px solid var(--h, var(--tt-accent)); outline-offset: 2px; }
.tt-pk input:disabled + span { opacity: .45; }
/* Kỳ báo cáo là mốc thời gian, không cần chấm màu; chữ số thẳng hàng. */
.tt-pick--plain .tt-pk span { padding-left: .85rem; font-variant-numeric: tabular-nums; }
.tt-pick--plain .tt-pk span::before { display: none; }
.tt-pick-fs { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: .45rem; }
.tt-pick-fs > legend { padding: 0; margin-bottom: .45rem; }
@media (prefers-reduced-motion: reduce) { .tt-pk span, .tt-pk span::before { transition: none; } }
