"""Contract cách ly tab trên MOBILE (14/08/2026 — bàn giao 2). Bug Danh thấy trên điện thoại thật (bản Space vừa deploy): mở app vào thẳng tab Analyzer — tab ĐẦU + MẶC ĐỊNH từ ``3740e17`` — mà đáy màn hình vẫn là UI tab Gợi ý (badge bi mục tiêu, chấm đầu cơ, thanh lực, nút Gợi ý/Đánh). Nguyên nhân: ``#quickbar`` nằm NGOÀI ``#panel``. ``setTab()`` chỉ ẩn/hiện các section BÊN TRONG ``#panel`` (``.controls``/``.legend``/``#drills``/ ``#analyzer``) nên không có gì với tới quickbar. Desktop không lộ vì ``#quickbar`` là ``display:none`` ngoài media query mobile — đúng vế "desktop không bị" trong báo cáo. Hai vế bị khoá ở đây, vì mỗi vế hỏng một kiểu: * **Trạng thái TĨNH lúc boot.** ``setTab()`` KHÔNG chạy khi mở app bình thường — nó chỉ chạy khi bấm tab, hoặc khi deep-link ``?qr=`` gọi ``exitAnalyzer()``. Trạng thái đầu do chính HTML tĩnh mang (nếp ``.controls``/``.legend`` có sẵn ``hidden``: MỘT nguồn sự thật, không flash tab). Sửa mỗi JS là bug còn nguyên ở đúng ca Danh gặp — mở app. * **Lối ra phải ở lại.** Trên mobile ``#panel`` là ``display:none`` cho tới khi "Chi tiết ▴" mở sheet. Ẩn cả ``#quickbar`` cho gọn là nhốt người dùng trong tab hiện tại — không còn nút nào mở panel để đổi tab. Test đọc FILE THẬT trong ``app/static/`` (nếp ``test_static_cache.py`` / ``test_scan.py``): repo không có JS runtime, nên cái khoá được là markup + nguồn ``setTab``. Vế mắt người (điện thoại thật) vẫn do smoke lo. """ from __future__ import annotations import re from pathlib import Path import pytest STATIC = Path(__file__).resolve().parents[1] / "app" / "static" # UI thuộc tab Gợi ý sống trong quickbar — phải biến mất ở tab Analyzer. # #qb-target = song sinh của #panel-target trong .controls (badge bi mục tiêu). QB_SHOT_UI = ["qb-spin", "qb-info", "qb-go", "qb-play"] # Điều hướng — PHẢI ở lại mọi tab (lối duy nhất mở #panel khi sheet đóng). QB_NAV = ["qb-drills", "qb-detail"] @pytest.fixture(scope="module") def html() -> str: return (STATIC / "index.html").read_text(encoding="utf-8") @pytest.fixture(scope="module") def js() -> str: return (STATIC / "app.js").read_text(encoding="utf-8") def _quickbar(html: str) -> str: m = re.search(r'', html, re.S) assert m, "không thấy