/* ─────────────────────────────────────────────────────────────
   모바일 전용 규칙 (2026-08-18)

   PC 화면은 그대로 두고, 좁은 화면에서만 켜진다. 그래서 모든 규칙을
   미디어 쿼리 안에만 둔다 — 이 파일 바깥으로 새어 나가는 규칙이 없어야
   PC UI가 바뀌지 않는다.

   핵심 결정
   · 사이드바는 화면을 가로로 먹지 않게 서랍(off-canvas)으로 바꾼다.
     열림 상태는 body.nav-open 하나로만 판단한다(PC의 .collapsed와 무관).
   · 표는 지우거나 접지 않는다. 정산 자료라 열이 다 보여야 하므로
     가로 스크롤로 두고, 첫 열만 고정해 어느 행인지 놓치지 않게 한다.
   · 손가락 조작을 위해 버튼·입력은 최소 40px 높이를 준다.
   ───────────────────────────────────────────────────────────── */

/* 서랍 뒤 어두운 막은 모바일 전용이다. PC에서는 0x0 투명이라 지금도 보이지 않지만,
   #content-row가 flex라 훗날 gap이 생기면 빈 칸이 될 수 있으니 아예 꺼 둔다. */
#nav-scrim { display: none; }

@media (max-width: 820px) {

  /* ── 상단바: 좁으니 부가 정보를 접고 핵심만 남긴다 ── */
  #topbar { padding: 0 10px; gap: 6px; }
  .topbar-left { gap: 4px; flex: 1; min-width: 0; }
  .topbar-left #page-title { font-size: 15px; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }
  .topbar-divider,
  #last-collected,                   /* '최근 수집' 시각 */
  .user-sep,
  #user-chip { display: none; }
  .header-right { gap: 6px; flex-shrink: 0; }
  #btn-collect, #btn-logout { padding: 8px 10px; font-size: 13px; }

  /* ── 사이드바: 서랍으로 ── */
  #content-row { display: block; }
  /* 상단바가 본문 칸 안으로 들어가서, 서랍은 화면 맨 위부터 덮는다 */
  #sidebar {
    position: fixed; left: 0; top: 0; z-index: 90;
    width: 264px; max-width: 84vw; height: 100vh;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: 2px 0 16px rgba(0, 0, 0, .12);
  }
  body.nav-open #sidebar { transform: none; }
  /* PC의 접힘(.collapsed) 규칙이 서랍 안에서 글자를 지우지 않도록 되돌린다 */
  #sidebar.collapsed { width: 264px; }
  #sidebar.collapsed .side-adv,
  #sidebar.collapsed .nav-label,
  #sidebar.collapsed .nav-caret { display: revert; }
  #sidebar.collapsed .nav-group.open .nav-children { display: revert; }
  #sidebar.collapsed .nav-parent { justify-content: flex-start; padding: 11px 12px; }
  /* 서랍 안에서는 브랜드 블록도 접지 않는다(PC의 .collapsed 규칙을 되돌린다) */
  #sidebar.collapsed .side-brand-block { justify-content: flex-start; padding: 14px 14px 10px; }
  #sidebar.collapsed .side-brand-block .app-name { display: block; }
  /* 서랍 뒤 어두운 막 — 탭하면 닫힌다(app.js에서 처리) */
  #nav-scrim { position: fixed; inset: 0; z-index: 80;
    background: rgba(0, 0, 0, .35); display: none; }
  body.nav-open #nav-scrim { display: block; }
  /* 메뉴를 고르면 바로 닫히므로 터치 영역을 넉넉히 */
  .nav-children button, .nav-parent { min-height: 44px; }

  /* ── 본문 ── */
  main { padding: 12px 12px 72px; }
  .section-title { margin: 20px 0 8px; padding-top: 14px; font-size: 15px; }

  /* 카드: 두 개씩 — 한 줄에 하나면 스크롤이 너무 길어진다 */
  .cards { gap: 8px; }
  .card { flex: 1 1 calc(50% - 4px); min-width: 0; padding: 11px 12px; }
  .cards.cards-grid4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }   /* 4열 격자도 모바일은 두 개씩 (#570) */
  .card .value { font-size: 19px; }
  .card .label { font-size: 12px; }
  .card .sub { font-size: 11px; white-space: normal; }

  /* 표: 열을 줄이지 않고 가로 스크롤. 첫 열은 붙여 둔다 */
  .table-wrap { -webkit-overflow-scrolling: touch; }
  table { font-size: 12px; }
  th, td { padding: 8px 9px; }
  .table-wrap th:first-child,
  .table-wrap td:first-child {
    position: sticky; left: 0; z-index: 2;
    background: var(--card); box-shadow: 1px 0 0 var(--border);
  }
  /* 고정 열도 본문 표와 같은 톤을 쓴다(theme.css 토큰) — 안 그러면 헤더만 옛 회색으로 남는다 */
  .table-wrap th:first-child { background: var(--c-thead-bg, #fafbfc); z-index: 3; }
  tr:hover td:first-child { background: #F3F7FD; }
  .table-wrap tr.total td:first-child { background: var(--c-thead-bg, #fafbfc); }
  /* 사업자별·브랜드별 정산표는 PC에서 고정 레이아웃이라 모바일에선 풀어준다 */
  #settle-biz-table, #settle-brand-table { table-layout: auto; }
  #settle-biz-table th:first-child,
  #settle-brand-table th:first-child { width: auto; }

  /* ── 필터: 한 줄에 하나씩, 입력은 가로 꽉 ──
     라벨을 flex 줄로 만들어야 .cap의 고정 폭이 먹는다. 이걸 빼면 '조회 월'·'채널'처럼
     글자 수가 다른 라벨마다 입력칸 시작 위치가 어긋난다(2026-08-20 지적). */
  .row-toolbar, .row-toolbar.flt { gap: 8px; }
  .row-toolbar.flt .ctl-label,
  .row-toolbar .ctl-label {
    width: 100%; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  }
  .row-toolbar.flt .ctl-label .cap,
  .row-toolbar .ctl-label .cap { flex: 0 0 5.2em; }
  /* styles.css가 줄의 **첫 라벨만** 3.6em으로 따로 잡아 둔다(PC에서 붙여 놓으려고).
     세로로 쌓이는 모바일에서는 그것 때문에 첫 줄만 입력칸이 왼쪽으로 튀어나온다.
     같은 자릿수로 맞춰 준다 — 선택자 무게가 같아 뒤에 오는 이 규칙이 이긴다. */
  .row-toolbar.flt .ctl-label:first-child .cap,
  .row-toolbar .ctl-label:first-child .cap { flex: 0 0 5.2em; }
  .row-toolbar.flt .ctl-label select,
  .row-toolbar.flt .ctl-label input,
  .row-toolbar .ctl-label select,
  .row-toolbar .ctl-label input { flex: 1; width: auto !important; min-width: 0; }
  .row-toolbar select, .row-toolbar input, .row-toolbar button,
  .flt select, .flt input, .flt button { min-height: 40px; font-size: 14px; }
  .flt .flt-actions { margin-left: 0; width: 100%; flex-wrap: wrap; }
  .flt .flt-actions button { flex: 1 1 auto; }
  .flt-box { padding: 10px 12px; }
  .row-toolbar .spacer { display: none; }      /* 우측 밀어내기는 의미가 없어진다 */

  /* ── ad-report 필터 (2026-09-04 모바일 정리) — 캡션(.cap) 없는 라벨 구조 ──
     한 줄에 하나씩 세로로 쌓고, 입력·셀렉트는 가로 꽉. 스위치(전환주체 등)는
     라벨 아래 버튼들이 균등 폭으로 줄바꿈된다. */
  .ad-filters .row-toolbar { row-gap: 8px; }
  .ad-filters .ctl-label {
    width: 100%; display: flex; align-items: center; gap: 6px;
    margin-left: 0 !important;
  }
  .ad-filters .ctl-label input[type="date"],
  .ad-filters .ctl-label input[type="month"],
  .ad-filters .ctl-label select,
  .ad-filters .ctl-label input { flex: 1; min-width: 0; width: auto !important; }
  /* 기간(날짜 2개)과 프리셋 셀렉트를 한 행에 (2026-09-04 지시 — 두 번째 확인).
     기간 라벨이 남은 폭을 다 쓰고, 프리셋은 내용 폭만. 360px 미만 폰에서는 날짜가 빡빡하다. */
  .ad-filters .ctl-label:has(> input[type="date"]) { width: auto; flex: 1 1 0; min-width: 0; }
  .ad-filters .ctl-label > input[type="date"] { padding-left: 4px; padding-right: 2px; font-size: 13px; }
  .ad-filters .preset-select { width: auto; flex: 0 0 auto; max-width: 96px; min-height: 40px; }
  /* 3단 스위치 — 인라인 스타일(inline-flex)을 덮어 버튼 균등 분배 */
  .ad-filters .ctl-label > span:last-child {
    flex: 1; display: flex !important; flex-wrap: wrap; gap: 4px;
  }
  .ad-filters .ctl-label > span:last-child button { flex: 1 1 auto; min-height: 38px; }
  /* 형태 현황의 광고형태 잠금 칸(.fmt-fixed)도 라벨의 마지막 span이라 위 스위치 규칙에 걸려 행 전체 폭이 됐다(2026-09-28 오스카 지적).
     옆 필터(디바이스 다중 선택)와 같은 내용 폭으로 */
  .ad-filters .ctl-label > span.fmt-fixed { flex: 0 1 auto; display: inline-block !important; }
  .ad-filters [data-af-xlsx] { width: 100%; min-height: 40px; }
  /* 실시간 현황 스위치(tm-filters)도 같은 규칙.
     주의: styleFilters()가 라벨 앞글자를 <span class="cap">으로 감싸므로 `> span`으로 잡으면 캡션까지
     flex:1이 되어 버튼이 오른쪽 절반으로 밀린다(2026-09-09 실사고) — 대시보드처럼 마지막 span만. */
  #tm-filters .ctl-label {
    width: 100%; display: flex; align-items: center; gap: 6px;
    margin-left: 0 !important;
  }
  #tm-filters .ctl-label > span:last-child {
    flex: 1; display: flex !important; flex-wrap: wrap; gap: 4px;
  }
  #tm-filters .ctl-label > span:last-child button { flex: 1 1 auto; min-height: 38px; }

  /* 소재 분석 툴바(운영 상태·소재 실적)도 같은 규칙 (2026-09-20 #193 오스카 게이트).
     이 두 묶음은 .ad-filters·#tm-filters 밖에 있어 위 규칙이 닿지 않았다. 인라인 스타일이
     display:inline-flex라 375px에서 다섯 번째 버튼([검수 반려])이 화면 밖으로 밀렸다
     (오스카 스크린샷 cr-seg-375.png). flex 항목은 min-width:auto라 min-content 아래로 줄지
     않는다 — nowrap인 inline-flex의 min-content = 버튼 폭 합계라 넘칠 수밖에 없었다.
     버튼이 하나 더 늘어도 안 깨지게 두 묶음을 함께 잡는다. */
  #cr-an-filter, #cr-an-mode {
    flex: 1; display: flex !important; flex-wrap: wrap; gap: 4px; min-width: 0;
  }
  #cr-an-filter button, #cr-an-mode button { flex: 1 1 auto; min-height: 38px; }

  /* ── 팝업: 화면을 거의 다 쓴다 ── */
  .modal-overlay { align-items: flex-end; }    /* 아래에서 올라오는 시트 형태 */
  .sakw-extra-grid { grid-template-columns: 1fr !important; }   /* 키워드 상세 하단 3열 → 모바일 1열 (2026-09-08) */
  .modal-card, .modal-card.wide {
    max-width: 100%; max-height: 92vh; border-radius: 14px 14px 0 0;
    padding: 18px 16px calc(18px + env(safe-area-inset-bottom));
  }
  .modal-actions { position: sticky; bottom: 0; background: var(--card);
    padding-top: 12px; margin-top: 14px; }
  .modal-actions button { flex: 1; min-height: 44px; }

  /* ── 그 밖 ── */
  .ov-charts, .inv-charts { grid-template-columns: 1fr; }
  .hbar-label { flex: 0 0 120px; font-size: 11.5px; }
  .pager { gap: 4px; }
  .pager button { min-width: 38px; min-height: 38px; }
  .form-grid { grid-template-columns: 1fr; }
  #toast { left: 12px; right: 12px; bottom: 12px; text-align: center; }
  .login-card { padding: 24px 18px; }
  /* 로딩 게이지는 작은 화면에서 조금 줄인다 */
  #load-ring .ring-box { width: 84px; height: 84px; }
  #load-ring .pct { font-size: 17px; }
}

/* 아주 좁은 화면(구형 폰) — 카드는 그래도 두 개씩 둔다.
   정산 화면은 카드가 8개까지 나와서 한 줄에 하나면 스크롤이 너무 길어진다.
   대신 글자를 줄여 '1,373,212,650원' 같은 긴 금액도 잘리지 않게 한다. */
@media (max-width: 420px) {
  .card { padding: 10px 11px; }
  .card .value { font-size: 16px; }
  .card .label { font-size: 11.5px; gap: 4px; }
  .card .sub { font-size: 10.5px; }
  #btn-collect { padding: 8px; font-size: 12px; }
}

/* ─────────────────────────────────────────────────────────────
   모바일 보정 (2026-09-07 지적 — 웍스 앱 내장 브라우저 캡처 기준)
   1) 합계 줄의 첫 칸이 가로 스크롤에 덮여 '31 39,260'처럼 보였다.
      styles.css가 합계 줄 전체를 위로 붙이면서(z-index 1) 첫 칸의 고정(left) z-index를
      같이 1로 낮춰 뒤 칸들이 위에 그려졌다. 첫 칸을 가장 위로 올리고 합계 배경을 준다.
   2) 기간 필터: 시작일 · 프리셋 · 종료일이 세 줄로 흩어졌다.
      1행 = 조회 월 + 프리셋, 2행 = 기간(시작 ~ 종료)로 고정한다.
   3) 필터 높이·섹션 제목 줄의 검색/버튼 줄바꿈 등 전반 압축.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 820px) {
  /* 1) 합계 줄 첫 칸 */
  .table-wrap tr.sum-top td:first-child {
    position: sticky; left: 0; z-index: 4; background: #eef3f0;
  }
  .table-wrap tr.sum-top td { top: var(--sum-top, 34px); }   /* 모바일 헤더 높이(패딩 8px) — 잰 값이 있으면 그것(#468) */
  .table-wrap th:first-child { z-index: 5; }         /* 헤더 첫 칸은 합계 첫 칸보다 위 */
  .table-wrap tr:hover.sum-top td:first-child { background: #eef3f0; }

  /* 2) 기간 필터 — 1행: 조회 월 + 프리셋, 2행: 기간 시작 ~ 종료 */
  .ad-filters .ctl-label:has(> input[type="month"]) { width: auto; flex: 1 1 52%; min-width: 0; }
  .ad-filters .preset-select { order: 1; width: auto; flex: 1 1 34%; max-width: none; min-width: 0; }
  .ad-filters .ctl-label:has(> input[type="date"]) {
    order: 2; width: 100%; flex: 0 0 100%; flex-wrap: nowrap;
  }
  .ad-filters .ctl-label > input[type="date"] { flex: 1 1 0; min-width: 0; font-size: 13px; padding-left: 4px; padding-right: 2px; }

  /* 3) 전반 압축 — 필터 높이 */
  .ad-filters .row-toolbar { row-gap: 6px; }
  .ad-filters .ctl-label select,
  .ad-filters .ctl-label input,
  .ad-filters .preset-select { min-height: 36px; font-size: 13.5px; }
  .ad-filters .ctl-label > span:last-child button { min-height: 34px; font-size: 13px; padding: 6px 8px; }
  .ad-filters [data-af-xlsx] { min-height: 36px; }
  /* 섹션 제목 줄(검색·엑셀·스위치) — 가로로 넘치지 않게 줄바꿈, 입력은 가로 꽉 */
  .section-title { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
  .section-title input, .section-title select { flex: 1 1 100%; width: auto !important; min-height: 36px; }
  .section-title button { min-height: 34px; }
  .section-title .spacer { display: none; }
  /* 제목 옆 설명 span(BEST/WORST 기준 안내 등)은 제 줄로 내려 접는다 — flex 아이템이라 길면 잘렸다 (2026-09-21) */
  #tab-creatives .section-title > .muted { flex: 1 1 100%; min-width: 0; white-space: normal; word-break: keep-all; line-height: 1.5; }
  #tab-creatives .cr-name:has(.chip.warn) { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
  #tab-creatives #cr-table td:first-child { min-width: 180px !important; max-width: 220px; white-space: normal !important; }
  /* 카드 여백·차트 박스 */
  .chart-box { padding: 10px; }
  .hint { font-size: 12px; line-height: 1.55; }
  /* 페이저는 한 줄에 안 들어가면 줄바꿈 */
  .pager { flex-wrap: wrap; justify-content: center; }
  .pager .pg-info { width: 100%; text-align: center; }
}

/* 가로 넘침 차단 (2026-09-07 지적 2차 — 대시보드 목표 진척률·소재 분석·키워드 분석에서 화면 전체가
   옆으로 밀려 제목·상단바가 잘렸다). 원인은 grid/flex 자식의 min-width:auto — 안에 nowrap 표·카드가 있으면
   그 폭만큼 부모가 넓어져 페이지가 가로로 늘어난다. 자식 min-width를 0으로, 넓은 블록은 자체 가로 스크롤로. */
@media (max-width: 820px) {
  html, body, #content-row { overflow-x: hidden; max-width: 100vw; }
  .an-grid > div, .cr-grid > div, .cr-card, .cr-card .cr-body, .cards .card { min-width: 0; }
  .kw-block { overflow-x: auto; max-width: 100%; }
  .kw-block > div > div[style*="min-width"] { min-width: 0 !important; }
  .chart-box { overflow-x: auto; max-width: 100%; }
  .cr-card .cr-img { width: 72px; height: 72px; flex-basis: 72px; }
  /* 키워드 분석 개별 모드의 캠페인·그룹 칸이 글자 단위로 쪼개지지 않게 */
  #kw-best-table td:nth-child(4), #kw-worst-table td:nth-child(4) { min-width: 170px; }
}

/* ─────────────────────────────────────────────────────────────
   대시보드 모바일 보정 (2026-09-09 지적 — 아이폰 캡처 기준)
   1) 목표 진척률: app.js가 그리드 열을 minmax(480px,1fr)로, 표 영역을 min-width:320px + 우측 메타
      박스(Report Date·영업일)로 놓아 폰 폭(360~390px)에서 오른쪽이 잘리고 메타 박스 글자가
      표 위로 겹쳤다. → 열 하나·표 영역 가로 꽉·메타 박스는 표 아래 한 줄, 고정 폭 td는 풀고
      표 자체는 가로 스크롤(잘리지 않게).
   2) 동기간 성과 비교: .cmp-table이 고정 레이아웃(width:100%, overflow:hidden)이라 세 지표 열이
      75px씩으로 눌려 '4,142,10'처럼 숫자가 잘렸다. → 자동 레이아웃 + 최소 폭으로 가로 스크롤,
      "(8월 대비 …)" 서브라인은 숫자 아래 줄로. 첫 열 고정은 rowspan 구조라 끈다.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 820px) {
  /* 1) 목표 진척률 */
  #db-goal-area > div { grid-template-columns: minmax(0, 1fr) !important; }
  #db-goal-area .kw-block { max-width: 100% !important; overflow: visible; }
  #db-goal-area .kw-block > div[style*="display:flex"] { padding: 8px 4px !important; gap: 10px !important; }
  #db-goal-area .kw-block > div[style*="display:flex"] > div:first-child {
    flex: 1 1 100% !important; min-width: 0 !important; overflow-x: auto; -webkit-overflow-scrolling: touch;
  }
  #db-goal-area .kw-block > div[style*="display:flex"] > div:last-child { flex: 1 1 100%; }
  #db-goal-area .kw-block > div[style*="display:flex"] > div:last-child table {
    width: 100% !important; min-width: 0 !important;
  }
  #db-goal-area table td[style*="width:150px"],
  #db-goal-area table td[style*="width:100px"] { width: auto !important; white-space: nowrap; }
  #db-goal-area table td, #db-goal-area table th { padding: 8px 5px; }
  #db-goal-area table td:nth-child(2) { min-width: 104px; }   /* 진척 막대·CPL 증감 문구 자리 (390px 폰에서 표 폭 334px 안) */

  /* 2) 동기간 성과 비교 */
  .table-wrap .cmp-table { table-layout: auto; width: auto; min-width: 100%; }
  .cmp-table td, .cmp-table th { overflow: visible; text-overflow: clip; white-space: nowrap; }
  .cmp-table th, .cmp-table td { padding: 8px 6px; }
  /* 셀 안 배치는 항상 막대 → 숫자 → 증감 세로 순(2026-09-09 지시 — 막대 폭에 따라 옆으로 붙었다
     아래로 갔다 하던 것을 통일). 막대 폭(%)은 app.js 인라인 그대로. */
  .cmp-table td > div { flex-direction: column; align-items: flex-start; gap: 3px; }
  .cmp-table .cmp-sub { display: block !important; flex: 0 0 auto; white-space: nowrap; margin-top: 0; }
  .cmp-table col:first-child, .cmp-table th:first-child, .cmp-table td[rowspan] { width: 56px !important; }
  .cmp-table col:nth-child(2), .cmp-table th:nth-child(2) { width: 44px !important; }
  /* rowspan 때문에 행마다 첫 칸이 달라 고정 열이 어긋난다 — 이 표는 고정을 끈다 */
  .table-wrap .cmp-table th:first-child, .table-wrap .cmp-table td:first-child {
    position: static; box-shadow: none;
  }

  /* 4) 표 안쪽 세로 스크롤 해제 (2026-09-09 지적 — 키워드 리포트): index.html·app.js가 표에
     max-height:560~640px + overflow-y:auto를 인라인으로 걸어 두어, 폰에서는 손가락이 표 안에서만
     구르고 페이지 위·아래로 못 간다. 본문(main) 안의 표는 전부 풀어 페이지가 그대로 스크롤되게
     한다(팝업 안 표는 팝업이 자체 스크롤이라 제외). 가로 스크롤(overflow-x:auto)은 유지. */
  main .table-wrap[style*="max-height"] { max-height: none !important; overflow-y: visible !important; }
  /* 캠페인·광고그룹처럼 PC에서 줄바꿈을 허용한 셀(white-space:normal 인라인)이 폰에서는 폭이 눌려
     글자 단위로 쪼개져 행이 세로로 길어진다 → 한 줄로(가로 스크롤). URL처럼 word-break를 준 셀은 제외. */
  main .table-wrap td[style*="white-space:normal"]:not([style*="word-break"]) { white-space: nowrap !important; }

  /* 5) 페이저(전 메뉴 공용 renderPagerInto, 2026-09-09 지적): 처음/이전/다음/끝 글자를 숨겨 기호만,
     번호는 app.js가 폰에서 3개만 그린다 → « ‹ 1 2 3 … 109 › » 한 줄. 위 줄은 '전체 N건 · p / pages 페이지'. */
  .pager { gap: 6px 0; padding: 10px 6px; }
  .pager .pg-info { width: 100%; text-align: center; font-size: 12.5px; }
  .pager .pg-nav { margin: 0 auto; gap: 3px; flex-wrap: nowrap; justify-content: center; }
  .pager .pg-txt { display: none; }
  .pager button, .pager .pg-btn { min-width: 34px; min-height: 36px; height: 36px; padding: 0 7px; font-size: 13px; line-height: 34px; }
  .pager button.pg-edge { padding: 0 8px; }
  .pager .pg-ell { padding: 0 1px; }

  /* 7) 소재 표(소재 분석 전체 소재 #cr-table · GFA 현황 소재별 성과 #da2-cr-table 등 *-cr-table, 2026-09-09 지적):
     첫 열(이미지+이름+유형 칩, min-width 220px)이 고정 열이라 폰 폭을 거의 다 차지해 숫자 열이 안 보였다 →
     첫 열 고정 해제, 이미지 36px, 이름·칩은 세로로, 첫 열 폭 150px 안. UTM·캠페인 열도 한 줄(가로 스크롤). */
  main .table-wrap table[id$="cr-table"] th:first-child,
  main .table-wrap table[id$="cr-table"] td:first-child { position: static; box-shadow: none; }
  table[id$="cr-table"] td:first-child { min-width: 0 !important; max-width: 160px; white-space: normal !important; }
  table[id$="cr-table"] td:first-child .cr-thumb img { width: 36px !important; height: 36px !important; margin-right: 6px !important; }
  table[id$="cr-table"] td:first-child .chip { display: inline-block; margin-top: 3px; font-size: 10.5px; }
  table[id$="cr-table"] td:first-child a { word-break: break-all; }
  table[id$="cr-table"] tr.sum-top td:first-child { position: static; }

  /* 6) 상품 관리(2026-09-09 지적): 상품 URL이 글자 단위로 쪼개져 행이 세로로 길었다 → 한 줄 말줄임(링크는 그대로),
     상품명도 한 줄 말줄임. 전체 URL은 PC나 [수정]에서 본다. */
  #dom-table td[style*="word-break"] { white-space: nowrap !important; word-break: normal !important;
    max-width: 200px; overflow: hidden; text-overflow: ellipsis; }
  #dom-table td:first-child { white-space: nowrap !important; max-width: 170px; overflow: hidden; text-overflow: ellipsis; }

  /* 3) 보종별 비중: 월 3열(repeat(3,1fr))이 폰 폭에 눌려 보종명과 숫자가 겹쳤다 → 월마다 한 블록씩 세로로 */
  /* minmax(0,1fr) — 1fr은 최소가 내용 폭이라 긴 보종명·숫자가 카드 밖으로 밀려 오른쪽이 잘렸다 (2026-09-29 #521) */
  #db-prod-share > div[style*="grid"] { grid-template-columns: minmax(0, 1fr) !important; gap: 14px !important; }
  #db-prod-share span[style*="flex:0 0 118px"] { flex-basis: 92px !important; }
  #db-prod-share > div[style*="grid"] > div { padding: 8px 0 4px; border-top: 1px dashed var(--border); }
  #db-prod-share > div[style*="grid"] > div:first-child { border-top: 0; padding-top: 0; }
}

/* ─────────────────────────────────────────────────────────────
   팝업(모달) 모바일 보정 (2026-09-15 지적 — 아이폰 캡처: 실시간 수집 [데이터 보기])
   "팝업 내용이 다 보이질 않는다"의 원인이 네 가지였다.
   1) 표가 카드 폭을 넘어가 오른쪽 열(금일 배분·달성율 / DB·전환)이 잘린 채 멈춰 있었다.
      열은 줄이지 않는다(보고 자료라 다 보여야 한다) — 컬럼명만 줄바꿈을 허용하고 글자·패딩을
      줄여 들어갈 만큼 넣고, 남는 폭은 가로 스크롤 + 첫 열 고정(위 블록)으로 본다.
   2) 가로로 더 있다는 표시가 없었다 → 넘치는 표에는 app.js markWideTables()가 .x-over를 달고
      바로 아래에 안내 한 줄(.x-tip)을 붙인다. 한 번 밀면 안내는 사라진다.
   3) 하단 [닫기] 줄이 sticky인데 카드 아래 여백(padding-bottom) 위에만 떠 있어, 마지막 행이
      버튼 밑으로 비쳐 보였다 → 아래 여백을 버튼 줄이 갖고 카드 좌우 끝까지 늘린다.
   4) theme.css의 제목 줄 `margin:-20px -20px`가 모바일 패딩(18/16px)과 어긋나 카드가 좌우로
      4px 스크롤됐다 → 모바일 패딩에 맞춘다. 카드의 가로 스크롤도 막는다.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 820px) {
  /* 4) 제목 줄 — 모바일 패딩(18px 16px)에 맞춰 카드 끝에 딱 붙인다 */
  .modal-card > h3, .modal-card > h2 { margin: -18px -16px 14px; padding: 13px 16px; font-size: 15.5px; }
  .modal-card, .modal-card.wide { overflow-x: hidden; padding: 18px 16px 0; }
  /* 인앱 브라우저(웍스 등)는 주소창을 vh에 포함해 92vh가 화면 밖으로 나간다 */
  @supports (height: 100dvh) {
    .modal-card, .modal-card.wide { max-height: 92dvh; }
  }

  /* 1) 팝업 안 표 — 컬럼명은 줄바꿈(단어 단위), 값은 한 줄 유지 */
  #modal-body table { font-size: 11.5px; }
  #modal-body th, #modal-body td { padding: 7px 6px; }
  #modal-body th { white-space: normal; word-break: keep-all; line-height: 1.3; }
  /* 첫 열(일자·이름)도 접는다 — '2026-09-08 (전주 화)'가 한 줄을 고집해 시간대별 표가
     혼자 80px 넘쳤다. 이 한 줄로 7열짜리 표가 폰 폭(390px) 안에 다 들어온다.
     (최소 폭은 주지 않는다 — 첫 열이 '채널'처럼 짧은 표까지 82px로 벌어져 오히려 넘쳤다.
      날짜가 두세 줄로 접히는 대신 7열이 다 보이는 쪽을 택한다.) */
  #modal-body td:first-child { white-space: normal; word-break: keep-all; }
  #modal-body .table-wrap { max-width: 100%; -webkit-overflow-scrolling: touch; }
  /* 팝업 안 표의 인라인 max-height(60vh)는 폰에서 스크롤을 두 겹으로 만든다 — 팝업이 곧 스크롤 */
  #modal-body .table-wrap[style*="max-height"] { max-height: none !important; overflow-y: visible !important; }

  /* 2) 가로로 더 있다는 표시 */
  #modal-body .table-wrap.x-over { border-right: 2px solid var(--c-secondary, #A9BEDE); }
  #modal-body .x-tip { margin: -10px 0 14px; font-size: 11.5px; color: var(--muted, #6B7280); text-align: right; }

  /* 3) 하단 버튼 줄이 마지막 행을 덮지 않게 — 아래 여백을 버튼 줄이 갖는다.
     표의 고정 열·고정 헤더가 z-index 2~5라, z-index 없는 버튼 줄 위로 그려져 [닫기] 밑에
     행이 비쳤다(사용자 캡처의 'SA Google Ads …') → 버튼 줄을 가장 위로 올린다. */
  .modal-actions {
    margin: 14px -16px 0; padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border); z-index: 10;
  }
}

/* ─────────────────────────────────────────────────────────────
   성과 알림 모바일 레이아웃 (2026-09-15 지시 "레이아웃과 디자인 좀 신경써주면 좋겠어")
   아이폰 캡처에서 ① 체크박스가 가로로 늘어나 라벨이 오른쪽 끝으로 밀려 두 줄로 깨졌고,
   ② 카드가 2+1로 어긋났고, ③ 11열 표(1,167px = 폰 폭의 세 배)가 오른쪽으로 잘려
   '대상·광고비'까지만 보였다.

   ①은 공통 함정이었다 — `.row-toolbar .ctl-label input { flex:1 }`(날짜·검색 입력을 가로로
   꽉 채우려던 규칙)이 체크박스까지 늘렸다. 체크박스·라디오만 빼 준다. 다른 화면의
   체크박스도 같이 고쳐진다.
   ③은 이 표가 '보고 자료'가 아니라 '조치 목록'이라, 열을 숨기지 않고 **한 행을 카드 한 장**으로
   눕힌다(정보는 그대로, 세로로 읽힌다). 라벨은 perf_watch.js가 td에 심은 data-th를 쓴다.
   PC(821px~)는 표 그대로다.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 820px) {
  /* ① 툴바 체크박스 — 늘리지 않는다(공통) */
  .row-toolbar .ctl-label input[type="checkbox"],
  .row-toolbar .ctl-label input[type="radio"],
  .row-toolbar input[type="checkbox"], .row-toolbar input[type="radio"] {
    flex: 0 0 auto !important; width: 18px !important; height: 18px;
    min-height: 0; padding: 0; margin: 0;
  }
  .row-toolbar .ctl-label:has(> input[type="checkbox"]) {
    width: auto; flex: 1 1 46%; min-width: 0; gap: 8px;
  }

  /* 성과 알림 툴바 — 1행 기간(3등분) · 2행 상태+버튼 · 3행 광고주 알림 스위치(#pa-advon, #376) · 4행 마지막 평가.
     #pa-advon이 order 목록에서 빠지면 order 0이 되어 기간 버튼 위 첫 줄에 혼자 올라간다(2026-09-27 오스카 반려). */
  #pa-toolbar { row-gap: 8px; }
  #pa-toolbar .seg { order: 1; display: flex; flex: 1 1 100%; gap: 6px; }
  #pa-toolbar .seg button { flex: 1; min-height: 40px; }
  #pa-status { order: 2; flex: 1 1 40%; min-width: 0; }
  #pa-run { order: 3; flex: 1 1 24%; }
  #pa-rules { order: 4; flex: 1 1 24%; }
  #pa-toolbar .ctl-label, #pa-toolbar #pa-advon { order: 5; }
  /* 공통 .ctl-label 폰 규칙(width 100%·flex)이 스위치 줄을 늘리지 않게 — 문구+스위치만 왼쪽에 둔다 */
  #pa-toolbar #pa-advon { width: auto; flex: 0 0 auto; flex-wrap: nowrap; min-height: 36px; }
  #pa-toolbar #pa-advon .pa-advon-st { text-align: left; }
  /* 위 ① 체크박스 규칙(18px !important)이 스위치 속 숨은 input까지 키우지 않게 */
  #pa-toolbar #pa-advon .tgl input { width: 0 !important; height: 0; }
  #pa-asof { order: 6; flex: 1 1 100%; font-size: 12px; line-height: 1.45; }

  /* ② 요약 카드 3개 — 숫자가 한 자리라 한 줄에 셋이 들어간다 */
  #pa-body .cards { gap: 6px; }
  #pa-body .cards .card { flex: 1 1 calc(33.333% - 4px); padding: 10px 9px; }
  #pa-body .cards .card .label { font-size: 11.5px; }
  #pa-body .cards .card .value { font-size: 20px; margin-top: 4px; }
  #pa-body .cards .card .sub { font-size: 10.5px; line-height: 1.35; margin-top: 3px;
    word-break: keep-all; }   /* '더 줄 만 / 한 곳'처럼 단어 중간에서 접히지 않게 */

  /* ③ 넓은 표 → 카드 목록 (.mcard) — 알림 표(11열)·변경 이력(10열) 공용.
     td의 data-th가 값 앞 라벨이 되고, 카드 안 순서는 표마다 아래에서 지정한다. */
  #pa-body .table-wrap, #pa-changes .table-wrap {
    border: 0; background: transparent; border-radius: 0; overflow: visible;
  }
  table.mcard { display: block; font-size: 13px; }
  table.mcard tbody { display: block; }
  table.mcard tr:first-child { display: none; }        /* 컬럼명 행 — 카드에선 값마다 라벨이 붙는다 */
  table.mcard tr {
    display: flex; flex-wrap: wrap; align-items: baseline;
    background: var(--card); border: 1px solid var(--border); border-radius: 12px;
    padding: 12px 14px; margin-bottom: 10px;
  }
  table.mcard tr.muted-row { opacity: .62; }
  table.mcard td {
    display: flex; width: 100%; gap: 10px; justify-content: space-between; align-items: baseline;
    border: 0; padding: 3px 0; text-align: left !important; white-space: normal !important;
    position: static !important; box-shadow: none !important;   /* 위 블록의 첫 열 고정 해제 */
  }
  table.mcard td::before {
    content: attr(data-th); flex: 0 0 auto;
    color: var(--c-text-sub, #6B7280); font-size: 12px; font-weight: 600;
  }
  table.mcard td:empty { display: none; }
  table.mcard td > .muted { text-align: right; }
  /* 카드 제목(대상)·머리 칩·메타 줄·버튼 줄의 공통 모양 — 어느 열인지는 표마다 지정 */
  table.mcard td.mc-chip { display: block; padding: 0 0 6px; font-size: 12.5px; }
  table.mcard td.mc-chip::before { display: none; }
  table.mcard td.mc-chip .chip { margin: 0; }
  table.mcard td.mc-title {
    display: block; font-size: 14.5px; font-weight: 700; line-height: 1.4;
    padding: 0 0 4px; max-width: none !important; overflow: visible !important;
    text-overflow: clip !important; white-space: normal !important;
  }
  table.mcard td.mc-title::before { display: none; }
  table.mcard td.mc-meta {
    width: 50%; font-size: 12px; color: var(--c-text-sub, #6B7280);
    padding: 0 0 8px; margin-bottom: 8px; border-bottom: 1px solid var(--border);
  }
  table.mcard td.mc-meta::before { display: none; }
  table.mcard td.mc-meta + td.mc-meta { justify-content: flex-end; }
  table.mcard td.mc-act {
    gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
  }
  table.mcard td.mc-act::before { display: none; }
  /* 인라인으로 작게 박아 둔 버튼(변경 이력 [되돌리기])도 카드에선 같은 크기로 */
  table.mcard td.mc-act button { flex: 1 1 0; min-height: 38px; min-width: 0;
    padding: 7px 4px !important; font-size: 13px !important; }

  /* 알림 표: 규칙 칩 → 대상 → 일자·광고주 → 지표 → 조치 */
  #pa-table td:nth-child(1) { order: 3; }
  #pa-table td:nth-child(2) { order: 4; }
  #pa-table td:nth-child(3) { order: 1; }
  #pa-table td:nth-child(4) { order: 2; }
  #pa-table td:nth-child(5) { order: 5; }
  #pa-table td:nth-child(6) { order: 6; }
  #pa-table td:nth-child(7) { order: 7; }
  #pa-table td:nth-child(8) { order: 8; }
  #pa-table td:nth-child(9) { order: 9; }
  #pa-table td:nth-child(10) { order: 10; }
  #pa-table td:nth-child(11) { order: 11; }

  /* 변경 이력: 종류 → 대상 → 시각·누가 → 광고주·매체 → 전·후 → 결과 → 되돌리기 */
  #pa-chg-table td:nth-child(1) { order: 3; }
  #pa-chg-table td:nth-child(2) { order: 4; }
  #pa-chg-table td:nth-child(3) { order: 5; }
  #pa-chg-table td:nth-child(4) { order: 6; }
  #pa-chg-table td:nth-child(5) { order: 1; }
  #pa-chg-table td:nth-child(6) { order: 2; }
  #pa-chg-table td:nth-child(7) { order: 7; }
  #pa-chg-table td:nth-child(8) { order: 8; }
  #pa-chg-table td:nth-child(9) { order: 9; }
  #pa-chg-table td:nth-child(10) { order: 10; }

  /* 알림 [보기] 팝업 — 두 칸 그리드(무슨 일인가 / 지금 할 일)는 폰에서 한 칸씩 */
  #modal-body > div[style*="grid-template-columns:1fr 1fr"] { grid-template-columns: 1fr !important; gap: 10px !important; }

  /* 상단바 — 아바타가 화면 끝에 닿아 잘려 보였다(인앱 브라우저). 오른쪽에 여유를 준다 */
  #topbar { padding-right: calc(10px + env(safe-area-inset-right, 0px)); }
  .appbar { gap: 2px; }
  .app-launch { width: 30px; height: 30px; }
  .app-launch svg { width: 18px; height: 18px; }
  .avatar { width: 30px; height: 30px; font-size: 12px; }
}

/* ── 로그인이 필요한 매체 팝업(extLoginReminder) — 좁은 폭에서는 한 줄에 글과 버튼이 같이 못 선다.
   [로그인하러 가기]를 아래로 내려 가로 전체를 쓰고(터치 타깃 44px), 줄 전체가 버튼으로 읽히게 한다
   (2026-09-20 지시 "들어가야 하는 버튼의 느낌으로"). 팝업 자체는 PC 크롬에서만 뜨지만
   좁은 창에서도 깨지지 않아야 한다. ── */
@media (max-width: 820px) {
  .exl-row { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px; }
  .exl-go { width: 100%; min-height: 44px; font-size: 14.5px; }
}

/* ── 월 청구 환율 칸 (2026-09-21) — 팝업 폭이 340px쯤이면 «월 · 환율 · [적용]» 세 칸이 한 줄에 못 선다.
   375px 정적 렌더에서 [적용]이 팝업 밖으로 잘려 나갔다. 한 칸씩 쌓고 버튼은 가로 전체·터치 44px. ── */
@media (max-width: 820px) {
  .fx-bill-row { grid-template-columns: 1fr; gap: 8px; }
  .fx-bill-row > button { width: 100%; min-height: 44px; margin-bottom: 0; }
}

/* ── [상품 관리] 툴바 (2026-09-22) — 폰에서는 「URL 기준」 셀렉트와 버튼 묶음이 줄을 바꿔 쌓이므로
   묶음 왼쪽 세로선은 뺀다(줄 머리에 선만 남는다). 셀렉트는 한 줄을 다 쓴다. ── */
@media (max-width: 820px) {
  #tab-domains .dom-actions { border-left: 0; padding-left: 0; flex-wrap: wrap; }
  #tab-domains .dom-src-ctl { flex: 1 1 100%; }
  #tab-domains .dom-src-ctl select { flex: 1; }
}

/* 제휴 매체 수정 팝업 — 보종별 단가 (#454): 매핑 추가 줄은 두 줄로, 표는 가로 스크롤 */
@media (max-width: 820px) {
  .pt-map-add { flex-wrap: wrap; }
  .pt-map-add input { flex-basis: 100%; }
  .pt-map-add select { flex: 1 1 0; width: auto; min-width: 0; }
  .pt-prod-table .pt-prod-price { min-width: 72px; }
  /* 매핑 표는 폰에서 행마다 두 줄 카드로 — 1줄 campaign 값 · 30일 전환, 2줄 보종 · 적용 범위.
     4열 그대로면 375px에서 '이 제휴 전용'·'운전자보험'이 잘렸다(#454 오스카 조건 4). 머리행은 숨기고 전환 수에 이름을 붙인다 */
  .pt-map-table, .pt-map-table tbody { display: block; }
  .pt-map-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; row-gap: 6px;
                     padding: 9px 10px; border-bottom: 1px solid var(--c-border, var(--border)); }
  .pt-map-table tr:first-child { display: none; }
  .pt-map-table tr.pt-map-bad { background: #fffaf2; }
  .table-wrap .pt-map-table td { padding: 0; border: 0; background: transparent !important; align-self: center;
                                 position: static; box-shadow: none; }   /* 공용 첫 열 고정(sticky + 세로선)을 끈다 — 카드에선 필요 없다 */
  .pt-map-table td[colspan] { grid-column: 1 / -1; }
  .pt-map-table td:nth-child(2) { text-align: right; }
  .pt-map-table td:nth-child(2)::before { content: "30일 전환 "; color: var(--muted); font-size: 11px; }
  .pt-map-table td:nth-child(3) select { width: 100%; min-width: 0; }
  .pt-map-table td:nth-child(4) select { width: auto; min-width: 124px; }
}

/* 두 줄 머리글 표의 둘째 줄 첫 칸 고정 해제 (2026-10-02 지적 — 목표 현황 '매체별 목표 현황' 아이폰 캡처).
   공용 첫 열 고정(th:first-child → left:0)이 둘째 머리글 줄의 첫 칸(현황 Ad Cost)까지 붙여, 가로로 밀면
   'Ad Cost'가 채널 칸 위에 겹쳐 남고 값 열과 어긋났다. 첫 열은 윗줄의 rowspan 칸이 이미 맡는다.
   위로 붙는 머리글(styles.css th top:0)은 살리고 왼쪽 고정만 끈다. 목표 현황 3표·리포트 그룹 머리글(app.js) 공통 */
@media (max-width: 820px) {
  .table-wrap tr:has(> th[rowspan]) + tr > th:first-child { left: auto; z-index: 2; box-shadow: none; }
}
