/* ============================================================
   TASKFLOW — MOBILE STYLES (≤768px)
   Tách riêng từ css/app.css (2026-07-23) theo yêu cầu user — chỉ tách CSS, vẫn 1 index.html/1 js/app.js,
   1 codebase/1 URL (R1 trong Plan/responsive-website.md), không phải bản mobile riêng.
   Load SAU css/app.css trong index.html — mọi rule ở đây override app.css khi khớp @media(max-width:768px).
   Plan đầy đủ: Plan/mobile-ui-port-2026-07-23.md. Lịch sử/verify từng phần: CHANGELOG.md (nhiều mục [2026-07-23]).

   QUY TẮC BẮT BUỘC khi sửa file này (đã 2 lần mắc lỗi, xem CHANGELOG):
   - Rule "mặc định ẩn trên desktop" (vd `.foo{display:none}`) PHẢI đứng TRƯỚC khối @media chứa rule
     hiện nó ra trên mobile — cùng specificity thì CSS ăn theo thứ tự đứng SAU trong file, không quan
     tâm có nằm trong @media hay không. File này có NHIỀU khối @media(max-width:768px) riêng biệt.
   ============================================================ */

/* MOBILE SHELL — single breakpoint 768px (R9: mọi thay đổi mobile nằm trong đây, không rò ra ngoài) */
#mobile-bottom-nav{display:none}
/* Mặc định desktop: ẩn — PHẢI đứng TRƯỚC @media này (không phải sau — xem bug đã ghi ở khối
   @media Slack Inbox bên dưới, cùng lỗi thứ tự CSS lặp lại lần 2 khi review lại 2026-07-23). */
.navbar-logo-m{display:none}
@media(max-width:768px){
  #sidebar{display:none}
  #navbar{padding:0 12px;gap:8px}
  .breadcrumb{display:none}
  /* Logo thay breadcrumb — sidebar (nơi duy nhất có logo) bị ẩn nên mobile mất logo hoàn toàn nếu
     không thêm; đúng vị trí/kiểu mockup (icon 2 ô xanh chồng nhau + chữ "TaskFlow" góc trên trái). */
  .navbar-logo-m{display:flex;align-items:center;gap:7px;flex-shrink:0}
  .navbar-logo-m svg{width:22px;height:22px;flex-shrink:0}
  .navbar-logo-m span{font-size:15px;font-weight:600;color:var(--heading);letter-spacing:-.2px}
  .presence-wrap{display:none}
  #myfilter-btn,#settings-btn{display:none} /* My Filters + Account dropdown: Account chuyển vào page More */
  .search-wrap{flex:0 0 38px;max-width:38px}
  .search-wrap input{width:38px;padding:0;border-radius:50%}
  .search-wrap input::placeholder{color:transparent}
  .btn-create{padding:9px;font-size:0}
  #content{padding-bottom:calc(60px + env(safe-area-inset-bottom))}
  .page{padding:16px}
  #mobile-bottom-nav{display:flex;position:fixed;left:0;right:0;bottom:0;height:60px;padding-bottom:env(safe-area-inset-bottom);background:var(--chrome-bg);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border-top:1px solid var(--border);z-index:20}
  .mnav-item{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;color:var(--text-2);font-size:10px;font-weight:600;cursor:pointer;position:relative;user-select:none}
  .mnav-item .icon-svg{width:20px;height:20px;opacity:.7}
  .mnav-item.active{color:var(--accent)}
  .mnav-item.active .icon-svg{opacity:1;color:var(--accent)}
  .mnav-badge{position:absolute;top:2px;right:calc(50% - 20px);background:var(--red);color:#fff;border-radius:99px;font-size:9px;font-weight:700;min-width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;padding:0 4px}
}

/* MORE HUB (page-more) — chỉ vào được qua bottom nav mobile, style không cần gate @media */
.more-section-label{font-size:11px;font-weight:600;color:var(--text-3);text-transform:uppercase;letter-spacing:.6px;margin:20px 4px 8px}
.more-section-label:first-of-type{margin-top:0}
.more-list{background:var(--surface);border-radius:var(--radius-lg);overflow:hidden}
.more-item{display:flex;align-items:center;gap:12px;padding:13px 16px;cursor:pointer;color:var(--text-1);font-size:14px;font-weight:500;border-bottom:1px solid var(--border)}
.more-item:last-child{border-bottom:none}
.more-item:hover{background:var(--surface-hover)}
.more-item-chev{margin-left:auto;width:16px;height:16px;opacity:.4;flex-shrink:0}
.more-item .team-dot{width:26px;height:26px;font-size:10px;flex-shrink:0}
.more-empty{padding:13px 16px;color:var(--text-3);font-size:13px}

/* Mặc định desktop: ẩn — PHẢI đứng TRƯỚC @media bên dưới, không phải sau, vì cùng specificity thì
   CSS lấy rule đứng SAU trong file bất kể có nằm trong @media hay không (bug thật gặp phải khi
   review lại — 2026-07-23: đặt nhầm sau @media khiến 3 phần tử này luôn display:none kể cả mobile). */
.si-mobile-back{display:none;align-items:center;gap:6px;color:var(--text-1);font-weight:600;font-size:12px;cursor:pointer;user-select:none;width:fit-content;padding:7px 14px;border-radius:999px;border:1px solid var(--border);background:var(--surface);margin-bottom:12px}
#si-thread-backdrop,#si-thread-edge-tab,#si-thread-close-btn{display:none}
#drawer-bg,.drawer{display:none}
#ptr-indicator{display:none}
@media(max-width:768px){
  /* Slack Inbox mobile — 1 pane tại 1 thời điểm, toggle bằng class .si-mobile-detail trên
     #page-slack-inbox (JS: siMobileView, xem js/app.js). Không xoá DOM 3 pane (R1). */
  #page-slack-inbox{height:calc(100vh - var(--nh,52px) - 60px - env(safe-area-inset-bottom))}
  #page-slack-inbox .si-layout{flex-direction:column}
  /* flex:1;min-height:0 bắt buộc — .si-pane-tree/.si-pane-thread vốn set width+flex-shrink:0 cho
     hàng NGANG (desktop); đổi cột mà thiếu 2 dòng này thì chiều cao co theo nội dung (flex-basis:
     auto) thay vì lấp cột, tràn khỏi #page-slack-inbox{overflow:hidden} và KHÔNG CUỘN ĐƯỢC — đây là
     bug thật đã xảy ra khi user test (2026-07-23), không phải lỗi thao tác. */
  /* Chỉ 1 pane hiện tại 1 thời điểm trên mobile nên không cần bỏ viền phải/thêm viền dưới như bản
     cũ (không còn pane nào đứng cạnh để chia) — giữ nguyên border/radius 4 cạnh như desktop. */
  #page-slack-inbox .si-pane-tree{width:100%;flex:1;min-height:0}
  #page-slack-inbox.si-mobile-detail .si-pane-tree{display:none}
  #page-slack-inbox:not(.si-mobile-detail) .si-pane-main{display:none}
  /* Detail: main chiếm full — trước đó main+thread chia 50/50 rồi sau đó cuộn-chung-1-luồng đều bị
     user chê "layout tệ"/"thread đâu" (2026-07-23). Giờ main tự cuộn riêng, full màn hình. */
  #page-slack-inbox.si-mobile-detail .si-pane-main{display:flex;flex:1;min-height:0;overflow:auto}
  /* Sticky — nút back luôn dính đỉnh màn hình dù cuộn tới đâu, không mất dấu. Kiểu pill (user chọn
     qua preview 2026-07-23, phương án C — giống style nút phụ .btn-secondary có sẵn trong app,
     không phải thanh full-width) — nền đục hơn var(--surface-solid) để nổi rõ trên nội dung cuộn
     phía sau, không cần đường viền dưới full-width như bản trước. */
  .si-mobile-back{display:inline-flex;position:sticky;top:10px;z-index:5;background:var(--surface-solid);box-shadow:var(--shadow-sm)}

  /* Panel "Toàn bộ thread" — drawer trượt từ CẠNH PHẢI (không còn stack trong luồng chính), mở qua
     tab cạnh phải (tap) hoặc vuốt từ mép phải màn hình vào (JS: siWireThreadSwipe). Đúng yêu cầu
     user 2026-07-23: "nút vuốt từ phải sang để mở panel". */
  #page-slack-inbox .si-pane-thread{position:fixed;top:0;right:0;bottom:0;width:88vw;max-width:380px;
    transform:translateX(100%);transition:transform .28s cubic-bezier(.25,.8,.4,1);z-index:60;
    background:var(--surface-solid);box-shadow:-8px 0 24px rgba(0,0,0,.4);border-left:1px solid var(--border);
    border-top:none;padding:56px 14px 24px;overflow:auto}
  #page-slack-inbox.si-thread-open .si-pane-thread{transform:translateX(0)}
  #si-thread-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:55}
  #page-slack-inbox.si-thread-open #si-thread-backdrop{display:block}
  #si-thread-edge-tab{display:none;position:fixed;right:0;top:50%;transform:translateY(-50%);z-index:50;
    background:var(--accent);color:#fff;padding:12px 6px;border-radius:10px 0 0 10px;font-size:11px;
    font-weight:700;writing-mode:vertical-rl;text-orientation:mixed;box-shadow:-2px 0 8px rgba(0,0,0,.3);
    cursor:pointer}
  #page-slack-inbox.si-thread-has #si-thread-edge-tab{display:block}
  #page-slack-inbox.si-thread-open #si-thread-edge-tab{display:none}
  #si-thread-close-btn{display:flex;position:absolute;top:12px;right:12px;width:32px;height:32px;
    align-items:center;justify-content:center;background:transparent;border:none;color:var(--text-2);
    font-size:18px;cursor:pointer;z-index:2}

  /* Phase C — Issues: popup full-viewport (không đổi issuesViewMode/deep-link, chỉ CSS — R2). */
  .issue-popup-overlay{padding:0}
  .issue-popup-overlay #detail-panel{max-width:100%;width:100%;height:100%;max-height:100%;border-radius:0}
  /* Split view (desktop: list + detail cạnh nhau) — mobile ẩn cột list, detail full width. Quay lại
     list bằng nút "▤ Table" có sẵn trên topbar (không thêm state/nút back mới — topbar không nằm
     trong .issues-split nên luôn còn chỗ bấm). */
  .issues-split{flex-direction:column}
  .issues-list-col{display:none}
  #issues-detail-dock{width:100%}

  /* Phase C — Dashboard/My Task/Project Hub (dùng chung 1 widget engine, grid 12 cột + inline
     grid-column:span N per widget) — ép về 1 cột trên mobile, !important vì span set inline.
     minmax(0,1fr) BẮT BUỘC, không phải 1fr suông — 1fr có min-width:auto ngầm định, nội dung bên
     trong widget (bảng/chart/KPI row nhiều cột) rộng hơn màn hình sẽ đẩy tràn cả cột thay vì co lại
     (bug tràn ngang user báo 2026-07-23, đúng lỗi grid kinh điển). overflow-x:auto trên từng widget
     làm lưới an toàn — nội dung nào thật sự cần rộng hơn (bảng nhiều cột) tự cuộn riêng trong widget
     đó, không kéo tràn cả trang.
     Bug thật phát hiện 2026-07-23 (user báo widget "tỉ lệ khung hình kì lạ", không full chiều ngang):
     nút "+ Add Widget" là 1 <div style="grid-column:span 6"> KHÔNG có class .dash-widget (bare div,
     xem renderDashboard()/renderMyTask() trong js/app.js) — rule cũ chỉ target `.dash-widget` nên bỏ
     sót div này, nó vẫn giữ nguyên "span 6" trên lưới chỉ có 1 cột minmax(0,1fr) → trình duyệt tự
     sinh thêm CỘT ẨN (implicit grid columns) để đáp ứng span 6, làm méo layout cả .dash-grid (đo
     được `grid-template-columns` computed ra 6 track thay vì 1, cột đầu ăn hết còn 5 cột sau 0px
     nhưng vẫn tính vào tổng chiều rộng grid khiến widget card bị co hẹp lại). Đổi selector sang
     `.dash-grid>div` (mọi child trực tiếp, không chỉ riêng widget card) để bắt luôn cả nút Add. */
  .dash-grid{grid-template-columns:minmax(0,1fr)!important}
  .dash-grid>div{grid-column:1/-1!important}
  .dash-widget{min-width:0;overflow-x:auto}
  .dash-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}

  /* Phase E2 — mọi modal (.overlay .modal) thành SHEET full-viewport (Create/Edit Issue, Project,
     Filter, Widget, Bulk Edit, Settings, Add Member, CSV, Checklist, Tool, Drill-down, Bảng đủ
     cột...) theo Plan/responsive-website.md mục 5, thay vì chỉ giới hạn max-width như Phase C.
     Không đổi JS — Cancel/Save/backdrop-click handler nào có sẵn vẫn y nguyên (R5). */
  .overlay{padding:0}
  /* !important bắt buộc — 9/9 modal có inline style="width:...px" riêng (420-900px), inline style
     luôn thắng CSS thường bất kể specificity/@media, chỉ !important mới ép được full-viewport thật. */
  .modal{width:100%!important;max-width:100%!important;height:100%!important;max-height:100%!important;border-radius:0}
  /* .modal-title dính đỉnh — margin âm bằng padding gốc của .modal (28px) để kéo ra sát mép, rồi tự
     bù lại padding + viền dưới, cùng pattern đã dùng cho .si-mobile-back/nút back Slack Inbox. */
  .modal-title{position:sticky;top:0;z-index:2;background:var(--surface);margin:-28px -28px 16px;padding:20px 28px 14px;border-bottom:1px solid var(--border)}

  /* Phase D — mọi bảng dùng .tbl-wrap (Project Members/Tools/Metrics/Activity/PNL...) đang
     overflow:hidden (chỉ để bo góc đẹp desktop) — trên mobile cột thừa bị CẮT MẤT hoàn toàn thay vì
     cuộn được, cùng loại bug R7 với widget. Chỉ đổi overflow-x, giữ overflow-y hidden (bo góc). */
  .tbl-wrap{overflow-x:auto}

  /* Chat/AI FAB đè lên bottom nav (R5) — nâng lên trên tab bar + safe-area. Chỉ đổi vị trí mặc định;
     nếu user đã kéo AI FAB đi chỗ khác, JS set inline style riêng sẽ tự override CSS này. */
  .chat-fab{bottom:calc(72px + env(safe-area-inset-bottom))}
  .ai-fab{bottom:calc(134px + env(safe-area-inset-bottom))}

  /* Phase E3 — Notif/My Filters/Account dropdown (.dd-menu) thành bottom-sheet thay vì hộp nhỏ neo
     theo icon (dễ tràn/lệch mép trên màn hẹp). Không đổi JS mở/đóng (toggle class .open có sẵn),
     chỉ đổi vị trí hiển thị. #myfilter-menu/#settings-menu không có tác dụng thực tế (nút trigger đã
     ẩn ở trên) nhưng áp cùng rule cho nhất quán, không cần loại trừ riêng. */
  .dd-menu{position:fixed;top:auto;left:0;right:0;bottom:0;border-radius:20px 20px 0 0;min-width:0;
    max-height:70vh;overflow:auto;box-shadow:0 -8px 24px rgba(0,0,0,.4);padding-bottom:env(safe-area-inset-bottom)}

  /* Search — cùng tinh thần bottom-sheet thay vì hộp nổi giữa màn hình cách đỉnh 100px (quá hẹp trên
     điện thoại). Không đổi openSearch()/logic tìm kiếm, chỉ đổi vị trí hiển thị. */
  #search-modal{align-items:flex-end;padding-top:0}
  .search-box{width:100%;border-radius:20px 20px 0 0;max-height:80vh}

  /* Create drawer — mockup muốn "+" mở drawer chọn New Issue/Project/Filter thay vì mở thẳng Create
     Issue (xem js/app.js: btn-create rẽ nhánh isMobileView()). Desktop không đổi hành vi. */
  #drawer-bg{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:900}
  #drawer-bg.open{display:block}
  .drawer{display:block;position:fixed;left:0;right:0;bottom:0;background:var(--surface-solid);border-radius:20px 20px 0 0;
    z-index:901;transform:translateY(100%);transition:transform .28s cubic-bezier(.25,.8,.4,1);
    max-height:70vh;overflow:auto;padding:10px 16px calc(20px + env(safe-area-inset-bottom))}
  .drawer.open{transform:translateY(0)}
  .drawer-handle{width:36px;height:4px;background:var(--border-strong);border-radius:2px;margin:0 auto 14px}
  .drawer-title{font-size:13px;font-weight:700;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px}

  /* Pull-to-refresh — html,body{overflow:hidden} (cuộn thật xảy ra trong #content) nên gesture kéo
     xuống-để-refresh mặc định của Chrome không có gì để bám, đặc biệt mất hẳn ở chế độ PWA standalone.
     Tự làm bằng tay: vuốt xuống khi #content đang ở đỉnh (scrollTop=0) → hiện icon xoay dần theo
     khoảng kéo → thả quá ngưỡng → location.reload() (JS: wirePullToRefresh() trong js/app.js).
     TÍNH NĂNG ĐANG TẮT (2026-07-24, user yêu cầu) — wirePullToRefresh() không được gọi nữa nên
     transform ẩn tĩnh (-60px) không còn đúng nữa với chiều cao navbar thật, khiến icon lộ hẳn ra
     đè lên nút "My Filters" thay vì nằm khuất phía trên. Bỏ hẳn `display:flex` ở đây, để mặc định
     `display:none` (khai báo ở #ptr-indicator{display:none} phía trên @media này) áp dụng — nếu
     sau này bật lại wirePullToRefresh(), phải thêm lại `display:flex` ở rule này cùng lúc. */
  #ptr-indicator{position:fixed;top:calc(var(--nh,52px) + 8px);left:50%;
    width:36px;height:36px;align-items:center;justify-content:center;border-radius:50%;
    background:var(--surface-solid);box-shadow:var(--shadow-md);color:var(--accent);z-index:30;
    transform:translate(-50%,-60px) rotate(0deg);transition:transform .2s ease-out}
  #ptr-indicator.dragging{transition:none}
  #ptr-indicator.spin i{animation:ptr-spin .6s linear infinite}
  @keyframes ptr-spin{to{transform:rotate(360deg)}}
}
