/* ===== 신차패키지 매장 업무시스템 — A 소프트페이퍼 ===== */

/* 노토 산스 KR(Noto Sans KR) — 앱 전체 공용 글씨체. CDN이 아니라 저장소
   안에 들어있는 로컬 파일이라 인터넷 연결과 무관하게 항상 로드된다.
   한글/한자(korean)와 영문·숫자·기호(latin)가 따로 파일로 나뉘어 있어서
   굵기별로 두 개씩(400/500/600/700) 선언한다. OFL 1.1 라이선스
   (동봉된 fonts/NotoSansKR-LICENSE.txt 참고). */
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-400-korean.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-500-korean.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-500-latin.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-600-korean.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-600-latin.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-700-korean.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("./fonts/NotoSansKR-700-latin.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  --bg: #f6f6f4;
  --ink: #17191c;
  --ink2: #2a2d32;
  --muted: #7d8189;
  --muted2: #5d626a;
  --faint: #9a9ea5;
  --line: rgba(23,25,28,0.07);
  --line2: rgba(23,25,28,0.09);
  --line3: rgba(23,25,28,0.14);
  --card: #ffffff;
  --accent: #3f658c;
  --accent-dark: #27425c;
  --accent-soft: #5980a6;
  --accent-bg: #eef2f7;
  --danger: #96555b;
  --danger-bg: #fbeeee;
  --good: #3f6b52;
  --good-bg: #eaf1ec;
}

* { box-sizing: border-box; }
html, body { margin: 0; }
button { all: unset; cursor: pointer; box-sizing: border-box; font-family: inherit; }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Noto Sans KR", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-dark); }
button { font-family: inherit; }
::selection { background: rgba(89,128,166,0.24); }

.fade { animation: fade .34s cubic-bezier(.16,1,.3,1) both; }
@media (prefers-reduced-motion: reduce) { .fade { animation: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

[contenteditable="true"] {
  outline: 1px dashed rgba(89,128,166,0.75);
  outline-offset: 2px;
  border-radius: 3px;
  min-width: 18px;
  cursor: text;
}
[contenteditable="true"]:hover { background: rgba(89,128,166,0.06); }
[contenteditable="true"]:focus { outline: 2px solid #5980a6; background: #fff; }
/* "내용 입력"류 안내 문구 — 실제 값이 아니라 무엇을 적을지 알려주는
   placeholder라는 걸 흐린 이탤릭체로 표시한다. 클릭하면 바로 지워진다. */
.ph { color: var(--faint) !important; font-style: italic; }

/* ===== shell / nav ===== */
.shell { display: flex; min-height: 100dvh; }

.sidebar {
  position: sticky; top: 0; align-self: flex-start; height: 100dvh;
  width: 236px; flex: 0 0 236px; padding: 22px 14px;
  display: flex; flex-direction: column; gap: 26px;
  transition: width 0.18s ease, flex-basis 0.18s ease, padding 0.18s ease;
  overflow: hidden;
}
.sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 0 8px; }
.sidebar-mark {
  width: 30px; height: 30px; border-radius: 9px; background: var(--ink); color: #fff;
  display: grid; place-content: center; font-size: 12px; font-weight: 600; flex: 0 0 auto;
}
.sidebar-name { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; white-space: nowrap; }

/* 사이드바 접기/펼치기 버튼 — 클릭할 때만 접히고 펼쳐지며(호버로 저절로
   열리지 않음), 다음에 다시 열어도 선택한 상태가 그대로 유지된다
   (STATE.sidebarCollapsed를 localStorage에 저장). */
.sidebar-collapse-btn {
  cursor: pointer; display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 10px; margin-top: -14px; border-radius: 9px; border: 0; background: transparent;
  font-size: 12px; color: var(--muted2);
}
.sidebar-collapse-btn:hover { background: rgba(23,25,28,0.05); }
.sidebar-collapse-ico { flex: 0 0 auto; width: 14px; text-align: center; font-weight: 700; }
.sidebar-collapse-label { white-space: nowrap; }

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; }
.nav-btn {
  cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: 10px; font-size: 13.5px; background: transparent; color: #5d626a; font-weight: 500;
  width: 100%; border: 0;
}
.nav-btn:hover { background: rgba(23,25,28,0.05); }
.nav-btn.active { background: var(--ink); color: #fff; font-weight: 600; }
.nav-btn .badge { font-size: 11.5px; color: #9a9ea5; }
.nav-btn.active .badge { color: rgba(255,255,255,0.6); }
/* 접혔을 때는 "작업지시서" 대신 짧은 "지시서"만 보여준다(아이콘이
   따로 없어서 긴 이름 대신 줄임말로 대체 — 모바일 하단 바에서 쓰는
   짧은 이름을 그대로 재사용). */
.nav-btn .nav-short { display: none; }

/* 사이드바 하단: "일반고객" 박스(위) + "영업사원별" 박스(아래) 두 개를
   세로로 쌓는다 — 서로 다른 숫자라 합계도 각자 따로 낸다(합산 안 함). */
.sidebar-foot { margin-top: auto; display: flex; flex-direction: column; gap: 10px; }
.sidebar-foot .k { font-size: 11.5px; color: var(--muted); }
.sidebar-foot .v { font-size: 14px; font-weight: 600; margin-top: 2px; }
.sidebar-foot .p { font-size: 12px; color: var(--muted); margin-top: 6px; }

/* 접힌 사이드바 — 아이콘 자리처럼 좁게 줄이고, 상호명·뱃지·결제
   요약처럼 좁은 폭에서 깨지는 내용은 숨긴다. 메뉴 자체(토글 버튼·
   네비게이션 줄임말)는 계속 보여서 바로 펼치거나 다른 페이지로
   이동할 수 있다. */
.sidebar.collapsed { width: 68px; flex: 0 0 68px; padding: 22px 8px; }
.sidebar.collapsed .sidebar-brand { justify-content: center; padding: 0; }
.sidebar.collapsed .sidebar-name { display: none; }
.sidebar.collapsed .sidebar-collapse-btn { justify-content: center; }
.sidebar.collapsed .sidebar-collapse-label { display: none; }
.sidebar.collapsed .sidebar-user { flex-direction: column; gap: 6px; }
.sidebar.collapsed .sidebar-user .who { display: none; }
.sidebar.collapsed .nav-btn { justify-content: center; padding: 10px 4px; }
.sidebar.collapsed .nav-btn .nav-full, .sidebar.collapsed .nav-btn .badge { display: none; }
.sidebar.collapsed .nav-btn .nav-short { display: inline; font-size: 11px; }
.sidebar.collapsed .sidebar-foot { display: none; }

.rep-box { padding: 14px 14px 12px; border-radius: 12px; background: #fff; border: 1px solid var(--line); }
.rep-box .k { font-weight: 600; color: #42464d; margin-bottom: 8px; font-size: 11.5px; }
.rep-summary-rows { display: flex; flex-direction: column; gap: 6px; max-height: 132px; overflow-y: auto; }
.rep-summary-row { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; color: #42464d; }
.rep-summary-row span:last-child { font-variant-numeric: tabular-nums; font-weight: 500; flex: 0 0 auto; }
.rep-summary-total {
  display: flex; justify-content: space-between; margin-top: 9px; padding-top: 9px;
  border-top: 1px solid var(--line); font-size: 13.5px; font-weight: 700;
}
.rep-summary-total span:last-child { font-variant-numeric: tabular-nums; }

.bottom-nav {
  display: none;
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 10;
  grid-template-columns: repeat(4,1fr); gap: 2px; padding: 6px; border-radius: 16px;
  background: rgba(255,255,255,0.92); backdrop-filter: blur(14px);
  border: 1px solid var(--line2); box-shadow: 0 8px 26px rgba(23,25,28,0.12);
}
.bottom-nav .nav-btn {
  min-height: 46px; display: grid; place-content: center; border-radius: 11px;
  font-size: 12px; text-align: center; padding: 0;
}

main { flex: 1; min-width: 0; padding-bottom: 0; }
/* 넓은 화면(전체화면 등)에서 폭을 막아두면 옆에 불필요한 여백이 크게
   남았다 — 카드/요약 그리드는 전부 auto-fill/auto-fit(반응형)이라 폭을
   늘려도 깨지지 않으니, 상한을 아예 없애고 화면을 최대한 꽉 채운다.
   견적서 등 .a4(실제 종이 크기 210mm 고정) 시트는 이 컨테이너 폭과 무관하게
   그대로다 — 인쇄 미리보기 목적상 종이 크기를 바꾸면 안 되기 때문. */
.container { max-width: none; margin: 0 auto; padding: 28px 24px 0; }
.container.wide { max-width: none; }

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.page-head h1 { margin: 0; font-size: 34px; line-height: 1.15; letter-spacing: -0.03em; font-weight: 600; }
.page-head p { margin: 6px 0 0; font-size: 14px; color: var(--muted); max-width: 65ch; }
.page-head .today { font-size: 12.5px; color: var(--faint); }

@media screen and (max-width: 899.98px) {
  .sidebar { display: none; }
  .bottom-nav { display: grid; }
  /* 메뉴가 8개라 하단 바가 4열×2줄(108px)인데 이 여백이 84px뿐이라
     카드 맨 아래 내용이 하단 바에 가려지는 문제가 있었다 — 하단 바
     높이(2줄 + 상하 패딩 + 화면 끝에서 뜬 12px)만큼 넉넉히 확보한다. */
  main { padding-bottom: 132px; }
}

/* ===== generic bits ===== */
.panel { background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 18px; }
.panel h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }

.toolbar { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; margin-bottom: 16px; }
.hint { font-size: 12px; color: var(--faint); }

.btn { cursor: pointer; min-height: 38px; padding: 9px 18px; border-radius: 10px; font-size: 13.5px; font-weight: 600; border: 1px solid transparent; }
.btn-dark { background: var(--ink); color: #fff; }
.btn-dark:hover { background: #2a2d32; }
.btn-outline { background: #fff; border: 1px solid var(--line3); color: var(--ink); }
.btn-outline:hover { background: #f0f0ef; }
.btn-edit { background: #fff; border: 1px solid var(--line3); color: var(--ink); }
.btn-edit.on { background: var(--accent-soft); color: #fff; border-color: var(--accent-soft); }
.btn-edit:hover { opacity: 0.85; }
.btn-soft { background: var(--accent-bg); color: var(--accent); font-weight: 600; }
.btn-soft:hover { opacity: 0.85; }
.btn-soft.on { background: var(--accent-soft); color: #fff; }
/* 숨김/보조 토글류(예: 결제내역서 "숨김 항목 보기") — btn-outline(흰 배경+테두리)이나
   btn-soft(옅은 파란)와 겹치지 않는, 무채색 톤의 세 번째 스타일. */
.btn-ghost { background: var(--line2); color: var(--muted2); border: 1px solid transparent; }
.btn-ghost:hover { background: var(--line3); }
/* 툴바 버튼 크기 3단계 — 매일 반복해서 누르는 핵심 동작(.btn-lg, 사실상
   기본 .btn과 같은 크기)일수록 크고, 드물게 쓰는 버튼일수록 한 단씩
   작아진다(.btn-md → .btn-sm). 페이지별로 .btn 자체를 더 작게 덮어쓴 곳
   (.orders-page 등)에서도 "이 버튼만은 크게/작게"가 먹히도록 .btn과
   함께 쓰는 조합 선택자도 같이 둔다(그 페이지 규칙보다 우선순위가 높다). */
.btn-lg { min-height: 38px; padding: 9px 18px; font-size: 13.5px; }
.btn-md { min-height: 34px; padding: 7px 15px; font-size: 12.5px; }
.btn-sm { min-height: 30px; padding: 6px 12px; font-size: 11.5px; border-radius: 8px; }
.orders-page .btn.btn-lg { min-height: 38px; padding: 9px 18px; font-size: 13.5px; }
.orders-page .btn.btn-sm { min-height: 30px; padding: 6px 12px; font-size: 11.5px; }

.pill { cursor: pointer; min-height: 34px; padding: 7px 14px; border-radius: 999px; font-size: 13px; background: #fff; color: #42464d; border: 0; }
.pill:hover { opacity: 0.85; }
.pill.active { background: var(--ink); color: #fff; }

.tab { cursor: pointer; min-height: 36px; padding: 8px 15px; border-radius: 999px; font-size: 13px; font-weight: 500; background: #fff; color: #42464d; border: 1px solid rgba(23,25,28,0.09); }
.tab:hover { opacity: 0.85; }
.tab.active { background: var(--ink); color: #fff; font-weight: 600; }

.filterbar-date { display: flex; align-items: center; gap: 7px; padding: 7px 12px; background: #fff; border: 1px solid var(--line3); border-radius: 10px; }
.filterbar-date input { all: unset; font-family: inherit; font-size: 12.5px; width: 112px; cursor: pointer; }
.filterbar-date .sep { color: #c3c6ca; }
.select-box, .search-box, .text-box { all: unset; box-sizing: border-box; cursor: pointer; font-family: inherit; font-size: 12.5px; padding: 9px 12px; background: #fff; border: 1px solid var(--line3); border-radius: 10px; }
/* select는 all:unset 때문에 display가 초기값(inline)으로 풀리면서
   flex 컨테이너 안에서 줄어들 공간이 모자라면 보이는 글자("최신
   입고순" 등)가 두 줄로 쪼개져 보이는 문제가 있었다 — 줄바꿈을 막고
   내용 폭만큼만 차지하게 고정해서, 좁을 땐 줄바꿈 대신 다음 줄로
   통째로 넘어가게(flex-wrap) 한다. */
.select-box { white-space: nowrap; flex: 0 0 auto; }
.select-box:disabled { opacity: 0.5; cursor: not-allowed; }
.text-box { cursor: text; }
/* 검색창은 남는 공간을 다 차지하도록 flex:1을 줬었는데, 혼자 한 줄을
   차지하게 되면(좁은 화면 등) 불필요하게 꽉 차 보였다 — 늘어나는 폭에
   상한을 둬서 너무 커지지 않게 한다. */
.search-box { flex: 1; min-width: 180px; max-width: 360px; padding: 9px 14px; cursor: text; }
/* 어두운 바(.table-card .bar) 위에 얹는 select(매출표 "일자별기록"의
   월 선택 등) — 닫혀있을 때 보이는 글자는 바 배경에 맞춰 흰색이어야
   하지만, 펼쳤을 때 나오는 옵션 목록은 브라우저가 대부분 밝은(흰)
   배경으로 그린다. select에 준 흰 글자색이 option에도 그대로
   상속되면 흰 배경에 흰 글자가 겹쳐 글자가 안 보이는 문제가 있어서,
   option에는 항상 어두운 글자색을 따로 지정해 되돌린다. */
.select-on-dark { background: transparent; border-color: rgba(255,255,255,0.35); color: #fff; }
.select-on-dark option { color: var(--ink); background: #fff; }

/* ===== dashboard ===== */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit,minmax(190px,1fr)); gap: 14px; }
.kpi-card { background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 18px; }
.kpi-card .label { font-size: 12.5px; color: var(--muted); }
.kpi-card .value-row { display: flex; align-items: baseline; gap: 5px; margin-top: 10px; }
.kpi-card .value { font-size: 34px; line-height: 1; font-weight: 600; letter-spacing: -0.035em; }
.kpi-card .unit { font-size: 12.5px; color: var(--muted); }
.kpi-card .sub { font-size: 12.5px; color: var(--muted); margin-top: 8px; }

.dash-grid { display: grid; grid-template-columns: minmax(0,1.45fr) minmax(0,1fr); gap: 20px; margin-top: 20px; }
@media screen and (max-width: 899.98px) { .dash-grid { grid-template-columns: minmax(0,1fr); } }
.dash-col { display: flex; flex-direction: column; gap: 20px; min-width: 0; }

.progress-panel { background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 6px 18px 12px; min-width: 0; }
.progress-panel .head { display: flex; align-items: center; justify-content: space-between; padding: 14px 0 10px; }
.progress-panel .head h2 { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.progress-panel .head button { cursor: pointer; font-size: 12.5px; color: var(--accent); }
.progress-panel .head button:hover { color: var(--accent-dark); }
.progress-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 13px 0; border-top: 1px solid var(--line); }
.progress-row .car { font-size: 14.5px; font-weight: 600; }
.progress-row .meta { font-size: 12.5px; color: var(--muted); }
.progress-row .right { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.chip { flex: 0 0 auto; white-space: nowrap; font-size: 13px; font-weight: 700; padding: 5px 11px; border-radius: 999px; }
.progress-row .date { white-space: nowrap; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

.status-list { display: flex; flex-direction: column; gap: 2px; }
.status-row { cursor: pointer; display: flex; align-items: center; justify-content: space-between; padding: 9px 10px; margin: 0 -10px; border-radius: 9px; font-size: 13.5px; border: 0; background: transparent; width: calc(100% + 20px); }
.status-row:hover { background: rgba(23,25,28,0.04); }
.status-row .lbl { color: #42464d; }
.status-row .cnt { font-weight: 600; font-variant-numeric: tabular-nums; }

.rep-panel .sub { font-size: 12px; color: var(--faint); margin-bottom: 16px; }
.rep-bars { display: flex; flex-direction: column; gap: 10px; }
.rep-bar-row { display: flex; align-items: center; gap: 10px; }
.rep-bar-row .name { flex: 0 0 62px; font-size: 12.5px; color: #42464d; white-space: nowrap; }
.rep-bar-row .track { flex: 1; min-width: 0; display: flex; height: 8px; background: rgba(23,25,28,0.05); border-radius: 4px; }
.rep-bar-row .fill { border-radius: 4px; }
.rep-bar-row .count { flex: 0 0 30px; text-align: right; font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
/* "일반고객"은 영업사원 순위가 아니라 별개 항목이라 점선으로 구분한다. */
.rep-bar-row.cust { margin-top: 4px; padding-top: 10px; border-top: 1px dashed var(--line); }
.rep-bar-row.cust .name, .rep-bar-row.cust .count { color: var(--muted); }

/* ===== work orders ===== */
/* 작업지시서 페이지 전용 축소 — .btn/.pill/.select-box 등은 본점결제·
   결제내역서·매출표 같은 다른 페이지에서도 그대로 쓰는 공용 컴포넌트라,
   거기까지 작아지지 않게 .orders-page(renderOrders() 루트) 안에서만
   덮어쓴다. */
.orders-page .toolbar { gap: 8px; }
.orders-page .btn { min-height: 33px; padding: 7px 14px; font-size: 12.5px; }
.orders-page .pill { min-height: 29px; padding: 6px 12px; font-size: 12px; }
.orders-page .filterbar-date { padding: 6px 10px; }
.orders-page .filterbar-date input { font-size: 12px; width: 100px; }
.orders-page .select-box, .orders-page .search-box { font-size: 12px; padding: 7px 10px; }
.orders-page .search-box { padding: 7px 12px; min-width: 150px; max-width: 260px; }

.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.order-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(296px,1fr)); gap: 14px; }
/* 카드마다 배지·가격 불일치 안내·메모 등 있는 내용이 달라 높이가 제각각
   이던 걸 "중간" 정도 높이로 고정한다. 내용이 이보다 적은 카드는 아래쪽에
   남는 공간을 .body의 flex:1 + .order-footer의 margin-top:auto로 채워서
   "작업 #.../출고" 줄이 카드 맨 아래에 가지런히 붙게 하고, 내용이 유난히
   많은 카드(메모 등)는 min-height라 그만큼 더 자라는 건 허용한다(잘리지
   않게). 아래 글씨 크기를 전체적으로 줄인 만큼 min-height도 같이
   낮춰서(500px→430px) 내용 적은 카드 하단에 빈 공간이 예전만큼 넓게
   남지 않게 했다. */
.order-card { background: #fff; border: 1px solid var(--line); border-radius: 13px; min-width: 0; min-height: 430px; display: flex; flex-direction: column; overflow: hidden; }
.order-card .top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 12px 16px; }
/* 선택 모드 — 작업지시서 카드 여러 건을 골라 한번에 상태를 바꿀 때.
   카드 전체가 클릭 대상이라(cursor:pointer) 체크박스는 순전히 표시용 —
   실제 토글은 카드 클릭(orderCardHtml의 data-act="toggle-select")이 한다. */
.order-card.selected { outline: 2px solid var(--accent-dark, #2563eb); outline-offset: -2px; }
#orderGrid .order-card[data-act="toggle-select"] { cursor: pointer; }
.order-select-check { flex: 0 0 auto; display: flex; align-items: center; padding-top: 2px; }
.order-select-check input { width: 18px; height: 18px; pointer-events: none; }
.order-card .body { padding: 0 16px 16px; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.order-card h3 { margin: 0; font-size: 16.5px; font-weight: 600; letter-spacing: -0.02em; }
.order-card .in-date { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.order-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 5px; }
/* 아이콘만 보이다가 hover/focus 시 옆에 라벨(삭제/복제/수정)이 스르륵
   펼쳐지는 아이콘 바. .icon-btn-label의 max-width를 0→값으로 트랜지션해서
   너비 애니메이션을 흉내낸다(실제 텍스트 폭을 JS로 재지 않는 순수 CSS
   방식이라, 라벨이 그 max-width보다 길면 잘릴 수 있음 — 지금 쓰는
   "삭제/복제/수정" 정도 길이에선 넉넉함). */
/* 평소에는 버튼 모양(배경/테두리) 없이 아이콘 그림만 카드 상단(어두운
   배경) 위에 떠 있고, 마우스를 올리거나(hover) 포커스했을 때만 버튼
   배경이 나타난다 — 액션(삭제/복제/수정)은 평소에도 그대로 클릭된다. */
.icon-btn {
  cursor: pointer; height: 26px; min-width: 26px; display: inline-flex; align-items: center;
  border-radius: 7px; border: 1px solid transparent; font-size: 12px; background: transparent;
  color: rgba(255,255,255,0.82);
  overflow: hidden; transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.icon-btn-ico { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-content: center; }
.icon-btn-label {
  display: inline-block; max-width: 0; padding-right: 0; opacity: 0; overflow: hidden;
  white-space: nowrap; font-size: 10.5px; font-weight: 600;
  transition: max-width 0.38s cubic-bezier(0.16,1,0.3,1), padding-right 0.38s cubic-bezier(0.16,1,0.3,1), opacity 0.22s ease;
}
.icon-btn:hover .icon-btn-label, .icon-btn:focus-visible .icon-btn-label {
  max-width: 52px; padding-right: 9px; opacity: 1;
}
.icon-btn.del:hover, .icon-btn.del:focus-visible { background: var(--danger-bg); border-color: var(--danger-bg); color: var(--danger); }
.icon-btn.dup .icon-btn-ico { font-size: 11px; }
.icon-btn.dup:hover, .icon-btn.dup:focus-visible { background: #f0f0ef; border-color: #f0f0ef; color: #5d626a; }
.icon-btn.edit .icon-btn-ico { font-size: 10px; }
.icon-btn.edit:hover, .icon-btn.edit:focus-visible { background: #f0f0ef; border-color: #f0f0ef; color: #42464d; }

.badge-row { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 9px; }
.badge { font-size: 10.5px; padding: 3px 7px; border-radius: 6px; white-space: nowrap; flex-shrink: 0; }
.badge.rec { background: var(--good-bg); color: var(--good); }
.badge.fee { background: var(--danger-bg); color: var(--danger); }
.badge.check { background: #fef3c7; color: #92610a; }
.badge.order { background: var(--accent-bg); color: var(--accent); }
.badge.settled { background: #f0f0ef; color: #7d8189; }
/* 보증서(유리막/썬팅)·출고서류 복사 — 완료됐을 때만 보이는 다른
   배지(기재완료 등)와 달리, 작업지시서 목록을 훑어볼 때 이미 됐는지
   아직 안 됐는지 바로 구분돼야 해서 두 상태 다 항상 띄우고 색으로만
   구분한다(켜짐=진한 초록 배경, 꺼짐=흐린 회색). */
.badge.docon { background: var(--good); color: #fff; font-weight: 700; }
.badge.docoff { background: #eceeef; color: #9a9ea5; }
.price-check-note { margin-top: 4px; font-size: 10.5px; color: #92610a; font-weight: 400; }
.pay-tbody.settled { opacity: 0.55; }
.pay-tbody.bulk-pick { cursor: pointer; }
.pay-tbody.selected td { background: var(--accent-bg); }
.deposit-row.settled { opacity: 0.55; }
.ledger-row-wrap.settled { opacity: 0.5; }

/* dt(카마스터/전면/측면(1열) 같은 라벨)는 카드마다 똑같이 반복되는 "고정
   텍스트"다. 예전엔 값(dd)보다 연한 회색이라 오히려 값보다 눈에 덜 띄어서
   카드를 위→아래로 훑을 때 무슨 항목인지 스캔하기 불편했다 — 라벨을
   진하게(굵게+어둡게) 바꿔서 왼쪽 라벨 열이 스캔 기준선 역할을 하게 했다. */
.spec-dl { margin: 10px 0 0; display: grid; grid-template-columns: 70px minmax(0,1fr); gap: 5px 10px; font-size: 11.5px; }
.spec-dl dt { color: #42464d; font-weight: 700; margin: 0; }
.spec-dl dd { margin: 0; color: #2a2d32; }
.spec-dl dd.hl {
  background: #fde047; color: #3d3200; font-weight: 600; border-radius: 3px;
  padding: 1px 6px; margin: -1px -6px; width: fit-content;
}

.vin-line { margin-top: 9px; font-size: 11px; color: var(--muted); }
.memo-box { margin-top: 9px; padding: 9px 11px; border-radius: 9px; background: var(--bg); font-size: 11.5px; color: #42464d; line-height: 1.5; }

.order-footer { display: flex; justify-content: space-between; gap: 12px; margin-top: auto; padding-top: 11px; border-top: 1px solid var(--line); font-size: 11.5px; color: var(--muted); }
.order-footer .out { color: var(--accent); font-weight: 600; }

/* ===== drawer ===== */
.drawer-overlay { position: fixed; inset: 0; z-index: 40; background: rgba(23,25,28,0.35); display: flex; justify-content: flex-end; }
/* window.confirm()/alert() 대체 다이얼로그. 드로어보다 위(45)에 뜨게 해서
   드로어가 열린 상태에서도(현재는 그럴 일이 없지만) 항상 보이게 한다. */
.confirm-box { z-index: 45; background: #fff; border-radius: 14px; padding: 22px; max-width: 360px; width: 100%; box-shadow: 0 8px 30px rgba(23,25,28,0.16); }
.confirm-box p { margin: 0 0 18px; font-size: 14px; color: var(--ink); line-height: 1.55; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 9px; }
/* 540px: "출고 날짜·출고 시간·결제방식·결제금액" 4칸을 한 줄에 두면서(.field-pair.cols-4)
   date input이 480px에서는 폭이 모자라 연도 마지막 자리가 잘렸다 — 그걸
   안 잘리게 할 최소 폭이 540px이었다. */
.drawer-panel { width: 540px; max-width: 100%; height: 100%; background: #fff; box-shadow: -8px 0 30px rgba(23,25,28,0.16); display: flex; flex-direction: column; }
@media screen and (max-width: 899.98px) { .drawer-panel { width: 100%; } }
.drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 18px; border-bottom: 1px solid rgba(23,25,28,0.08); }
.drawer-head h3 { margin: 0; font-size: 15.5px; font-weight: 600; letter-spacing: -0.02em; }
.drawer-close { cursor: pointer; width: 26px; height: 26px; display: grid; place-content: center; border-radius: 7px; font-size: 15px; color: #5d626a; background: transparent; border: 0; }
.drawer-close:hover { background: #f0f0ef; }

/* 필드가 20개 넘게 있어서 세로로 한참 스크롤해야 했다 — 2열이던 그리드를
   3열로 늘려서(칸 하나하나는 좁아지지만 한 줄에 더 많은 항목이 들어가서
   전체 줄 수가 줄어든다) + 패딩·글씨·입력창 높이를 전반적으로 낮춰서
   화면에 한 번에 보이는 항목 수를 최대한 늘렸다. PPF만 옵션 선택
   드롭다운이 딸려 있어 좁은 칸에선 답답해서 전체 폭(.full)으로 뺐다. */
.drawer-form { flex: 1; min-height: 0; overflow: auto; padding: 14px 16px; display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 8px 9px; }
.field { display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--muted); }
.field.full { grid-column: 1 / -1; }
/* 3열 그리드에 그냥 맡기면 필드 2개가 짝이 안 맞아 엉뚱한 필드끼리
   한 줄에 묶인다(예: 차대번호가 결제금액 옆이 아니라 결제방식 옆에 옴).
   "결제방식·결제금액"/"차대번호·계약번호"처럼 항상 정확히 둘이 나란히
   있어야 하는 쌍은 전체 폭을 차지하는 자체 2열 미니 그리드로 묶는다. */
.field-pair { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 8px 9px; }
.field-pair.cols-4 { grid-template-columns: repeat(4,minmax(0,1fr)); }
/* 결제금액 칸은 가격표 대조 안내문이 붙어서 옆 3칸(출고 날짜·출고
   시간·결제방식)보다 키가 크다 — 그냥 한 줄로 두면 그리드가 행 높이를
   결제금액에 맞춰 늘리면서 나머지 3칸 밑에 빈 공간이 생긴다. 결제금액을
   오른쪽 4번째 칸에 두 줄(1~2행)에 걸쳐 세로로 고정해 자기 내용만큼만
   차지하게 하고, 그 옆(1~3번째 칸)의 둘째 줄에 남는 공간을 스위치
   3개(출고서류 복사·고객부담금·기재완료) 줄로 채운다. */
.field-pay-amt { grid-row: 1 / span 2; }
/* .check-row(뒤에 나오는 grid-column:1/-1)와 클래스 특이도가 같아서
   순서상 밀릴 수 있어, .field-pair를 앞에 붙여 특이도를 확실히 높였다. */
.field-pair .field-switches-row { grid-column: 1 / span 3; grid-row: 2; border: 0; padding: 0; align-items: center; }
/* 모바일은 드로어가 화면 폭 그대로(최대 540px 아님)라 4칸으로 두면 날짜
   입력칸이 다시 잘린다 — 좁은 화면에서만 2×2로 접는다. 이때는 위의
   결제금액 세로 걸침·스위치 줄 끼워넣기도 의미가 없어서(칸이 2개뿐이라
   4번째 칸 자체가 없음) 둘 다 일반 순서로 되돌린다. */
@media screen and (max-width: 899.98px) {
  .field-pair.cols-4 { grid-template-columns: repeat(2,minmax(0,1fr)); }
  .field-pay-amt { grid-row: auto; }
  .field-pair .field-switches-row { grid-column: 1 / -1; grid-row: auto; }
}
.field input:not([type="checkbox"]), .field select, .field textarea {
  all: unset; box-sizing: border-box; width: 100%; font-family: inherit; font-size: 12.5px; color: var(--ink);
  padding: 6px 8px; border: 1px solid var(--line3); border-radius: 7px;
}
.field select { cursor: pointer; }
.field textarea { line-height: 1.45; resize: vertical; }
.field-label { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.hl-check { display: flex; align-items: center; cursor: pointer; }
.hl-check input { accent-color: #eab308; width: 13px; height: 13px; cursor: pointer; }

.check-row { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 10px 0; border-top: 1px solid rgba(23,25,28,0.08); border-bottom: 1px solid rgba(23,25,28,0.08); }
.check-row .lead { font-size: 13px; font-weight: 700; color: var(--ink); align-self: center; }
.check-row label { display: flex; align-items: center; gap: 6px; font-size: 12px; cursor: pointer; }
.check-row input { accent-color: var(--accent-soft); width: 14px; height: 14px; }
/* 보증서발행(유리막/썬팅)·출고서류 복사·고객부담금·기재완료 — 작은
   체크박스/스위치는 멀리서 훑어볼 때 켜짐/꺼짐이 눈에 잘 안 띈다는
   신고로, 켜지면 색이 꽉 차는 알약(pill) 버튼으로 바꿨다. 저장 방식은
   그대로 checkbox라 겉모양만 바뀐다 — 실제 <input>은 화면에서 숨기고
   그 옆 .pill-body를 checked 여부에 따라 꾸민다. */
.pill-toggle { gap: 0; }
.pill-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.pill-body {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px;
  border-radius: 999px; border: 1.5px solid var(--line3); background: #fff;
  font-size: 14px; font-weight: 700; color: var(--muted); line-height: 1.2;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.pill-body::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--line3); flex: none; transition: background 0.15s; }
.pill-input:checked + .pill-body { background: var(--accent-soft); border-color: var(--accent-soft); color: #fff; }
.pill-input:checked + .pill-body::before { background: #fff; }
.pill-input:focus-visible + .pill-body { outline: 2px solid var(--accent-soft); outline-offset: 2px; }
/* "기본 패키지에서 제외" — 라벨 옆에 체크박스를 나란히 붙이지 않고, 라벨
   아래에 2개씩 2줄로 나열한다(라벨 옆은 그냥 여백으로 비워둠). */
.check-row.stack { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 6px 14px; }
.check-row.stack .lead { grid-column: 1 / -1; }

.drawer-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 16px; border-top: 1px solid rgba(23,25,28,0.08); }
.drawer-foot .btn { min-height: 32px; padding: 7px 15px; font-size: 12.5px; }

/* ===== quote (A4) ===== */
.a4wrap { padding: 22px 0 60px; }
.a4 {
  width: 210mm; max-width: 100%; min-height: 297mm; box-sizing: border-box; background: #fff;
  border: 1px solid rgba(23,25,28,0.09); box-shadow: 0 6px 30px rgba(23,25,28,0.07);
  padding: 12mm 13mm; display: flex; flex-direction: column;
}
.q-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; padding-bottom: 8px; border-bottom: 2px solid var(--ink); }
.q-head h2 { margin: 0; font-size: 27px; font-weight: 600; letter-spacing: 0.24em; }
.q-head .en { font-size: 12px; color: var(--muted); margin-top: 6px; letter-spacing: 0.02em; }
.q-head .shop { text-align: right; font-size: 11.5px; color: #5d626a; line-height: 1.75; }
.q-head .shop .name { font-size: 14px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }

.q-meta { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 0 26px; margin-top: 12px; }
.q-meta-row { display: grid; grid-template-columns: 68px minmax(0,1fr); gap: 10px; padding: 6px 0; border-bottom: 1px solid rgba(23,25,28,0.09); font-size: 12.5px; }
.q-meta-row .k { color: #8a8e95; }
.q-meta-row .v { font-weight: 500; }

.q-h3 { margin: 11px 0 6px; font-size: 13px; font-weight: 600; letter-spacing: 0.06em; color: #42464d; }
/* "3. 안내 사항"(과 그 아래 입금계좌/서명 칸)은 내용이 짧은 견적서에서도
   페이지 중간에 붕 뜨지 않고 항상 아래쪽에 붙어 있어야 한다 — 남는
   세로 여백은 이 섹션 "위"로 몰아주고(margin-top:auto), 안내사항과
   그 아래 입금계좌/서명 칸 사이는 붙어서 그대로 고정 간격만 남는다. */
.q-h3.tight { margin: auto 0 5px; }

.q-thead { display: grid; grid-template-columns: 76px minmax(0,1fr) 96px; gap: 12px; padding: 8px 10px; background: var(--ink); color: #fff; font-size: 11.5px; letter-spacing: 0.04em; }
.q-work-row { display: grid; grid-template-columns: 76px minmax(0,1fr) 96px; gap: 12px; padding: 6px 10px; border-bottom: 1px solid rgba(23,25,28,0.08); font-size: 12.5px; align-items: baseline; }
.q-work-row .k { color: #5d626a; }
.q-work-row .v { line-height: 1.55; }
.q-work-row .amt { text-align: right; font-variant-numeric: tabular-nums; color: #5d626a; }
.q-subtotal { display: flex; justify-content: space-between; padding: 7px 10px; background: var(--bg); font-size: 12.5px; font-weight: 600; }
.q-subtotal span:last-child { font-variant-numeric: tabular-nums; }

.q-opt-row { display: grid; grid-template-columns: minmax(0,1fr) 96px; gap: 12px; padding: 6px 10px; border-bottom: 1px solid rgba(23,25,28,0.08); font-size: 12.5px; }
.q-opt-row .amt { text-align: right; font-variant-numeric: tabular-nums; color: #5d626a; }

.q-sumbox { margin-top: 14px; border: 1px solid var(--line3); }
.q-sum-row { display: flex; justify-content: space-between; gap: 14px; padding: 7px 14px; border-bottom: 1px solid rgba(23,25,28,0.08); font-size: 12.5px; color: #42464d; }
.q-sum-row span:last-child { font-variant-numeric: tabular-nums; }
.q-cash-row { display: flex; justify-content: space-between; align-items: baseline; gap: 14px; padding: 11px 14px; background: var(--ink); color: #fff; }
.q-cash-row .lbl { font-size: 13px; letter-spacing: 0.04em; }
.q-cash-row .amt { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }

.q-notes { margin: 0; padding-left: 18px; font-size: 11px; color: #5d626a; line-height: 1.5; }

.q-foot { margin-top: 14px; display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 26px; }
.q-foot .bank { font-size: 11.5px; color: #5d626a; }
.q-foot .bank .line { font-size: 12.5px; color: var(--ink); font-weight: 500; margin-top: 6px; }
.q-foot .sign { font-size: 11.5px; color: #5d626a; text-align: right; }
.q-foot .sign .row { margin-top: 22px; display: flex; justify-content: flex-end; gap: 10px; align-items: baseline; }
.q-foot .sign .u { display: inline-block; width: 120px; border-bottom: 1px solid rgba(23,25,28,0.4); }

/* ===== 견적서 상담 도우미(컨트롤러 / 빠른 견적 만들기) =====
   왼쪽부터 컨트롤러, 빠른 견적 만들기, A4 순서로 한 줄에 나란히 놓는다.
   인쇄에는 노출되면 안 되니 둘 다 .noprint. 좁은 화면에서는 flex-wrap으로
   자연스럽게 A4 위/아래로 쌓인다. */
.q-page { display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; align-items: flex-start; }
.q-side {
  width: 300px; max-width: 100%; flex: 0 0 300px; background: #fff; border: 1px solid var(--line);
  border-radius: 14px; padding: 16px; display: flex; flex-direction: column; gap: 10px; align-self: flex-start;
}
.q-side-title { font-size: 13px; font-weight: 600; color: var(--ink); margin-bottom: 2px; }
.q-side-title small { display: block; font-weight: 400; color: var(--muted); font-size: 11px; margin-top: 2px; }
.q-side-field { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: #5d626a; }
.q-side-field .select-box { width: 100%; }
.q-side-field .search-box, .q-side-field .text-box { width: 100%; }
.q-side-check { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink); cursor: pointer; }
.q-side-subtitle { font-size: 11.5px; font-weight: 600; color: #8a8e95; margin-top: 4px; }
.q-ppf-list { display: flex; flex-direction: column; gap: 2px; max-height: 220px; overflow-y: auto; border: 1px solid var(--line); border-radius: 10px; padding: 6px 10px; }
.q-ppf-item { display: flex; align-items: center; gap: 8px; padding: 5px 0; font-size: 12px; color: #42464d; cursor: pointer; }
.q-ppf-item span:first-of-type { flex: 1; }
.q-ppf-item .amt { color: #8a8e95; font-variant-numeric: tabular-nums; }
.q-side-total { display: flex; justify-content: space-between; align-items: baseline; padding: 10px 12px; background: var(--bg); border-radius: 10px; font-size: 13px; font-weight: 600; }
.q-side-total .amt { font-size: 16px; font-variant-numeric: tabular-nums; }
.q-calc-empty { font-size: 12px; color: var(--muted); padding: 6px 0; }

/* 컨트롤러의 "기준 가격 수정" 목록 — 이름 + 가격 입력칸 + (직접 추가한
   항목만) 삭제 버튼을 한 줄에. */
.qc-price-list { display: flex; flex-direction: column; gap: 2px; max-height: 220px; overflow-y: auto; border: 1px solid var(--line); border-radius: 10px; padding: 6px 10px; }
.qc-price-row { display: flex; align-items: center; gap: 6px; padding: 3px 0; }
.qc-price-name { flex: 1; min-width: 0; font-size: 11.5px; color: #42464d; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qc-price-row .qc-price-input { width: 84px; flex: 0 0 auto; text-align: right; }
.qc-price-del { flex: 0 0 auto; width: 18px; height: 18px; padding: 0; border: 0; background: none; color: var(--muted); cursor: pointer; font-size: 14px; line-height: 1; }
.qc-price-del:hover { color: #c0392b; }

/* ===== printable tables (가격표 / 필름단가 / 결제내역서 / 본점결제 공용) ===== */
.printflow { padding: 24px 0 60px; }
.stack { display: flex; flex-direction: column; gap: 20px; }
/* 결제내역서(.narrow)·본점결제(.ledger)만 다른 페이지(가격표/필름단가는
   폭 제한이 아예 없음)보다 훨씬 좁게(900px/860px) 잡혀 있어서, 넓은
   화면에서 유독 옆 여백이 커 보였다 — 다른 시트들과 똑같이 폭 제한을
   없애 .container(위쪽 규칙 참고)가 허용하는 만큼 꽉 채우게 했다. */

.card-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(280px,1fr)); gap: 16px; align-items: start; }
/* 가격표 페이지(.card-grid.wide)는 카드 6장을 4열로 묶는데, 열마다
   카드 수가 다르다(윈도우필름/필름농도는 혼자, 파노라마+PPF·TPE+코일매트는
   두 장씩 세로로 쌓임 — .card-col 참고) — 그래서 grid 항목은 실제로는
   "4개"(열 래퍼)뿐이다. auto-fill을 쓰면 화면이 넓을 때 실제 항목 수보다
   빈 트랙이 더 생겨서 4개가 왼쪽에 몰리고 오른쪽에 빈 공간이 남는다 —
   auto-fit을 쓰면 빈 트랙이 생기지 않고 있는 열만 폭을 나눠 가져 화면을
   고르게 채운다(.card-grid.pair와 같은 이유로 같은 방식을 쓴다). */
/* 가격표: 카드마다 둥근 모서리·개별 테두리·16px 여백을 두던 걸, 엑셀
   표처럼 여백 없이 딱 붙여서 오와 열을 맞췄다. 방법은 흔한 "테두리
   대신 배경색 틈으로 선을 보여주는" 기법 — 그리드/열 자체를 선 색
   (var(--line))으로 칠하고, 카드 사이 간격을 정확히 1px만 둬서 그
   1px 틈으로 얇은 구분선이 보이게 한다(카드 자체엔 테두리를 안 줘서
   겹쳐서 두꺼워지는 자리가 생기지 않는다). 바깥 테두리는 그리드
   자체에 1px을 둬서 표 전체를 감싼다. */
.card-grid.wide {
  grid-template-columns: repeat(auto-fit,minmax(320px,1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  /* 열마다 카드 개수·줄 수가 달라(예: TPE매트+코일매트 열이 윈도우필름
     열보다 훨씬 짧음) 그냥 두면 짧은 열 밑에 빈 공간이 남는다 —
     stretch로 모든 열을 가장 긴 열 높이에 맞춰 늘린다(빈틈없이). */
  align-items: stretch;
}
.card-grid.pair { grid-template-columns: repeat(auto-fit,minmax(330px,1fr)); }
/* 가격표 카드 열 래퍼 — 한 열 안에 카드 1장 또는 2장을 위아래로 쌓는다
   (예: 파노라마/썬루프 위, PPF 부위별 추가옵션 아래). 위 그리드와 같은
   방식(1px 틈 + 선 색 배경)으로 쌓인 카드 사이도 이어 붙인다. */
.card-col { display: flex; flex-direction: column; gap: 1px; background: var(--line); }
/* 그리드가 열을 가장 긴 열 높이까지 늘려도(align-items:stretch), 짧은
   열 안의 카드들 자체는 그대로라 밑에 빈 틈이 남는다 — 그 열의 마지막
   카드를 남는 높이만큼 늘려서(내용 없는 흰 여백으로 자기 칸을 채움)
   바닥까지 완전히 맞춘다. */
.card-col .table-card:last-child { flex: 1; }
.card-grid.wide .table-card { border: 0; border-radius: 0; }

.calc-card { background: #fff; border: 1px solid var(--line); border-radius: 14px; margin-bottom: 16px; overflow: hidden; }
.calc-card-title { padding: 11px 15px; background: var(--ink); color: #fff; font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
.calc-card-body { padding: 14px 15px; display: flex; flex-direction: column; gap: 10px; }
.calc-input { all: unset; box-sizing: border-box; width: 100%; font-family: inherit; font-size: 14px; padding: 10px 13px; background: var(--bg); border: 1px solid var(--line3); border-radius: 10px; }
.calc-input:focus { border-color: var(--accent-soft); background: #fff; }
.calc-result { font-size: 13px; color: var(--muted); line-height: 1.5; }
.calc-result.ok { color: var(--good); font-weight: 500; }
.calc-result.ok strong { color: var(--accent-dark); font-size: 15px; }
.calc-result.err { color: var(--danger); }
/* 필름단가 계산기 · 드롭다운+M수 한 줄(고르면 오른쪽에 바로 가격) */
.calc-select-row { display: flex; flex-direction: row; align-items: center; gap: 10px; padding-top: 10px; border-top: 1px solid var(--line3); }
.calc-select-row .select-box { width: 190px; }
.calc-select-row .text-box { width: 80px; }
.calc-price-display { margin-left: auto; font-weight: 700; font-size: 16px; white-space: nowrap; }

/* 영역 캡처 모드 — 켜져 있는 동안 대상 영역 안에서는 드래그가 전부 캡처용
   선택으로 바뀐다는 걸 커서/드래그 금지로 미리 알려준다. */
.capture-target { cursor: crosshair; user-select: none; -webkit-user-select: none; }
.capture-select-box { position: absolute; z-index: 9999; border: 2px dashed var(--accent-dark, #2563eb); background: rgba(37,99,235,0.12); pointer-events: none; }
.capture-toast {
  position: fixed; z-index: 10000; transform: translate(-50%,-80%); opacity: 0;
  background: #17191c; color: #fff; font-size: 12.5px; font-weight: 600;
  padding: 8px 14px; border-radius: 8px; white-space: nowrap; pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease; box-shadow: 0 6px 18px rgba(0,0,0,0.18);
}

.table-card { background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
/* PPF 부위별 추가옵션/윈도우필름 카드에 직접 추가한 항목의 삭제 버튼과
   "숨김" 체크 — .row는 .k/.v 두 칸이 space-between으로 양끝 정렬돼
   있어서, 세 번째·네 번째 자식으로 그냥 붙이면 .v가 가운데로 밀린다.
   그래서 둘 다 절대위치로 오른쪽에 나란히 얹고, 자리만큼 오른쪽
   패딩을 둔다. */
.table-card .row.has-controls { position: relative; padding-right: 78px; }
.row-del { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; display: grid; place-content: center; border-radius: 6px; font-size: 13px; color: #c3c6ca; background: transparent; border: 0; cursor: pointer; }
.row-del:hover { background: var(--danger-bg); color: var(--danger); }
/* "숨김" 체크 — 켜면 이 가격표 화면(수정 모드 끈 평소 화면)에서는
   항목이 아예 안 보이지만, 결제내역서 가격 대조 계산에는 그대로
   반영된다(고객에게 안 보여줘도 되는 내부용 조정 옵션을 만들 때).
   수정 모드에서는 흐리게 표시해 계속 관리할 수 있다. */
.row-hide-toggle { position: absolute; right: 32px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; gap: 3px; font-size: 10.5px; color: var(--muted); cursor: pointer; white-space: nowrap; }
.row-hide-toggle input { width: 12px; height: 12px; margin: 0; cursor: pointer; }
.table-card .row.row-hidden { opacity: 0.5; }
.table-card .bar { padding: 11px 15px; background: var(--ink); color: #fff; font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
.table-card .bar small { font-weight: 400; color: rgba(255,255,255,0.6); }
.table-card .sub-head { display: flex; justify-content: space-between; gap: 12px; padding: 8px 15px; background: var(--bg); font-size: 11.5px; color: #8a8e95; }
.table-card .row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 2px 12px; padding: 9px 15px; border-top: 1px solid rgba(23,25,28,0.055); font-size: 13px; }
/* .k(제품명)는 flex-shrink 기본값 + word-break 기본 규칙 때문에, .v(필름농도처럼
   아주 긴 값)가 자리를 다 차지하면 폭이 0에 가깝게 눌려서 한글이 "루/마/버/텍/스"
   처럼 한 글자씩 세로로 쪼개지는 문제가 있었다(3단 인쇄 레이아웃에서 실제 발견).
   keep-all + 최소 폭으로 이름은 통째로 유지하고, 값 쪽이 대신 줄바꿈되게 한다. */
.table-card .row .k { color: #2a2d32; font-weight: 600; min-width: 76px; flex: 1 1 55%; word-break: keep-all; overflow-wrap: break-word; }
.table-card .row .v { color: #45484d; font-weight: 600; font-variant-numeric: tabular-nums; flex: 1 1 35%; text-align: right; white-space: normal; word-break: normal; overflow-wrap: break-word; }

.base-card { border-radius: 0; } /* 아래 카드 그리드도 모서리를 각지게 맞춰서(엑셀 표 느낌) 통일 */
.base-card .sub-head { grid-template-columns: minmax(120px,1fr) minmax(0,1.6fr) minmax(110px,1fr); display: grid; }
.base-card .row { display: grid; grid-template-columns: minmax(120px,1fr) minmax(0,1.6fr) minmax(110px,1fr); gap: 12px; padding: 11px 16px; font-size: 12.5px; }
.base-card .row .k { font-weight: 500; }
.base-card .row .v { color: #5d626a; }
.base-card .row .m { text-align: right; color: var(--danger); font-variant-numeric: tabular-nums; }

/* 기본 패키지 포함 구성(base-card)을 절반 폭으로 줄이고 그 옆에 추가
   안내 카드를 나란히 붙인다. 두 카드는 내용 줄 수가 다른데(3줄 vs
   6줄), align-items:stretch로 짧은 카드를 긴 카드 높이까지 늘리고,
   그 카드의 마지막 행에 flex:1을 줘서(빈 여백으로) 바닥 라인을
   맞춘다 — 위에서 4열 가격표에 쓴 것과 같은 방식. 좁은 화면에서는
   flex-wrap으로 자동으로 세로 1열로 쌓인다. */
.two-card-row { display: flex; flex-wrap: wrap; gap: 16px; align-items: stretch; }
.two-card-row .table-card { flex: 1 1 340px; min-width: 0; display: flex; flex-direction: column; }
.two-card-row .table-card > .row:last-child { flex: 1; }
/* 기본 패키지/추가 안내 두 카드를 최대한 압축해서 그만큼 아래 4열
   표가 화면 위쪽에 더 가깝게 붙도록 글자 크기·줄 간격을 줄였다. */
.two-card-row .bar { padding: 6px 12px; font-size: 12px; }
.two-card-row .sub-head { padding: 4px 12px; font-size: 10px; }
.two-card-row .row { padding: 4px 12px; font-size: 11px; }
.two-card-row .base-card .row { padding: 5px 13px; font-size: 10.5px; gap: 8px; }

.fallback-banner { padding: 11px 15px; border-radius: 11px; background: var(--danger-bg); color: var(--danger); font-size: 12.5px; }

/* 매출표: 열이 많은(월별집계 11열) 표라 카드 안 flex .row 대신 진짜 <table>을
   쓴다 — <tr>은 원래 블록처럼 페이지 경계에서 자연스럽게 끊기고(가격표
   인쇄에서 grid/다단이 깨졌던 문제의 원인이 아예 없는 구조), 모바일 폭에서는
   컨테이너를 가로 스크롤시켜 표가 눌려 찌그러지는 걸 막는다. */
.table-scroll { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.data-table th, .data-table td { padding: 8px 12px; text-align: left; white-space: nowrap; }
.data-table th.num, .data-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table thead th { background: var(--bg); color: #8a8e95; font-weight: 600; font-size: 11px; border-bottom: 1px solid rgba(23,25,28,0.09); }
.data-table tbody td { border-top: 1px solid rgba(23,25,28,0.055); color: #2a2d32; }
.data-table tbody tr:hover td { background: rgba(23,25,28,0.02); }
.data-table td.data-empty { color: var(--muted); text-align: center; padding: 20px 12px; white-space: normal; }
.data-table tfoot td { border-top: 1px solid var(--line3); background: var(--bg); font-weight: 700; }

.summary-grid { display: grid; grid-template-columns: repeat(auto-fit,minmax(170px,1fr)); gap: 14px; }
.summary-grid.pay { grid-template-columns: repeat(auto-fit,minmax(180px,1fr)); }
.summary-card { padding: 18px; border-radius: 14px; border: 1px solid var(--line); }
.summary-card .k { font-size: 12px; opacity: 0.65; }
.summary-card .v { font-size: 24px; font-weight: 600; letter-spacing: -0.03em; margin-top: 6px; font-variant-numeric: tabular-nums; }
.summary-card.pay .v { font-size: 26px; }

.ledger-table { display: grid; grid-template-columns: 82px minmax(0,1fr) 100px 30px; gap: 10px; align-items: center; padding: 9px 16px; font-size: 13px; color: #2a2d32; border-top: 1px solid rgba(23,25,28,0.055); }
.ledger-note { padding: 0 16px 8px 108px; font-size: 11px; color: #92610a; }
.ledger-empty { padding: 14px 16px; font-size: 12.5px; color: var(--muted); }
.ledger-head { display: grid; grid-template-columns: 82px minmax(0,1fr) 100px 30px; gap: 10px; padding: 9px 16px; font-size: 11.5px; }
.ledger-head.plus { background: var(--bg); color: var(--muted); }
.ledger-head.minus { background: var(--danger-bg); color: var(--danger); }
.ledger-total { display: flex; justify-content: space-between; gap: 12px; padding: 12px 16px; font-size: 13.5px; font-weight: 600; }
.ledger-total.plus { background: var(--bg); }
.ledger-total.minus { background: var(--danger-bg); color: var(--danger); }
.ledger-del { cursor: pointer; width: 26px; height: 26px; display: grid; place-content: center; border-radius: 7px; font-size: 13px; color: #c3c6ca; background: transparent; border: 0; }
.ledger-del:hover { background: rgba(23,25,28,0.06); color: var(--danger); }
.ledger-date { font-variant-numeric: tabular-nums; color: var(--muted); }
.ledger-amt { text-align: right; font-variant-numeric: tabular-nums; }
.ledger-amt.minus { color: var(--danger); font-weight: 600; }

.pay-empty { margin-top: 22px; padding: 34px 20px; border: 1px dashed rgba(23,25,28,0.18); border-radius: 14px; text-align: center; color: var(--muted); font-size: 13.5px; }
/* 결제건 목록을 카드 세로쌓기 대신 표로 바꿔서 밀도를 크게 높였다(한
   화면·한 페이지에 더 많은 건이 들어가야 하는 요청) — 결제건 하나가
   <tbody> 하나(패키지/추가옵션 여러 줄 + 소계)이고, 번호·날짜·차종/고객은
   그 결제건의 첫 줄에 rowspan으로 세로 병합해 반복을 없앴다. */
/* 내역(.pt-desc) 칸은 줄바꿈을 허용해서 긴 설명도 읽기 좋게 하는데, 그
   상태로 좁은 화면에 들어가면 표가 가로 스크롤되는 대신 그냥 쪼그라들며
   글자가 세로로 잔뜩 줄바꿈돼 버린다(실제로 겪음) — min-width로 자연스러운
   폭을 지켜서, 좁은 화면에서는 기존처럼(.table-scroll) 가로 스크롤이
   뜨게 한다. */
/* width:100%였을 때는 폭 제한이 없는 컨테이너(넓은 화면)에서 표가
   화면 끝까지 억지로 늘어나고, 그 남는 폭을 전부 내역(.pt-desc) 칸이
   떠안아서 내용과 금액 사이에 실제 글자 길이와 무관하게 거대한 빈
   공간이 생겼다(실제 신고) — width:100%를 빼서 표가 내용만큼만
   넓어지게 하고, min-width로 너무 좁아지는 것만 막는다. */
.pay-table { max-width: 100%; min-width: 760px; border-collapse: collapse; font-size: 12.5px; background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.pay-table thead th { background: var(--ink); color: #fff; font-weight: 600; text-align: left; padding: 8px 12px; font-size: 11px; letter-spacing: 0.02em; white-space: nowrap; }
.pay-table thead th.pt-amt { text-align: right; }
.pay-table td { padding: 7px 12px; border-bottom: 1px solid rgba(23,25,28,0.06); vertical-align: top; }
.pay-table .pt-master { font-weight: 700; white-space: nowrap; }
.pay-table .pt-num { color: var(--muted); white-space: nowrap; }
.pay-table .pt-date { color: var(--muted); white-space: nowrap; font-size: 12px; }
/* 차종/고객 칸 자체는 짧지만, 가격 불일치일 때 그 안에 같이 들어가는
   "가격표 대조 ○○○원 · 입력값과 다름" 안내문이 한 줄로 쭉 펴지면
   그 길이가 열 전체 폭이 되어(내역 칸과 같은 문제) 표가 불필요하게
   넓어진다 — max-width로 상한을 둬서 안내문도 자연스럽게 줄바꿈되게
   한다. */
.pay-table .pt-title { font-weight: 600; min-width: 150px; max-width: 280px; }
.pay-table .pt-title .badge { margin-left: 6px; font-weight: 500; }
.pay-table .pt-kind { color: #8a8e95; white-space: nowrap; }
/* 표 레이아웃(table-layout:auto)에서 한 칸의 "선호 폭"은 줄바꿈 없이 한
   줄로 쭉 폈을 때의 길이로 계산된다 — 내역 중 유독 긴 한 줄(예: 패키지+
   여러 추가옵션을 전부 나열한 줄)이 있으면 그 폭이 열 전체의 폭이 되고,
   같은 칸을 쓰는 다른 모든 행도 실제 글자 길이와 무관하게 그 넓은 폭을
   그대로 물려받아 내용과 금액 사이에 큰 빈 공간이 생긴다. max-width로
   상한을 둬서 그런 긴 줄은 두 줄로 접히게 하고, 짧은 내용들은 꼭 필요한
   만큼만(표 자체도 내용 기준으로 줄어들며) 차지하게 한다. */
.pay-table .pt-desc { max-width: 480px; }
.pay-table .pt-amt { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pay-table .pt-subtotal td { font-weight: 700; background: var(--bg); border-bottom: 2px solid var(--line); }
/* td 자체의 display를 flex로 바꾸면 표 레이아웃(특히 colspan 너비 계산)이
   깨져서(실제로 겪음 — 소계 줄이 왼쪽에 쪼그라들고 나머지가 텅 빔), td는
   기본 table-cell로 두고 안에 flex wrapper를 하나 더 둔다. */
.pay-table .pt-subtotal-inner { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pay-table tbody:last-child tr:last-child td { border-bottom: 0; }
/* 표 맨 아래 "총액" 줄 — 결제건별 소계(.pt-subtotal)보다 한 단계 더
   진하게 둬서, 여러 건이 쭉 나열돼도 맨 밑의 총합계가 항상 눈에 띈다. */
.pay-table .pt-grandtotal td { font-weight: 700; font-size: 13.5px; background: var(--ink); color: #fff; border-bottom: 0; }
.pay-group-actions { display: inline-flex; gap: 8px; font-weight: 400; }
.btn-tiny { cursor: pointer; min-height: 32px; padding: 7px 14px; border-radius: 8px; font-size: 12.5px; border: 0; }
.btn-tiny.soft { background: var(--accent-bg); color: var(--accent); font-weight: 600; }
.btn-tiny.soft:hover { opacity: 0.85; }
.btn-tiny.outline { background: transparent; border: 1px solid rgba(23,25,28,0.12); color: var(--danger); }
.btn-tiny.outline:hover { background: var(--danger-bg); }

.deposit-list { margin-top: 22px; display: flex; flex-direction: column; gap: 2px; }
.deposit-row { display: flex; flex-wrap: wrap; row-gap: 4px; justify-content: space-between; gap: 14px; padding: 13px 16px; border-radius: 11px; background: var(--accent-bg); font-size: 13.5px; }
/* 좁은 화면(모바일)에서 .left(날짜·내용)가 눌리면 "07월 15일"처럼 짧은
   날짜조차 한 글자씩 세로로 쪼개지는 문제가 있었다(가격표 인쇄에서 겪은
   것과 같은 원인). keep-all로 단어 단위 유지 + flex-wrap으로 자리가
   없으면 .right가 다음 줄로 내려가게 해서, 텍스트가 눌려 쪼개지는 대신
   줄바꿈되게 한다. */
.deposit-row .left { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; word-break: keep-all; overflow-wrap: break-word; }
.deposit-row .sep { color: var(--faint); }
.deposit-row .right { flex: 0 0 auto; display: flex; gap: 6px; align-items: center; }
.deposit-row .cum { font-size: 11.5px; color: var(--muted); }
.deposit-row .amt { font-weight: 600; font-variant-numeric: tabular-nums; }

.bank-line { margin: 18px 0 0; font-size: 13px; color: var(--muted); }

/* ===== 로그인 화면 (Netlify 등 자체 배포에서 requireLogin:true일 때만) ===== */
.auth-screen { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--bg); }
.auth-card { width: 100%; max-width: 360px; background: #fff; border: 1px solid var(--line); border-radius: 16px; padding: 28px 26px; box-shadow: 0 10px 40px rgba(23,25,28,0.06); display: flex; flex-direction: column; }
.auth-logo { width: 40px; height: 40px; border-radius: 10px; background: var(--ink); color: #fff; display: grid; place-content: center; font-weight: 700; font-size: 13px; margin-bottom: 14px; }
.auth-card h2 { margin: 0; font-size: 19px; letter-spacing: -0.02em; }
.auth-sub { margin: 4px 0 20px; font-size: 13px; color: var(--muted); }
.auth-field { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted2); margin-bottom: 12px; }
.auth-field input, .auth-field select { all: unset; box-sizing: border-box; width: 100%; font: inherit; font-weight: 400; color: var(--ink); padding: 10px 12px; background: var(--bg); border: 1px solid var(--line3); border-radius: 10px; }
.auth-error { font-size: 12.5px; color: var(--danger); background: var(--danger-bg); padding: 9px 12px; border-radius: 9px; margin-bottom: 12px; }
.auth-ok { font-size: 12.5px; color: var(--good); background: var(--good-bg); padding: 9px 12px; border-radius: 9px; margin-bottom: 12px; }
.auth-submit { width: 100%; justify-content: center; margin-top: 4px; }
.sidebar-user { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 2px; margin-bottom: 4px; border-bottom: 1px solid var(--line); font-size: 12px; color: var(--muted); }
.sidebar-user .who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-user button { flex: 0 0 auto; color: var(--muted2); cursor: pointer; font-size: 12px; font-weight: 600; }
.sidebar-user button:hover { color: var(--ink); }

/* ===== 회원관리 ===== */
.card { background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 18px; }
.card-title { font-size: 14.5px; font-weight: 700; margin-bottom: 14px; }
.member-create-form { display: flex; flex-direction: column; }
.member-list { display: flex; flex-direction: column; }
.member-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line); }
.member-row:first-child { border-top: 0; }
.member-email { font-weight: 600; font-size: 13.5px; }
.member-meta { font-size: 12px; color: var(--muted); margin-top: 2px; }

/* ===== 매장 설정 ===== */
.config-list-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.config-list-row input { flex: 1; box-sizing: border-box; font: inherit; color: var(--ink); padding: 10px 12px; background: var(--bg); border: 1px solid var(--line3); border-radius: 10px; }

/* ===== print ===== */
@page { size: A4; margin: 0; }
@media print {
  * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; color-adjust: exact !important; }
  body { background: #fff; }
  .noprint { display: none !important; }
  /* .container는 화면용 상단 여백(28px)을 갖고 있는데, 인쇄용 래퍼들의 패딩만
     0으로 되돌리고 이건 안 지워서 모든 인쇄 페이지 맨 위에 죽은 공간이 남아
     A4 한 장 분량 콘텐츠가 다음 페이지로 넘어가던 원인이었다. */
  .container { padding: 0 !important; max-width: none !important; }
  .a4wrap { padding: 0 !important; max-width: none !important; }
  /* 견적서 상담 도우미(.q-side)는 이미 .noprint라 안 보이지만, 감싸는
     .q-page 자체를 인쇄용 block 흐름으로 되돌려서 .a4가 다른 인쇄 페이지
     들과 똑같이(flex 없이) 안정적으로 찍히게 한다. */
  .q-page { display: block !important; }
  [contenteditable] { outline: 0 !important; background: none !important; }
  .printflow { padding: 10mm !important; }
  /* 카드 전체를 break-inside:avoid로 묶으면, 윈도우필름처럼 행이 20개가
     넘어 한 페이지에 다 안 들어가는 카드는 통째로 다음 페이지로 밀려나면서
     현재 페이지 나머지가 텅 빈 채로 남는다(실제로 확인된 원인). 카드는
     페이지 사이에서 쪼개지게 두고, 대신 "행 하나"가 페이지 경계에 걸려
     반으로 잘리는 것만 막는다. 결제내역서 카드처럼 원래 짧은 카드는
     어차피 한 페이지 안에 들어가니 그대로 안 쪼개진 것처럼 보인다. */
  [data-pcard] { break-inside: auto; }
  .table-card .row, .base-card .row, .ledger-table, .deposit-row, .data-table tr { break-inside: avoid; }
  /* 결제건 표(.pay-table)는 table-card와 반대로 간다 — 한 결제건(tbody)이
     보통 1~4줄뿐이라, 페이지 경계에서 번호·날짜·차종 rowspan 셀이 반으로
     잘리는 것보다는 결제건 통째로 다음 페이지로 넘기는 편이 안전하다.
     표 자체(thead)는 네이티브 인쇄 분할로 페이지마다 헤더가 반복된다. */
  .pay-table tr { break-inside: avoid; }
  .pay-table thead { display: table-header-group; }
  .data-table thead { display: table-header-group; } /* 페이지 넘어가도 헤더 반복 */
  .data-table { font-size: 9.5px !important; }
  .data-table th, .data-table td { padding: 4px 7px !important; }
  /* 화면처럼 2~3열로 채워보려고 grid, 그다음 CSS 다단(column)까지 시도했다.
     grid는 우리 헤드리스 크롬 테스트로는 멀쩡했지만 실제 사용자 크롬에서는
     "기본 패키지" 카드 뒤 콘텐츠 전체가 다음 페이지로 통째로 밀리면서 현재
     페이지가 거의 텅 비고 다음 페이지 내용이 잘려 보이는 문제가 재현됐다.
     다단(column)으로 바꿔도 우리 테스트에서 똑같은 증상이 재현됐다(column-fill:
     auto를 줘도, .stack의 flex를 block으로 바꿔도 동일) — 즉 "여러 카드를
     담은 큰 컨테이너를 페이지 중간에서 자연스럽게 이어 쪼개는" 동작 자체가
     크롬 인쇄 엔진에서 안정적으로 보장되지 않는다는 뜻이다. 실제로 안 잘리고
     빈 페이지도 안 생기는 걸 화면 스크린샷+PDF로 검증된 방식은 결국 카드를
     위→아래 한 줄로 쌓는 일반 블록 흐름뿐이라, 다단/그리드를 포기하고 이걸로
     되돌렸다. 대신 화면보다 글자·여백을 확 줄여서 페이지 수를 최대한 줄인다
     — "작게 해서라도 다 보여야 한다"는 요청 반영. */
  .card-grid, .card-grid.wide, .card-grid.pair { display: block !important; }
  .card-grid > *, .card-grid.wide > *, .card-grid.pair > * { margin-bottom: 8px; }
  /* 화면에서는 그리드 틈으로 선을 보여주려고 .card-grid.wide/.card-col에
     선 색 배경을 깔아뒀는데(위 화면용 규칙 참고), 인쇄는 카드가 위→아래
     한 줄로 쌓이는 블록 흐름이라 그 배경이 카드 사이 여백에 그대로
     색으로 드러나 버린다 — 인쇄에서는 원래대로 흰 배경에 테두리 있는
     카드로 되돌린다. */
  .card-grid.wide { background: none !important; border: 0 !important; }
  .card-col { background: none !important; gap: 8px !important; }
  .card-grid.wide .table-card, .card-col .table-card { border: 1px solid var(--line) !important; border-radius: 10px !important; }
  .card-col .table-card:last-child { flex: initial !important; }
  .base-card { border-radius: 10px !important; }
  .two-card-row { display: block !important; }
  .two-card-row .table-card { border-radius: 10px !important; margin-bottom: 8px; }
  .two-card-row .table-card > .row:last-child { flex: initial !important; }
  .summary-grid, .summary-grid.pay { display: flex !important; flex-wrap: wrap; gap: 8px !important; }
  .summary-card { flex: 1 1 150px; padding: 10px !important; }
  .summary-card .v { font-size: 17px !important; margin-top: 2px !important; }
  .table-card .bar { padding: 6px 10px !important; font-size: 11.5px !important; }
  .table-card .sub-head { padding: 3px 10px !important; font-size: 9.5px !important; }
  .table-card .row { padding: 3px 10px !important; font-size: 10px !important; gap: 2px 8px !important; }
  .table-card .row .k { min-width: 60px !important; }
  .base-card .row { padding: 5px 9px !important; font-size: 9.5px !important; }
  .base-card .sub-head { padding: 3px 9px !important; font-size: 9px !important; }
  /* .stack은 화면에서 flex-direction:column인데, 크롬 인쇄 페이지 나눔은
     flex 컨테이너 안에서도 grid만큼이나 들쭉날쭉하다(자식 하나가 남은 공간에
     안 맞으면 그 자식 전체를 다음 페이지 맨 위로 밀어버려 현재 페이지에
     큰 빈 공간이 남을 수 있다 — 기본 패키지 카드 뒤로 가격표 3단 카드가
     통째로 다음 페이지로 밀리는 걸로 실제 확인됨). 인쇄 시엔 일반 블록
     쌓기로 바꿔서 이 문제를 피한다. */
  .stack { display: block !important; }
  .stack > * { margin-bottom: 10px; }
  /* 결제내역서(영업사원별 청구/입금 표) — 요청대로 글자·여백을 줄여서
     한 페이지에 더 많은 건이 들어가게 한다. */
  .stack.narrow { max-width: none; }
  .pay-table { font-size: 10px !important; }
  .pay-table th, .pay-table td { padding: 4px 7px !important; }
  .deposit-list { margin-top: 10px !important; }
  .deposit-row { padding: 7px 11px !important; font-size: 11px !important; }
  /* 296mm(297mm보다 살짝 작게): 297mm를 정확히 맞추면 mm->px 반올림 오차 때문에
     프린트 엔진이 아주 살짝(0.5px) 넘치는 걸로 계산해 빈 페이지를 하나 더
     만들어내는 경우가 있어, 안전 여백으로 1mm 줄여둔다. */
  .a4 { width: 210mm !important; height: 296mm; min-height: 0; overflow: hidden; box-shadow: none !important; border: 0 !important; margin: 0 !important; border-radius: 0 !important; }
}
