/* components.css — 공통 컴포넌트 v2 (AD.DASH 디자인 이식: 사이드바 + 섹션 악센트 + 메트릭 타일)
 * 색·간격은 tokens.css 변수만 사용. 다크모드는 토큰 재정의로 자동 대응. */
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { background: var(--bg); color: var(--ink); font-family: var(--font); font-size: var(--fs-body); letter-spacing: var(--ls-tight); }
a { color: var(--primary); }

/* ── 앱 셸: 좌 사이드바 + 우 본문 ─────────────────────────────── */
.app { display: flex; min-height: 100vh; width: 100%; } /* 풀 화면 폭 (2026-08-03 사용자 지시) */
.sidebar { width: var(--sidebar-w); flex: none; background: var(--surface); border-right: 1px solid var(--border); padding: var(--sp-4) var(--sp-3); position: sticky; top: 0; height: 100vh; overflow-y: auto; }
.side-logo { display: flex; align-items: center; gap: var(--sp-2); font-family: var(--font-display); font-weight: 800; font-size: 15px; padding: var(--sp-2) var(--sp-2) var(--sp-4); }
.side-logo .logo-dot { width: 22px; height: 22px; border-radius: 6px; background: var(--brand); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800; overflow: hidden; }
/* 성조기 마크 (2026-10-01) — 로고 칸은 꽉 채우고, 버튼 안에서는 작은 배지로. 테두리는 흰 바탕에서 깃발이 뭉개지지 않게. */
.side-logo .logo-dot { background: transparent; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18); }
.side-logo .logo-dot .flag-us { width: 100%; height: 100%; display: block; object-fit: cover; }
.btn-ghost .flag-us { width: 15px; height: 10px; border-radius: 2px; vertical-align: -1px; margin-right: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.15); }
.main { flex: 1; min-width: 0; padding: var(--sp-4) var(--sp-5) var(--sp-6); }

/* 사이드바 내비 (tab-btn 클래스 유지 — data.js 탭 전환과 연동) */
.tab-btn { display: flex; align-items: center; gap: var(--sp-2); width: 100%; text-align: left; font-family: var(--font); font-size: 13.5px; font-weight: 600; color: var(--ink-2); background: transparent; border: 0; border-radius: var(--radius-sm); padding: 9px var(--sp-3); cursor: pointer; margin-bottom: 2px; }
.tab-btn:hover { background: var(--surface-sub); color: var(--ink); }
.tab-btn.active { background: var(--primary-bg); color: var(--primary); }
.tab-btn .nav-ico { width: 18px; text-align: center; flex: none; }
/* 대분류 그룹 (2026-08-12) — 실적·계획 / 채널 성과 / 회원·CRM */
.nav-group + .nav-group { margin-top: var(--sp-4); }
.nav-group-t { font-size: 10.5px; font-weight: 800; letter-spacing: .04em; color: var(--ink-3);
  padding: 0 var(--sp-3) var(--sp-1); }

/* ── 헤더 ─────────────────────────────────────────────────────── */
.app-header { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.app-header h1 { font-family: var(--font-display); font-size: var(--fs-h1); font-weight: 800; }
.app-header .sub { color: var(--ink-3); font-size: var(--fs-small); }
.header-right { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.badge-lock { font-size: var(--fs-caption); color: var(--sig-red); background: var(--sig-red-bg); border-radius: var(--radius-pill); padding: 3px 10px; font-weight: 700; }
.badge-fresh { font-size: var(--fs-caption); font-weight: 700; border-radius: var(--radius-pill); padding: 3px 10px; color: var(--sig-green); background: var(--sig-green-bg); }
.badge-fresh.stale { color: var(--sig-yellow); background: var(--sig-yellow-bg); }
.btn-ghost { font-family: var(--font); font-size: var(--fs-small); font-weight: 600; color: var(--ink-2); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 6px 12px; cursor: pointer; }
.btn-ghost:hover { color: var(--ink); box-shadow: var(--shadow); }
.btn-ghost:active { transform: scale(.95); }

/* 데이터 정체 경고 스트립 (AD.DASH 관례) */
.alert-strip { display: none; align-items: center; gap: var(--sp-2); font-size: var(--fs-small); font-weight: 600; color: #fff; background: var(--primary); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); }
.alert-strip.show { display: flex; }
.alert-strip.danger { background: var(--sig-red); }

/* ── 필터 바 ──────────────────────────────────────────────────── */
.filter-bar { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); align-items: center; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4); box-shadow: var(--shadow); }
.filter-group { display: flex; align-items: center; gap: var(--sp-2); }
.filter-bar label { font-size: var(--fs-caption); color: var(--ink-3); font-weight: 700; }
.filter-bar select { font-family: var(--font); font-size: var(--fs-small); font-weight: 600; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); cursor: pointer; }
.filter-bar input[type="number"] { font-family: var(--font); font-size: var(--fs-small); font-weight: 600; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); width: 84px; }
.filter-bar input[type="date"] { font-family: var(--font); font-size: var(--fs-small); font-weight: 600; padding: 5px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink); }
[data-theme="dark"] .filter-bar input[type="date"] { color-scheme: dark; }
.filter-note { font-size: var(--fs-caption); color: var(--ink-3); margin-left: auto; }

/* 표 가운데 정렬 셀 (제휴처 등 카테고리형 컬럼) */
.tbl td.ctr { text-align: center; }

/* ── 프로모션 미니 타임라인 (월 목표 진도율 카드 — 이번 달 주요 프로모션) ── */
.promo-strip { display: flex; flex-direction: column; gap: 6px; margin-top: var(--sp-2); }
.ps-row { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-caption); }
.ps-name { flex: 0 0 170px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ps-track { position: relative; flex: 1; height: 10px; background: var(--border); border-radius: 5px; }
.ps-bar { position: absolute; top: 0; height: 100%; border-radius: 5px; }
.ps-today { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--sig-red); }
.ps-range { flex: 0 0 auto; color: var(--ink-3); white-space: nowrap; }

/* ── 미니 진행 바 (월 목표 진도율 타일 — AD.DASH 브랜드별 진척 스타일) ── */
.mini-bar { position: relative; height: 6px; border-radius: 3px; background: var(--border); margin-top: var(--sp-2); overflow: hidden; }
.mini-bar span { display: block; height: 100%; border-radius: 3px; }
/* 시간 경과율 세로선 — 막대(월 목표 진도율)가 이 선보다 왼쪽이면 뒤처진 페이스 (2026-08-18) */
.mini-bar .mark { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--ink-3); }

/* ── 카드 (섹션) — 상단 악센트 보더 + 아이콘 타이틀 ───────────── */
.card { position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--sp-4) var(--sp-4); box-shadow: var(--shadow); overflow: hidden; }
.card + .card { margin-top: var(--sp-5); }
.card h2 { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 800; margin-bottom: var(--sp-2); display: flex; align-items: center; gap: var(--sp-2); }
/* 섹션 번호 배지 — 탭 안에서 자동 채번 (CSS counter, JS 무관) */
.tab-panel { counter-reset: sec; }
.card > h2 { counter-increment: sec; }
.card > h2::before {
  content: counter(sec); flex: none;
  width: 21px; height: 21px; border-radius: 50%;
  background: var(--panel-acc, var(--brand)); color: #fff;
  font-size: 12px; font-weight: 800; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.card .howto { font-size: var(--fs-caption); color: var(--ink-3); margin-bottom: var(--sp-3); line-height: 1.5; }
/* 표 자료 출처 (2026-08-07 — 모든 데이터 표 하단 공통) */
.card .src-note { font-size: var(--fs-caption); color: var(--ink-3); opacity: 0.85; margin-top: var(--sp-2); }
/* 탭 내 대구분 헤더 (2026-08-07 — 광고성과 하단 "실제 전환 검증" 섹션) */
.section-divider { font-family: var(--font-display); font-size: var(--fs-h1, 1.3rem); font-weight: 800; margin: var(--sp-6) 0 var(--sp-2); padding-top: var(--sp-4); border-top: 2px solid var(--border); }
/* 대구분 헤더 아래 안내문 — 카드 '밖'이라 `.card .howto`가 안 걸려 본문 크기(14px)로 뜨고
   아래 카드와 간격이 0px이었다 (실측 2026-09-04). 캡션 크기로 낮추고 숨 쉴 틈을 준다. */
.section-divider + .howto { font-size: var(--fs-caption); color: var(--ink-3); line-height: 1.5;
  margin: 0 0 var(--sp-5); max-width: 90ch; }
/* 갭 대조 표 — 지표 그룹 경계선 */
.tbl th.gsep, .tbl td.gsep { border-left: 2px solid var(--border); }

/* 🖼️ 소재 갤러리 (2026-08-08) */
.cr-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--sp-3); margin-top: var(--sp-2); }
.cr-card { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface); display: flex; flex-direction: column; }
.cr-thumb { position: relative; aspect-ratio: 1 / 1; background: color-mix(in srgb, var(--border) 40%, transparent); }
.cr-thumb-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cr-thumb-ph { width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-1); color: var(--ink-3); font-size: var(--fs-caption); }
.cr-thumb-ico { font-size: 34px; line-height: 1; }
.cr-badge-type { position: absolute; top: 6px; left: 6px; background: var(--acc-kpi); color: #fff; font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 999px; }
.cr-body { padding: var(--sp-2) var(--sp-3) var(--sp-3); display: flex; flex-direction: column; gap: 4px; }
.cr-title { font-weight: 700; font-size: 0.85rem; }
.cr-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.cr-tag { font-size: 10.5px; color: var(--ink-3); background: color-mix(in srgb, var(--border) 45%, transparent); padding: 1px 6px; border-radius: 999px; }
.cr-tag-ch { color: var(--brand-strong); background: var(--brand-soft); border-color: transparent; font-weight: 700; }   /* 갤러리 매체 칩 (2026-09-22) */
.cr-metrics { display: flex; justify-content: space-between; gap: var(--sp-2); font-size: 11.5px; color: var(--ink-2, var(--ink-1)); margin-top: 2px; flex-wrap: wrap; }
.cr-dim { color: var(--ink-3); font-weight: 400; font-size: 0.85em; }
/* 🗂️ 완성본 라이브러리 (2026-08-10) */
a.cr-lib { text-decoration: none; color: inherit; }
a.cr-lib:hover { box-shadow: var(--shadow); }
.cr-play { position: absolute; right: 8px; bottom: 8px; width: 26px; height: 26px; border-radius: 50%; background: rgba(0,0,0,.55); color: #fff; font-size: 11px; display: flex; align-items: center; justify-content: center; }
.cr-name { font-size: 11.5px; font-weight: 600; line-height: 1.35; word-break: break-all; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cr-lib-nav { flex-wrap: wrap; }
/* 프로모션별 구분 (2026-08-12) */
.cr-promo { margin-top: var(--sp-4); }
.cr-promo:first-of-type { margin-top: var(--sp-2); }
.cr-promo-hd { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
  padding-bottom: var(--sp-1); border-bottom: 2px solid var(--panel-acc, var(--border)); }
.cr-promo-date { font-size: 11px; font-weight: 700; color: #fff; background: var(--panel-acc, var(--ink-3));
  padding: 1px 7px; border-radius: 999px; flex: none; }
.cr-promo-name { font-weight: 700; font-size: 0.9rem; }
.cr-promo-meta { font-size: var(--fs-caption); color: var(--ink-3); margin-left: auto; }
.cr-promo-off .cr-promo-name { color: var(--ink-3); }
.cr-promo-off .cr-promo-hd { border-bottom-color: var(--border); }
.cr-promo-off .cr-gallery { opacity: .62; }
/* 파일명 줄 수가 달라도 카드가 행 높이만큼 늘어나지 않도록 (아래 빈 여백 방지) */
.cr-promo .cr-gallery { align-items: start; }
/* 필터 행 — 월(대분류) / 프로모션 2단 (2026-08-13) */
.cr-nav-label { font-size: 11px; font-weight: 700; color: var(--ink-3); align-self: center;
  margin-right: var(--sp-1); flex: none; }
/* 완성본 라이브러리 범위 토글 (당월 소재만 / 전체 보관분) — 2026-08-19 */
.cr-scope-pick { gap: 6px; margin-bottom: var(--sp-2); }
.cr-scope {
  font-family: var(--font); font-size: var(--fs-small); font-weight: 700;
  color: var(--ink-2); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 6px 14px; cursor: pointer;
}
.cr-scope:hover { color: var(--ink); border-color: var(--primary); }
.cr-scope.on { color: #fff; background: var(--primary); border-color: var(--primary); }
.cr-promo-nav { margin-top: var(--sp-1); padding-top: var(--sp-2);
  border-top: 1px dashed var(--border); }
.cr-nav-date { font-size: 10px; font-weight: 700; color: var(--panel-acc, var(--ink-3)); }
/* 탭 패널별 악센트 색 — 카드 상단 보더 + 섹션 타이틀 레일 공용 */
#panel-overview { --panel-acc: var(--acc-daily); }
#panel-signup { --panel-acc: var(--acc-kpi); }
#panel-channels { --panel-acc: var(--acc-channel); }
#panel-revenue { --panel-acc: var(--acc-revenue); }
#panel-creative { --panel-acc: var(--acc-creative); }
#panel-customer { --panel-acc: var(--acc-customer); }
#panel-affiliate { --panel-acc: var(--acc-revenue); }
#panel-crm { --panel-acc: var(--brand); }
#panel-calendar { --panel-acc: var(--acc-channel); }
#panel-promo { --panel-acc: var(--acc-kpi); }
/* 상단 3px 악센트는 최상위 섹션 카드에만 — 카드 안에 중첩된 KPI 카드는 제외 */
.card:not(.kpi-card) { border-top: 3px solid var(--panel-acc, var(--border)); }

/* 행사 티어 칩 (2026-08-08 — 캘린더 탭 투입 위계) */
.tier-chip { display: inline-block; font-size: 10.5px; font-weight: 800; padding: 1px 8px; border-radius: 999px; white-space: nowrap; }
.tier-chip.tier-s { background: #B45309; color: #fff; }
.tier-chip.tier-1 { background: #DC2626; color: #fff; }
.tier-chip.tier-2 { background: #2563EB; color: #fff; }
.tier-chip.tier-3 { background: #059669; color: #fff; }
.tier-chip.tier-na { background: color-mix(in srgb, var(--border) 60%, transparent); color: var(--ink-3); font-weight: 600; }
/* 행사 스킴 원문 셀 — 줄바꿈 보존 + 가독 폭 */
.tbl td.scheme-txt { white-space: pre-line; min-width: 320px; max-width: 560px; font-size: 12px; line-height: 1.55; }

.grid { display: grid; gap: var(--sp-5); }
.card + .grid, .grid + .card, .grid + .grid { margin-top: var(--sp-5); }   /* 2026-09-22 카드↔그리드도 카드↔카드와 같은 한 칸 */
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1280px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
.grid-5 { grid-template-columns: repeat(5, 1fr); gap: var(--sp-3); }
@media (max-width: 1400px) { .grid-5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 1024px) { .grid-5 { grid-template-columns: repeat(2, 1fr); } }
/* 5열 카드는 폭이 좁아 값·라벨을 살짝 축소 */
.grid-5 .kpi-card .kpi-value { font-size: var(--fs-h1, 1.5rem); }
.grid-5 .kpi-card .kpi-label { font-size: var(--fs-caption); }

/* ── 메트릭 타일 + 델타 칩 (일일 리포트·WoW 블록) ─────────────── */
.tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: var(--sp-2); }
.metric-tile { background: var(--surface-sub); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); padding: var(--sp-3); }
/* 강조 타일 — 배경 채움 대신 좌측 신호 레일 (타일 표면은 전부 동일, 의미는 색으로 유지) */
.metric-tile.tint-primary { box-shadow: inset 3px 0 0 var(--info); }
.metric-tile.tint-success { box-shadow: inset 3px 0 0 var(--sig-green); }
.metric-tile.tint-warning { box-shadow: inset 3px 0 0 var(--sig-yellow); }
.metric-tile.tint-accent { box-shadow: inset 3px 0 0 var(--brand); }
.metric-tile.tint-danger { box-shadow: inset 3px 0 0 var(--sig-red); }
/* 상단 필터 다중 선택 (2026-09-07) — <select>를 감춘 체크박스 드롭다운 */
.ms-hidden { display: none !important; }
.ms { position: relative; display: inline-block; }
.ms-btn { font: inherit; font-size: var(--fs-caption); font-weight: 700; color: var(--ink-1);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 4px 10px; cursor: pointer; max-width: 260px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
/* 화살표는 문자로 직접 — BE 같은 16진 이스케이프는 뒤 문자와 붙어 'BE'가 새어 나온다 */
.ms-btn::after { content: ' ▾'; color: var(--ink-3); }
.ms-btn:hover { border-color: var(--ink-3); }
.ms-btn.on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.ms-pop { display: none; position: absolute; z-index: 60; top: calc(100% + 4px); left: 0;
  min-width: 210px; max-height: 340px; overflow: auto; padding: var(--sp-2);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: 0 8px 24px rgba(0,0,0,.16); }
.ms-pop.show { display: block; }
.ms-sec { font-size: 10px; font-weight: 800; color: var(--ink-3); text-transform: uppercase;
  letter-spacing: .4px; margin: var(--sp-2) 0 4px; }
.ms-sec:first-child { margin-top: 0; }
.ms-tools { display: flex; gap: 4px; margin-bottom: 4px; }
/* 필터 안 검색 — 항목이 많은 프로모션에서 이름으로 바로 찾기 (2026-09-21 사용자 요청) */
.ms-search { width: 100%; box-sizing: border-box; font: inherit; font-size: var(--fs-caption);
  padding: 4px 8px; margin-bottom: 4px; color: var(--ink-1); background: var(--surface-sub);
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm); }
.ms-search:focus { outline: none; border-color: var(--brand); }
.ms-item.hide { display: none; }
.ms-empty { font-size: var(--fs-caption); color: var(--ink-3); padding: 4px; }
.ms-empty.hide { display: none; }
.ms-tools button { flex: 1; font: inherit; font-size: 10px; font-weight: 700; cursor: pointer;
  color: var(--ink-2); background: var(--surface-sub); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 3px 6px; }
.ms-tools button:hover { color: var(--ink-1); border-color: var(--ink-3); }
.ms-item { display: flex; align-items: center; gap: 6px; padding: 4px 6px; cursor: pointer; text-align: left; width: 100%; box-sizing: border-box;
  font-size: var(--fs-caption); border-radius: var(--radius-sm); }
.ms-item:hover { background: var(--surface-sub); }
.ms-item input { margin: 0; cursor: pointer; }
.ms-single { display: block; width: 100%; text-align: left; font: inherit;
  font-size: var(--fs-caption); cursor: pointer; padding: 3px 6px; border: 0;
  background: transparent; color: var(--ink-1); border-radius: var(--radius-sm); }
.ms-single:hover { background: var(--surface-sub); }
.ms-single.on { background: color-mix(in srgb, var(--brand) 18%, transparent); font-weight: 700; }

/* 📌 업무·테스트 — 완료 목록 접기 (2026-09-07) */
.task-done { margin-top: var(--sp-3); border-top: 1px dashed var(--border); padding-top: var(--sp-2); }
.task-done > summary { cursor: pointer; user-select: none; font-size: var(--fs-caption);
  font-weight: 700; color: var(--ink-2); padding: var(--sp-1) 0; }
.task-done > summary:hover { color: var(--ink-1); }
.task-done[open] > summary { margin-bottom: var(--sp-2); }

/* 긴 표를 접어 두는 공통 스타일 (2026-09-09 — 지역 501개처럼 카드가 화면을 먹는 경우) */
.tbl-more { margin-top: var(--sp-2); }
.tbl-more > summary { cursor: pointer; user-select: none; font-size: var(--fs-caption);
  font-weight: 700; color: var(--ink-2); padding: var(--sp-1) 0; }
.tbl-more > summary:hover { color: var(--ink-1); }
.tbl-more[open] > summary { margin-bottom: var(--sp-2); }

/* 표 컬럼 정렬 (2026-09-04) — 헤더 클릭으로 내림차순 → 오름차순 → 원래대로 */
.tbl thead th.sortable { cursor: pointer; user-select: none; }
.tbl thead th.sortable:hover { background: color-mix(in srgb, var(--ink-3) 14%, transparent); }
.tbl thead th.sortable.sorted { background: color-mix(in srgb, var(--brand) 16%, transparent); }
.tbl thead th .sort-ind { font-size: 9px; margin-left: 3px; opacity: .85; }
   /* 🧊 미구매 회원 풀 (2026-09-03) */
/* 기준일 바 — 이번 달 표본이 얇을 때 지난달로 건너뛰는 버튼 (2026-09-03) */
.asof-jump { margin-left: 6px; padding: 1px 7px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface-sub); color: var(--ink-2);
  font: inherit; font-size: var(--fs-caption); font-weight: 700; cursor: pointer; }
.asof-jump:hover { background: var(--surface); color: var(--ink-1); border-color: var(--ink-3); }
.metric-tile .m-label { font-size: var(--fs-caption); color: var(--ink-2); font-weight: 700; }
.metric-tile .m-value { font-family: var(--font-display); font-size: 20px; font-weight: 800; margin: 3px 0 5px; letter-spacing: -.4px; }
.metric-tile .m-deltas { display: flex; flex-wrap: wrap; gap: 4px; }
.metric-tile .m-sub { font-size: var(--fs-caption); color: var(--ink-3); margin-top: 4px; }
.delta { font-size: 10.5px; font-weight: 700; border-radius: var(--radius-pill); padding: 1px 7px; color: var(--ink-3); background: var(--sig-na-bg); white-space: nowrap; }
.delta.good { color: var(--sig-green); background: var(--sig-green-bg); }
.delta.bad { color: var(--sig-red); background: var(--sig-red-bg); }

/* 서브 섹션 라벨 (▸ 유입 단계 …) */
.block-label { font-size: var(--fs-small); font-weight: 800; color: var(--ink-2); margin: var(--sp-4) 0 var(--sp-2); padding-left: var(--sp-2); border-left: 3px solid var(--primary); }

/* ── KPI 카드 (탭①) ───────────────────────────────────────────── */
.kpi-card { position: relative; height: 100%; }
.kpi-card .kpi-label { font-size: var(--fs-small); color: var(--ink-2); font-weight: 700; }
.kpi-card .kpi-value { font-family: var(--font-display); font-size: var(--fs-hero); font-weight: 800; margin: var(--sp-1) 0; letter-spacing: -.5px; }
.kpi-card .kpi-target { font-size: var(--fs-caption); color: var(--ink-3); }
.kpi-card .kpi-note { font-size: var(--fs-small); color: var(--ink-2); margin-top: var(--sp-2); line-height: 1.55; border-top: 1px dashed var(--border); padding-top: var(--sp-2); }
.kpi-card .kpi-note-list { margin: 0; padding-left: 1.1em; }
.kpi-card .kpi-note-list li { margin: 2px 0; }   /* 각주 불렛 3줄 (2026-09-21) */
.kpi-card.degraded { background: var(--surface-sub); }
.kpi-card.degraded .kpi-value { color: var(--ink-3); font-size: var(--fs-h2); }

/* 신호등 뱃지 — 아이콘+텍스트 동반 (색 단독 금지) */
.sig { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-caption); font-weight: 700; border-radius: var(--radius-pill); padding: 2px 9px; vertical-align: middle; }
.sig-green { color: var(--sig-green); background: var(--sig-green-bg); }
.sig-yellow { color: var(--sig-yellow); background: var(--sig-yellow-bg); }
.sig-red { color: var(--sig-red); background: var(--sig-red-bg); }
.sig-na { color: var(--sig-na); background: var(--sig-na-bg); }

/* 서브 드라이버 칩 */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip { border: 0; border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); background: var(--surface-sub); min-width: 150px; }
.chip .c-label { font-size: var(--fs-caption); color: var(--ink-2); font-weight: 700; }
.chip .c-value { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 800; }
.chip .c-sub { font-size: var(--fs-caption); color: var(--ink-3); }

/* ── 표 — 헤더 가운데 · 숫자 우 · 글자 좌 (AGENTS §3) ─────────── */
.tbl-scroll { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-table); }
.tbl th { text-align: center; font-weight: 700; color: var(--ink-2); background: var(--surface-sub); padding: 6px var(--sp-1); border-bottom: 2px solid var(--border); white-space: nowrap; }
.tbl .th-sub { display: block; font-weight: 400; font-size: 10.5px; color: var(--ink-3); }
.tbl td { padding: 6px var(--sp-1); border-bottom: 1px solid var(--border-soft); white-space: nowrap; }
.tbl td.num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl td.txt { text-align: left; }
.tbl tr.row-total { font-weight: 700; background: var(--brand-soft); }
.tbl tr.row-grand td { border-bottom: 2px solid var(--primary); }
.ct-tag { font-weight: 400; color: var(--ink-3); font-size: var(--fs-caption); }
.m-sep { color: var(--border); margin: 0 2px; }
/* 셀 안 강등 표기 — 미집계('– 8월부터') · 부분집계(*) 보조 문구 (2026-08-12 중간 퍼널) */
.tbl td .cell-na { font-weight: 400; font-size: 10.5px; color: var(--ink-3); margin-left: 3px; }
.tbl tr.row-broken td { color: var(--ink-3); }
.tbl tr.clickable { cursor: pointer; }
.tbl tr.clickable:hover { background: var(--surface-sub); }

/* 📣 매체별 성과 요약 (control_tower.js) — 2026-08-19 가시성 개선
   비중 = 미니 막대 · ROAS = 배경 색 농도. 숫자를 읽기 전에 '큰 돈 × 낮은 효율'이 눈에 띄게 한다. */
.tbl td .cost-bar { display: block; height: 4px; margin-top: 3px; border-radius: 2px;
  background: color-mix(in srgb, var(--border) 70%, transparent); overflow: hidden; }
.tbl td .cost-bar > span { display: block; height: 100%; border-radius: 2px; background: var(--primary); }
/* ROAS 히트 — 100%(본전)를 경계로 5단계. 색만으로 판단하지 않도록 숫자는 그대로 둔다. */
.tbl td.heat-0 { background: color-mix(in srgb, var(--sig-red) 16%, transparent); }
.tbl td.heat-1 { background: color-mix(in srgb, var(--sig-na) 16%, transparent); }
.tbl td.heat-2 { background: color-mix(in srgb, var(--sig-green) 12%, transparent); }
.tbl td.heat-3 { background: color-mix(in srgb, var(--sig-green) 24%, transparent); }
.tbl td.heat-4 { background: color-mix(in srgb, var(--sig-green) 38%, transparent); }
/* 집행이 사실상 없는 매체 — 숨기지 않고 무게만 낮춘다 */
.tbl tr.row-tiny td { opacity: .55; }
.tbl tr.row-tiny td.txt::after { content: ' · 집행 미미'; font-size: 10px; color: var(--ink-3); }
.tbl tr.drill td { background: var(--surface-sub); font-size: var(--fs-caption); }

/* ── 해석·경고 배너 ────────────────────────────────────────────── */
.interp { font-size: var(--fs-small); color: var(--ink-2); line-height: 1.55; background: var(--info-bg); border-left: 3px solid var(--primary); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); margin-top: var(--sp-3); }
.interp.warn { border-left-color: var(--sig-yellow); background: var(--sig-yellow-bg); }
.interp.danger { border-left-color: var(--sig-red); background: var(--sig-red-bg); }
.incident-banner { margin: 0 0 var(--sp-3); }
.inc-cmp { margin-top: var(--sp-2); }
.inc-cmp > summary { cursor: pointer; font-weight: 600; color: var(--ink-1); }
.inc-cmp-tbl { margin-top: var(--sp-2); background: var(--surface); }
.inc-cmp-tbl th, .inc-cmp-tbl td { padding: var(--sp-1) var(--sp-2); }
.inc-cmp-tbl .inc-cur { background: var(--info-bg); font-weight: 600; }
.inc-warn { color: var(--sig-red); }
.inc-day { color: var(--sig-red); font-weight: 600; }
/* 🚨 사고 각주 (CR-03) — 카드 하단 1줄. 배너 대신 이것만 남긴다(2026-09-18 사용자 결정) */
.howto.inc-foot { color: var(--sig-red); border-left: 3px solid var(--sig-red); padding-left: var(--sp-2); margin-top: var(--sp-2); }
.interp.good { border-left-color: var(--sig-green); background: var(--sig-green-bg); }

/* ── 게이지·차트 ──────────────────────────────────────────────── */
.gauge { background: var(--surface-sub); border-radius: var(--radius-sm); height: 22px; position: relative; overflow: hidden; }
.gauge .fill { height: 100%; border-radius: var(--radius-sm); }
.gauge .mark { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--ink-3); }
.chart-box { position: relative; height: 300px; }

/* ── 탭 패널·푸터 ─────────────────────────────────────────────── */
.tab-panel { display: none; }
.tab-panel.active { display: block; }
.footnote { font-size: var(--fs-caption); color: var(--ink-3); margin-top: var(--sp-5); line-height: 1.6; }
#app-error { color: var(--sig-red); font-weight: 600; }
#app-error:not(:empty) { padding: var(--sp-3) 0; }

/* ── 반응형: 900px 미만 사이드바 → 상단 가로 내비 ─────────────── */
@media (max-width: 900px) {
  .app { flex-direction: column; }
  .sidebar { width: 100%; height: auto; position: static; border-right: 0; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: var(--sp-1); padding: var(--sp-2) var(--sp-3); overflow-x: auto; }
  .side-logo { padding: 0 var(--sp-2) 0 0; white-space: nowrap; }
  .tab-btn { width: auto; white-space: nowrap; margin-bottom: 0; }
  .tab-btn .nav-ico { display: none; }
  /* 가로 내비에서는 그룹 래퍼를 투명하게 만들어 버튼만 한 줄로 흐르게 하고,
     그룹 사이는 구분선으로 대신한다 (좁은 화면에서 제목 줄은 공간 낭비) */
  .nav-group { display: contents; }
  .nav-group-t { display: none; }
  .nav-group + .nav-group > .tab-btn:first-of-type {
    border-left: 1px solid var(--border); margin-left: var(--sp-2); padding-left: var(--sp-3); }
  .main { padding: var(--sp-3); }
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
}
@media (min-width: 901px) and (max-width: 1120px) {
  .grid-3 { grid-template-columns: 1fr; }
  .grid-2 { grid-template-columns: 1fr; }
}
/* 소재 갤러리 — 원본 링크 있는 카드 표시 (2026-08-13) */
.cr-open { position: absolute; right: 6px; top: 6px; width: 20px; height: 20px; border-radius: 6px;
  background: rgba(0,0,0,.55); color: #fff; font-size: 11px; line-height: 20px; text-align: center; }
/* 소재 갤러리 합본 — 미집행 배지 (2026-08-13) */
.cr-badge-off { position: absolute; left: 6px; top: 6px; font-size: 10px; font-weight: 700;
  color: var(--ink-2); background: color-mix(in srgb, var(--surface) 88%, transparent);
  border: 1px solid var(--border); padding: 1px 7px; border-radius: 999px; }
.cr-metrics .cr-dim { font-size: 11px; }
/* 완성본 라이브러리 — 프로모션 드롭다운 (2026-08-13, 버튼 나열 대체) */
.cr-promo-pick { margin-top: var(--sp-2); }
.cr-promo-pick select { font-family: var(--font); font-size: var(--fs-small); font-weight: 600;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); cursor: pointer; max-width: 380px; }
/* 📌 업무·테스트 일정 (광고성과 인사이트 하단 · 2026-08-13) */
.task-cal { margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px dashed var(--border); }
/* 캐러셀 — 실물은 그대로 두고 '여러 장 넘김'임을 프레임 안쪽에서 표시 (2026-08-13) */
.cr-carousel-peek { position: absolute; top: 0; right: 0; bottom: 0; width: 14px; z-index: 1;
  background: linear-gradient(to right, transparent, rgba(0,0,0,.16));
  border-left: 1px solid rgba(255,255,255,.55);
  box-shadow: inset -5px 0 0 -4px rgba(255,255,255,.7); pointer-events: none; }
.cr-badge-carousel { position: absolute; left: 6px; bottom: 6px; z-index: 2;
  font-size: 10px; font-weight: 700; color: #fff; background: rgba(0,0,0,.62);
  padding: 2px 7px; border-radius: 999px; }
/* 인플루언서 소재 — ROAS가 평균을 크게 웃도는데 CTR이 낮아 눈에 안 띄는 유형이라 배지로 못 박는다 */
.cr-badge-inf { position: absolute; right: 6px; bottom: 6px; z-index: 2;
  font-size: 10px; font-weight: 800; color: #fff; background: var(--sig-green, #2E7D32);
  padding: 2px 7px; border-radius: 999px; }
/* 자동매칭 썸네일 — 사람이 검수한 링크가 아니라 집행일+형식+토큰으로 맞춘 추정.
   확정분과 한눈에 갈리도록 경고색을 쓴다 (우상단: 확정분은 여기에 ↗가 온다) */
.cr-badge-auto { position: absolute; right: 6px; top: 6px; z-index: 2;
  font-size: 10px; font-weight: 800; color: #fff; background: rgba(180,83,9,.92);
  /* 썸네일 사진 위에 얹히는 배지라 테마 토큰이 아니라 고정 앰버를 쓴다 —
     --sig-yellow는 다크에서 #FBBF24로 밝아져 흰 글씨가 읽히지 않는다
     (.cr-badge-carousel이 고정 검정을 쓰는 것과 같은 이유) */
  padding: 2px 7px; border-radius: 999px; letter-spacing: -.2px; }
/* 🖼️ 갤러리 카드 판정 1줄 (C-4 · 2026-09-21) — 평균 대비 ROAS %p · 비용 순위 → 액션 */
.cr-verdict { font-size: 11px; font-weight: 700; color: var(--ink-2); margin-top: 4px; padding-top: 4px; border-top: 1px dashed var(--border); }
.cr-verdict.good { color: var(--sig-green); }
.cr-verdict.warn { color: var(--sig-yellow, var(--ink-2)); }
.cr-verdict.bad { color: var(--sig-red); }
/* 🗂️ 완성본 라이브러리 기본 접힘 (D-7) — 수백 장이 페이지 길이를 잡아먹지 않게 */
.cr-lib-wrap > summary { cursor: pointer; list-style: none; }
.cr-lib-wrap > summary::-webkit-details-marker { display: none; }
.cr-lib-wrap > summary h2 { display: inline; }
.cr-lib-wrap > summary::before { content: '▸ '; color: var(--ink-3); }
.cr-lib-wrap[open] > summary::before { content: '▾ '; }
/* 🧩 소구×형식 매트릭스 행 내 최고 ROAS 칸 (D-6 · 인라인 font-weight 제거) · 갤러리 매체별 칩 (D-3) */
.tbl td.cr-best { font-weight: 700; color: var(--sig-green); }
.cr-chans { margin-top: 2px; }
/* 🎬 인플루언서 드릴다운 (C-3 · 2026-09-21) — 소구 축 '인플루언서' 한 줄을 개별명으로 펼치는 접이식 표 */
.cr-drill { margin-top: var(--sp-3); border: 1px dashed var(--border); border-radius: var(--radius); padding: var(--sp-2) var(--sp-3); }
.cr-drill > summary { cursor: pointer; font-size: var(--fs-small); font-weight: 600; color: var(--ink-2); }
.cr-drill[open] > summary { margin-bottom: var(--sp-2); }
/* 🚨 사고 구간에 걸린 소재 — 카드 수치는 사고 행 제외값 (C-1 · 2026-09-21). 사진 위 배지라 고정 적색 */
.cr-badge-inc { position: absolute; left: 6px; top: 6px; z-index: 2;
  font-size: 10px; font-weight: 800; color: #fff; background: rgba(220,38,38,.92);
  padding: 2px 7px; border-radius: 999px; letter-spacing: -.2px; }
.cr-thumb .cr-badge-type + .cr-badge-inc, .cr-thumb .cr-badge-inc ~ .cr-badge-type { top: 28px; }
/* ✅ 사람이 시트에서 확정한 링크 — 세 등급 중 최상 (C-2 · 2026-09-21). 사진 위 배지라 고정 녹색 */
.cr-badge-human { position: absolute; right: 6px; top: 6px; z-index: 2;
  font-size: 10px; font-weight: 800; color: #fff; background: rgba(22,163,74,.92);
  padding: 2px 7px; border-radius: 999px; letter-spacing: -.2px; }
/* 이미지 대조로 찾은 썸네일 — 토큰 추정(앰버)보다 근거가 강하므로 색을 나눈다 */
.cr-badge-api { position: absolute; right: 6px; top: 6px; z-index: 2;
  font-size: 10px; font-weight: 800; color: #fff; background: rgba(13,110,120,.92);
  padding: 2px 7px; border-radius: 999px; letter-spacing: -.2px; }

/* 📊 매체별 주차 성과 (channels.js wowTableHtml) — 값 아래 전주比·전월比 2줄 */
.wow-pick { font-size: var(--fs-small); font-weight: 400; color: var(--ink-2); margin-left: var(--sp-3); }
.wow-pick select { font: inherit; padding: 2px var(--sp-2); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink-1); }
.tbl-wow td.num { vertical-align: top; padding-top: 7px; padding-bottom: 7px; }
.tbl td .wow { display: block; margin-top: 3px; line-height: 1.4; }
.tbl td .wow i { display: block; font-style: normal; font-weight: 700; font-size: 10px; color: var(--ink-3); }
.tbl td .wow i.up { color: var(--sig-green); }
.tbl td .wow i.dn { color: var(--sig-red); }
.tbl td .wow i.na { color: var(--ink-3); opacity: .55; }
.tbl-wow .tw { display: inline-block; width: 12px; color: var(--ink-3); }

/* 📄 리포트 탭 (report.js) — 하위 탭 · 섹션 제목 · 발행 복사 */
.subtabs { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.subtab { border: 1px solid var(--border); background: var(--surface); color: var(--ink-2); font: inherit; font-weight: 700; font-size: var(--fs-small); padding: var(--sp-2) var(--sp-4); border-radius: var(--radius-pill); cursor: pointer; }
.subtab:hover { background: var(--surface-sub); }
.subtab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.rep-h3 { font-size: var(--fs-small); font-weight: 800; color: var(--ink-1); margin: var(--sp-5) 0 var(--sp-2); }
.rep-h3:first-of-type { margin-top: var(--sp-2); }
.rep-copy { margin-left: var(--sp-3); font-size: var(--fs-caption); }
.rep-copy-src { display: none; width: 100%; min-height: 200px; margin-top: var(--sp-3); font-family: var(--font-mono, monospace); font-size: 11px; line-height: 1.5; padding: var(--sp-3); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-sub); color: var(--ink-1); }

/* 📣 유입 상세 드릴다운 (utm_amp.js) — 캠페인·콘텐츠 단계 + 매체 리포트 갭 */
.tbl .tw { display: inline-block; width: 12px; color: var(--ink-3); }
.tbl-utm td.txt { max-width: 460px; overflow: hidden; text-overflow: ellipsis; }
.tbl-utm td.gap-bad { color: var(--sig-red); font-weight: 700; }
.tbl-utm td.gap-ok { color: var(--sig-green); font-weight: 700; }
/* 위 두 규칙은 .tbl-utm 전용이라 다른 표(관제탑 지면별 퍼널·고객 분석)에서는 색이 안 났다 → 전역화 */
.tbl td.gap-bad { color: var(--sig-red); font-weight: 700; }
.tbl td.gap-ok { color: var(--sig-green); font-weight: 700; }
/* 카드 제목 옆 '스냅샷' 뱃지 — 이 카드만 기간 필터를 안 따른다는 경고 */
.tag-snap { font-size: 10.5px; font-weight: 800; color: var(--sig-yellow); background: var(--sig-yellow-bg);
  border-radius: var(--radius-pill); padding: 2px 9px; letter-spacing: .01em; }

/* 📄 리포트 — 보고서 머리 3블록 (report.js) */
.rep-lead { font-size: var(--fs-small); line-height: 1.65; color: var(--ink-1); background: var(--info-bg); border-left: 4px solid var(--primary); border-radius: var(--radius-sm); padding: var(--sp-3) var(--sp-4); margin: var(--sp-3) 0 var(--sp-4); }
.rep-lead.good { border-left-color: var(--sig-green); background: var(--sig-green-bg); }
.rep-lead.danger { border-left-color: var(--sig-red); background: var(--sig-red-bg); }
.rep-score { margin-bottom: var(--sp-4); }
.rep-score .chip { min-width: 160px; flex: 1 1 160px; }
.rep-score .c-sub { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 3px; }
.verdicts { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--sp-3); margin-bottom: var(--sp-2); }
.vcol { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--sp-3); background: var(--surface-sub); }
.vcol .vhead { font-weight: 800; font-size: var(--fs-small); margin-bottom: var(--sp-2); }
.vcol ul { margin: 0; padding-left: 1.1em; }
.vcol li { font-size: var(--fs-caption); line-height: 1.6; color: var(--ink-2); margin-bottom: 4px; }
.vcol li.none { color: var(--ink-3); list-style: none; margin-left: -1.1em; }
.vcol.v-good { border-left: 3px solid var(--sig-green); }
.vcol.v-bad { border-left: 3px solid var(--sig-red); }
.vcol.v-watch { border-left: 3px solid var(--sig-yellow); }
.rep-detail > summary { cursor: pointer; font-weight: 700; font-size: var(--fs-small); color: var(--ink-2); padding: var(--sp-2) 0; }
.rep-detail > summary:hover { color: var(--ink-1); }

/* 🗂️ 탭별 요약 (tab_summary.js) — 종합 대시보드 중단 */
.ts-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--sp-3); }
.ts-card { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--sp-3); background: var(--surface-sub); cursor: pointer; transition: border-color .12s, transform .12s; }
.ts-card:hover { border-color: var(--primary); transform: translateY(-1px); }
.ts-head { display: flex; align-items: center; gap: 6px; font-weight: 800; font-size: var(--fs-small); color: var(--ink-1); margin-bottom: var(--sp-2); }
.ts-ico { font-size: 14px; }
.ts-go { margin-left: auto; font-size: 10.5px; font-weight: 700; color: var(--ink-3); }
.ts-card:hover .ts-go { color: var(--primary); }
.ts-stats { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-2); }
.ts-stat { min-width: 90px; }
.ts-l { font-size: 10.5px; color: var(--ink-3); font-weight: 700; }
.ts-v { font-family: var(--font-display); font-size: 17px; font-weight: 800; color: var(--ink-1); line-height: 1.25; }
.ts-s { font-size: 10px; color: var(--ink-3); line-height: 1.4; }
.ts-i { font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.55; border-top: 1px solid var(--border-soft); padding-top: var(--sp-2); }

/* 사이드바 하위 항목 — 종합 대시보드 아래 주간/월간 리포트 (index.html .nav-sub) */
.tab-btn.nav-sub { padding-left: calc(var(--sp-4) + 14px); font-size: var(--fs-caption); }
.tab-btn.nav-sub .nav-ico { opacity: .85; }
.tab-btn.nav-sub { position: relative; }
.tab-btn.nav-sub::before { content: '└'; position: absolute; left: var(--sp-3); color: var(--ink-3); font-size: 10px; }

/* 📅 데이터 기준일 바 (index.html #data-asof · data.js buildFreshness) — 2026-08-18
   헤더 우측 작은 배지는 배지 4개에 묻혀 아무도 못 봤다 → 전체 폭으로 빼고 기준일 2축을 함께 노출 */
.data-asof { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3);
  border: 1px solid var(--sig-green); border-left: 5px solid var(--sig-green);
  background: var(--sig-green-bg); border-radius: var(--radius-sm);
  padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-3); }
.data-asof.stale { border-color: var(--sig-yellow); border-left-color: var(--sig-yellow); background: var(--sig-yellow-bg); }
.data-asof[hidden] { display: none; }
.asof-ico { font-size: 17px; line-height: 1; }
.asof-t { font-weight: 800; font-size: var(--fs-small); color: var(--ink-1); }
.asof-item { display: inline-flex; align-items: baseline; gap: 6px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 3px 10px; }
.asof-k { font-size: 10.5px; font-weight: 700; color: var(--ink-3); }
.asof-d { font-family: var(--font-display); font-size: 15px; font-weight: 800; color: var(--ink-1); }
.asof-s { font-size: 10.5px; font-weight: 800; border-radius: var(--radius-pill); padding: 1px 7px; }
.asof-s.ok { color: var(--sig-green); background: var(--sig-green-bg); }
.asof-s.warn { color: var(--sig-yellow); background: var(--sig-yellow-bg); }
.asof-s.bad { color: var(--sig-red); background: var(--sig-red-bg); }
.asof-s.na { color: var(--ink-3); background: var(--surface-sub); }
.asof-note { flex: 1 1 100%; font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.55; }

/* 번호 없는 카드 (🗂️ 탭별 요약 등) — 자동 번호 ①②③에서 제외 */
.card.card-plain > h2 { counter-increment: none; }
.card.card-plain > h2::before { content: none; }

/* 🗂️ 탭별 요약 — 8장을 한 줄에 (2026-08-18 사용자 지정). 좁은 화면에선 자동 축소·줄바꿈 */
.ts-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); gap: var(--sp-2); }
.ts-card { padding: var(--sp-2) var(--sp-3); }
.ts-head { font-size: var(--fs-caption); margin-bottom: 6px; gap: 4px; }
.ts-go { display: none; }  /* 폭이 좁아 숨김 — 카드 전체가 클릭 대상이고 hover 시 테두리로 표시 */
.ts-stats { flex-direction: column; gap: 5px; margin-bottom: 6px; }
.ts-stat { min-width: 0; }
.ts-v { font-size: 15px; }
.ts-l, .ts-s { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 해석은 절대 숨기지 않는다 (수치+해석은 이 프로젝트 1번 룰) — 폭이 아니라 높이로 흡수한다 */
.ts-i { font-size: 10.5px; line-height: 1.45; padding-top: 6px;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
/* 8장 한 줄 유지가 목표 — 노트북(1440)에서도 한 줄이 되도록 브레이크포인트를 낮춘다 */
@media (max-width: 1240px) { .ts-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .ts-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* 🛰️ 관제탑 (control_tower.js) — 성과 요약 타일 · 퍼널 차트 */
/* 2026-09-22 디자인 점검: 9열 고정이 1300~1600px에서 ₩1,960,123,222(약 19.6억) 같은 전체 자릿수 금액을 잘라냈다(금액 축약 금지 룰과 충돌).
   → 열 수는 폭에 맞춰 자동(최소 180px), 타일 간격 sp-3, 값·라벨은 말줄임 대신 줄바꿈. (약 N억) 괄호는 <small>로 한 덩어리 줄바꿈. */
.ct-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--sp-3); width: 100%; margin-bottom: var(--sp-4); }
.ct-grid.ct-grid-4 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.ct-grid.ct-grid-6 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.ct-tile { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); background: var(--surface-sub); min-width: 0; }
.ct-l { font-size: 10.5px; font-weight: 700; color: var(--ink-3); white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.3; }
.ct-v { font-family: var(--font-display); font-size: 17px; font-weight: 800; color: var(--ink-1); line-height: 1.3; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
/* 사고 구간이 섞인 타일 — 숫자를 그대로 믿으면 안 된다는 표시 (2026-09-09 회원수 증감 카드) */
.ct-tile.ct-tile-warn { border-color: var(--sig-red); background: var(--sig-red-bg); }
.ct-tile.ct-tile-warn .ct-l { color: var(--sig-red); }
.ct-d { margin-top: 2px; }
.ct-d .wow i { font-size: 10.5px; font-weight: 800; }
.ct-s { font-size: 10px; color: var(--ink-3); line-height: 1.4; }
.chart-box.chart-sm { height: 220px; }
@media (max-width: 900px)  { .ct-grid, .ct-grid.ct-grid-4, .ct-grid.ct-grid-6 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-2); } }

/* .wow 증감 색 — 표 밖(관제탑 타일 등)에서도 적용되도록 전역 규칙 (기존 .tbl td .wow 는 표 전용이었음) */
.wow i { display: block; font-style: normal; font-weight: 700; font-size: 10px; line-height: 1.4; color: var(--ink-3); }
.wow i.up { color: var(--sig-green); }
.wow i.dn { color: var(--sig-red); }
.wow i.na { color: var(--ink-3); opacity: .55; }

/* 타일 하단 보조 문구 — 세그먼트마다 줄바꿈 (2026-08-19 가시성 개선) */
ul.seg { margin: 0; padding-left: 1.05em; list-style: disc; }
.seg-i { display: list-item; line-height: 1.5; }
.seg-i + .seg-i { margin-top: 1px; }
.seg-i::marker { color: var(--ink-3); font-size: .85em; }

/* 타일·칩 그리드 — (구) 2026-08-19 한 줄 고정(grid-auto-flow:column + 가로 스크롤)은 1300~1600px에서
   기간 합계 13칩이 화면 밖으로 밀려 ₩1,960,123,222(약 19.6억)가 잘렸다(2026-09-22 사용자 실측).
   → 폭에 맞춰 열 수를 정하고(최소 190px) 넘치면 다음 줄로. 타일 간격 sp-3, 전체 폭 사용. */
.tile-grid {
  display: grid; grid-auto-flow: row; grid-auto-columns: auto;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-3); width: 100%; overflow-x: visible; padding-bottom: 0;
}
/* .chips 는 KPI 카드 안에 중첩돼 있어(좁은 부모) 한 줄로 강제하면 글자가 짓눌린다 →
   기본은 기존 flex-wrap 유지. 폭이 넉넉한 곳만 .chips-row 로 한 줄을 지정한다. */
.chips.chips-row {
  display: grid; grid-auto-flow: row; grid-auto-columns: auto;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-3); width: 100%; overflow-x: visible; padding-bottom: 0;
}
.tile-grid > *, .chips-row > * { min-width: 0; }
.chips-row .chip { min-width: 0; overflow: visible; }
.tile-grid > * { overflow: visible; }
/* 값·라벨은 줄바꿈 — (구) 말줄임은 '가입 CPA (사이트, ₩)' 같은 라벨의 끝을 숨겼다 (2026-09-22) */
.tile .t-label, .chip .c-label { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.3; }
.chip .c-value, .tile .t-value, .metric-tile .m-value { white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }

/* ══════════════════════════════════════════════════════════════════
   디자인 개선안 C·D (2026-08-19) — 표현 계층만, 데이터 로직 무관
   ══════════════════════════════════════════════════════════════════ */

/* C안 — 범례(.howto) 접기. ui_polish.js가 긴 것에만 .howto-clamp를 붙인다.
   ⚠ 수치 해석 스트립은 대상 아님 (CLAUDE.md 수치+해석 동시 노출 룰 유지) */
.card .howto.howto-clamp {
  /* 1줄로 접는다 — 2줄(2.7em)로 접던 때는 원문이 대개 2~3줄이라 0~1줄만 가려져서
     '눌러도 그대로'로 보였다 (2026-08-24 사용자 신고). */
  position: relative; max-height: 1.55em; overflow: hidden;
  cursor: pointer; padding-right: 76px;
}
.card .howto.howto-clamp::after {
  content: '▸ 정의 펼치기'; position: absolute; right: 0; bottom: 0;
  color: var(--primary); font-weight: 700; padding-left: 26px;
  background: linear-gradient(90deg, transparent, var(--surface) 32%);
}
.card .howto.howto-clamp:hover::after { text-decoration: underline; }
.card .howto.howto-clamp.howto-open { max-height: none; padding-right: 0; padding-bottom: 1.5em; }
.card .howto.howto-clamp.howto-open::after { content: '▾ 접기'; background: none; padding-left: 0; }
.card .howto.howto-clamp:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--radius-sm); }

/* D안 — 섹션 목차 레일 (position:fixed — 본문 레이아웃을 밀지 않는다) */
.sec-toc {
  position: fixed; right: 14px; top: 96px; width: 172px; max-height: 72vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--sp-2); box-shadow: var(--shadow); z-index: 40;
}
.sec-toc-t {
  font-size: 9.5px; font-weight: 800; letter-spacing: .05em; color: var(--ink-3);
  padding: 2px var(--sp-2) var(--sp-2);
}
.sec-toc a {
  display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--ink-2);
  padding: 5px 8px; border-radius: var(--radius-sm); text-decoration: none;
  border-left: 2px solid transparent;
}
.sec-toc a em {
  flex: none; width: 15px; height: 15px; border-radius: 50%; font-style: normal;
  background: var(--border); color: var(--ink-2);
  font-size: 9px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center;
}
.sec-toc a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sec-toc a:hover { background: var(--surface-sub); color: var(--ink); }
.sec-toc a.on { color: var(--primary); background: var(--primary-bg); border-left-color: var(--primary); font-weight: 700; }
.sec-toc a.on em { background: var(--panel-acc, var(--primary)); color: #fff; }
/* 본문이 풀 화면 폭이라 레일이 겹친다 — 레일이 보이는 폭에서만 본문 우측 여백을 확보 */
@media (min-width: 1641px) { .main { padding-right: calc(172px + var(--sp-5) + 14px); } }
/* 화면이 좁으면 겹치므로 숨긴다 */
@media (max-width: 1640px) { .sec-toc { display: none !important; } }
@media print { .sec-toc { display: none !important; } }

/* ── B안 (2026-08-19) — 넓은 표 그룹화·고정·강조 ─────────────────
   19열 표를 퍼널 4단계로 묶고, 매체명 열을 고정하고, 결론 지표(ROAS)에만 색을 준다.
   .tbl-grp 가 붙은 표에만 적용 — 다른 표는 그대로. */

/* 그룹 헤더 행 */
.tbl-grp thead tr.grp-head th {
  font-size: 10px; font-weight: 800; letter-spacing: .06em;
  padding: 3px var(--sp-1); border-bottom: 1px solid var(--border);
}
.tbl-grp .grp-head .g-input { color: var(--ink-3); background: var(--surface-sub); }
.tbl-grp .grp-head .g-traffic { color: var(--primary); background: var(--primary-bg); }
.tbl-grp .grp-head .g-explore { color: var(--acc-kpi); background: color-mix(in srgb, var(--acc-kpi) 10%, transparent); }
.tbl-grp .grp-head .g-result { color: var(--sig-green); background: var(--sig-green-bg); }

/* 매체명 열 고정 — 가로 스크롤해도 어느 매체 행인지 잃지 않는다 */
.tbl-grp th:first-child, .tbl-grp td:first-child {
  position: sticky; left: 0; z-index: 2;
  background: var(--surface);
  box-shadow: 2px 0 4px -2px rgba(0, 0, 0, .18);
}
.tbl-grp thead th:first-child { background: var(--surface-sub); z-index: 3; }
.tbl-grp tr.row-total td:first-child { background: var(--brand-soft); }
.tbl-grp tr.drill td:first-child { background: var(--surface-sub); }

/* 비중 셀 — 숫자 뒤 비율 막대 */
.tbl-grp td.share-cell { position: relative; }
.tbl-grp td.share-cell > i {
  position: absolute; left: var(--sp-1); top: 50%; transform: translateY(-50%);
  height: 12px; border-radius: 2px; background: var(--brand); opacity: .2;
}
.tbl-grp td.share-cell > span { position: relative; }

/* ROAS 히트맵 — 결론 지표에만 (시리즈 색 재사용 아님, 상태 표현) */
.tbl-grp td.hm-a { background: color-mix(in srgb, var(--sig-green) 22%, transparent); }
.tbl-grp td.hm-b { background: color-mix(in srgb, var(--sig-green) 13%, transparent); }
.tbl-grp td.hm-c { background: color-mix(in srgb, var(--sig-green) 6%, transparent); }
.tbl-grp td.hm-d { background: color-mix(in srgb, var(--sig-yellow) 14%, transparent); }

/* ── A안 (2026-08-19) — 탭별 요약 우선순위 3단 ────────────────────
   급한 것 1개(대형·빨강) · 주의 최대 3개(중형·앰버) · 정상은 칩.
   8장 전체는 지우지 않고 .ts-grid-fold 로 접어 둔다. */

/* 1단 — 가장 급한 신호 */
.ts-prio {
  display: flex; align-items: center; gap: var(--sp-4); cursor: pointer;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 4px solid var(--sig-red); border-radius: var(--radius-sm);
  padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-2);
  transition: border-color .12s, transform .12s;
}
.ts-prio:hover { transform: translateY(-1px); border-color: var(--sig-red); }
.ts-prio-body { min-width: 0; }
.ts-prio-k {
  font-size: var(--fs-caption); font-weight: 800; color: var(--sig-red);
  background: var(--sig-red-bg); padding: 2px 9px; border-radius: var(--radius-pill);
}
.ts-prio-h { font-family: var(--font-display); font-size: 19px; font-weight: 800; margin: 6px 0 3px; letter-spacing: -.4px; }
.ts-prio-w { font-size: var(--fs-small); color: var(--ink-2); line-height: 1.5; }
.ts-prio-go {
  margin-left: auto; flex: none; font-size: var(--fs-small); font-weight: 700;
  color: var(--primary); background: var(--primary-bg);
  padding: 8px var(--sp-3); border-radius: var(--radius-sm); white-space: nowrap;
}

/* 2단 — 주의 */
.ts-watch-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); margin-bottom: var(--sp-2); }
.ts-watch {
  cursor: pointer; background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--sig-yellow); border-radius: var(--radius-sm);
  padding: var(--sp-2) var(--sp-3); transition: border-color .12s, transform .12s;
}
.ts-watch:hover { transform: translateY(-1px); border-color: var(--sig-yellow); }
.ts-watch-t { font-family: var(--font-display); font-size: 14.5px; font-weight: 800; letter-spacing: -.3px; }
.ts-watch-s { font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.5; margin-top: 3px; }

/* 3단 — 정상 칩 */
.ts-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: var(--sp-2); }
.ts-chip {
  cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-caption); color: var(--ink-2);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 4px 11px;
}
.ts-chip:hover { color: var(--ink); border-color: var(--primary); }
.ts-chip > i { width: 6px; height: 6px; border-radius: 50%; background: var(--sig-green); flex: none; }
/* 펼치기 버튼 — 칩 줄 끝의 11.5px 링크였을 때 아무도 못 찾았다 → 카드 폭 전체 바로 승격 */
.ts-more {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; margin-top: var(--sp-3);
  font-family: var(--font); font-size: var(--fs-body); font-weight: 800; text-align: left;
  color: var(--primary); background: var(--primary-bg);
  border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent);
  border-radius: var(--radius); padding: 13px var(--sp-4); cursor: pointer;
}
.ts-more:hover {
  background: color-mix(in srgb, var(--primary) 12%, var(--surface));
  border-color: var(--primary); box-shadow: var(--shadow);
}
.ts-more:active { transform: scale(.995); }
.ts-more-ico {
  font-size: 13px; line-height: 1; flex: none;
  width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; background: var(--primary);
}
.ts-more.open .ts-more-ico { transform: rotate(180deg); }
.ts-more-s {
  margin-left: auto; font-size: var(--fs-caption); font-weight: 600; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 900px) { .ts-more-s { display: none; } }

/* 8장 전체 — 기본 접힘 */
.ts-grid-fold { display: none; }
.ts-grid-fold.open { display: grid; margin-top: var(--sp-3); }

@media (max-width: 1100px) {
  .ts-watch-row { grid-template-columns: 1fr; }
  .ts-prio { flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
  .ts-prio-go { margin-left: 0; }
}

/* ── 전체 퍼널 스트립 (📣 매체별 성과 요약 상단 · 2026-08-24) ──────────────
   막대 길이는 로그 스케일 — 노출(수천만)과 구매(수천)의 자릿수 차이를 흡수한다. */
.fn-wrap { margin: var(--sp-2) 0 var(--sp-3); }
.fn-row { display: grid; grid-template-columns: 150px 1fr 120px; align-items: center; gap: var(--sp-2); }
.fn-name { font-size: var(--fs-caption); font-weight: 700; color: var(--ink); line-height: 1.25; }
.fn-name .fn-sub { display: block; font-weight: 400; color: var(--ink-3); }
.fn-bar { background: var(--surface-sub); border-radius: var(--radius-sm); height: 22px; overflow: hidden; }
.fn-bar > i {
  display: block; height: 100%; border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--primary), var(--acc-kpi));
}
.fn-val { text-align: right; font-size: var(--fs-caption); font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; }
.fn-gap { grid-column: 2; margin: 3px 0 3px 150px; padding-left: var(--sp-2);
  font-size: var(--fs-caption); color: var(--ink-2); border-left: 2px dotted var(--border); }
.fn-gap b { color: var(--ink); }
@media (max-width: 700px) {
  .fn-row { grid-template-columns: 96px 1fr 84px; }
  .fn-gap { margin-left: 96px; }
}

/* Breakdown 표 — 각 행이 무엇과 비교됐는지 (2026-08-24) */
.trend-cmp { display: block; font-size: var(--fs-caption); color: var(--ink-3); font-weight: 400; }

/* 👑 기네스 — 지금 집행 중 최고 성과 (2026-08-25) ---------------------------- */
/* 부문(기획전·매체·소재)별 1위를 나란히. 색·간격은 전부 토큰으로만 잡는다. */
.gns-wrap { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin-top: var(--sp-3); }
.gns-item { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--sp-3);
  background: var(--surface-sub); border-top: 3px solid var(--sig-green); }
.gns-dim { font-size: var(--fs-caption); color: var(--ink-3); letter-spacing: var(--ls-tight); }
.gns-name { font-size: var(--fs-body); font-weight: 700; color: var(--ink); margin-top: 2px;
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; word-break: break-all; }
.gns-crown { font-size: 1.15em; line-height: 1; }
.gns-rec { font-size: var(--fs-caption); font-weight: 700; color: var(--sig-green);
  border: 1px solid var(--sig-green); border-radius: var(--radius-pill); padding: 0 6px; white-space: nowrap; }
.gns-roas { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 700;
  color: var(--sig-green); font-variant-numeric: tabular-nums; margin-top: var(--sp-1); }
.gns-sub { font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.5; margin-top: 2px; }
/* 이슈 카드 안 기네스 알림 줄 — 경고가 아니라 알림이라 초록 계열 */
.interp.gns-alert { border-left-color: var(--sig-green); background: var(--sig-green-bg); margin-bottom: var(--sp-2); }
/* 표 안 1위 왕관 */
.tbl .row-crown { margin-right: 4px; }

/* 👑 기네스 — 🗂️ 오늘 봐야 할 것 카드 안 3칸 줄 (2026-08-25) */
.ts-gns-head { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
  margin-top: var(--sp-3); font-family: var(--font-display); font-size: 14.5px;
  font-weight: 800; letter-spacing: -.3px; color: var(--ink); }
.ts-gns-note { font-family: var(--font); font-size: var(--fs-caption); font-weight: 400; color: var(--ink-3); }
.ts-gns-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-2); margin-top: 6px; margin-bottom: var(--sp-2); }
.ts-gns { cursor: pointer; background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--sig-green); border-radius: var(--radius-sm);
  padding: var(--sp-2) var(--sp-3); transition: border-color .12s, transform .12s; }
.ts-gns:hover { transform: translateY(-1px); border-color: var(--sig-green); }
.ts-gns-t { font-size: var(--fs-caption); color: var(--ink-3); display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.ts-gns-rec { font-weight: 700; color: var(--sig-green); border: 1px solid var(--sig-green);
  border-radius: var(--radius-pill); padding: 0 5px; white-space: nowrap; }
.ts-gns-n { font-family: var(--font-display); font-size: 14.5px; font-weight: 800;
  letter-spacing: -.3px; color: var(--ink); margin-top: 2px;
  overflow: visible; text-overflow: clip; white-space: normal; overflow-wrap: anywhere; }   /* 2026-09-22 소재명 전체 노출 */
.ts-gns-v { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 700;
  color: var(--sig-green); font-variant-numeric: tabular-nums; line-height: 1.1; margin-top: 2px; }
.ts-gns-s { font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.5; margin-top: 2px; }
@media (max-width: 700px) { .ts-gns-row { grid-template-columns: 1fr; } }

/* 소스 신선도 + 어트리뷰션 배지 (2026-08-26) — 숫자를 읽기 전에 기준부터 */
.ts-fresh-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: var(--sp-3); }
.ts-fresh { font-size: var(--fs-caption); color: var(--ink-2); background: var(--surface-sub);
  border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 2px 9px; white-space: nowrap; }
.ts-fresh b { color: var(--ink); font-variant-numeric: tabular-nums; }
.ts-fresh.lag { border-color: var(--sig-red); background: var(--sig-red-bg); }
.ts-fresh.lag i { font-style: normal; color: var(--sig-red); font-weight: 700; }
.ts-fresh.attr-on { border-color: var(--primary); background: var(--primary-bg); }
.ts-fresh-note { font-size: var(--fs-caption); color: var(--ink-3); }

/* 주 단위 퍼널 변화 — 변화 없음 표기 (2026-08-27) */
.tbl .wow i.fw-flat { color: var(--ink-3); }

/* 데이터 갱신 알림 배너 — js/fresh_watch.js
   열어둔 탭이 옛 숫자를 보여주는 걸 막는다. 자동 reload는 하지 않으므로
   사용자가 놓치지 않게 상단 고정 + 대비 높은 배경을 쓴다. */
#fresh-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 9999;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  background: var(--primary); color: #fff;
  font-size: var(--fs-small); font-weight: 600;
  box-shadow: var(--shadow);
}
#fresh-bar .fresh-txt { flex: 1; min-width: 0; }
#fresh-bar .fresh-go {
  flex: none; border: 0; cursor: pointer;
  border-radius: var(--radius-sm); padding: var(--sp-1) var(--sp-3);
  background: #fff; color: var(--primary);
  font-size: var(--fs-small); font-weight: 800;
}
#fresh-bar .fresh-x {
  flex: none; border: 0; cursor: pointer; background: transparent; color: #fff;
  font-size: var(--fs-h); line-height: 1; padding: 0 var(--sp-1); opacity: .8;
}
#fresh-bar .fresh-x:hover { opacity: 1; }
@media (max-width: 640px) {
  #fresh-bar { flex-wrap: wrap; gap: var(--sp-2); }
  #fresh-bar .fresh-txt { flex-basis: 100%; }
}

/* 주 단위 퍼널 변화 — 단계별 미니 라인 4개 (js/control_tower.js)
   단계마다 정상 범위가 달라 한 축에 겹칠 수 없다. 각 셀이 자기 축을 갖는다. */
.fw-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-3); margin: var(--sp-3) 0;
}
.fw-cell {
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  padding: var(--sp-2) var(--sp-3); background: var(--surface-sub); min-width: 0;
}
.fw-head { font-size: var(--fs-caption); color: var(--ink-2); }
.fw-head .fw-sub { color: var(--ink-3); margin-left: var(--sp-1); font-weight: 500; }
.fw-now {
  font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 800;
  display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
}
.fw-now .fw-d { font-family: var(--font); font-size: var(--fs-caption); font-weight: 700;
  font-style: normal; color: var(--ink-3); }
.fw-now .fw-d.up { color: var(--sig-green); }
.fw-now .fw-d.dn { color: var(--sig-red); }
.fw-chart { height: 96px; margin-top: var(--sp-1); }
@media (max-width: 1100px) { .fw-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .fw-grid { grid-template-columns: 1fr; } }

/* 어필리에이트 — 매출 기여율이 목표를 넘은 날 (js/affiliate.js) */
.tbl tr.aff-hit > td { background: var(--sig-green-bg); }
.tbl tr.aff-hit > td:first-child { box-shadow: inset 3px 0 0 var(--sig-green); font-weight: 700; }
.aff-flag { font-size: var(--fs-caption); }

/* 이번 달 주요 프로모션 — 종료된 행사 접기 (js/overview.js)
   진행 중·예정은 항상 전부 보이고, 종료만 이 버튼 아래로 내린다. */
.promo-more { margin-top: var(--sp-2); }
.promo-strip.promo-done { margin-top: var(--sp-2); opacity: .78; }

/* KPI 6칸 — 매출 카드 추가(2026-08-31)로 5→6장이 됐다.
   grid-5의 반응형 단계를 그대로 쓰되 최상단만 6칸으로 넓힌다. */
.grid.grid-kpi6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 1600px) { .grid.grid-kpi6 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1024px) { .grid.grid-kpi6 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .grid.grid-kpi6 { grid-template-columns: 1fr; } }

/* 완성본 라이브러리 매체 칩 (js/creative.js) — 범위 버튼과 같은 형태를 쓰되
   칩이 많아 줄바꿈되므로 wrap + 개수 배지를 얹는다. */
.cr-chan-pick { flex-wrap: wrap; row-gap: var(--sp-1); }
.cr-chan {
  font-family: var(--font); font-size: var(--fs-small); font-weight: 700;
  color: var(--ink-2); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 6px 12px; cursor: pointer;
}
.cr-chan:hover { color: var(--ink); border-color: var(--primary); }
.cr-chan.on { color: #fff; background: var(--primary); border-color: var(--primary); }
.cr-chan b { font-weight: 800; opacity: .75; margin-left: 2px; }
.cr-chan.on b { opacity: .9; }
.cr-chan[data-chan="none"] { border-style: dashed; color: var(--ink-3); }
.cr-chan[data-chan="none"].on { color: #fff; background: var(--sig-na); border-color: var(--sig-na); }

/* 월초 폴백 안내 — 기본 기간이 직전 달로 잡혔을 때만 뜬다. 기준일 바 안에서
   한 줄을 차지해, 지난달 수치를 이번 달로 오독하지 않게 못 박는다 (2026-09-02) */
.asof-fallback { display: block; flex-basis: 100%; margin-top: var(--sp-2);
  font-size: var(--fs-small); color: var(--ink-2);
  border-left: 3px solid var(--sig-yellow); padding-left: var(--sp-2); }

/* ══ 👥 회원 인사이트 (js/member.js · 2026-09-04) ═══════════════════════════
   카드 제목 옆 구간 배지 + 두 조각 분할 막대 + 이름·막대·값 3열 비교 행.
   Chart.js를 쓸 만큼 데이터가 많지 않은 비교(2개 항목·월 5행)에 쓴다. */
.card h2 .card-scope {
  font-family: var(--font); font-size: var(--fs-caption); font-weight: 700;
  color: var(--ink-3); background: var(--surface-sub);
  border: 1px solid var(--border-soft); border-radius: var(--radius-pill);
  padding: 2px 8px; white-space: nowrap;
}
/* 분할 막대 — 색 두 조각으로 전체 100%를 나눈다. 글자는 막대 안에 넣지 않는다
   (다크 모드에서 대비가 무너지고, 조각이 좁아지면 잘린다) → 아래 범례로 뺀다. */
.split-bar { display: flex; height: 22px; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--surface-sub); margin-bottom: var(--sp-2); }
.split-bar > span { display: block; height: 100%; }
.split-bar .sb-a { background: var(--sig-green); }
.split-bar .sb-b { background: var(--sig-yellow); }
.sb-key { display: inline-block; width: 10px; height: 10px; border-radius: 2px;
  vertical-align: middle; margin-right: 4px; }
.sb-key-a { background: var(--sig-green); }
.sb-key-b { background: var(--sig-yellow); }
/* 비교 행 — [이름 | 막대 | 값] */
.cmp-rows { display: block; }
.cmp-row { display: grid; grid-template-columns: 128px minmax(0, 1fr) auto;
  align-items: center; gap: var(--sp-3); margin-top: var(--sp-2); }
.cmp-row .cmp-name { font-size: var(--fs-caption); font-weight: 700; color: var(--ink-2); }
.cmp-row .cmp-track { display: block; height: 14px; background: var(--surface-sub);
  border-radius: var(--radius-sm); overflow: hidden; }
.cmp-row .cmp-fill { display: block; height: 100%; border-radius: var(--radius-sm); }
.cmp-row .cmp-val { font-family: var(--font-display); font-size: var(--fs-small);
  font-weight: 800; color: var(--ink); white-space: nowrap; }
.cmp-sub { font-size: var(--fs-caption); color: var(--ink-3);
  margin: 2px 0 0 calc(128px + var(--sp-3)); }
@media (max-width: 640px) {
  .cmp-row { grid-template-columns: 96px minmax(0, 1fr) auto; }
  .cmp-sub { margin-left: calc(96px + var(--sp-3)); }
}

/* ═══════════════════════════════════════════════════════════════════
   🔗 시트→DB 미러(Supabase) 상태 스트립 — js/mirror_status.js (2026-09-09)
   #data-asof(데이터 기준일 바) 바로 아래에 붙는다. 같은 "이 화면 데이터를 믿어도 되나"
   계열 정보라 옆에 둬야 읽히고, 종합 탭 안에 넣으면 다른 탭에서 안 보인다.
   정상일 때는 접힌 한 줄(중립 색), 지연·중단이면 펼친 채 신호색으로 바뀐다.
   색·간격·radius 하드코딩 금지 — 전부 var(--*) 토큰.
   ═══════════════════════════════════════════════════════════════════ */
.mirror-bar {
  border: 1px solid var(--border); border-left: 3px solid var(--sig-na);
  border-radius: var(--radius-sm); background: var(--surface-sub);
  padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3);
}
.mirror-bar.lv-ok   { border-left-color: var(--sig-green); }
.mirror-bar.lv-warn { border-left-color: var(--sig-yellow); background: var(--sig-yellow-bg); border-color: var(--sig-yellow); }
.mirror-bar.lv-bad  { border-left-color: var(--sig-red);    background: var(--sig-red-bg);    border-color: var(--sig-red); }
.mirror-bar.lv-na   { border-left-color: var(--sig-na); }

.mirror-bar > .ms-sum {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3);
  cursor: pointer; list-style: none;
}
.mirror-bar > .ms-sum::-webkit-details-marker { display: none; }
.ms-ico { font-size: 14px; line-height: 1; }
.ms-t { font-weight: 800; font-size: var(--fs-small); color: var(--ink); }
.ms-badge { font-size: 10.5px; font-weight: 800; border-radius: var(--radius-pill); padding: 1px 8px; }
.ms-badge.ok   { color: var(--sig-green);  background: var(--sig-green-bg); }
.ms-badge.warn { color: var(--sig-yellow); background: var(--surface); }
.ms-badge.bad  { color: var(--sig-red);    background: var(--surface); }
.ms-badge.na   { color: var(--ink-3);      background: var(--surface); }

.ms-body .ms-item { display: inline-flex; align-items: baseline; gap: var(--sp-1); }   /* 미러 카드 전용 — 필터 .ms-item(multi_select.js)과 클래스명이 겹쳐 2열로 흐트러졌던 것 격리 (2026-09-21) */
.ms-k { font-size: 10.5px; font-weight: 700; color: var(--ink-3); }
.ms-v { font-size: var(--fs-small); font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; }
.ms-rel { font-size: 10.5px; color: var(--ink-2); }
/* 펼침 힌트 — 접혀 있을 때만 "더 볼 게 있다"를 알린다 */
.ms-more { font-size: 10.5px; font-weight: 700; color: var(--primary); margin-left: auto; }
.ms-more::before { content: '▸ '; }
.mirror-bar[open] > .ms-sum .ms-more::before { content: '▾ '; }

/* 해석 — 수치+해석 동반 원칙(CLAUDE.md 1번 룰). 폭이 좁아도 숨기지 않고 줄로 흡수한다 */
.ms-i { flex: 1 1 100%; font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.6; }
.ms-i .ms-s { display: inline; }
.ms-i .ms-s:first-child { font-weight: 700; color: var(--ink); }

.ms-body { margin-top: var(--sp-3); border-top: 1px solid var(--border-soft); padding-top: var(--sp-3); }
.ms-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); margin-bottom: var(--sp-2); }
.ms-read { font-size: var(--fs-caption); color: var(--ink-2); line-height: 1.55; margin: 0 0 var(--sp-2); }
.ms-body .src-note { font-size: var(--fs-caption); color: var(--ink-3); opacity: .85; margin-top: var(--sp-2); }
.ms-body .tbl { max-width: 620px; }
.ms-body .tbl td.ms-gap { color: var(--sig-red); font-weight: 800; }

@media (max-width: 640px) {
  .ms-more { margin-left: 0; }
}

/* 고객분석 상단 회원 실적 KPI 6카드 (customer_kpi.js) — 스택바·범례·힌트 */
.ck-tile .ct-v small { font-family: var(--font-body); font-size: 10px; font-weight: 600; color: var(--ink-3); margin-left: 2px; }
.ck-bar { display: flex; height: 8px; border-radius: var(--radius-sm); overflow: hidden; background: var(--surface); margin: var(--sp-1) 0 2px; }
.ck-seg { display: block; height: 100%; }
.ck-legs { display: flex; flex-wrap: wrap; gap: 2px var(--sp-2); font-size: 10px; color: var(--ink-3); margin-bottom: 2px; }
.ck-leg b { display: inline-block; width: 7px; height: 7px; border-radius: 2px; margin-right: 3px; vertical-align: middle; }
.ck-vs { color: var(--ink-3); }
.ck-hint { color: var(--ink-2); margin-top: 2px; border-top: 1px dashed var(--border); padding-top: 2px; }
.ck-foot { margin-top: var(--sp-2); }
.ck-card > h3 { margin-bottom: var(--sp-3); }   /* 제목↔KPI 타일 사이 한 칸 (2026-09-21 사용자 지시) */

/* 🏆 어필리에이트 게시자 Tier 장표 (js/aff_tier.js · 2026-09-21 CR-19 §4-1) — Tier 배지·요약 스트립·승강 표시
   2026-09-22 CR-23 B-3: Tier는 분류라 신호등 색을 쓰지 않는다 → --tier-* 램프. C(점검)는 점선 테두리 + 🚩. */
.aft-strip { margin-bottom: var(--sp-3); }
.aft-cell-S { box-shadow: inset 3px 0 0 var(--tier-s); }
.aft-cell-A { box-shadow: inset 3px 0 0 var(--tier-a); }
.aft-cell-B { box-shadow: inset 3px 0 0 var(--tier-b); }
.aft-cell-C { box-shadow: inset 3px 0 0 var(--tier-c); border-style: dashed; }
.aft-tier { display: inline-block; font-size: var(--fs-caption); font-weight: 800; border-radius: var(--radius-pill); padding: 1px 8px; white-space: nowrap; }
.aft-S { color: var(--tier-s-ink); background: var(--tier-s); }
.aft-A { color: var(--tier-a-ink); background: var(--tier-a); }
.aft-B { color: var(--tier-b-ink); background: var(--tier-b); }
.aft-C { color: var(--tier-c-ink); background: var(--tier-c); outline: 1px dashed var(--ink-3); outline-offset: -1px; }
.aft-D { color: var(--tier-d-ink); background: var(--tier-d); }
.aft-up { color: var(--sig-green); font-weight: 700; }
.aft-down { color: var(--sig-red); font-weight: 700; }
.aft-same, .aft-new { color: var(--ink-3); }
.aft-card .tbl td.aft-move { white-space: normal; min-width: 220px; max-width: 420px; line-height: 1.45; }
.aft-b { margin-top: var(--sp-2); }

/* 📌 스코어보드 공용 (js/scoreboard.js · 2026-09-21 CR-22) — 전일·전주요일 구분 · 기준일 소스 뱃지 · 접이식 정의 */
.sb-src { display: inline-block; font-size: 9.5px; font-weight: 800; border-radius: var(--radius-pill); padding: 0 6px; margin-left: 2px; vertical-align: middle; }
.sb-src-pt { color: var(--info); background: var(--info-bg); }
.sb-src-amp { color: var(--acc-kpi); background: var(--sig-na-bg); }
.sb-how { margin-top: var(--sp-2); }
.sb-how > summary { cursor: pointer; user-select: none; font-size: var(--fs-caption); color: var(--ink-3); }
.sb-how > summary:hover { color: var(--ink-1); }
.sb-how-body { margin-top: var(--sp-1); line-height: 1.5; }
.sb-card .ct-v { white-space: normal; overflow: visible; text-overflow: clip; }   /* 값이 길면 줄바꿈 — 말줄임으로 자릿수를 숨기지 않는다 */
.sb-card .ct-v { font-size: 20px; }   /* CR-23 B-1: 스코어보드 값 20px 고정(.m-value와 동일) · 26px 신설 금지 · 금액은 전체 자릿수 + 줄바꿈 허용 */

/* 📣 유입 상세 — 흐름도(.utm-flow-) · 탐색기(.utm-ex-) · 표 토글 (js/utm_amp.js cardSrcMed · 2026-09-21 docs/SPEC_UTM_FLOW_EXPLORER_2026-09-21.md)
   색·간격·radius 전부 토큰 — 다크모드는 토큰 재정의로 자동. SVG fill도 var(--sig-*)만 쓴다. */
.utm-flow { margin: var(--sp-2) 0 var(--sp-2); }
.utm-flow-svg { display: block; width: 100%; max-width: none; height: auto; margin: 0; font-family: var(--font); }   /* 2026-09-22 카드 전폭 사용 (viewBox 1200×560) · 1600 넘으면 글자만 비대해져 상한 */
.utm-flow-band { opacity: .28; cursor: pointer; transition: opacity .15s; }
.utm-flow-band:hover, .utm-flow-band.sel { opacity: .55; }
.utm-flow-lbl { cursor: pointer; }
.utm-flow-lbl:hover { text-decoration: underline; }
.utm-flow-best-line { margin: var(--sp-2) 0 0; padding: var(--sp-2) var(--sp-3); font-size: var(--fs-caption);
  color: var(--ink-2); background: var(--brand-soft); border-radius: var(--radius-sm); }   /* 선택 조합 최고 소재 한 줄 (2026-09-23) */
.utm-flow-best-line b { color: var(--ink-1); }
.utm-flow-band.g4, .utm-flow-bar.g4 { fill: var(--sig-green); }
.utm-flow-band.g3, .utm-flow-bar.g3 { fill: var(--brand); }
.utm-flow-band.g2, .utm-flow-bar.g2 { fill: var(--sig-yellow); }
.utm-flow-band.g1, .utm-flow-bar.g1 { fill: var(--sig-red); }
.utm-flow-band.g0, .utm-flow-bar.g0 { fill: var(--sig-na); }
.utm-flow-lbl { font-size: 12.5px; fill: var(--ink-2); cursor: pointer; }   /* viewBox 1400로 넓혀 글자가 작아진 만큼 보정 (2026-09-23) */
.utm-flow-lbl.sel { font-weight: 800; fill: var(--ink); }
.utm-flow-axis { font-size: 12.5px; font-weight: 700; fill: var(--ink-3); }
.utm-flow-legend { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); font-size: var(--fs-caption); color: var(--ink-3); margin-top: var(--sp-1); }
.utm-flow-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 4px; vertical-align: -1px; }
.utm-flow-legend i.g4 { background: var(--sig-green); }
.utm-flow-legend i.g3 { background: var(--brand); }
.utm-flow-legend i.g2 { background: var(--sig-yellow); }
.utm-flow-legend i.g1 { background: var(--sig-red); }
.utm-flow-hint { color: var(--ink-2); font-weight: 700; }

.utm-sec { container-type: inline-size; }   /* 사이드바가 있어 뷰포트가 아니라 카드 폭으로 판단 (1024px 뷰포트 = 카드 ~750px) */
.utm-ex { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: var(--sp-3); margin-top: var(--sp-3); }   /* 2026-09-22 트리 300→340px */
@media (max-width: 820px) { .utm-ex { grid-template-columns: 1fr; } }
@container (max-width: 820px) { .utm-ex { grid-template-columns: 1fr; } .utm-ex-bd .tbl td.txt { max-width: 240px; } }
.utm-ex-l, .utm-ex-r { background: var(--surface-sub); border: 1px solid var(--border-soft); border-radius: var(--radius-sm); padding: var(--sp-3); min-width: 0; }
.utm-ex-h { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-2); font-size: var(--fs-caption); font-weight: 700; color: var(--ink-2); margin-bottom: var(--sp-2); }
.utm-ex-h small { font-weight: 400; color: var(--ink-3); }
.utm-ex-row { display: grid; grid-template-columns: 14px minmax(0, 1fr) 64px 44px; align-items: center; gap: var(--sp-1); padding: 3px var(--sp-1); border-radius: var(--radius-sm); font-size: var(--fs-small); color: var(--ink); cursor: pointer; }
.utm-ex-row:hover { background: var(--surface); }
.utm-ex-row.sel { background: var(--primary-bg); color: var(--primary); }
.utm-ex-row.lv2 { padding-left: calc(var(--sp-1) + 14px); font-size: var(--fs-caption); }
.utm-ex-row.lv3 { padding-left: calc(var(--sp-1) + 28px); font-size: var(--fs-caption); }
.utm-ex-tw { color: var(--ink-3); font-size: 10px; text-align: center; }
.utm-ex-name { overflow: visible; text-overflow: clip; white-space: normal; overflow-wrap: anywhere; line-height: 1.3; }   /* 2026-09-22 캠페인명 전체 노출 (말줄임 금지) */
.utm-ex-dot { display: inline-block; width: 8px; height: 8px; border-radius: var(--radius-pill); margin-right: 5px; background: var(--ink-3); }
.utm-ex-dot.paid { background: var(--acc-channel); }
.utm-ex-dot.crm { background: var(--acc-customer); }
.utm-ex-dot.aff { background: var(--acc-revenue); }
.utm-ex-dot.aeo { background: var(--acc-kpi); }
.utm-ex-dot.none { background: var(--sig-na); }
.utm-ex-dot.etc { background: var(--ink-3); }
.utm-ex-dot.paid2 { background: var(--acc-creative); }
.utm-ex-dot.org { background: var(--brand); }
.utm-ex-leg-note { flex-basis: 100%; color: var(--ink-3); }
.utm-ex-bar { height: 6px; background: var(--border); border-radius: 3px; overflow: hidden; }
.utm-ex-bar i { display: block; height: 100%; background: var(--primary); border-radius: 3px; }
.utm-ex-pct { text-align: right; font-variant-numeric: tabular-nums; font-size: var(--fs-caption); color: var(--ink-2); }
.utm-ex-row.sel .utm-ex-pct { color: inherit; }
.utm-ex-more { font-size: var(--fs-caption); color: var(--primary); cursor: pointer; padding: 4px var(--sp-1); user-select: none; }
.utm-ex-more:hover { text-decoration: underline; }
.utm-ex-leg { display: flex; flex-wrap: wrap; gap: 2px var(--sp-2); font-size: 10.5px; color: var(--ink-3); margin-top: var(--sp-2); border-top: 1px dashed var(--border); padding-top: var(--sp-1); }
.utm-ex-crumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1); font-size: var(--fs-small); color: var(--ink-2); margin-bottom: var(--sp-3); }
.utm-ex-crumb .cur { font-weight: 800; color: var(--ink); max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.utm-ex-crumb .utm-ex-sep { color: var(--ink-3); }
.utm-ex-crumb [data-utm-sel] { cursor: pointer; color: var(--primary); max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.utm-ex-crumb [data-utm-sel]:hover { text-decoration: underline; }
.utm-ex-chip { margin-left: var(--sp-1); }
.utm-ex-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); }
@media (max-width: 1100px) { .utm-ex-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.utm-ex-tiles .metric-tile { min-width: 0; overflow: hidden; }
.utm-ex-tiles .metric-tile .m-value { font-size: 17px; white-space: normal; overflow-wrap: anywhere; }   /* 전체 자릿수 유지 — 말줄임으로 자릿수를 숨기지 않는다 */
.utm-ex-gap { font-size: var(--fs-small); font-weight: 700; margin-left: var(--sp-1); color: var(--ink-2); }
.utm-ex-gap.gap-bad { color: var(--sig-red); }
.utm-ex-gap.gap-ok { color: var(--sig-green); }
.utm-ex-bd { margin-top: var(--sp-3); }
.utm-ex-bd .tbl-scroll { max-height: 520px; overflow-y: auto; }
.utm-ex-bd .tbl td.txt { max-width: 360px; overflow: hidden; text-overflow: ellipsis; }
.utm-ex-bd td.g4 { color: var(--sig-green); font-weight: 700; }
.utm-ex-bd td.g3 { color: var(--brand-strong); font-weight: 700; }
.utm-ex-bd td.g2 { color: var(--sig-yellow); font-weight: 700; }
.utm-ex-bd td.g1 { color: var(--sig-red); font-weight: 700; }
.utm-ex-note { margin: var(--sp-3) 0 0; }
.utm-ex-r .interp { margin: var(--sp-2) 0 var(--sp-3); }   /* 2026-09-22 해석이 타일 위로 올라와 아래 간격도 필요 */
.utm-ex-s + .utm-ex-s { margin-left: 2px; }
.utm-tbl-toggle { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); }
.utm-tbl-hint { font-size: var(--fs-caption); color: var(--ink-3); }
.utm-tbl-wrap { margin-top: var(--sp-2); }
.utm-tbl-wrap[hidden] { display: none; }
@media print {
  .utm-ex-l, .utm-tbl-toggle { display: none !important; }
  .utm-ex { grid-template-columns: 1fr; }
  .utm-flow-band { opacity: .4; }
}

/* ═══ CR-23 4탭 개편 공용 컴포넌트 (2026-09-22 docs/DESIGN_REVIEW_tabs4_2026-09-22.md §3) ═══ */

/* §3-2 신호등 배지 줄 (js/insight_badges.js) — .ts-chip 재사용 · 신규 클래스는 .ib-row/.ib-open 2개
   🔴 → 🟡 → 🟢 순 · 칩 클릭 → 아래로 한 문장 + 액션 펼침 · 빨강 개수 = 오늘 할 일 수 */
.ib-row { margin-top: 0; margin-bottom: var(--sp-2); }
.ib-row .ts-chip { font-weight: 700; }
.ib-row .ts-chip > i.ib-red { background: var(--sig-red); }
.ib-row .ts-chip > i.ib-yellow { background: var(--sig-yellow); }
.ib-row .ts-chip > i.ib-green { background: var(--sig-green); }
.ib-row .ts-chip > i.ib-na { background: var(--sig-na); }
.ib-row .ts-chip.ib-on { border-color: var(--primary); color: var(--ink); background: var(--primary-bg); }
.ib-open { display: none; font-size: var(--fs-small); color: var(--ink-2); line-height: 1.55; background: var(--surface-sub); border: 1px solid var(--border-soft); border-left: 3px solid var(--primary); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); margin: 0 0 var(--sp-2); }
.ib-open.ib-show { display: block; }
.ib-open.ib-red { border-left-color: var(--sig-red); }
.ib-open.ib-yellow { border-left-color: var(--sig-yellow); }
.ib-open.ib-green { border-left-color: var(--sig-green); }
.ib-open .ib-act { display: block; margin-top: 3px; color: var(--ink); font-weight: 700; }
.ib-count { font-size: var(--fs-caption); color: var(--ink-3); margin-left: auto; }

/* §3-3 쌍피라미드 .tier-pyramid (js/tier_pyramid.js · SVG) — 좌 = 개수 비중 · 우 = 판매/구매자 비중 · 층 높이 균등 · 좌우 스케일 독립
   B-4: 본문은 풀폭, 이 컴포넌트만 max-width 720px. 색은 --tier-* 램프만 (fill 속성에 var 사용). */
.tier-pyramid { max-width: 100%; margin: var(--sp-3) 0; }   /* 2026-09-28 가시성: 896px 캡 해제 → 카드 전폭 (viewBox 1100 기준 ×1.2 확대 렌더) */
.tier-pyramid svg { display: block; width: 100%; height: auto; font-family: var(--font); }
.tier-pyramid .tp-axis { font-size: 13px; font-weight: 800; fill: var(--ink-2); }
.tier-pyramid .tp-mid { font-size: 15px; font-weight: 800; fill: var(--ink); }
.tier-pyramid .tp-sub { font-size: 11.5px; fill: var(--ink-3); }
.tier-pyramid .tp-val { font-size: 13px; font-weight: 800; fill: var(--ink-2); }
.tier-pyramid .tp-in { font-size: 13px; font-weight: 700; }
.tier-pyramid .tp-rep { font-size: 11.5px; fill: var(--ink-3); }
.tier-pyramid .tp-s { fill: var(--tier-s); } .tier-pyramid .tp-s-ink { fill: var(--tier-s-ink); }
.tier-pyramid .tp-a { fill: var(--tier-a); } .tier-pyramid .tp-a-ink { fill: var(--tier-a-ink); }
.tier-pyramid .tp-b { fill: var(--tier-b); } .tier-pyramid .tp-b-ink { fill: var(--tier-b-ink); }
.tier-pyramid .tp-c { fill: var(--tier-c); stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 4 3; } .tier-pyramid .tp-c-ink { fill: var(--tier-c-ink); }
.tier-pyramid .tp-d { fill: var(--tier-d); } .tier-pyramid .tp-d-ink { fill: var(--tier-d-ink); }
.tier-pyramid .tp-track { fill: var(--surface-sub); stroke: var(--border-soft); }
.tp-caption { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-1) var(--sp-4); font-size: var(--fs-small); color: var(--ink-3); line-height: 1.5; }   /* 2026-09-28 피라미드 전폭에 맞춰 캡 해제 · 글자 caption→small */
.tp-caption b { color: var(--ink-2); }
.tp-caption .tp-dot { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 4px; vertical-align: -1px; }
.tp-caption .tp-dot.tp-s { background: var(--tier-s); } .tp-caption .tp-dot.tp-a { background: var(--tier-a); } .tp-caption .tp-dot.tp-b { background: var(--tier-b); }
.tp-caption .tp-dot.tp-c { background: var(--tier-c); border: 1px dashed var(--ink-3); } .tp-caption .tp-dot.tp-d { background: var(--tier-d); }
details.tp-more { margin-top: var(--sp-2); }
details.tp-more > summary { cursor: pointer; user-select: none; font-size: var(--fs-caption); color: var(--ink-3); }
details.tp-more > summary:hover { color: var(--ink-1); }

/* Tier 칩 (게시자·기획전 Tier · 캘린더의 행사 티어 .tier-chip.tier-1/2/3와 별개) */
.tier-pill { display: inline-block; font-size: var(--fs-caption); font-weight: 800; border-radius: var(--radius-pill); padding: 1px 8px; white-space: nowrap; }
.tier-pill.tier-s { color: var(--tier-s-ink); background: var(--tier-s); }
.tier-pill.tier-a { color: var(--tier-a-ink); background: var(--tier-a); }
.tier-pill.tier-b { color: var(--tier-b-ink); background: var(--tier-b); }
.tier-pill.tier-c { color: var(--tier-c-ink); background: var(--tier-c); outline: 1px dashed var(--ink-3); outline-offset: -1px; }
.tier-pill.tier-d { color: var(--tier-d-ink); background: var(--tier-d); }

/* 파레토(어필 게시자 · 접이식) — 막대 = 판매 · 색 = Tier · 누적선 + 80%/95% 점선 */
.pareto-box { position: relative; height: 260px; max-width: 1280px; }

/* 💰 광고비 대비 성적 가로막대 (js/promo_ads.js) — 길이 = 광고비 · 끝 점 = ROAS · 목표 ROAS 세로선 */
.pa-wrap { max-width: 1280px; }
.pa-row { display: grid; grid-template-columns: 200px minmax(0, 1fr) 150px; align-items: center; gap: var(--sp-2); padding: 3px 0; border-bottom: 1px dashed var(--border-soft); }
.pa-row:last-child { border-bottom: 0; }
.pa-name { font-size: var(--fs-small); color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-track { position: relative; height: 18px; background: var(--surface-sub); border-radius: var(--radius-sm); overflow: visible; }
.pa-bar { position: absolute; left: 0; top: 0; height: 100%; border-radius: var(--radius-sm); background: color-mix(in srgb, var(--acc-channel) 55%, transparent); }
.pa-bar.pa-base { background: color-mix(in srgb, var(--ink-3) 40%, transparent); }
.pa-dot { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; transform: translate(-50%, -50%); border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--border); }
.pa-dot.g4 { background: var(--sig-green); } .pa-dot.g3 { background: var(--sig-yellow); } .pa-dot.g1 { background: var(--sig-red); } .pa-dot.gna { background: var(--sig-na); }
.pa-target { position: absolute; top: -4px; bottom: -4px; width: 0; border-left: 2px dashed var(--ink-2); }
.pa-cost { font-size: var(--fs-caption); color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }
.pa-legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); color: var(--ink-3); margin-top: var(--sp-2); }
.pa-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: -1px; }

/* 🔻 나란한 깔때기 2개 (js/promo_score.js) — UV → PDP → 구매 · 단계 사이 격차 %p */
.fn2-wrap { display: grid; grid-template-columns: 1fr 96px 1fr; gap: var(--sp-2); align-items: stretch; max-width: 1280px; }
.fn2-col h4 { margin: 0 0 var(--sp-1); font-size: var(--fs-small); font-weight: 800; color: var(--ink-2); text-align: center; }
.fn2-step { position: relative; height: 40px; margin: 0 auto 4px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; font-size: var(--fs-caption); font-weight: 700; color: var(--ink); min-width: 72px; white-space: nowrap; }
.fn2-step.fn2-paid { background: color-mix(in srgb, var(--acc-channel) 28%, var(--surface-sub)); }
.fn2-step.fn2-org { background: color-mix(in srgb, var(--sig-green) 24%, var(--surface-sub)); }
.fn2-step small { font-weight: 600; color: var(--ink-3); margin-left: 4px; }
.fn2-rate { text-align: center; font-size: 10.5px; color: var(--ink-3); margin: -2px 0 4px; height: 14px; }
.fn2-mid { display: flex; flex-direction: column; }
.fn2-mid .fn2-gap { height: 40px; margin-bottom: 4px; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: 10px; color: var(--ink-3); text-align: center; line-height: 1.2; }
.fn2-mid .fn2-gap b { font-size: var(--fs-caption); }
.fn2-mid .fn2-gap b.good { color: var(--sig-green); } .fn2-mid .fn2-gap b.bad { color: var(--sig-red); }
.fn2-mid .fn2-gaprate { height: 14px; margin: -2px 0 4px; font-size: 10px; color: var(--ink-3); text-align: center; }
.fn2-mid .fn2-gaprate b.good { color: var(--sig-green); } .fn2-mid .fn2-gaprate b.bad { color: var(--sig-red); }

/* 🚩 점검 게시자 · 링크 1줄 카드 */
.card.card-link { padding: var(--sp-3) var(--sp-4); }
.card.card-link p { margin: 0; font-size: var(--fs-small); color: var(--ink-2); }
.card.card-link a { color: var(--primary); font-weight: 700; cursor: pointer; }

/* 표 단위 일/주 토글 (어필 📊 일별 추이 · 기획전) — btn-ghost 재사용 + active */
.seg-toggle { display: inline-flex; gap: 4px; margin-left: var(--sp-2); vertical-align: middle; }
.seg-toggle .btn-ghost { padding: 2px 10px; font-size: var(--fs-caption); }
.seg-toggle .btn-ghost.active { color: var(--primary); border-color: var(--primary); background: var(--primary-bg); }

/* ═══ 2026-09-22 디자인 전수 점검 (사용자 실측 1300~1600px) — 잘림 0 · 가로 넘침 0 · 간격 통일 ═══
   금액 표기 룰(전체 자릿수 + (약 N억) 병기 · 축약 금지)은 그대로 두고, 괄호 병기만 <small>로 감싸 한 덩어리로 줄바꿈한다.
   <small>은 score_channels/customer_kpi가 직접 넣고, 순수 텍스트로 온 값(fmt.full)은 js/amount_wrap.js가 렌더 뒤 감싼다. */
.c-value small, .m-value small, .t-value small, .kpi-value small, .ct-v small, .ts-v small, .ts-gns-v small, small.approx {
  display: inline-block; white-space: nowrap; font-family: var(--font-body); font-size: 10.5px; font-weight: 600;
  color: var(--ink-3); margin-left: 4px; vertical-align: baseline; letter-spacing: 0; }
/* 2026-09-22 순서 역전 '5.7억 (₩566,804,729)' — 괄호(전체 자릿수)가 길면 아래 줄로. 값 노드 안의 <small>은 항상 블록으로 내려 카드 폭 무관하게 안 잘린다 */
.c-value small.approx, .m-value small.approx, .t-value small.approx, .kpi-value small.approx, .ct-v small.approx, .ts-v small.approx, .ts-gns-v small.approx {
  display: block; margin-left: 0; margin-top: 1px; line-height: 1.3; }
.kpi-value small { font-size: var(--fs-caption); }
/* 표 위아래 숨 쉴 틈 — 표가 안내문·인사이트에 붙어 보이던 것 */
.card .tbl-scroll { margin-top: var(--sp-2); }
.card .tbl-scroll + .src-note, .card table.tbl + .src-note { margin-top: var(--sp-3); }
.card .interp + .tbl-scroll, .card .interp + table.tbl, .card .interp + .block-label, .card .interp + .chart-box, .card .interp + .tile-grid, .card .interp + .ct-grid { margin-top: var(--sp-3); }
/* 인사이트가 표 '위'로 올라간 자리 — 아래 표와 한 칸 (2026-09-22 사용자: 인사이트는 모든 표 위에) */
.interp.above { margin-top: var(--sp-2); margin-bottom: var(--sp-3); }
/* 차트 카드는 폭 제한 없음 — 카드 전폭. 높이만 유지 */
.chart-box { width: 100%; max-width: none; }
/* 비중 막대(100%)가 셀 좌 여백만큼 밖으로 삐져나오던 것 — 셀 안에서 끝나게 (가로 넘침 0) */
.tbl-grp td.share-cell > i { max-width: calc(100% - 2 * var(--sp-1)); }

/* 표 정렬 표식 강화 (2026-09-22 — 사용자 "정렬이 안 된다": 기능은 있었지만 클릭 전엔 아무 표식이 없었다)
 * 정렬 가능한 헤더는 항상 옅은 ↕ · 호버하면 진해지고 · 정렬 중이면 ▼/▲를 브랜드색으로 */
.tbl thead th.sortable .sort-ind { display: inline-block; min-width: 9px; }
.tbl thead th.sortable .sort-ind:empty::before { content: '↕'; opacity: .35; }
.tbl thead th.sortable:hover .sort-ind:empty::before { opacity: 1; color: var(--brand); }
.tbl thead th.sortable:hover { color: var(--ink); }
.tbl thead th.sortable.sorted .sort-ind { color: var(--brand); font-weight: 800; opacity: 1; }

/* 모든 데이터 표의 본문·헤더 크기 통일 */
.tab-panel table.tbl th, .tab-panel table.tbl td { font-size: var(--fs-table); }

/* ===== 📆 주간 리포트 새 양식 (report_weekly.js · 2026-10-01) ===== */
.tab-btn[hidden] { display: none; }   /* 일간·월간 리포트 숨김 — .tab-btn의 display:flex가 hidden 속성을 이기므로 명시 */
.rw-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; }
.rw-head h2 { margin: 0; }
.rw-asof { font-size: var(--fs-caption); color: var(--ink-3); }
.rw-tools .wow-pick { margin-left: 0; }
.rw-first { display: block; margin-top: var(--sp-4); font-size: var(--fs-small); }
.rw-tools { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin: var(--sp-2) 0 var(--sp-3); }
.rw-sec { font-size: var(--fs-h2); font-weight: 800; color: var(--ink); margin: var(--sp-5) 0 var(--sp-2); padding-bottom: var(--sp-1); border-bottom: 2px solid var(--border); }
.rw-sec:first-of-type { margin-top: var(--sp-2); }
.rw-block { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: var(--sp-4); align-items: start; padding: var(--sp-3) 0 var(--sp-4); border-bottom: 1px solid var(--border-soft); }
.rw-block:last-child { border-bottom: 0; }
@media (max-width: 1100px) { .rw-block { grid-template-columns: minmax(0, 1fr); } }
.rw-tag { display: inline-block; font-size: var(--fs-caption); font-weight: 800; color: var(--ink-2); margin-bottom: var(--sp-1); }
.rw-hl { font-size: var(--fs-body); font-weight: 800; color: var(--primary); line-height: 1.55; margin: 0 0 var(--sp-1); }
.rw-hl2 { font-size: var(--fs-small); font-weight: 700; color: var(--primary); line-height: 1.55; margin: 0 0 var(--sp-2); }
.rw-sub { margin: 0 0 var(--sp-2); padding-left: var(--sp-4); font-size: var(--fs-small); color: var(--ink); line-height: 1.6; }
.rw-sub li { margin-bottom: 2px; }
.rw-note { font-size: var(--fs-caption); color: var(--ink-3); line-height: 1.5; margin: var(--sp-1) 0 0; }
.rw-close { font-size: var(--fs-small); font-weight: 700; color: var(--sig-green); background: var(--sig-green-bg); border-radius: var(--radius-sm); padding: var(--sp-1) var(--sp-2); margin: var(--sp-1) 0 var(--sp-2); }
.rw-wait { font-size: var(--fs-small); font-weight: 700; color: var(--sig-red); }
.rw-chart { position: relative; height: 260px; }
.rw-promo { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--sp-3); }
.rw-pcard { background: var(--surface-sub); border-radius: var(--radius-sm); padding: var(--sp-3); }
.rw-pcard h4 { margin: 0 0 var(--sp-1); font-size: var(--fs-small); font-weight: 800; color: var(--ink); }
.rw-pcard .rw-sub { padding-left: var(--sp-3); font-size: var(--fs-caption); }
.rw-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4); }
@media (max-width: 1000px) { .rw-two { grid-template-columns: minmax(0, 1fr); } }
.rw-two h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-small); font-weight: 800; }
.rw-ads { margin-top: var(--sp-5); }
.rw-ads > summary { cursor: pointer; font-weight: 800; font-size: var(--fs-body); color: var(--ink-2); padding: var(--sp-2) 0; }
.rw-ads > summary:hover { color: var(--ink); }

/* ===== 📅 일간 리포트 새 양식 (report_daily.js · 2026-10-01) ===== */
.rd-promo { font-size: var(--fs-small); color: var(--ink-2); background: var(--surface-sub); border-radius: var(--radius-sm); padding: var(--sp-2) var(--sp-3); margin: 0 0 var(--sp-3); line-height: 1.6; }
.rd-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: var(--sp-3); margin: var(--sp-3) 0; }
.rd-kpi { background: var(--surface-sub); border-radius: var(--radius-sm); padding: var(--sp-3); min-width: 0; }
.rd-kpi h4, .rw-two h4, .rd-three h4 { margin: 0 0 var(--sp-2); font-size: var(--fs-small); font-weight: 800; color: var(--ink); }
.rd-kpi .tbl td.gsep { font-weight: 700; color: var(--primary); }
.rd-h4 { margin: var(--sp-4) 0 var(--sp-2); font-size: var(--fs-small); font-weight: 800; color: var(--ink); }
.rd-three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-3); }
@media (max-width: 1200px) { .rd-three { grid-template-columns: minmax(0, 1fr); } }
