/* ===================================================================
   LOCAHOME — HỆ THỐNG GIAO DIỆN
   Định hướng: PropTech cao cấp. Nền sáng, Navy làm màu thương hiệu,
   Emerald làm màu hành động, Gold dùng cực kỳ tiết chế.
   Mobile-first: phần lớn người dùng vào từ điện thoại qua Zalo/Facebook/TikTok.
   =================================================================== */

/* ---------------------------------------------------------------- CHỮ
   Plus Jakarta Sans nếu có, không thì rơi về font hệ thống (SF Pro trên máy
   Apple, Segoe UI Variable trên Windows). Bản tự lưu trên máy chủ được ưu tiên
   trước bản trên Google Fonts — chạy `npm run vendor:fonts` để tải về.        */
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('/vendor/fonts/plus-jakarta-sans.woff2') format('woff2');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---- NỀN TẢNG THƯƠNG HIỆU ---- */
  --navy:      #0B132B;   /* Obsidian Navy: chữ tiêu đề, thanh bar, khối nhấn */
  --navy-2:    #1C2541;   /* Navy nhạt hơn, dùng cho gradient */
  --emerald:   #10B981;   /* màu hành động chính */
  --emerald-d: #04865E;   /* Emerald đậm: bản dùng được làm CHỮ trên nền trắng (4.59:1) */
  --emerald-s: #ECFDF5;   /* Emerald rất nhạt, nền khối mềm */
  --gold:      #D4AF37;   /* Champagne Gold: CHỈ dùng trên nền tối */
  --gold-d:    #93701B;   /* Gold đậm: bản DUY NHẤT được phép làm chữ trên nền sáng (4.59:1) */
  --gold-s:    #FBF6E7;

  /* ---- CHỮ VÀ ĐƯỜNG KẺ ---- */
  --ink:    #0B132B;      /* chữ chính */
  --ink-2:  #4B5563;      /* chữ phụ */
  --ink-3:  #8A94A6;      /* chữ mờ, nhãn */
  --line:   #E7EAEF;
  --line-2: #F1F3F7;

  /* ---- MẶT NỀN ---- */
  --bg:    #FFFFFF;       /* mặt thẻ */
  --bg-2:  #F8F9FA;       /* nền trang */
  --bg-3:  #F3F4F6;

  --good: #04865E;
  --warn: #B45309;
  --bad:  #DC2626;

  /* ---- BO GÓC ---- */
  --r-sm: 10px; --r: 14px; --r-lg: 20px; --r-xl: 28px;

  /* ---- ĐỔ BÓNG: mờ, rộng, gần như không thấy viền tối ----
     Đây là thứ tách một giao diện cao cấp khỏi một giao diện bình dân: bóng
     phải rộng và nhạt, không phải đậm và sát.                                */
  --sh-1: 0 1px 2px rgba(11,19,43,.04), 0 2px 8px rgba(11,19,43,.03);
  --sh-2: 0 8px 30px rgba(11,19,43,.06), 0 2px 6px rgba(11,19,43,.03);
  --sh-3: 0 20px 60px rgba(11,19,43,.12), 0 4px 12px rgba(11,19,43,.04);
  --sh-gold: 0 0 0 3px rgba(212,175,55,.28), 0 8px 24px rgba(212,175,55,.35);

  --font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'SF Pro Display',
          'Segoe UI Variable Display', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-num: 'SF Mono', 'JetBrains Mono', 'Roboto Mono', ui-monospace, 'Cascadia Mono',
              Menlo, Consolas, monospace;

  /* ---- VÙNG AN TOÀN ĐIỆN THOẠI (tai thỏ, thanh home) ---- */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* mặc định theo mảng Thuê */
  --brand: var(--emerald); --brand-d: var(--emerald-d);
  --brand-soft: var(--emerald-s); --brand-ink: #065F46;
}

/* Ba mảng kinh doanh dùng chung khung Navy, chỉ khác một màu nhấn.
   Mọi màu làm CHỮ trên nền trắng đều đã chọn bản đủ đậm để đạt tương phản
   WCAG AA 4.5:1 — bản tươi hơn chỉ dùng làm nền có chữ trắng đè lên. */
.theme-RENT { --brand: var(--emerald);  --brand-d: var(--emerald-d); --brand-soft: var(--emerald-s); --brand-ink: #065F46; }
.theme-STAY { --brand: #927031;         --brand-d: #7A5D28;         --brand-soft: var(--gold-s);    --brand-ink: #6B5220; }
.theme-SALE { --brand: #1E3A8A;         --brand-d: #172F6E;         --brand-soft: #EEF2FF;         --brand-ink: #1E3A8A; }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { margin: 0; padding: 0; height: 100%; }
body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg-2);
  font-size: 15px;
  line-height: 1.55;
  letter-spacing: -.005em;
  overscroll-behavior: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }
h1, h2, h3, h4 { margin: 0; line-height: 1.22; font-weight: 800; letter-spacing: -.025em; color: var(--navy); }

/* Mọi con số tiền/đo lường dùng chữ số đều bề rộng, để cột số không nhảy
   khi giá trị đổi và các hàng thẳng cột với nhau. */
b, strong, .num, td.num, th.num { font-variant-numeric: tabular-nums; }

/* ============================================================= THANH TRÊN */
.topbar {
  position: sticky; top: 0; z-index: 40;
  padding-top: var(--safe-t);
  background: rgba(255,255,255,.82);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--line);
}
.topbar-inner { display: flex; align-items: center; gap: 10px; padding: 10px 14px; min-width: 0; flex-wrap: wrap; }

/* Chiều cao thanh trên, dùng lại để tính chiều cao khung bản đồ. Để nó là biến
   thì đổi bố cục thanh trên không làm lệch bản đồ. */
:root { --topbar-h: 57px; }

/* Dưới 560px, ba mảng kinh doanh xuống hàng riêng chiếm trọn bề ngang.
   Nhồi logo + 3 mảng + nút tài khoản trên cùng một hàng ở khổ điện thoại làm
   chữ "Mua bán" bị cắt cụt — trông như lỗi hiển thị chứ không như nội dung
   cuộn được. */
@media (max-width: 559px) {
  :root { --topbar-h: 106px; }
  .vertical-tabs { order: 3; flex: 1 0 100%; }
  .topbar-inner { padding-bottom: 8px; row-gap: 8px; }
}

.logo { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }
.logo-mark { width: 32px; height: 32px; display: block; flex: 0 0 auto; }
.logo-text {
  display: inline; font-weight: 800; font-size: 17px;
  letter-spacing: .01em; text-transform: uppercase; color: var(--navy);
}
.logo-text .vn { color: var(--emerald); }
.topbar-links { margin-left: auto; display: none; gap: 6px; flex: 0 0 auto; }
@media (min-width: 720px) { .topbar-links { display: flex; } }

/* ==================================================== chuyển đổi 3 mảng */
.vertical-tabs {
  display: flex; gap: 2px; padding: 3px; background: var(--bg-3);
  border-radius: 999px; border: 1px solid transparent;
  min-width: 0; overflow-x: auto; scrollbar-width: none; flex: 1 1 auto;
}
.vertical-tabs::-webkit-scrollbar { display: none; }
.vtab {
  padding: 8px 14px; border-radius: 999px; font-size: 13.5px; font-weight: 600;
  color: var(--ink-2); white-space: nowrap; flex: 1 0 auto;
  transition: background .2s, color .2s, box-shadow .2s;
}
.vtab[aria-selected="true"] {
  background: var(--bg); color: var(--navy); font-weight: 700;
  box-shadow: 0 1px 3px rgba(11,19,43,.10);
}

/* ============================================================== BỐ CỤC */
.map-shell { position: relative; height: calc(100dvh - var(--topbar-h) - var(--safe-t)); overflow: hidden; }
#map, .map-canvas-wrap { position: absolute; inset: 0; }
.map-canvas-wrap canvas { width: 100%; height: 100%; display: block; touch-action: none; }

.map-overlay { position: absolute; z-index: 10; }
/* ------------------------------------------- THANH CÔNG CỤ TRÊN BẢN ĐỒ --
   Hai hàng, cùng chiều rộng, không bao giờ tự xuống dòng.

   Bản trước là `display:flex; flex-wrap:wrap` với bốn nút dài ngắn khác nhau,
   nên trình duyệt tự quyết định chỗ ngắt dòng theo độ dài chữ. Kết quả trên
   điện thoại là hai hàng so le mép phải — và nó còn đổi kiểu vỡ mỗi khi nhãn
   sắp xếp đổi độ dài. Lưới hai hàng cố định thì trông giống nhau ở mọi máy. */
.map-tools {
  top: 12px; left: 12px; right: 12px;
  display: grid; gap: 8px; justify-items: stretch;
}
.tool-primary { width: 100%; justify-content: center; font-weight: 650; }

/* Ba ô bằng nhau trong một viên thuốc liền. Nền và viền đặt ở khối bao ngoài
   để ba ô trông như một vật thể, không phải ba nút dính nhau. */
.tool-seg {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-radius: 999px; overflow: hidden;
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(11,19,43,.06); box-shadow: var(--sh-1);
}
.tool-seg .chip {
  border-radius: 0; border: 0; box-shadow: none; background: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  justify-content: center; padding: 9px 6px; gap: 5px; min-width: 0;
}
.tool-seg .chip + .chip { box-shadow: inset 1px 0 0 rgba(11,19,43,.08); }
/* Nhãn sắp xếp có thể dài hơn ô; cắt bằng dấu ba chấm thay vì đẩy vỡ lưới. */
.tool-seg .chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tool-seg .chip .ic { flex: 0 0 auto; }
.tool-seg .chip.active { background: var(--navy); color: #fff; box-shadow: none; }
.tool-seg .chip.active + .chip { box-shadow: none; }

/* Màn hình rộng: một hàng duy nhất, căn trái, không kéo giãn hết chiều ngang. */
@media (min-width: 620px) {
  .map-tools { grid-auto-flow: column; justify-content: start; align-items: start; }
  .tool-primary { width: auto; }
  .tool-seg { grid-template-columns: repeat(3, auto); }
  .tool-seg .chip { padding: 9px 15px; }
}

/* Màn hình rất hẹp: bỏ chữ ở hai ô phụ, giữ biểu tượng. Chữ bị cắt còn hai ký
   tự thì vô nghĩa hơn hẳn so với một biểu tượng rõ ràng. */
@media (max-width: 340px) {
  .tool-seg .chip#btn-filter span, .tool-seg .chip#btn-poi span { display: none; }
}
.map-tools-right { position: absolute; right: 12px; bottom: 206px; display: grid; gap: 8px; z-index: 10; }

/* ================================================================ CHIP */
.chip {
  display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto;
  padding: 9px 15px; border-radius: 999px; background: rgba(255,255,255,.92);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(11,19,43,.06); box-shadow: var(--sh-1);
  font-size: 13px; font-weight: 600; color: var(--navy); white-space: nowrap;
  min-height: 38px; transition: transform .16s, box-shadow .16s;
}
.chip:active { transform: scale(.97); }
.chip.active { background: var(--navy); color: #fff; border-color: var(--navy); }
.chip.active .ic { stroke: #fff; }
.chip.ghost { background: rgba(255,255,255,.92); }

.fab {
  width: 44px; height: 44px; border-radius: 50%; background: rgba(255,255,255,.94);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  box-shadow: var(--sh-2); display: grid; place-items: center;
  border: 1px solid rgba(11,19,43,.06); color: var(--navy);
  font-size: 17px; font-weight: 600; transition: transform .16s;
}
.fab:active { transform: scale(.94); }
.fab.primary { background: var(--navy); color: #fff; border-color: var(--navy); }
.fab.primary .ic { stroke: #fff; }

/* ==================================================== ICON NÉT ĐƠN SẮC
   Toàn bộ icon tiện ích là SVG nét, một màu, thừa hưởng màu chữ xung quanh.
   Không dùng emoji: emoji mỗi hệ điều hành vẽ một kiểu, màu sặc sỡ, và phá vỡ
   nhịp thị giác của một giao diện cao cấp.                                   */
.ic {
  width: 18px; height: 18px; flex: 0 0 auto;
  /* inline-block chứ không phải block: icon hay nằm xen giữa chữ (sao đánh giá,
     nhãn phương tiện). Để display:block là nó tự xuống dòng riêng, tách khỏi
     đoạn chữ đi kèm. Trong hộp flex thì thuộc tính này bị bỏ qua nên nút bấm
     không đổi gì. */
  display: inline-block; vertical-align: -.18em;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.ic-lg { width: 22px; height: 22px; stroke-width: 1.5; }
.ic-sm { width: 15px; height: 15px; stroke-width: 1.7; }

/* ========================================================= BẢNG TRƯỢT */
/* Vị trí của bảng do biến `--sheet-y` quyết định, và `--keo` là phần dịch
   thêm theo ngón tay trong lúc kéo. Tách làm hai biến vì lúc kéo mà ghi đè
   thẳng `transform` thì bảng nhảy vọt lên đỉnh màn hình ngay khi chạm tay —
   mỗi trạng thái có một vị trí gốc khác nhau. */
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--bg); border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: var(--sh-3); max-height: 88%;
  display: flex; flex-direction: column;
  --sheet-y: calc(100% - 182px);
  transform: translateY(calc(var(--sheet-y) + var(--keo, 0px)));
  transition: transform .32s cubic-bezier(.32,.72,0,1);
}
.sheet.peek   { --sheet-y: calc(100% - 182px); }
.sheet.half   { --sheet-y: 38%; }
.sheet.full   { --sheet-y: 0px; }
.sheet.hidden { --sheet-y: 100%; }

/* `touch-action: none` là dòng quan trọng nhất ở đây. Thiếu nó, trình duyệt
   có quyền hiểu cú vuốt dọc trên tay cầm là cuộn trang — và khi nó quyết định
   như vậy thì nó HUỶ chuỗi sự kiện con trỏ, `pointerup` không bao giờ tới,
   bảng không nhúc nhích. Đó là cái "dính" lúc được lúc không.
   Vùng chạm cũng được nới cao hơn: tay cầm cũ chỉ cao chừng 24px. */
.sheet-grip {
  padding: 14px 0 10px; display: grid; place-items: center;
  cursor: grab; flex: 0 0 auto; touch-action: none; user-select: none;
}
.sheet-grip:active { cursor: grabbing; }
.sheet-grip i { width: 44px; height: 5px; border-radius: 99px; background: var(--line); display: block; }
.sheet-body {
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0 16px calc(28px + var(--safe-b));
  scroll-behavior: smooth;
}

/* ====================================================== THẺ TIN ĐĂNG */
.card-row {
  display: flex; gap: 13px; padding: 14px 0; border-bottom: 1px solid var(--line-2);
  transition: opacity .15s;
}
.card-row:last-child { border-bottom: none; }
.card-row:active { opacity: .6; }
.card-thumb {
  width: 108px; height: 82px; border-radius: var(--r); object-fit: cover;
  background: var(--line-2); flex: 0 0 auto;
}
.card-main { min-width: 0; flex: 1; }
.card-title {
  font-weight: 700; font-size: 14.5px; line-height: 1.35; color: var(--navy);
  letter-spacing: -.015em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card-addr {
  color: var(--ink-3); font-size: 12.5px; margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card-price {
  color: var(--navy); font-weight: 800; font-size: 16px; margin-top: 5px;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.card-price small { font-weight: 600; color: var(--ink-3); font-size: 12px; letter-spacing: 0; }
.card-meta { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 6px; font-size: 12px; color: var(--ink-2); }

/* =============================================================== NHÃN */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 7px; font-size: 11.5px; font-weight: 650;
  background: var(--bg-3); color: var(--ink-2);
  align-self: flex-start; flex: 0 0 auto; line-height: 1.35;
  letter-spacing: -.005em;
}
.badge.loca { background: var(--brand-soft); color: var(--brand-ink); }
.badge.good { background: #E7F7EF; color: #065F46; }
.badge.warn { background: #FDF3E3; color: #7C4A0B; }
.badge.bad  { background: #FDECEC; color: #991B1B; }
/* Nhãn hạng sang: dành riêng cho tin nổi bật. Gold trên nền Navy — đây là một
   trong ba chỗ duy nhất trong toàn hệ thống được dùng màu vàng. */
.badge.lux {
  background: linear-gradient(135deg, var(--navy), var(--navy-2));
  color: var(--gold); border: 1px solid rgba(212,175,55,.35);
}

/* ================================================ GHIM GIÁ TRÊN BẢN ĐỒ */
/* Ghim giá: NỀN NAVY CHỮ TRẮNG.
   Bản trước dùng nền trắng viền xám — trên nền bản đồ xám nhạt nó gần như hoà
   vào nhau và trông y hệt một nút bấm giao diện thường. Khối tối đặc trên nền
   sáng mới tạo được lớp phân tầng rõ, đúng cách Airbnb và Realtor.com làm.
   Chữ số để 650 chứ không phải 750: nét mảnh hơn trên nền tối trông đắt hơn,
   nền tối vốn đã làm chữ dày lên về mặt thị giác. */
.price-pin {
  position: absolute; transform: translate(-50%, -100%); z-index: 5;
  background: var(--navy); border: 1px solid rgba(255,255,255,.14); color: #fff;
  padding: 6px 12px; border-radius: 999px;
  font-size: 12.5px; font-weight: 650; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 2px 10px rgba(11,19,43,.28), 0 1px 3px rgba(11,19,43,.20);
  white-space: nowrap; cursor: pointer;
  transition: transform .18s cubic-bezier(.34,1.56,.64,1), background .18s, color .18s, box-shadow .18s;
}
.price-pin:hover { transform: translate(-50%,-100%) scale(1.06); }
/* Tin đã xem: mờ đi để mắt tự bỏ qua, nhưng vẫn đọc được */
.price-pin.seen { background: rgba(11,19,43,.55); color: rgba(255,255,255,.82); }
/* Ghim đang được chọn: phóng to nhẹ, đổi sang Navy nền Gold chữ, có quầng sáng.
   Chỉ đúng MỘT ghim trên bản đồ được ở trạng thái này tại một thời điểm. */
/* Ghim đang chọn: ĐẢO NGƯỢC hẳn sang nền vàng chữ Navy. Khi mọi ghim đều là
   khối tối, muốn một ghim nổi bật thì phải đổi cực sáng chứ không thể chỉ đổi
   sắc — đó là lý do bản trước (Navy nền, chữ vàng) không đủ khác biệt nữa. */
.price-pin.active {
  background: var(--gold); color: var(--navy); border-color: rgba(255,255,255,.5);
  font-weight: 800;
  transform: translate(-50%,-100%) scale(1.16);
  box-shadow: var(--sh-gold); z-index: 9;
}
.price-pin.cluster {
  background: var(--navy-2); color: #fff; padding: 7px 13px;
  border-color: rgba(255,255,255,.2); font-weight: 750;
}
.poi-pin {
  position: absolute; transform: translate(-50%,-50%); z-index: 4;
  width: 28px; height: 28px; border-radius: 50%; background: var(--bg);
  border: 1px solid rgba(11,19,43,.08); box-shadow: var(--sh-1);
  display: grid; place-items: center; cursor: pointer; color: var(--ink-2);
}
.poi-pin .ic { width: 15px; height: 15px; }
.home-pin {
  position: absolute; transform: translate(-50%,-100%); z-index: 8;
  width: 36px; height: 36px; border-radius: 50% 50% 50% 4px; rotate: -45deg;
  background: var(--navy); border: 3px solid #fff; box-shadow: var(--sh-2);
}
.home-pin::after {
  content: ''; position: absolute; inset: 9px; border-radius: 50%; background: var(--gold);
}
.dest-pin {
  position: absolute; transform: translate(-50%,-50%); z-index: 7;
  padding: 5px 10px; border-radius: 9px; background: var(--navy); color: #fff;
  font-size: 11.5px; font-weight: 650; box-shadow: var(--sh-2); white-space: nowrap;
}

/* ==================================================== ĐIỂM LOCASCORE
   Vòng điểm là nơi duy nhất trên nền sáng được dùng sắc vàng, và chỉ khi điểm
   đạt mức xuất sắc — nhờ hiếm nên nó mới có sức nặng.                        */
.score-ring { --v: 0; width: 66px; height: 66px; position: relative; flex: 0 0 auto; }
.score-ring::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--sc, var(--emerald)) calc(var(--v) * 1%), var(--line-2) 0);
}
.score-ring::after {
  content: ''; position: absolute; inset: 6px; border-radius: 50%; background: var(--bg);
  /* Bóng đổ vào trong làm vòng tròn nổi khỏi mặt giấy thay vì nằm phẳng trên đó */
  box-shadow: 0 2px 8px rgba(11,19,43,.10) inset, 0 1px 2px rgba(11,19,43,.06);
}
.score-ring b {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 19px; font-weight: 800; z-index: 1; color: var(--navy);
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.score-ring { filter: drop-shadow(0 4px 12px rgba(11,19,43,.10)); }
.score-ring.elite { filter: drop-shadow(0 4px 14px rgba(212,175,55,.38)); }
.score-ring.elite::before { background: conic-gradient(var(--gold) calc(var(--v) * 1%), var(--line-2) 0); }

/* Nhãn cạnh vòng điểm ("Vị trí xuất sắc" + dòng giải thích). Bản trước để 750
   và màu nhạt nên trên màn hình điện thoại ngoài sáng gần như không đọc được. */
.score-label b { display: block; font-size: 14.5px; font-weight: 800; letter-spacing: -.02em; }
.score-label span { display: block; font-size: 12px; color: var(--ink-2); font-weight: 500; margin-top: 1px; }
.score-bar { height: 5px; border-radius: 99px; background: var(--line-2); overflow: hidden; }
.score-bar i { display: block; height: 100%; border-radius: 99px; background: var(--emerald); transition: width .5s ease; }

/* =============================================================== KHỐI */
.panel {
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 16px; margin: 14px 0; box-shadow: var(--sh-1);
}
.panel-title {
  font-size: 11px; font-weight: 750; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .09em; margin-bottom: 12px;
}
.row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 0; }
.row + .row { border-top: 1px solid var(--line-2); }
.muted { color: var(--ink-3); font-size: 12.5px; }
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(146px,1fr)); gap: 12px; }
.kpi { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r); padding: 14px; box-shadow: var(--sh-1); }
.kpi b { display: block; font-size: 23px; letter-spacing: -.03em; margin-top: 3px; color: var(--navy); }

/* ================================================= HOÁ ĐƠN CHI PHÍ
   Khối tổng chi phí ở thực tế được dựng theo lối hoá đơn điện tử: số dùng font
   đều bề rộng, các dòng ngăn bằng nét đứt mảnh, dòng tổng nằm trên nền Navy.
   Mục tiêu là tạo cảm giác minh bạch tài chính, không phải trang trí.        */
.invoice { padding: 4px 0 0; }
.invoice-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px dashed var(--line);
}
.invoice-line:last-of-type { border-bottom: none; }
.invoice-line .lbl { font-size: 13.5px; color: var(--ink-2); min-width: 0; }
.invoice-line .lbl small { color: var(--ink-3); font-size: 12px; }
.invoice-line .amt {
  font-family: var(--font-num); font-size: 13.5px; font-weight: 600;
  color: var(--navy); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.invoice-total {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 12px; padding: 14px 16px; border-radius: var(--r);
  background: linear-gradient(135deg, var(--navy), var(--navy-2)); color: #fff;
}
.invoice-total .lbl { font-size: 12.5px; font-weight: 650; color: rgba(255,255,255,.72);
  text-transform: uppercase; letter-spacing: .07em; }
.invoice-total .amt {
  font-family: var(--font-num); font-size: 20px; font-weight: 700; color: var(--gold);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.invoice-note { margin-top: 10px; font-size: 12px; color: var(--ink-3); line-height: 1.5; }

/* =========================================== ĐẶC QUYỀN THÀNH VIÊN (phí)
   Khối so sánh phí môi giới. Nền Navy chuyển đen, chữ trắng, con số tiết kiệm
   màu Gold — chỗ thứ ba và cũng là chỗ cuối cùng dùng vàng.                  */
.privilege {
  border-radius: var(--r-lg); padding: 18px; margin: 14px 0; color: #fff;
  background: linear-gradient(135deg, #0B132B 0%, #16203D 55%, #05070F 100%);
  box-shadow: var(--sh-2); position: relative; overflow: hidden;
}
.privilege::after {
  content: ''; position: absolute; top: -60%; right: -30%;
  width: 260px; height: 260px; border-radius: 50%;
  background: radial-gradient(circle, rgba(212,175,55,.16), transparent 70%);
  pointer-events: none;
}
.privilege-eyebrow {
  font-size: 10.5px; font-weight: 750; letter-spacing: .14em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 8px;
}
.privilege h3 { color: #fff; font-size: 17px; letter-spacing: -.02em; margin-bottom: 14px; }
.privilege .row { border: none; padding: 7px 0; }
.privilege .row + .row { border-top: 1px solid rgba(255,255,255,.08); }
.privilege .row span { color: rgba(255,255,255,.68); font-size: 13.5px; }
.privilege .row b { color: #fff; font-variant-numeric: tabular-nums; }
/* Hai lớp này phải thắng `.privilege .row b` ở trên, nên viết kèm `b` cho đủ
   độ ưu tiên. Thiếu chữ `b` thì số tiền tiết kiệm ra màu trắng như mọi số khác
   và cả khối mất điểm nhấn — đúng chỗ quan trọng nhất lại chìm nhất. */
.privilege .row b.strike { color: rgba(255,255,255,.42); text-decoration: line-through; font-weight: 600; }
.privilege .row b.save { color: var(--gold); font-weight: 800; font-size: 17px; }
.privilege .fine { margin-top: 12px; font-size: 11.5px; color: rgba(255,255,255,.5); line-height: 1.5; }

/* ============================================ CAM KẾT VỚI NGƯỜI ĐI THUÊ
   Khối này thay cho bảng so sánh hoa hồng từng đặt nhầm ở màn hình khách.
   Thông điệp ở đây là "bạn không mất phí" — nên giữ tông bình thản, sạch sẽ.
   Dùng nền vàng hay gradient cho nó là phản tác dụng: trông như đang chào bán
   một gói dịch vụ, đúng cái hiểu nhầm cần tránh. */
/* Nền kem ấm + viền vàng nhạt. Nền xanh lá nhạt của bản trước làm khối này
   trông như một thông báo trạng thái hệ thống; nền kem đưa nó về đúng nhóm
   "cam kết của thương hiệu". Đây là chỗ thứ tư và cuối cùng được chạm tới sắc
   vàng, và cũng chỉ ở mức viền với icon, không phải mảng lớn. */
.assurance {
  border-color: rgba(212,175,55,.32);
  background: linear-gradient(160deg, #FDFBF7 0%, #FFFDF9 55%, #FFFFFF 100%);
  box-shadow: var(--sh-2);
}
.assurance-head { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.assurance-head .ic { color: var(--gold-d); stroke-width: 1.7; }
.assurance-head b { font-size: 15.5px; color: var(--navy); letter-spacing: -.025em; }
.assurance p { margin: 0; font-size: 13.5px; color: var(--ink-2); line-height: 1.6; }
.assurance-list {
  display: flex; flex-wrap: wrap; gap: 9px 18px; margin-top: 14px;
  padding-top: 13px; border-top: 1px dashed rgba(212,175,55,.35);
}
.assurance-list span {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 650; color: var(--navy);
}
/* Icon khiên nhỏ màu vàng đậm thay cho dấu tích xanh: dấu tích nói "đã xong",
   chiếc khiên nói "bạn được bảo vệ" — đúng thông điệp cần truyền hơn. */
.assurance-list .ic { color: var(--gold-d); stroke-width: 1.9; }

/* ================================================ CHỌN VAI KHI ĐĂNG KÝ */
.role-grid { display: grid; gap: 10px; }
.auth-sep { display: flex; align-items: center; gap: 12px; margin: 14px 0 10px; }
.auth-sep::before, .auth-sep::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.auth-sep span { font-size: 12px; color: var(--ink-3); }
/* Thay cho nút "Chưa có tài khoản? Đăng ký". Một dòng chữ nói rõ là không cần
   bấm gì thêm, thay vì một nút dẫn tới đúng cái ô nhập đang hiện ngay trên đó. */
/* Hàng công tắc bật/tắt trong bảng cài đặt. */
.switch-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--line-2); cursor: pointer;
}
.switch-row:last-of-type { border-bottom: 0; }
.switch-row > span { min-width: 0; }
.switch-row b { display: block; font-size: 13.5px; color: var(--navy); }
.switch-row em {
  display: block; font-style: normal; font-size: 12px; color: var(--ink-3);
  margin-top: 2px; line-height: 1.45;
}
/* Công tắc trượt, dựng từ chính ô đánh dấu để giữ được thao tác bàn phím và
   trình đọc màn hình — vẽ một cái nút giả bằng div là mất cả hai. */
.switch-row input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; flex: 0 0 auto;
  width: 44px; height: 26px; border-radius: 999px; background: var(--bg-3);
  border: 1px solid var(--line); position: relative; cursor: pointer;
  transition: background .2s, border-color .2s;
}
.switch-row input[type="checkbox"]::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px;
  border-radius: 50%; background: #fff; box-shadow: var(--sh-1);
  transition: transform .2s;
}
.switch-row input[type="checkbox"]:checked { background: var(--emerald-d); border-color: var(--emerald-d); }
.switch-row input[type="checkbox"]:checked::after { transform: translateX(18px); }
.switch-row input[type="checkbox"]:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }

/* ================================================ BANNER THÔNG BÁO SỐNG ==
   Trượt xuống từ mép trên, ngay dưới thanh trên. Trên điện thoại chiếm gần hết
   bề ngang để đọc được bằng mắt liếc; trên máy tính neo về bên phải để không
   che nội dung đang xem. */
.noti-stack {
  position: fixed; z-index: 90;
  top: calc(var(--topbar-h) + var(--safe-t) + 8px);
  left: 10px; right: 10px;
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}
@media (min-width: 640px) {
  .noti-stack { left: auto; width: 380px; right: 16px; }
}

.noti-card {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 11px; text-align: left; width: 100%;
  padding: 13px 14px; border-radius: var(--r-lg);
  background: rgba(255,255,255,.97);
  backdrop-filter: saturate(180%) blur(16px); -webkit-backdrop-filter: saturate(180%) blur(16px);
  border: 1px solid var(--line); box-shadow: var(--sh-3);
  animation: noti-vao .34s cubic-bezier(.2,.9,.3,1.2);
  position: relative; overflow: hidden;
}
/* Vạch màu bên trái nói loại việc mà không cần đọc chữ. */
.noti-card::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--ink-3);
}
.noti-viec::before { background: var(--emerald); }
.noti-tien::before { background: var(--gold); }
.noti-xong::before { background: var(--emerald); }
.noti-nhac::before { background: var(--warn); }
.noti-loi::before  { background: var(--bad); }

.noti-card.di { animation: noti-ra .38s ease forwards; }
@keyframes noti-vao { from { opacity: 0; transform: translateY(-14px) scale(.97); } }
@keyframes noti-ra  { to   { opacity: 0; transform: translateY(-10px) scale(.98); } }

.noti-ic {
  width: 36px; height: 36px; border-radius: 10px; flex: 0 0 auto;
  display: grid; place-items: center; color: #fff; background: var(--navy);
}
.noti-viec .noti-ic { background: linear-gradient(135deg, var(--emerald-d), var(--emerald)); }
.noti-tien .noti-ic { background: linear-gradient(135deg, #93701B, var(--gold)); }

.noti-body { min-width: 0; flex: 1; display: block; }
.noti-body b { display: block; font-size: 14px; color: var(--navy); letter-spacing: -.015em; }
.noti-body span {
  display: block; font-size: 12.5px; color: var(--ink-2); margin-top: 3px; line-height: 1.45;
}
.noti-close {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; color: var(--ink-3);
  transform: rotate(45deg);           /* dấu + thành dấu × */
}
.noti-close:hover { background: var(--bg-3); color: var(--ink); }

.build-tag { margin-top: 14px; text-align: center; font-size: 11px; color: var(--ink-3);
  letter-spacing: .04em; -webkit-user-select: text; user-select: text; }
.auth-note { margin: 10px 2px 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); text-align: center; }

/* Câu lệnh để người dùng chép đi chạy. Cho phép bôi đen (nhiều nơi khác trong
   ứng dụng đã tắt) và cho cuộn ngang thay vì tự xuống dòng — lệnh bị ngắt giữa
   chừng mà chép nguyên si là chạy sai. */
pre.cmd {
  margin: 0; padding: 10px 12px; border-radius: var(--r-md);
  background: var(--navy); color: #E9EDF5;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px; line-height: 1.5;
  overflow-x: auto; white-space: pre; -webkit-user-select: text; user-select: text;
}
code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: .92em; background: var(--bg-2); padding: 1px 5px; border-radius: 5px;
  -webkit-user-select: text; user-select: text;
}
.role-card {
  display: flex; gap: 13px; align-items: flex-start; text-align: left;
  padding: 15px; border-radius: var(--r-lg); background: var(--bg);
  border: 1px solid var(--line); box-shadow: var(--sh-1); width: 100%;
  transition: border-color .18s, box-shadow .18s, transform .18s;
}
.role-card:hover { border-color: var(--navy); box-shadow: var(--sh-2); }
.role-card:active { transform: scale(.99); }
.role-ic {
  width: 42px; height: 42px; border-radius: 12px; flex: 0 0 auto;
  display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, var(--navy), var(--navy-2));
}
.role-body { min-width: 0; display: block; }
.role-body b { display: block; font-size: 15.5px; color: var(--navy); letter-spacing: -.02em; }
.role-body em {
  display: block; font-style: normal; font-size: 12.5px; font-weight: 650;
  color: var(--emerald-d); margin-top: 2px;
}
.role-body span { display: block; font-size: 12.5px; color: var(--ink-2); margin-top: 6px; line-height: 1.5; }

/* Lối đăng nhập nhanh cho người quay lại — đặt trên ba thẻ vai trò.
   Nền Navy để tách hẳn khỏi ba thẻ trắng bên dưới: đây là "vào thẳng tài khoản
   cũ", không phải "chọn thêm một vai trò mới". */
.quick-login {
  display: flex; gap: 13px; align-items: center; text-align: left; width: 100%;
  padding: 15px; border-radius: var(--r-lg);
  background: linear-gradient(135deg, var(--navy), var(--navy-2));
  border: 1px solid var(--navy); box-shadow: var(--sh-2);
  transition: box-shadow .18s, transform .18s;
}
.quick-login:active { transform: scale(.99); }
.quick-login .role-ic { background: rgba(255,255,255,.14); }
.quick-login .role-body b { color: #fff; }
.quick-login .role-body em { color: #9FE8C8; font-weight: 600; }

/* ============================================ ĐỊNH DANH & ĐIỀU PHỐI */
/* Ô tải ảnh giấy tờ */
.upload-slot + .upload-slot { margin-top: 8px; }
.upload-btn {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 13px 14px; border-radius: var(--r); background: var(--bg-2);
  border: 1.5px dashed var(--line); color: var(--ink-2); min-height: 60px;
}
.upload-btn.done { border-style: solid; border-color: var(--emerald-d); background: var(--emerald-s); }
.upload-btn.done .ic { color: var(--emerald-d); }
.upload-btn b { display: block; font-size: 14px; color: var(--navy); }
.upload-btn em { display: block; font-style: normal; font-size: 12px; color: var(--ink-3); margin-top: 2px; }

/* Cam kết phạm vi công việc */
.scope-box { background: linear-gradient(160deg, #FDFBF7, #FFFFFF); border-color: rgba(212,175,55,.3); }
.scope-list { margin: 6px 0 14px; padding-left: 18px; font-size: 13px; line-height: 1.6; color: var(--ink-2); }
.scope-list.ok li::marker { color: var(--emerald-d); }
.scope-list.no li::marker { color: var(--bad); }
.scope-list.no li { color: var(--navy); font-weight: 600; }
.scope-ack {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 12px;
  padding: 12px; border-radius: var(--r); background: var(--bg-2); cursor: pointer;
}
.scope-ack input { width: 20px; height: 20px; margin: 0; flex: 0 0 auto; accent-color: var(--navy); }
.scope-ack span { font-size: 13px; font-weight: 600; color: var(--navy); }

/* Danh sách lỗi biểu mẫu — hiện tất cả cùng lúc, không bắt sửa từng cái */
.form-errors { border-color: var(--bad); background: #FEF5F5; }
.form-errors b { color: var(--bad); font-size: 14px; }
.form-errors ul { margin: 8px 0 0; padding-left: 18px; font-size: 13px; color: var(--ink-2); line-height: 1.7; }

/* Hàng chọn (lý do từ chối, chọn CTV) */
.pick-row {
  display: flex; gap: 11px; align-items: flex-start; cursor: pointer;
  padding: 12px 13px; border-radius: var(--r); border: 1px solid var(--line);
  background: var(--bg); min-height: 46px;
}
.pick-row:has(input:checked) { border-color: var(--navy); background: var(--bg-2); }
.pick-row input { width: 19px; height: 19px; margin: 0; flex: 0 0 auto; accent-color: var(--navy); }
.pick-row > span { font-size: 13.5px; }
.agent-pick b { display: block; font-size: 14px; color: var(--navy); display: flex;
  align-items: center; gap: 6px; flex-wrap: wrap; }
.agent-pick em { display: block; font-style: normal; font-size: 12px; color: var(--ink-2); margin-top: 3px; }
.agent-pick.declined { opacity: .55; }
.warn-line {
  display: block; font-style: normal; font-size: 11.5px; margin-top: 5px;
  color: var(--bad); font-weight: 600;
}
.warn-line.gold { color: var(--gold-d); }

/* Hàng chờ điều phối */
.dispatch-row.overdue { border-color: var(--bad); box-shadow: 0 0 0 3px rgba(220,38,38,.06); }
.decline-note {
  margin-top: 8px; padding: 8px 10px; border-radius: var(--r-sm);
  background: #FEF5F5; color: var(--bad); font-size: 12px; font-weight: 600;
  display: flex; gap: 6px; align-items: flex-start;
}

/* Bảng thông tin hồ sơ KYC */
.kyc-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-2);
}
.kyc-grid span { display: block; font-size: 11px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); font-weight: 700; }
.kyc-grid b { display: block; font-size: 13.5px; color: var(--navy); margin-top: 2px;
  word-break: break-word; }
.kyc-shots { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.kyc-shots a { display: block; width: 96px; }
.kyc-shots img {
  width: 96px; height: 68px; object-fit: cover; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--bg-3); display: block;
}
.kyc-shots span { display: block; font-size: 11px; color: var(--ink-3); margin-top: 4px; text-align: center; }

/* ================================================== ẢNH TRONG TIN ĐĂNG */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
.photo-cell { position: relative; border-radius: var(--r); overflow: hidden; aspect-ratio: 4/3; }
.photo-cell img { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--bg-3); }
.photo-cell.cover { outline: 2px solid var(--navy); outline-offset: -2px; }
.photo-tag {
  position: absolute; left: 6px; top: 6px; padding: 3px 8px; border-radius: 6px;
  background: var(--navy); color: var(--gold); font-size: 10.5px; font-weight: 700;
}
/* Nút xoá dùng icon dấu cộng xoay 45° — một hình dùng cho hai việc, đỡ phải
   nuôi thêm một icon chỉ để làm dấu X. */
.photo-del {
  position: absolute; right: 5px; top: 5px; width: 26px; height: 26px; border-radius: 50%;
  background: rgba(11,19,43,.72); color: #fff; display: grid; place-items: center;
  backdrop-filter: blur(6px);
}
.photo-del .ic { transform: rotate(45deg); stroke-width: 2.2; }
.photo-cover {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 5px;
  background: rgba(11,19,43,.72); color: #fff; font-size: 10.5px; font-weight: 650;
  backdrop-filter: blur(6px); opacity: 0; transition: opacity .16s;
}
.photo-cell:hover .photo-cover, .photo-cell:active .photo-cover { opacity: 1; }
@media (pointer: coarse) { .photo-cover { opacity: 1; } }
.photo-empty {
  grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 26px 18px; border: 1.5px dashed var(--line); border-radius: var(--r);
  color: var(--ink-3); text-align: center; font-size: 12.5px;
}

/* ============================================ LỘ TRÌNH HAI LỚP */
.route-layer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 8px; padding-bottom: 7px; border-bottom: 1px solid var(--line-2);
}
.route-layer-name {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 750; letter-spacing: .06em;
  text-transform: uppercase; color: var(--navy);
}
.route-toggle { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.route-toggle input { width: 15px; height: 15px; margin: 0; accent-color: var(--navy); }
.route-toggle span { font-size: 11.5px; color: var(--ink-3); }

.route-row {
  display: flex; align-items: center; gap: 10px; padding: 9px 0; cursor: pointer;
  border-bottom: 1px solid var(--line-2);
}
.route-row:last-of-type { border-bottom: none; }
.route-row:active { opacity: .6; }
.route-row b { font-size: 13.5px; color: var(--navy); font-weight: 700; }
/* Chấm màu khớp đúng màu tuyến vẽ trên bản đồ — đó là thứ duy nhất nối dòng
   trong danh sách với đường trên bản đồ. */
.route-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.route-ic {
  width: 26px; height: 26px; border-radius: 8px; flex: 0 0 auto;
  display: grid; place-items: center; background: var(--bg-3); color: var(--ink-2);
}
.route-row.essential b { font-weight: 600; }
.route-time { text-align: right; flex: 0 0 auto; }
.route-time b { display: block; font-size: 15px; font-variant-numeric: tabular-nums; }
.route-time span { display: block; font-size: 11px; color: var(--ink-3); }
.route-summary {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px; padding-top: 10px; border-top: 1.5px solid var(--line);
  font-size: 13.5px;
}
.route-invite {
  padding: 16px; border-radius: var(--r); background: var(--bg-2);
  border: 1.5px dashed var(--line);
}
.route-invite b { display: block; font-size: 14.5px; color: var(--navy); }
.route-invite p { margin: 6px 0 12px; font-size: 13px; color: var(--ink-2); line-height: 1.55; }

/* ============================================================ NÚT BẤM */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 20px; border-radius: var(--r); font-weight: 700; font-size: 14.5px;
  letter-spacing: -.01em; background: var(--navy); color: #fff;
  border: 1px solid transparent; min-height: 46px;
  transition: transform .16s, box-shadow .16s, filter .16s;
}
.btn:active { transform: scale(.985); }
.btn:hover { filter: brightness(1.12); }
.btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }
.btn.block { width: 100%; }
.btn.accent { background: var(--emerald); }
.btn.ghost { background: var(--bg); color: var(--navy); border-color: var(--line); box-shadow: var(--sh-1); }
.btn.soft { background: var(--brand-soft); color: var(--brand-ink); }
.btn.danger { background: var(--bad); }
.btn.sm { padding: 8px 14px; font-size: 13px; border-radius: var(--r-sm); min-height: 38px; }
.btn .ic { stroke: currentColor; }

/* Thanh hành động cố định đáy màn hình, nền kính mờ.
   Đệm thêm safe-area để nút không nằm dưới thanh home của iPhone.           */
.action-bar {
  position: sticky; bottom: 0; z-index: 15;
  margin: 16px -16px 0; padding: 14px 16px calc(14px + var(--safe-b));
  background: rgba(255,255,255,.86);
  backdrop-filter: saturate(180%) blur(24px);
  -webkit-backdrop-filter: saturate(180%) blur(24px);
  border-top: 1px solid rgba(11,19,43,.06);
}
.action-bar .hint { text-align: center; margin-top: 9px; font-size: 12px; color: var(--ink-3); }

/* ============================================================== BIỂU MẪU */
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 12.5px; font-weight: 650; color: var(--ink-2); margin-bottom: 6px; }
.input, select.input, textarea.input {
  width: 100%; padding: 12px 14px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--bg);
  /* 16px là ngưỡng bắt buộc: nhỏ hơn thì Safari trên iPhone tự phóng to trang
     khi người dùng chạm vào ô nhập, và không tự thu lại. */
  font-size: 16px; outline: none; min-height: 46px;
  transition: border-color .16s, box-shadow .16s;
}
.input:focus { border-color: var(--navy); box-shadow: 0 0 0 3px rgba(11,19,43,.08); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* ========================================================= TRANG QUẢN TRỊ */
.page { max-width: 1180px; margin: 0 auto; padding: 20px 16px calc(60px + var(--safe-b)); }
.tabbar { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 18px; overflow-x: auto; scrollbar-width: none; }
.tabbar::-webkit-scrollbar { display: none; }
.tabbar button {
  padding: 11px 15px; font-size: 14px; font-weight: 650; color: var(--ink-3);
  border-bottom: 2px solid transparent; white-space: nowrap; min-height: 44px;
}
.tabbar button[aria-selected="true"] { color: var(--navy); border-bottom-color: var(--navy); }
table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th, td { text-align: left; padding: 11px 10px; border-bottom: 1px solid var(--line-2); }
th { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-3); font-weight: 700; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-num); }

/* ================================================================ KHÁC */
.toast {
  position: fixed; left: 50%; bottom: calc(24px + var(--safe-b)); transform: translateX(-50%);
  background: var(--navy); color: #fff; padding: 13px 20px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; z-index: 200; box-shadow: var(--sh-3);
  opacity: 0; pointer-events: none; transition: .24s; max-width: calc(100vw - 32px);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(-4px); }
.toast.err { background: var(--bad); }
.toast.ok  { background: var(--emerald-d); }

.modal-back {
  position: fixed; inset: 0; background: rgba(11,19,43,.5);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  z-index: 100; display: none; align-items: flex-end; justify-content: center;
}
.modal-back.show { display: flex; }
.modal {
  background: var(--bg); border-radius: var(--r-xl) var(--r-xl) 0 0; width: 100%;
  max-width: 560px; max-height: 92dvh; overflow-y: auto;
  padding: 10px 18px calc(28px + var(--safe-b));
}
@media (min-width: 640px) {
  .modal-back { align-items: center; }
  .modal { border-radius: var(--r-xl); padding-bottom: 28px; }
}

.otp-display {
  font-family: var(--font-num);
  font-size: 38px; font-weight: 700; letter-spacing: .18em;
  text-align: center; padding: 20px;
  background: linear-gradient(135deg, var(--navy), var(--navy-2));
  color: var(--gold); border-radius: var(--r-lg); font-variant-numeric: tabular-nums;
}
.otp-input {
  font-family: var(--font-num);
  font-size: 28px; letter-spacing: .3em; text-align: center; font-weight: 700;
  padding: 16px; width: 100%; border: 1.5px solid var(--line); border-radius: var(--r);
  background: var(--bg); color: var(--navy);
}
.otp-input:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px rgba(11,19,43,.08); }

.timeline { position: relative; padding-left: 24px; }
.timeline::before { content: ''; position: absolute; left: 6px; top: 6px; bottom: 6px; width: 1.5px; background: var(--line); }
.timeline-item { position: relative; padding: 7px 0; font-size: 13px; }
.timeline-item::before {
  content: ''; position: absolute; left: -22px; top: 13px;
  width: 9px; height: 9px; border-radius: 50%; background: var(--ink-3); border: 2px solid var(--bg);
}
.timeline-item.done::before { background: var(--emerald); }

.empty { text-align: center; padding: 44px 24px; color: var(--ink-3); }
.spinner {
  width: 20px; height: 20px; border: 2px solid var(--line); border-top-color: var(--navy);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.offline-note {
  position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); z-index: 6;
  background: rgba(11,19,43,.8); color: #fff; font-size: 11px; padding: 5px 12px;
  border-radius: 999px; pointer-events: none; backdrop-filter: blur(8px);
}
.scroll-x { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
.scroll-x::-webkit-scrollbar { display: none; }

/* ================================================= YÊU THÍCH & SO SÁNH */
.fav-btn {
  position: absolute; top: 10px; left: 80px; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%;
  background: rgba(255,255,255,.94); box-shadow: var(--sh-1);
  color: var(--ink-3); display: grid; place-items: center;
  backdrop-filter: blur(8px);
}
.fav-btn.on { color: #E11D48; }
.fav-btn.on .ic { fill: currentColor; }
.cmp-check {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 8px; font-size: 12px; color: var(--ink-3); cursor: pointer;
  min-height: 30px;
}
.cmp-check input { width: 16px; height: 16px; accent-color: var(--navy); }
.chip input[type="checkbox"] { margin-right: 5px; accent-color: var(--navy); }

/* ============================================ CHUẨN CHẠM TRÊN ĐIỆN THOẠI
   Mọi thứ bấm được phải đạt tối thiểu 44×44 điểm — ngưỡng Apple đặt ra và
   Google cũng khuyến nghị tương đương. Dưới ngưỡng đó tỉ lệ bấm trượt tăng vọt
   trên màn hình cảm ứng.                                                     */
@media (pointer: coarse) {
  .vtab, .tabbar button, .btn, .fab, .chip { min-height: 44px; }
  .vtab { display: inline-flex; align-items: center; justify-content: center; }
  .fav-btn { width: 34px; height: 34px; }
}

/* Người dùng bật giảm chuyển động thì tắt hết hiệu ứng — đây là thiết lập trợ
   năng, không phải tuỳ chọn trang trí. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ================================================ THẺ KIỂM DUYỆT TIN ĐĂNG
   Màn hình này quyết định tin nào được lên sóng, nên nó phải hiển thị đúng
   thứ khách sẽ nhìn thấy: ảnh ở kích thước xem được, mô tả đầy đủ, giá và
   bảng phí. Một hàng chữ "4 ảnh" không đủ để duyệt bất cứ điều gì.          */
.mod-card { padding: 14px; }
.mod-card + .mod-card { margin-top: 12px; }
.mod-head { display: flex; gap: 10px; align-items: flex-start; }
.mod-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

/* Dải ảnh cuộn ngang: trên điện thoại không đủ chỗ xếp lưới, mà thu nhỏ ảnh
   thành tem thì lại không duyệt được ảnh. Cuộn ngang giữ ảnh đủ lớn. */
.mod-photos {
  display: flex; gap: 8px; margin-top: 10px;
  overflow-x: auto; padding-bottom: 4px;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
}
.mod-photo {
  flex: 0 0 auto; width: 132px; height: 100px; padding: 0; border: 0;
  border-radius: 10px; overflow: hidden; background: var(--line);
  cursor: zoom-in; scroll-snap-align: start;
}
.mod-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mod-nophoto {
  display: flex; align-items: center; gap: 8px; margin-top: 10px;
  padding: 12px; border-radius: 10px;
  background: #FDECEC; color: #991B1B; font-size: 14px;
}
.mod-desc {
  margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  background: var(--bg-soft, #F6F7F9); font-size: 14px; line-height: 1.55;
  max-height: 160px; overflow: auto; white-space: normal;
}
.mod-fees { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.mod-actions {
  display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap;
  justify-content: flex-end; align-items: center;
}
.mod-actions .btn { flex: 1 1 auto; justify-content: center; }
@media (max-width: 420px) { .mod-actions .btn { flex: 1 1 100%; } }

/* ====================================================== TIN BỊ TỪ CHỐI
   Lý do phải nằm ngay trên cái tin nó nói về, đủ nổi để không lướt qua được.
   Bản trước chỉ gửi lý do trong một thông báo — thông báo trôi đi, tin thì
   nằm lại, nên chủ nhà thấy tin không lên mà không có chỗ nào nói vì sao.  */
.ly-do-tu-choi {
  margin-top: 8px; padding: 10px 12px;
  border-radius: 10px; border-left: 3px solid #B91C1C;
  background: #FDECEC;
}
.ly-do-dau {
  display: flex; align-items: center; gap: 6px;
  font-weight: 650; font-size: 13px; color: #991B1B;
}
.ly-do-dau .ic { flex: 0 0 auto; }
.ly-do-chu { margin-top: 4px; font-size: 14px; line-height: 1.5; color: #7F1D1D; }

/* Banner phải tự tay đóng: viền trái đậm để phân biệt với banner tự biến mất,
   và nút đóng rõ hơn vì đó là cách duy nhất bỏ nó đi. */
.noti-card.noti-o-lai { border-left: 4px solid #B91C1C; }
.noti-card.noti-o-lai .noti-close { opacity: 1; }

/* =========================================== TIN CỦA ĐỐI TÁC (AFFILIATE)
   Hai luồng chạy song song thì giao diện phải cho thấy điều đó — người tìm
   nhà cần biết bấm vào tin nào là rời khỏi LocaHome, TRƯỚC khi bấm. Dùng sắc
   xanh dương: khác hẳn xanh lá thương hiệu và đỏ cảnh báo, nên đọc ra "khác
   nguồn" chứ không phải "tốt hơn" hay "có vấn đề".                          */
.badge.doi-tac {
  background: #E8F0FE; color: #1A4FA0;
  display: inline-flex; align-items: center; gap: 4px;
}
.badge.doi-tac .ic { width: 13px; height: 13px; }

/* Vệt mảnh ở mép trái thẻ: nhận ra được khi lướt nhanh mà không ồn ào. */
.card-row.the-doi-tac { border-left: 3px solid #1A4FA0; }

.khoi-doi-tac {
  border: 1px solid #C7D9F7;
  background: #F4F8FF;
}
.khoi-doi-tac .panel-title {
  display: flex; align-items: center; gap: 6px; color: #1A4FA0;
}
.khoi-doi-tac .btn { background: #1A4FA0; }

/* ================================== BẢN CŨ CÒN KẸT TRONG MÁY NGƯỜI DÙNG
   Service worker giữ mã giao diện lại trong máy để chạy được khi mất mạng.
   Cái giá là sau một bản sửa, người dùng mở lên thấy y hệt như cũ — không lỗi,
   không dấu hiệu gì. Thanh này bám đáy màn hình cho tới khi được bấm; nó báo
   một sự thật mà người dùng không có cách nào tự biết.                       */
.thanh-cap-nhat {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 9999;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-radius: 14px;
  background: #0B132B; color: #fff;
  box-shadow: 0 10px 30px rgba(11, 19, 43, .28);
  animation: cap-nhat-len .32s ease;
}
@keyframes cap-nhat-len { from { transform: translateY(120%); } to { transform: none; } }
.thanh-cap-nhat-chu { flex: 1; min-width: 0; font-size: 13.5px; line-height: 1.45; }
.thanh-cap-nhat-chu b { display: block; }
.thanh-cap-nhat-chu span { color: rgba(255, 255, 255, .68); }
.thanh-cap-nhat .btn { flex: 0 0 auto; background: #fff; color: #0B132B; }
.thanh-cap-nhat .btn:disabled { opacity: .6; }
@media (max-width: 420px) {
  .thanh-cap-nhat { flex-direction: column; align-items: stretch; gap: 8px; }
  .thanh-cap-nhat .btn { width: 100%; }
}

/* Gợi ý ngay trong biểu mẫu đăng tin affiliate. Đây là chỗ dễ mất tiền nhất
   mà không có dấu hiệu gì: dán nhầm link thường thay vì link tiếp thị thì tin
   vẫn chạy, khách vẫn tới nơi, chỉ có hoa hồng là không bao giờ về. Lời nhắc
   phải nằm ngay cạnh ô nhập, không phải trong tài liệu ở đâu đó. */
.goi-y-link {
  margin: -4px 0 14px; padding: 10px 12px;
  border-radius: 10px; background: #F4F8FF; border: 1px solid #C7D9F7;
  font-size: 13px; line-height: 1.55;
}
.goi-y-link summary {
  cursor: pointer; font-weight: 650; color: #1A4FA0;
  list-style: none; min-height: 22px;
}
.goi-y-link summary::-webkit-details-marker { display: none; }
.goi-y-link summary::before { content: '▸ '; }
.goi-y-link[open] summary::before { content: '▾ '; }
.goi-y-link p { margin: 8px 0 0; }
.goi-y-link code {
  background: rgba(26, 79, 160, .1); padding: 1px 4px; border-radius: 4px;
}

/* ============================================ GHIM ĐANG CHỌN = LOGO LOCAHOME
   Khi mọi ghim khác đều là viên thuốc màu Navy, ghim đang chọn đổi hẳn hình
   dạng chứ không chỉ đổi màu — mắt nhận ra khác biệt về HÌNH nhanh hơn nhiều
   so với khác biệt về SẮC, nhất là trên nền bản đồ nhiều màu.                */
.ghim-logo {
  position: absolute; transform: translate(-50%, -100%); z-index: 10;
  display: flex; flex-direction: column; align-items: center;
  cursor: pointer; pointer-events: auto;
  animation: ghim-tha .34s cubic-bezier(.34, 1.4, .64, 1);
}
.ghim-logo .ghim-hinh {
  width: 46px; height: 46px; display: block;
  filter: drop-shadow(0 4px 10px rgba(11, 19, 43, .38));
}
.ghim-logo .ghim-hinh g { fill: var(--brand, #10B981); }
.ghim-logo .ghim-lo { fill: #fff; }
.ghim-gia {
  margin-top: -6px;
  background: var(--navy, #0B132B); color: #fff;
  padding: 3px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 700; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(11, 19, 43, .3);
  border: 1px solid rgba(255, 255, 255, .18);
}
@keyframes ghim-tha {
  from { transform: translate(-50%, -140%) scale(.7); opacity: 0; }
  to   { transform: translate(-50%, -100%) scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .ghim-logo { animation: none; } }

/* ═══════════════════════════════════════════ THẺ NHANH KHI BẤM GHIM BẢN ĐỒ
   Thẻ trượt lên từ đáy, nổi TRÊN bản đồ. Ảnh chiếm phần trên vì người tìm nhà
   quyết định bằng mắt trước khi đọc chữ.

   Về chuyển động: một nhịp bật nhẹ khi thẻ lên (cubic-bezier có phần vượt quá
   1) tạo cảm giác vật thể có khối lượng thật, khác hẳn kiểu trượt tuyến tính
   phẳng lì. Nội dung bên trong vào sau thẻ một nhịp và lệch nhau từng dòng —
   mắt bám theo được thứ tự đọc thay vì bị dội cả khối chữ cùng lúc.          */
.the-nhanh {
  position: fixed; left: 10px; right: 10px; bottom: 10px; z-index: 60;
  max-width: 460px; margin: 0 auto;
  background: var(--card, #fff); border-radius: 20px; overflow: hidden;
  box-shadow: 0 24px 60px -18px rgba(11, 19, 43, .45),
              0 2px 8px rgba(11, 19, 43, .12);
  transform: translateY(112%);
  opacity: 0;
  transition: transform .42s cubic-bezier(.22, 1.25, .36, 1), opacity .24s ease;
  will-change: transform;
}
.the-nhanh.mo { transform: translateY(0); opacity: 1; }

.tn-dong {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(11, 19, 43, .55); color: #fff; cursor: pointer;
  display: grid; place-items: center;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transform: rotate(45deg);                     /* dấu cộng thành dấu nhân */
  transition: background .16s, transform .16s;
}
.tn-dong:hover { background: rgba(11, 19, 43, .78); transform: rotate(45deg) scale(1.08); }
.tn-dong .ic { width: 18px; height: 18px; }

/* ---- dải ảnh ---- */
.ba-khung { position: relative; height: 200px; background: var(--line); overflow: hidden; border-radius: 0; }
.ba-truot {
  display: flex; height: 100%; overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.ba-truot::-webkit-scrollbar { display: none; }
.ba-o { flex: 0 0 100%; scroll-snap-align: center; position: relative; overflow: hidden; }
.ba-o img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  opacity: 0; transform: scale(1.06);
  transition: opacity .5s ease, transform 1.1s cubic-bezier(.22, 1, .36, 1);
}
/* Ảnh hiện dần và thu về đúng kích thước — che được khoảnh khắc ảnh nhảy vào
   đột ngột khi tải xong, thứ luôn trông như trang bị giật. */
.ba-o img.hien { opacity: 1; transform: scale(1); }
.ba-o.hong::after {
  content: 'Ảnh không tải được'; position: absolute; inset: 0;
  display: grid; place-items: center; font-size: 13px; color: var(--muted);
  background: var(--line);
}
.ba-khung::after {                                /* lớp phủ để chữ giá đọc được */
  content: ''; position: absolute; inset: auto 0 0 0; height: 82px;
  background: linear-gradient(transparent, rgba(11, 19, 43, .62));
  pointer-events: none;
}
.ba-phu .tn-gia-noi, .tn-gia-noi {
  position: absolute; left: 14px; bottom: 12px; z-index: 2;
  color: #fff; font-size: 21px; font-weight: 800; letter-spacing: -.02em;
  text-shadow: 0 1px 8px rgba(11, 19, 43, .5);
  font-variant-numeric: tabular-nums;
}
.tn-gia-noi small { font-size: 12px; font-weight: 600; opacity: .85; margin-left: 3px; }
.ba-dem {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  background: rgba(11, 19, 43, .55); color: #fff;
  padding: 3px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  font-variant-numeric: tabular-nums;
}
.ba-cham {
  position: absolute; left: 0; right: 0; bottom: 8px; z-index: 2;
  display: flex; justify-content: center; gap: 5px; pointer-events: none;
}
.ba-cham i {
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255, 255, 255, .5);
  transition: width .22s ease, background .22s ease;
}
.ba-cham i.on { width: 16px; border-radius: 3px; background: #fff; }

.ba-khung.ba-trong, .the-nhanh .tn-cho {
  height: 132px; display: grid; place-items: center; gap: 6px;
  color: var(--muted); font-size: 13px; background: var(--bg, #F6F7F9);
}
.ba-khung.ba-trong .ic { width: 26px; height: 26px; opacity: .5; }
.tn-spin {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--brand);
  animation: tn-quay .7s linear infinite;
}
@keyframes tn-quay { to { transform: rotate(360deg); } }

/* ---- phần chữ ---- */
.tn-than { padding: 14px 16px 16px; }
.tn-hang { display: flex; gap: 12px; align-items: flex-start; }
.tn-title {
  font-size: 16px; font-weight: 700; line-height: 1.35; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.tn-addr {
  font-size: 13px; color: var(--muted); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tn-diem {
  flex: 0 0 auto; text-align: center; line-height: 1.1;
  background: var(--brand-soft, #ECFDF5); border-radius: 12px; padding: 7px 10px;
}
.tn-diem b { display: block; font-size: 17px; color: var(--brand-ink, #065F46); }
.tn-diem span { font-size: 10px; color: var(--muted); letter-spacing: .04em; }

.tn-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.tn-tong {
  margin-top: 10px; padding: 9px 11px; border-radius: 10px;
  background: var(--bg, #F6F7F9); font-size: 13px; color: var(--ink-2, #3D4A60);
}
.tn-nut { display: flex; gap: 8px; margin-top: 12px; }
.tn-nut .btn { flex: 1; justify-content: center; }
.tn-nut .btn:last-child { flex: 1.6; }

/* Nội dung vào sau thẻ một nhịp, lệch dần từng dòng. */
.the-nhanh.mo .tn-d1 { animation: tn-len .4s .10s both cubic-bezier(.22, 1, .36, 1); }
.the-nhanh.mo .tn-d2 { animation: tn-len .4s .16s both cubic-bezier(.22, 1, .36, 1); }
.the-nhanh.mo .tn-d3 { animation: tn-len .4s .22s both cubic-bezier(.22, 1, .36, 1); }
.the-nhanh.mo .tn-d4 { animation: tn-len .4s .28s both cubic-bezier(.22, 1, .36, 1); }
@keyframes tn-len {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .the-nhanh { transition: opacity .2s ease; transform: none; }
  .the-nhanh.mo .tn-d1, .the-nhanh.mo .tn-d2,
  .the-nhanh.mo .tn-d3, .the-nhanh.mo .tn-d4 { animation: none; }
  .ba-o img { transition: opacity .2s ease; transform: none; }
}

/* ══════════════════════════════════════════════════════════ BẢNG TIN CHẠY
   Thanh mảnh dưới thanh điều hướng. Nền Navy đậm để tách hẳn khỏi phần giao
   diện thao tác — nội dung ở đây là thông báo, không phải nút bấm, và người
   dùng cần nhận ra khác biệt đó ngay mà không phải đọc.                     */
.bang-tin {
  background: var(--navy, #0B132B);
  color: rgba(255, 255, 255, .92);
  border-top: 1px solid rgba(255, 255, 255, .08);
  overflow: hidden;
  font-size: 13px; line-height: 1;
}
.bt-khung { overflow: hidden; padding: 9px 0; }

.bt-dai {
  display: flex; width: max-content;
  animation: bt-troi 30s linear infinite;
}
.bt-nua { display: flex; align-items: center; white-space: nowrap; }
@keyframes bt-troi { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.bt-muc { display: inline-flex; align-items: center; gap: 7px; padding: 0 16px; }
.bt-muc a { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(255,255,255,.35); }
.bt-muc a:hover { border-bottom-color: currentColor; }
.bt-ic { display: inline-flex; flex: 0 0 auto; }
.bt-ic .ic { width: 14px; height: 14px; }
.bt-ngan { color: rgba(255, 255, 255, .28); }

/* Ba loại tin, ba sắc. Chỉ tô BIỂU TƯỢNG chứ không tô cả dòng chữ — chữ màu
   trên nền tối rất nhanh mất tương phản, và một thanh nhiều màu chữ đọc mệt. */
.bt-hot .bt-ic { color: var(--gold, #D4A429); }
.bt-km  .bt-ic { color: #5FCFA8; }
.bt-tin .bt-ic { color: rgba(255, 255, 255, .55); }

/* Bản lần lượt: dùng khi người dùng bật "giảm chuyển động". */
.bt-tinh { position: relative; min-height: 15px; }
.bt-mot {
  position: absolute; inset: 0; display: flex; align-items: center;
  opacity: 0; transition: opacity .5s ease; pointer-events: none;
}
.bt-mot.hien { opacity: 1; pointer-events: auto; }

@media (prefers-reduced-motion: reduce) {
  .bt-dai { animation: none; }
}

/* Xem trước bảng tin ngay trong màn hình quản trị — người soạn phải thấy đúng
   thứ khách sẽ thấy, vì đây là chỗ duy nhất trong hệ thống mà nội dung gõ ra
   hiện trước mọi khách ngay lập tức, không qua bước duyệt nào. */
.bt-xem-truoc {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  color: rgba(255, 255, 255, .92); font-size: 13px;
}
.bt-cham-loai {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center; background: var(--bg, #F6F7F9);
}
.bt-cham-loai.bt-hot { background: #FBF3DF; color: #93701B; }
.bt-cham-loai.bt-km  { background: #E3F4EE; color: #0B6E52; }
.bt-cham-loai.bt-tin { background: var(--line); color: var(--muted); }

/* ---- Nút lùi/tới trên băng ảnh ----------------------------------------
   Vuốt ngang là cử chỉ của điện thoại; với chuột thì không có cách nào cuộn
   ngang một dải ảnh. Thiếu hai nút này, người dùng máy tính nhìn thấy "1/5"
   mà mãi đứng ở ảnh đầu và kết luận là hỏng.                              */
.ba-mui {
  position: absolute; top: 50%; z-index: 2;
  width: 34px; height: 34px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(11, 19, 43, .5); color: #fff; cursor: pointer;
  display: grid; place-items: center; transform: translateY(-50%);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: background .16s, opacity .16s;
}
.ba-mui:hover { background: rgba(11, 19, 43, .78); }
.ba-mui:disabled { opacity: .25; cursor: default; }
.ba-mui .ic { width: 19px; height: 19px; }
.ba-lui { left: 8px; }
.ba-toi { right: 8px; }
.ba-toi .ic { transform: rotate(180deg); }

/* Chấm chỉ vị trí ảnh — bấm được để nhảy thẳng tới ảnh bất kỳ. */
.ba-cham { pointer-events: auto; }
.ba-cham button {
  width: 7px; height: 7px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .5); cursor: pointer;
  transition: width .22s ease, background .22s ease;
}
.ba-cham button.on { width: 18px; border-radius: 3px; background: #fff; }

/* ---- Thẻ ở trạng thái THU GỌN -----------------------------------------
   Khách chạm vào bản đồ là họ đang muốn nhìn bản đồ. Thẻ rút về một dòng —
   vẫn giữ ảnh, tên và giá để không mất dấu căn đang xem — thay vì đóng hẳn,
   vì đóng hẳn thì họ phải đi tìm lại đúng cái ghim vừa bấm.               */
.tn-gon {
  display: none; width: 100%; align-items: center; gap: 12px;
  padding: 10px 12px; border: 0; background: transparent;
  cursor: pointer; text-align: left; color: inherit;
}
.tn-gon img, .tn-gon-trong {
  width: 46px; height: 46px; flex: 0 0 auto;
  border-radius: 10px; object-fit: cover; background: var(--line);
}
.tn-gon-chu { flex: 1; min-width: 0; display: block; }
.tn-gon-chu b {
  display: block; font-size: 14px; font-weight: 650; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tn-gon-chu > span {
  font-size: 13px; color: var(--brand); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tn-gon-mo {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center; background: var(--bg, #F6F7F9);
  color: var(--muted);
}
.tn-gon-mo .ic { width: 16px; height: 16px; transform: rotate(90deg); }

.the-nhanh.gon .ba-khung,
.the-nhanh.gon .tn-than,
.the-nhanh.gon .tn-dong { display: none; }
.the-nhanh.gon .tn-gon { display: flex; }
/* Bo tròn nhỏ lại khi thu gọn: khối thấp mà bo góc lớn trông như viên thuốc. */
.the-nhanh.gon { border-radius: 14px; }

/* ════════════════════════════════════════════════ NÚT & DANH SÁCH TIN ĐÃ LƯU
   Nút trái tim ở thanh trên cùng mang huy hiệu số. Đây là câu trả lời cho
   "tôi đang lưu bao nhiêu tin" — trước đây không có chỗ nào trả lời được.   */
.chip-luu { position: relative; }
.chip-luu.co-tin { color: var(--bad, #B91C1C); }
.chip-luu.co-tin .ic { fill: currentColor; }
.chip-so {
  position: absolute; top: -5px; right: -5px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 999px; background: var(--bad, #B91C1C); color: #fff;
  font-size: 10.5px; font-weight: 700; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
  border: 1.5px solid var(--card, #fff);
}

.dl-hang {
  display: flex; gap: 10px; align-items: stretch;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.dl-hang:last-child { border-bottom: 0; }
.dl-hang > img, .dl-khong-anh {
  width: 78px; height: 66px; flex: 0 0 auto;
  border-radius: 10px; object-fit: cover; background: var(--line);
}
.dl-chu {
  flex: 1; min-width: 0; text-align: left; border: 0; background: transparent;
  padding: 0; cursor: pointer; color: inherit;
  display: flex; flex-direction: column; gap: 2px; justify-content: center;
}
.dl-chu b {
  font-size: 14.5px; font-weight: 650; color: var(--ink); line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.dl-dia {
  font-size: 12.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dl-gia {
  font-size: 14px; font-weight: 750; color: var(--brand);
  font-variant-numeric: tabular-nums;
}
.dl-gia small { font-size: 11.5px; font-weight: 500; color: var(--muted); margin-left: 3px; }

/* Tin chủ nhà đã ẩn hoặc đã cho thuê: mờ đi và không bấm vào được nữa. Hiện
   như bình thường rồi để người dùng bấm vào khoảng không còn tệ hơn nhiều. */
.dl-hang.da-go > img, .dl-hang.da-go .dl-chu { opacity: .5; }
.dl-hang.da-go .dl-chu { cursor: default; }

.dl-bo {
  flex: 0 0 auto; width: 38px; border: 0; background: transparent;
  color: var(--bad, #B91C1C); cursor: pointer; border-radius: 10px;
  display: grid; place-items: center; align-self: center;
  transition: background .16s;
}
.dl-bo .ic { fill: currentColor; width: 20px; height: 20px; }
.dl-bo:hover { background: #FDECEC; }

/* Trang chi tiết: băng ảnh đứng riêng nên tự bo góc và tách khỏi tiêu đề. */
#sheet-body > .ba-khung { border-radius: var(--r-lg); margin-bottom: 4px; }
/* Không có giá đè lên thì bỏ luôn lớp phủ tối, nếu không nó làm tối đáy ảnh
   mà chẳng để làm gì. */
.ba-khung:not(:has(.ba-phu))::after { display: none; }
.ba-phu { position: absolute; left: 14px; bottom: 12px; z-index: 2; }

/* Khu vực chưa có dữ liệu tiện ích: nói thẳng thay vì chấm 0 điểm.
   Điểm 0 kèm nhãn "Khá vắng tiện ích" là lời khẳng định sai về căn nhà —
   hệ thống chưa biết gì về khu vực, chứ không phải khu vực không có gì. */
.chua-cham-diem {
  display: flex; align-items: center; gap: 7px;
  padding: 8px 11px; border-radius: 12px;
  background: var(--bg, #F6F7F9); color: var(--muted);
  font-size: 12px; line-height: 1.35; max-width: 190px;
}
.chua-cham-diem .ic { flex: 0 0 auto; opacity: .6; }

/* ================================== MỜI THÊM VÀO MÀN HÌNH CHÍNH
   Hiện SAU khi người dùng lưu một tin, không phải lúc vừa mở trang: lúc đó họ
   chưa biết LocaHome là gì, lời mời chỉ làm vướng và gần như ai cũng bỏ qua —
   mà bỏ qua một lần là mất luôn cơ hội sau. Lưu tin xong thì câu hỏi "lần sau
   xem lại ở đâu" đang nằm sẵn trong đầu họ.
   Dùng chung hình dáng với .thanh-cap-nhat để người dùng nhận ra ngay đây là
   một thanh hệ thống, không phải quảng cáo.                                  */
.thanh-cai-dat {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 9998;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px; border-radius: 16px;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #E6E8EC);
  box-shadow: 0 14px 40px rgba(11, 19, 43, .18);
  animation: cai-dat-len .34s cubic-bezier(.22, 1, .36, 1);
}
@keyframes cai-dat-len { from { transform: translateY(130%); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .thanh-cai-dat { animation: none; } }

.cai-dat-icon { flex: 0 0 auto; border-radius: 11px; }
.cai-dat-chu { flex: 1; min-width: 0; font-size: 13.5px; line-height: 1.5; }
.cai-dat-chu b { display: block; font-size: 15px; margin-bottom: 2px; }
.cai-dat-chu > span { color: var(--muted, #6B7280); }

.cai-dat-buoc { margin: 8px 0 0; padding-left: 18px; color: var(--ink, #0B132B); }
.cai-dat-buoc li { margin: 4px 0; display: flex; align-items: center; gap: 6px; }
.cai-dat-buoc .ic-chia-se { width: 16px; height: 16px; flex: 0 0 auto; }

.cai-dat-nut { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; }
.cai-dat-nut .btn.ghost { background: transparent; color: var(--muted, #6B7280); }

@media (max-width: 460px) {
  .thanh-cai-dat { flex-wrap: wrap; }
  .cai-dat-nut { flex-direction: row; width: 100%; }
  .cai-dat-nut .btn { flex: 1; }
}

/* ============================= BĂNG TIN CUỘN NGANG (trạng thái thu gọn)
   Ở trạng thái thu gọn, danh sách tin nằm NGANG: vuốt phải↔trái để chuyển
   giữa các căn, thay vì phải kéo bảng lên — thao tác cũ vừa khó trúng vừa hay
   dính. Cuộn ngang ở đây là `scroll-snap` GỐC của trình duyệt, không một dòng
   xử lý chạm nào do mình viết, nên không có gì để dính: quán tính, nảy biên,
   cuộn bằng bàn phím hay bằng chuột đều do trình duyệt lo, và lo đúng trên
   mọi máy. Cùng một bài học đã rút ra khi sửa băng ảnh trong tin.            */
.ds-dau {
  display: flex; align-items: baseline; gap: 10px;
  padding: 2px 0 8px;
}
.ds-dau h2 { font-size: 17px; }
.ds-dau .ds-tagline { flex: 1; min-width: 0; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ds-xem-tat-ca {
  display: none; flex: 0 0 auto;
  background: none; border: 0; padding: 4px 0;
  color: var(--brand-ink); font: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}

.sheet.peek .ds-dau .ds-tagline { display: none; }
.sheet.peek .ds-xem-tat-ca { display: block; }

.sheet.peek .sheet-body { overflow-y: hidden; padding-left: 0; padding-right: 0; }
.sheet.peek .ds-dau { padding-left: 16px; padding-right: 16px; }

.sheet.peek .ds-tin {
  display: flex; gap: 12px;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* Chặn cuộn lan: vuốt hết băng thì DỪNG, không kéo luôn cả trang phía sau. */
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  padding: 2px 16px calc(14px + var(--safe-b));
  scrollbar-width: none;
}
.sheet.peek .ds-tin::-webkit-scrollbar { display: none; }

.sheet.peek .ds-tin > .card-row {
  flex: 0 0 86%;                 /* chừa mép căn kế tiếp để người dùng BIẾT còn vuốt được */
  /* `min-width: 0` là dòng bắt buộc, không phải trang trí.
     Mặc định mỗi flex item có `min-width: auto`, nghĩa là KHÔNG ĐƯỢC hẹp hơn
     nội dung bên trong nó. Thẻ tin có địa chỉ và hàng nhãn dài, nên bề rộng
     tối thiểu ấy lớn hơn 86% — và nó đè luôn lên 86%. Đo thực tế: khai 86%
     của 398px (đáng ra 342px) mà thẻ vẫn rộng 429px, tức là chiếm trọn màn
     hình và mất hẳn mép căn kế tiếp. Không có mép ấy thì người dùng không có
     dấu hiệu nào cho biết còn vuốt được nữa. */
  min-width: 0;
  scroll-snap-align: center;
  border: 1px solid var(--line-2); border-radius: 16px;
  padding: 12px; margin: 0;
  background: var(--surface, #fff);
}
.sheet.peek .ds-tin > .card-row:last-child { border-bottom: 1px solid var(--line-2); }
.sheet.peek .cmp-check { display: none; }   /* so sánh thuộc về danh sách đầy đủ */

/* Chiều cao lúc thu gọn phải vừa ĐỦ MỘT THẺ TRỌN VẸN.
   Mức cũ 182px là tính cho danh sách dọc, nơi thẻ bị cắt ngang cũng không sao
   vì cuộn xuống là thấy tiếp. Với băng ngang thì khác: cắt ngang thẻ là cắt
   mất giá và các nhãn, mà vuốt ngang không làm nó hiện ra — người dùng buộc
   phải kéo bảng lên, đúng cái thao tác mình vừa bỏ đi.
   Đo thực tế: tay cầm 29 + dòng tiêu đề 39 + thẻ 177 + thở 20 = 265px. */
@media (max-width: 759px) {
  .sheet.peek { --sheet-y: calc(100% - 265px); }
}

/* Căn đang xem được viền đậm lên, khớp với ghim đang sáng trên bản đồ. */
.sheet.peek .ds-tin > .card-row.dang-xem {
  border-color: var(--brand, #0B132B);
  box-shadow: 0 0 0 1px var(--brand, #0B132B);
}

/* Máy có chuột: vuốt ngang không phải thao tác tự nhiên, nên hiện thêm nút.
   Đây đúng là lỗi đã mắc ở băng ảnh — làm xong chỉ vuốt được, và ảnh thứ hai
   trở thành không với tới bằng chuột. */
@media (hover: hover) and (pointer: fine) {
  .sheet.peek .ds-tin { scroll-behavior: smooth; }
  .sheet.peek .ds-tin::-webkit-scrollbar { display: block; height: 8px; }
  .sheet.peek .ds-tin { scrollbar-width: thin; }
}

/* Màn rộng: danh sách dọc vẫn hợp lý hơn, không ép cuộn ngang. */
@media (min-width: 760px) {
  .sheet.peek .ds-tin { display: block; overflow: visible; padding-bottom: 0; }
  .sheet.peek .ds-tin > .card-row { border: 0; border-bottom: 1px solid var(--line-2);
    border-radius: 0; padding: 14px 0; background: none; }
  .sheet.peek .ds-xem-tat-ca { display: none; }
  .sheet.peek .ds-dau .ds-tagline { display: block; }
  .sheet.peek .sheet-body { padding-left: 16px; padding-right: 16px; }
}
