/* ── 0. iOS safe-area (SV-6a69) ────────────────────────────────────────────
   증상: 아이폰에서 좌상단 햄버거가 **상태바(시계·다이나믹 아일랜드)와 겹쳐 안 눌림**.
   원인: safe-area inset 처리가 레포 전체에 0건이었고 버튼이 top:12px 고정이었다.
        PWA standalone + status-bar-style=black-translucent 라 콘텐츠가 상태바 밑까지
        올라오므로 더 심하다.
   설계: 인셋을 변수로 한 번만 정의해 쓴다(테스트에서 이 변수만 덮어써 검증 가능).
        노치 없는 기기·데스크톱에서는 env() 가 0 이라 아무 영향이 없다. */
:root {
  --sat: env(safe-area-inset-top, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
}

/* 상단 고정 햄버거 — 상태바 아래로 내리고 터치 타깃 44px 확보 */
.sidebar-toggle-mobile {
  top: calc(12px + var(--sat)) !important;
  left: calc(12px + var(--sal)) !important;
  width: 44px !important;
  height: 44px !important;
}

/* ★SV-208e: 고정 햄버거가 스크롤 시 카드 헤더를 덮는다(실측 — 마이페이지 「0 오늘 받은 티켓」의
   숫자, 티켓보드 「티켓 현황」이 44x44 버튼 밑으로 들어간다. 3화면 공통·선존재 결함).
   ★없애도 되는 이유 = **완전 중복 진입점**이다. 탭바의 [전체메뉴](sidebar.html:276 #tabbarMore)가
   base.html:139 에서 **같은 openSidebar** 를 부른다 — 같은 드로어, 같은 15개 항목.
   ★브레이크포인트도 정확히 같다: 햄버거 style.css:2574 `@media (max-width:960px)` ·
   탭바 이 파일 `@media (max-width:960px)`. 즉 햄버거가 뜨는 구간엔 **항상** 전체메뉴 탭이 있다.
   (그 일치는 test_safe_area_css.py::test_tabbar_breakpoint_matches_sidebar_drawer 가 지킨다.)
   되돌리려면 이 블록만 지우면 된다 — style.css 의 원래 규칙은 손대지 않았다. */
@media (max-width: 960px) {
  .sidebar-toggle-mobile { display: none !important; }
}

/* 본문이 상태바 밑으로 파고들지 않게 (햄버거는 ≤960px 에서 뜬다) */
@media (max-width: 960px) {
  .app-shell main { padding-top: calc(64px + var(--sat)) !important; }
  .sidebar { padding-top: var(--sat); padding-bottom: var(--sab); }
}

/* 하단 홈 인디케이터·좌우 노치(가로모드) */
body { padding-left: var(--sal); padding-right: var(--sar); }
/* ★f81d: 예전 셀렉터 `footer, .app-footer` 는 **죽은 규칙**이었다.
   실제 마크업은 <footer class="site-footer"> 인데, style.css 의
   `@media(max-width:640px) .site-footer { padding: ... }`(클래스 0,1,0 + shorthand)가
   요소 셀렉터(0,0,1)를 이기고 padding-bottom 까지 리셋해서 인셋이 1px 도 반영되지 않았다.
   같은 특이도(0,1,0)로 맞추고, mobile.css 가 style.css 뒤에 로드되므로 이쪽이 이긴다. */
.site-footer, footer, .app-footer { padding-bottom: calc(var(--sab) + 8px) !important; }
/* 토스트도 홈 인디케이터 위로 — bottom:24px 고정이라 인셋을 무시했다 */
.toast { bottom: calc(24px + var(--sab)) !important; }

/* 모바일 반응형 정비 (SV-fe80)
 *
 * 원칙: **리디자인 아님.** 데스크톱 레이아웃이 폰에서 깨지는 것만 바로잡는다.
 *   - 가로 스크롤 0 (넘치는 건 해당 컨테이너 안에서만 스와이프)
 *   - 데스크톱 기준 고정 폰트를 폰에서 축소(clamp)
 *   - 터치 타깃 44px 확보
 * 데스크톱(641px 이상)에는 어떤 규칙도 적용되지 않는다.
 */

@media (max-width: 640px) {

  /* ── 0. 가로 스크롤 차단(근본 수정은 style.css 의 minmax(0,1fr); 여기는 잔여 방어) ── */
  img, video, canvas, svg, table, pre { max-width: 100%; }
  pre, code { overflow-x: auto; }

  /* ── 1. 대시보드 히어로 — 폰트 과대·두 줄 깨짐·상단 잘림 해소 ── */
  .dz { padding: 14px 14px 32px !important; gap: 14px !important; }
  .dz-hero { padding: 20px 16px 18px !important; }
  .dz-hero h1 {
    font-size: clamp(20px, 6.4vw, 26px) !important;   /* 31px 고정 → 화면 비례 */
    margin-top: 12px !important;
    line-height: 1.28 !important;
    word-break: keep-all;                              /* 한국어 어절 단위 줄바꿈 */
  }
  .dz-hero img[alt="VERADI"] { top: 16px !important; right: 14px !important; height: 16px !important; }
  .dz-chip {
    flex-wrap: wrap;
    /* ★우상단 로고를 피하는 여유. 감이 아니라 **잰 값**이다(2026-08-13 실측):
         로고 폭 62.5px(폰에서 height:16px) + 우측 offset 14px = 히어로 우변에서 76.5px,
         히어로 padding-right 16px 를 빼면 알약 컨테이닝블록을 **60.5px** 파고든다.
         60px 이었을 때 알약 우끝이 로고 좌끝을 **0.5px** 침범했다(390·360·320 전부 동일 —
         max-width 가 걸려 있어 침범량이 폭과 무관하게 일정하다).
       65 = 60.5 + 4.5px 여백. ★상한이기도 하다 — 68 이상으로 올리면 320px 에서 알약이
         2줄 → 4줄로 늘어난다(실측). 그래서 더 키우지 않았다. */
    max-width: calc(100% - 65px);
    font-size: 11px !important;
    line-height: 1.5;
  }
  /* ★SV-5623 알약이 '날짜 · 근속' 두 조각이 되면서 폰에서 **줄이 접힌다**. 접히는 것
       자체는 위 max-width 가 로고를 막아 주는 설계(겹치는 대신 접는다)라 그대로 두되,
       가운뎃점은 **폰에서 감춘다** — 안 그러면 1 줄 끝에 '·' 만 덩그러니 남는다(실측).
     실측(390px · 2026-08-14): 알약 안쪽 폭 상한 225px 인데 한 줄에 필요한 폭은
       날짜 112.4 + gap 8 + 점 6.5 + gap 8 + 근속(6년 8개월) 72.5 + 좌우 padding 26 = 233.4
       → 8.4px 모자라 접혔다. 점을 빼면 218.9 로 **한 줄에 들어온다**.
     ★그래도 접히는 경우가 남는다: 근속이 두 자리 연차('11년 11개월' 등)면 +13.2px 라
       390 에서도 접히고, 360·320 은 상한(195·155)이라 늘 접힌다. 그때의 모양이
       「날짜」/「근속 …」 두 줄로 **깔끔해야** 해서 점을 감추는 것이다.
     ★데스크톱에는 점이 그대로 있다(여기는 640px 이하 전용). */
  .dz-chip-sep { display: none; }
  .dz-stat { min-height: 44px; }                       /* 터치 타깃 */

  /* ── 2. 티켓 칸반 — ★폰에서는 세로 아코디언(91ca) ──────────────────────
     이전엔 보드 안에서 옆으로 스와이프하게 뒀는데(9caa) 장호님 실사용에서
     "오른쪽으로 계속 밀어야 한다"는 지적. 폰에서는 **가로 스크롤 자체를 없애고**
     상태별 섹션을 세로로 쌓는다. 접기/펴기는 JS 가 붙이지만, **JS 가 실패해도
     전 섹션이 그냥 펼쳐진 채 세로로 보이므로 화면이 깨지지 않는다**(탭 방식은 JS 실패 시 전멸).
     데스크톱(641px+)은 기존 칸반 그대로. */
  .tk-page, .tk-head, .tk-new, .tk-board { max-width: 100%; }
  .tk-head { flex-wrap: wrap; gap: 10px; }
  .tk-head h1 { padding-left: calc(52px + var(--sal)); }   /* 고정 햄버거가 제목을 가리지 않게 */
  .tk-board {
    flex-direction: column;
    overflow-x: visible;              /* ★가로 스크롤 제거 */
    gap: 10px;
  }
  .tk-col {
    flex: 1 1 auto !important;
    width: 100%; max-width: 100%;
  }
  .tk-col-head {
    cursor: pointer; min-height: 44px; padding: 8px 6px;
    font-size: 13px; text-transform: none; letter-spacing: 0;
  }
  .tk-col-head::after { content: "▾"; margin-left: 8px; opacity: .55; transition: transform .15s; }
  .tk-col.tk-collapsed .tk-card, .tk-col.tk-collapsed .tk-empty { display: none; }
  .tk-col.tk-collapsed .tk-col-head::after { transform: rotate(-90deg); display: inline-block; }
  .tk-col.tk-collapsed { padding-bottom: 6px; }

  /* 마이페이지 대시보드 그리드 — 폰에서는 1열. ★`1fr` 은 min-width:auto 라 내용이
     길어지면 트랙이 뷰포트를 넘긴다(9caa 의 .app-shell 과 같은 패턴). minmax(0,1fr) 로 고정. */
  .tk-dash-grid, .tk-dash-grid2 { grid-template-columns: minmax(0, 1fr) !important; }
  /* ★SV-9176: `.tk-sum` 은 그리드 레이아웃이 아니라 **오늘 요약 4칸 스코어카드**다.
     1열로 강제하니 폰에서 4행 = 261px 을 먹었다(실측). 요약 지표를 세로로 쌓는 대시보드는
     없다 — 2~4열 한 줄이 통용 패턴이다. minmax(0,1fr) 의 원래 목적(내용이 길 때 트랙이
     뷰포트를 넘기지 않게)은 그대로 두고 **열 수만** 2로 되돌린다.
     영향 범위: `.tk-sum` 은 레포 전체에서 tickets_dashboard.html 한 곳에만 쓰인다
     (grep 전수 확인) → 다른 화면 영향 0. */
  .tk-sum { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .tk-dash-grid2 > .tk-panel { grid-column: auto !important; grid-row: auto !important; }
  .tk-panel { max-width: 100%; overflow-x: auto; }

  /* 새 수정지시 폼 — 한 줄에 여러 요소가 끼지 않게 세로로 쌓는다 */
  .tk-new-row { flex-direction: column; align-items: stretch; gap: 8px; }
  .tk-new-row > * { width: 100%; }
  .tk-new-row input, .tk-new-row select, .tk-new-row button { min-height: 44px; }
  .tk-filter { flex-wrap: wrap; }
  .tk-filter a { min-height: 40px; display: inline-flex; align-items: center; }

  /* ★6cd4 배너·서브링크·팀 드롭다운 — 폰에서 가로로 밀지 않게 전부 wrap/세로 정렬 */
  .tk-banner { flex-direction: column; align-items: flex-start; gap: 6px; max-width: 100%; }
  .tk-banner-t { white-space: normal; }
  .tk-banner-go { margin-left: 0; min-height: 40px; display: inline-flex; align-items: center; }
  .tk-sublinks { flex-wrap: wrap; max-width: 100%; }
  .tk-sublinks a { min-height: 36px; display: inline-flex; align-items: center; }
  .tk-exam-filter, .tk-team-filter { max-width: 100%; }
  .tk-exam-filter select, .tk-team-filter select { max-width: 100%; min-height: 40px; }
  /* 마감 배지가 길어져도 카드 폭을 넘기지 않게 줄바꿈 허용 */
  .tk-mrow .tk-m.due { white-space: normal; }

  /* ── 3. 회의실 문항 그리드 — 버튼 넘침·터치 타깃 ── */
  .er-btn { min-height: 44px; padding-left: 10px; padding-right: 10px; }
  .er-btn.re { max-width: 100%; }

  /* ── 3-b. 사이드바(햄버거로 여는 오프캔버스) 항목 44px ── */
  .sidebar a, .sidebar .nav-item, .sidebar button {
    min-height: 44px; display: flex; align-items: center;
  }

  /* ── 4. 공통 터치 타깃(44px 권장치) ── */
  button, .btn, a.btn, input[type="submit"] { min-height: 44px; }
  input, select, textarea { font-size: 16px; }         /* iOS 자동 확대 방지 */

  /* ── 5. 표 — ★전 페이지 공통 규칙(9caa) ─────────────────────────────────
     실측: /admin/users·/teams/admin +403px, /admin/reports +136px 로 **페이지 전체가**
     좌우로 밀렸다(장호님 3회 지적). 표마다 래퍼를 넣는 방식은 새 표가 생길 때마다
     빠뜨리게 되므로, table 자체를 스크롤 컨테이너로 만든다 → 표 안에서만 스와이프.
     (display:block 은 표 폭이 셀 내용을 따라가게 하는 표준 기법) */
  table { display: block; width: 100%; max-width: 100%; overflow-x: auto;
          -webkit-overflow-scrolling: touch; }
  /* ★셀은 자연 폭을 유지해야 한다. tr 에 min-width:100% 를 주면 셀이 뷰포트에 압축돼
     헤더가 '속/직/위' 처럼 한 글자씩 세로로 쪼개졌다(계측은 통과하는데 육안이 최악).
     nowrap 으로 각 셀이 제 폭을 갖게 하고, 넘치는 만큼 표 안에서 스와이프한다. */
  table th, table td { white-space: nowrap; }

  /* ── 5-a. 관리자 표는 폰에서 '행 = 카드' 로 (9caa) ────────────────────────
     컬럼이 7~8개고 셀 안에 select·체크박스가 들어가는 표는 폰에서 가로 스크롤로도
     읽기 어렵다(헤더가 화면 밖으로 나가 어떤 값인지 알 수 없음).
     각 셀을 '라벨 : 값' 한 줄로 세워 스크롤 없이 읽게 한다.
     data-label 은 템플릿의 헤더 텍스트를 그대로 옮긴 것. */
  /* ★overflow-x 를 visible 로 풀면 카드로 못 바뀐 잔여 폭이 문서로 전파돼 페이지가 밀린다
     (실측: 표 콘텐츠 390 > 박스 300 → deScroll 435). auto 로 유지해 표 안에서 흡수한다. */
  table.admin-table { display: block; overflow-x: auto; }
  table.admin-table thead { display: none; }
  table.admin-table tbody, table.admin-table tr, table.admin-table td { display: block; width: auto; }
  table.admin-table tr {
    border: 1px solid var(--line, #E8E2D8); border-radius: 12px;
    padding: 10px 12px; margin-bottom: 10px; background: var(--card, #fff);
  }
  table.admin-table td {
    white-space: normal; border: none; padding: 5px 0;
    display: flex; gap: 10px; align-items: flex-start; justify-content: space-between;
  }
  table.admin-table td::before {
    content: attr(data-label); flex: 0 0 34%;
    font-size: 12px; font-weight: 600; color: var(--gray, #73849E);
  }
  table.admin-table td:empty, table.admin-table td[data-label=""]::before { display: none; }
  .table-wrap, .tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* ── 5-b. 폼 컨트롤·진행바가 폭을 넘지 않게(/ptis/library +65px) ──
     ★핵심: flex 아이템의 min-width 는 기본 auto 라 **콘텐츠(긴 select)가 폭을 고정**한다
     (실측: 뷰포트 390/360 어디서든 label 이 392px 로 동일했다). min-width:0 을 풀고
     가로 줄바꿈 대신 세로로 쌓아 뷰포트를 넘지 않게 한다. */
  select, input, textarea { max-width: 100%; box-sizing: border-box; }
  /* ★상단 진행바는 position:fixed 인데 조상에 transform 이 걸리면 컨테이닝 블록이
     뷰포트가 아니라 그 조상이 된다 → max-width:100% 가 소용없다(실측 435px).
     뷰포트 단위로 고정한다. */
  .bb-progress-bar { max-width: 100vw !important; width: 100vw !important; left: 0 !important; }
  .form { flex-direction: column; align-items: stretch; }
  .form > label { min-width: 0 !important; max-width: 100%; width: 100%; }
  .form select, .form input[type="text"], .form input[type="search"] { width: 100%; }

  /* ── 5-c. 장식 오브가 만든 넘침 클립(/signup +23px) ──
     오브는 배경 장식이라 넘쳐도 보일 필요가 없다. 컨테이너에서 잘라낸다. */
  .auth-mesh-wrap, .mesh-bg { overflow: hidden; max-width: 100%; }
  .mesh-orb { pointer-events: none; }
  /* ★17d2: 카드가 `width: min(420px, 96vw)` 라 96vw(374px)가 **부모의 안쪽 폭**(390−32=358)을
     넘어 오른쪽으로 12px 삐져나갔다. vw 는 부모 padding 을 모른다 → 폰에선 100% 로 맞춘다. */
  .auth-mesh-wrap > section.auth { width: 100% !important; }
}

/* ── 6. 문항 이미지 — 잘림 해소 + 기존 라이트박스를 폰에서 읽히게 ────────────
   문제였던 것: .er-thumb 가 object-fit:cover + aspect-ratio 3/4 라 폰(1열)에서는
   문항 좌우가 통째로 잘려 나갔다("…격은 1초일 때" 처럼 글자가 끊김).
   썸네일이 작은 데스크톱(5열)에서는 의도된 크롭이므로 데스크톱은 건드리지 않는다. */
@media (max-width: 640px) {
  .er-thumb-wrap { aspect-ratio: auto !important; max-height: 62vh; }
  .er-thumb { height: auto !important; object-fit: contain !important; }
}

/* ★f3f7: 라이트박스는 공용 컴포넌트(lightbox.css)로 이관 — 전체폭 오버라이드 제거. */

/* ── 7. 모바일 하단 탭바 (SV, 2026-08-12 장호님 지시) ────────────────────────
   마크업: templates/partials/sidebar.html 끝(<nav class="tabbar">). 탭 선정 근거도 거기 있다.

   ★데스크톱 무변경의 근거가 이 두 줄이다:
     · 기본값이 `display:none` — 미디어쿼리 밖에서는 **어떤 폭에서도 안 뜬다**.
     · 켜는 곳은 아래 `@media (max-width: 960px)` **한 곳뿐**. 960px 은 style.css:2563 의
       사이드바 오프캔버스 전환점과 **같은 값**이다 — 즉 탭바는 '사이드바가 화면에서
       사라지는 순간'에만 나타난다(둘이 동시에 보이거나 둘 다 없는 구간이 생기지 않는다).
       ★두 값이 갈리면 그 사이 폭에서 메뉴가 통째로 사라진다 → 테스트로 고정
         (tests/test_safe_area_css.py::test_tabbar_breakpoint_matches_sidebar_drawer).

   ★색·폰트 신규 0 — 전부 style.css:3692~ 'VERADI 디자인 통일 override'(A안) 값 재사용:
     #FFFFFF(.card) · rgba(40,34,24,.10)(사이드바 경계) · #17538F(primary) ·
     rgba(23,83,143,.09)(.sidebar-nav a.active 배경) · #5F5849(.who-role) · 11px(.sidebar-section-label). */
.tabbar { display: none; }

@media (max-width: 960px) {
  .tabbar {
    display: flex;
    align-items: stretch;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    /* 89 = .sidebar-backdrop, 90 = --z-sidebar. 그 **아래**에 둔다 → 드로어가 열리면
       탭바도 백드롭에 덮여 어두워지고, 탭바를 눌러도 드로어가 닫힌다(포커스 하나). */
    z-index: 88;
    box-sizing: border-box;
    background: #FFFFFF;
    border-top: 1px solid rgba(40,34,24,.10);
    /* ★iOS 홈 인디케이터: 하단 인셋만큼 **바 자체를 두껍게** 한다(바를 띄우면 그 밑에
       배경이 비친다). 좌우 인셋은 가로모드 노치용 — 이 파일 §0 의 --sab/--sal/--sar 재사용. */
    padding: 4px calc(2px + var(--sar)) calc(4px + var(--sab)) calc(2px + var(--sal));
  }
  .tabbar-item {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-height: 52px;                 /* 터치 타깃 44px 이상 */
    padding: 6px 2px;
    position: relative;
    background: none;
    border: 0;
    border-radius: 9px;
    cursor: pointer;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.2;
    color: #5F5849;
    text-decoration: none;
  }
  .tabbar-item svg { width: 21px; height: 21px; flex: none; }
  /* 라벨이 길어도 탭 폭을 밀지 않게(3~4칸이 균등해야 한다) */
  .tabbar-item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tabbar-item.on { color: #17538F; background: rgba(23,83,143,.09); }
  /* ★현재 미사용 — 뱃지를 달던 유일한 탭(확인 필요)이 2026-08-13 지시로 내려갔다.
     지우지 않은 이유: sidebar.html 의 '되살리려면' 주석이 마크업 한 줄만 되돌리라고
     적혀 있는데 이 규칙까지 지우면 그 복구가 스타일 없이 조용히 깨진다. */
  .tabbar-badge {
    position: absolute; top: 3px; left: 50%; margin-left: 5px;
    background: #17538F; color: #fff;
    font-size: 10px; font-weight: 700; line-height: 1;
    padding: 2px 5px; border-radius: 999px;
  }

  /* ★본문 가림 방지 — 바 높이(4+52+4=60) + 여유 12 + 하단 인셋.
     .site-footer 는 style.css 의 `@media(max-width:640px) .site-footer{padding:...}` shorthand 가
     padding-bottom 을 리셋하므로 !important 가 필요하다(이 파일 §0 f81d 와 같은 이유). */
  .app-shell main { padding-bottom: calc(72px + var(--sab)) !important; }
  .site-footer { padding-bottom: calc(72px + var(--sab)) !important; }
}

