@charset "UTF-8";
/* ═══════════════════════════════════════════════════════════════════
   MTS 공용 부품 (컴포넌트) — 화면이 쓰는 유일한 부품 창고.
   토큰: core/tokens.css   ·   실물 카탈로그: /office/ui/   ·   문서: docs/디자인시스템.md

   ★ 원칙 (리바이벌의 실패를 반복하지 않기 위해)
     업무 고유의 것(대사 등급 A/B/C, 세목, 급여 항목)만 그 화면의 것이고,
     **글꼴·글자크기·색·버튼·입력칸·폼 배치·키보드 이동은 전 화면이 똑같다.**
     그래서 그것들은 전부 여기 한 곳에만 있다.

   ⚠ 새 부품이 필요하면
     1) 여기에 추가하고  2) /office/ui/ 카탈로그에 예시를 얹는다.
     화면 템플릿의 <style>에 새 부품을 만들지 않는다. (그게 리바이벌이 무너진 방식)
     화면 <style>에 남겨도 되는 것 = **그 화면에만 있는 업무 고유 레이아웃뿐.**
   ═══════════════════════════════════════════════════════════════════ */

/* ── 0. 기본 ─────────────────────────────────────────── */
/* 화면 넘김을 부드럽게 — 업무관리 ↔ 마감 내역처럼 주소가 바뀌는 탭을 누르면 흰 화면이 번쩍이며 바뀌던 것(사장님 2026-10-23).
   브라우저가 옛 화면을 붙잡고 있다가 새 화면과 겹쳐 바꾼다(같은 사이트 안 이동만 · 크롬 126+ · 못 하는 브라우저는 예전대로).
   ⚠ 두 화면이 모두 이 줄을 읽어야 켜진다 — 공용 부품 창고에 둔 까닭. 움직임을 줄여 둔 PC 에선 끈다. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 120ms; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
html { background: var(--canvas); }
* { box-sizing: border-box; }
/* hidden 은 언제나 숨긴다 — .btn 의 display 가 hidden 을 이겨 [시즌 시작]이 늘 보이던 일(2026-10-18) */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-md);
  line-height: var(--lh);
  color: var(--ink);
  background: var(--canvas);
}

h1 { font-size: var(--fs-h1); margin: 0 0 var(--s4); }
h2 { font-size: var(--fs-h2); margin: 0 0 var(--s3); }
a { color: var(--brand); }

/* 포커스 링 — 키보드로 다니는 사람에게 지금 어디인지 항상 보이게.
   ⚠ outline:none 을 어디에도 쓰지 않는다 (접근성이자 입력 속도 문제). */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

/* ── 1. 레이아웃 ──────────────────────────────────────── */
.page { max-width: var(--page-w); margin: var(--s6) auto; padding: 0 var(--s4); }
.page--wide { max-width: var(--page-w-wide); }
/* 창 폭을 다 쓴다 — 가로로 긴 격자(업무관리 · 사장님 2026-10-19 「창을 최대한 넓게」) · 양옆 여백만 조금 */
.page--full { max-width: none; margin: var(--s3) 0; padding: 0 var(--s3); }
/* ⚠ width:100% — 포털 body 가 flex 가운데 정렬이라(legacy) 폭을 안 주면 내용 폭으로 줄어든다 */
.page--narrow { width: 100%; max-width: var(--page-w-portal); margin: 0 auto; padding: var(--s4) var(--s3) 60px; }

/* 사무실 상단 바 */
.appbar {
  background-color: var(--appbar-bg); background-image: none; color: var(--appbar-ink);
  border-bottom: 1px solid var(--appbar-line);
  box-shadow: 0 2px 0 var(--paper), 0 3px 0 var(--appbar-line);   /* 장부 머리 이중선 */
  padding: var(--s2) var(--s6);
  display: flex; align-items: center; gap: var(--s6);
}
.appbar .brand { display: flex; align-items: center; gap: var(--s2);
                 font-weight: 700; font-size: var(--fs-h2); color: var(--appbar-ink);
                 text-decoration: none; }
/* 로고에 이미 상호가 있으므로 옆 글자는 「사무실 / 고객센터」 꼬리표만 (중복 방지) */
.appbar .brand img { height: 34px; width: auto; display: block; }
.brand-label { font-size: var(--fs-sm); font-weight: 600; opacity: .75;
               padding-left: var(--s2); border-left: 1px solid currentColor; }
/* ⚠ 메뉴가 늘면(14칸) 좁은 창에서 ①글자가 한 자씩 세로로 쌓였고(1차) ②줄바꿈을 허용하니 네 줄로 쌓여
   상단바가 비대해졌다(2차 · 사장님 「상단바가 이상하잖아」) ⇒ **상단바는 언제나 한 줄**.
   메뉴가 모자라면 옆으로 밀어 본다(끝이 흐려져 「더 있다」를 알린다). 근본 해결 = 좌측 접이 메뉴(셸 작업). */
.appbar { flex-wrap: nowrap; height: var(--appbar-h); padding-top: 0; padding-bottom: 0; }
.appbar nav { display: flex; flex-wrap: nowrap; gap: var(--s4); flex: 1 1 auto; min-width: 0;
              overflow-x: auto; scrollbar-width: none; align-self: stretch; align-items: center;
              -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
                      mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
              padding-right: 28px; }
.appbar nav::-webkit-scrollbar { display: none; }
.appbar .brand, .appbar-user { flex-shrink: 0; }
.appbar nav a { color: var(--appbar-soft); text-decoration: none; font-size: var(--fs-md); white-space: nowrap;
                padding: 2px 0; border-bottom: 2px solid transparent; }
.appbar nav a:hover { color: var(--appbar-ink); }
.appbar nav a[aria-current="page"] { color: var(--appbar-ink); font-weight: 700; border-bottom-color: var(--seal); }   /* 지금 화면 = 인주 밑줄 */
/* 상단바 오른쪽 — 로그인한 사람 · 비밀번호 · 로그아웃(POST 라 버튼이지만 링크처럼 보이게) */
.appbar-user { margin-left: auto; display: flex; align-items: center; gap: var(--s3);
               font-size: var(--fs-sm); color: var(--appbar-soft); white-space: nowrap; }
.appbar-user a, .appbar-user button { color: var(--appbar-soft); text-decoration: none; background: none;
               border: 0; padding: 0; font: inherit; cursor: pointer; }
.appbar-user a:hover, .appbar-user button:hover { color: var(--appbar-ink); }
.appbar-user form { margin: 0; }

/* ── 1-b. 사무실 셸 — 좌측 접이 메뉴 (2026-10-02 · 리바이벌 셸과 같은 치수) ──────────
   ★ 메뉴 바탕도 상단바와 같은 **귀리색 리넨** — 먹색 띠가 종이 화면에서 이질적이었다(사장님 지적).
   ★ 지금 화면 = 장부 **색인 탭**(종이가 튀어나오고 왼쪽에 인주 표시).
   펼침 --side-w 232 / 접힘 --side-w-min 56(아이콘 레일) · 640px 이하 = 위에 작은 바 + 서랍. */
.shell { display: flex; min-height: 100vh; }
.shell-main { flex: 1 1 auto; min-width: 0; }
.sidebar {
  width: var(--side-w); flex-shrink: 0; position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden;
  background-color: var(--appbar-bg); background-image: none;
  border-right: 1px solid var(--appbar-line); box-shadow: 1px 0 0 var(--paper);
  transition: width var(--dur) var(--ease);
  scrollbar-width: none;   /* 세로 스크롤바 안 보이게(사장님) — 메뉴가 길면 스크롤은 그대로 된다 */
}
.sidebar::-webkit-scrollbar { display: none; }
.side-head { display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s3); min-height: var(--appbar-h);
             border-bottom: 1px solid var(--appbar-line); }
/* 화면 안 로고(brand_logo 태그) — 글자는 color 를, 심볼은 --logo-* 토큰을 따른다 */
.brand-logo { display: block; height: 26px; width: auto; }
.side-brand { color: var(--appbar-ink); display: block; }
.side-toggle { width: 32px; height: 32px; flex-shrink: 0; border: 0; background: transparent; cursor: pointer;
               border-radius: var(--r-sm); display: inline-flex; flex-direction: column; justify-content: center;
               align-items: center; gap: 4px; padding: 0; }
.side-toggle span { display: block; width: 16px; height: 2px; background: var(--appbar-ink); border-radius: 1px; }
.side-toggle:hover { background: var(--label-paper); }
.side-menu { padding: var(--s2) 0; }
.side-group-title { font-size: var(--fs-xs); font-weight: 700; color: var(--appbar-soft); padding: var(--s3) var(--s4) var(--s1);
                    letter-spacing: .06em; white-space: nowrap; }
/* 메뉴 묶음 접기(office/menu.py FOLDED · 2026-10-06) — 제목을 눌러 펼친다. 펼친 묶음은 지금과 똑같이 보인다 */
.side-fold > summary { list-style: none; cursor: pointer; }
.side-fold > summary::-webkit-details-marker { display: none; }
.side-fold:not([open]) > summary::after { content: ' +'; }
.side-item { display: flex; align-items: center; gap: var(--s3); width: calc(100% - 16px); margin: 2px var(--s2);
             padding: 6px var(--s2); border: 0; border-radius: var(--r-sm); background: transparent;
             color: var(--appbar-soft); font: inherit; font-size: var(--fs-md); text-decoration: none;
             text-align: left; cursor: pointer; white-space: nowrap; position: relative; }
.side-item:hover { background: var(--label-paper); color: var(--appbar-ink); }
/* 지금 화면 = 리바이벌처럼 **왼쪽 굵은 선 + 흰 굵은 글자**(밝은 종이 칸은 진한 메뉴에서 튀었다). 선 색은 로고의 금 */
.side-item.is-on { background: var(--label-paper); color: var(--appbar-ink); font-weight: 700;
                   box-shadow: inset 3px 0 0 var(--seal); }
/* 아이콘 = Lucide({% icon %}) · 글자색을 따른다 */
.ico { width: 18px; height: 18px; flex-shrink: 0; display: inline-block; vertical-align: -3px; }
.side-ico { width: 18px; height: 18px; margin-left: 4px; opacity: .85; }
.side-item.is-on .side-ico { opacity: 1; color: var(--seal); }
.side-text { overflow: hidden; text-overflow: ellipsis; }
.side-dot { width: 7px; height: 7px; border-radius: 50%; margin-left: auto; flex-shrink: 0; }
.side-dot.tone-danger { background: var(--danger); }
.side-dot.tone-warn { background: var(--chart-warn); }
.side-foot { margin-top: auto; padding: var(--s2) 0 var(--s3); border-top: 1px solid var(--appbar-line); }
.side-foot form { margin: 0; }
.side-who { font-size: var(--fs-xs); color: var(--appbar-soft); padding: var(--s1) var(--s4) var(--s2); white-space: nowrap; }
/* ⚙ 설정 — 왼쪽 메뉴 맨 아래 접이(리바이벌 .side-foot 「설정」과 같은 틀 · 2026-10-18). 정의 = office/menu.py SETTINGS */
.side-settings > summary { list-style: none; cursor: pointer; }
.side-settings > summary::-webkit-details-marker { display: none; }
.side-settings > summary::after { content: '+'; margin-left: auto; color: var(--appbar-soft); }
.side-settings[open] > summary::after { content: '−'; }
.side-sub { padding-left: var(--s6); }
/* 「거래처」 묶음 머리 — 지금 거래처(굵게 · 금색 왼선) · 최근 · 고르기 (2026-10-18 · office/menu.py) */
.side-client.is-current { font-weight: 700; color: var(--appbar-ink); box-shadow: inset 3px 0 0 var(--seal); }
.side-client.is-empty { color: var(--seal); }
.side-rule { height: 1px; margin: var(--s1) var(--s4); background: var(--appbar-line); }
.sidebar.is-collapsed .side-client.side-sub { display: none; }.sidebar.is-collapsed .side-sub { padding-left: 0; }
.sidebar.is-collapsed .side-settings > summary::after { display: none; }/* 접힘 = 아이콘 레일 */
.sidebar.is-collapsed { width: var(--side-w-min); }
.sidebar.is-collapsed .side-text, .sidebar.is-collapsed .side-brand,
.sidebar.is-collapsed .side-group-title { display: none; }
/* 아이콘 레일에선 접힌 묶음을 통째로 숨긴다 — 제목(펼칠 손잡이)이 안 보이니 반쯤 보이면 헷갈린다 */
.sidebar.is-collapsed .side-fold:not([open]) { display: none; }
.sidebar.is-collapsed .side-head { justify-content: center; padding: 0; }
.sidebar.is-collapsed .side-item { justify-content: center; padding: 6px 0; margin: 3px 6px; width: calc(100% - 12px); }
.sidebar.is-collapsed .side-dot { position: absolute; top: 3px; right: 3px; }
.mobile-bar, .side-backdrop { display: none; }
@media (max-width: 640px) {
  .shell { display: block; }
  .mobile-bar { display: flex; align-items: center; gap: var(--s2); height: 48px; padding: 0 var(--s2);
                position: sticky; top: 0; z-index: 30;
                background-color: var(--appbar-bg); background-image: none;
                border-bottom: 1px solid var(--appbar-line); }
  .mobile-bar .brand-logo { height: 22px; }
  .sidebar { position: fixed; z-index: 40; left: 0; top: 0; width: 260px; transform: translateX(-100%);
             transition: transform var(--dur) var(--ease); }
  .sidebar.is-collapsed { width: 260px; }
  .sidebar.is-open { transform: none; box-shadow: var(--shadow-modal); }
  body.side-open .side-backdrop { display: block; position: fixed; inset: 0; z-index: 35; background: rgba(38, 34, 28, .35); }
}
/* 상단 탭 띠 — 장부 색인처럼 종이 탭이 리넨 띠에 꽂혀 있다. 지금 탭 = 종이 + 위쪽 인주선 */
.shell-main { display: flex; flex-direction: column; height: 100vh; }
.tabstrip { display: flex; align-items: flex-end; gap: 3px; min-height: var(--tab-h); padding: 6px var(--s2) 0;
            flex-shrink: 0; overflow-x: auto; scrollbar-width: none;
            background: var(--line); border-bottom: 1px solid var(--line-3); }   /* 리바이벌처럼 밝은 띠 */
.tabstrip::-webkit-scrollbar { display: none; }
.tabstrip:empty { display: none; }
.wtab { display: flex; align-items: center; gap: var(--s1); max-width: 180px; min-width: 88px; height: 30px;
       padding: 0 6px 0 var(--s3); cursor: pointer; flex-shrink: 1;
       background: var(--surface-2); color: var(--ink-2); font-size: var(--fs-sm); font-weight: 600;
       border: 1px solid var(--line-3); border-bottom: none; border-radius: 8px 8px 0 0; }
.wtab:hover { background: var(--surface); color: var(--ink); }
.wtab.is-on { background: var(--surface); color: var(--brand); font-weight: 700; box-shadow: inset 0 3px 0 var(--seal);
             margin-bottom: -1px; height: 31px; }
.wtab-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wtab-x { width: 20px; height: 20px; flex-shrink: 0; border: 0; background: transparent; color: inherit; opacity: .7;
         border-radius: 3px; cursor: pointer; font-size: 15px; line-height: 1; padding: 0; }
.wtab-x:hover { background: var(--gray-200); color: var(--ink); }
.tab-panes { flex: 1 1 auto; min-height: 0; position: relative; }
.tab-pane { display: none; height: 100%; overflow: auto; }
.tab-pane.is-on { display: block; }
.tab-pane iframe { display: block; width: 100%; height: 100%; border: 0; background: var(--canvas); }
/* 탭 안(iframe)에서 열린 화면 = 몸통만 */
.in-frame .sidebar, .in-frame .mobile-bar, .in-frame .tabstrip, .in-frame .side-backdrop { display: none !important; }
.in-frame .shell, .in-frame .shell-main { display: block; height: auto; }
.in-frame .tab-pane { height: auto; overflow: visible; }
@media (max-width: 640px) {
  .tabstrip { display: none; }
  .shell-main { height: auto; display: block; }
  .tab-pane { height: auto; overflow: visible; }
}

@media print { .sidebar, .mobile-bar, .side-backdrop, .tabstrip { display: none !important; } }

/* 포털 상단 바 (모바일 한 줄)
   ★ 밑줄 골드 = 「여기는 고객 화면」 신호. 브랜드 색을 사무실과 공유하는 대신
     형태로 구분한다(폭·둥근 카드·엄지 버튼·이 라인). tokens.css §고객 포털 참고. */
.topbar { display: flex; align-items: center; gap: var(--s2); padding: var(--s1) 2px var(--s2);
          border-bottom: 2px solid var(--gold); margin-bottom: var(--s3); }
.topbar .brand { display: flex; align-items: center; gap: var(--s2);
                 color: var(--brand); font-weight: 800; font-size: var(--fs-h2);
                 text-decoration: none; }
.topbar .brand img { height: 26px; width: auto; display: block; max-width: 180px; object-fit: contain; }
/* 사무소 상호(로고를 안 올린 사무실) — 375px 에서 로그아웃을 밀어내지 않게 말줄임 */
.topbar .brand-name { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 사무소 인사말 — 포털 홈 맨 위 한 줄(core/branding.py ③) */
.greeting { margin: 0 0 var(--s2); padding-left: var(--s2); border-left: 3px solid var(--brand-accent);
            color: var(--ink); font-size: var(--fs-lg); white-space: pre-line; }
.topbar .who { margin-left: auto; font-size: var(--fs-sm); color: var(--muted); }
.topbar a { font-size: var(--fs-sm); color: var(--muted); text-decoration: none; }

/* 카드 — 화면의 기본 단위. 모든 묶음은 카드 안에 있다. */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: var(--s5); margin-bottom: var(--s4);
}
.card--tight { padding: var(--s3) var(--s4); }
/* 안쪽 여백 없는 카드 — 위에 쪽 탭(.tabs--page)이 붙고 아래 표가 꽉 차는 화면(업무관리 · 마감 내역 · 마스터) ·
   ⚠ 화면마다 둘레 상자를 따로 만들면 탭을 오갈 때 테두리가 움직인다(사장님 10-21 「이것도 틀이 아니지?」) */
.card--flush { padding: 0; overflow: hidden; }
.card--soft { border: none; box-shadow: var(--shadow-card); }
.card--alert { border: 2px solid var(--ok); }
/* 사람이 처리할 차례인데 오래 밀린 것(답 없음 등) — 「답 왔음」(.card--alert, 초록)과 색으로 갈린다 (2026-10-06) */
.card--warn { border: 2px solid var(--warn); }
.card > h2 { font-size: var(--fs-md); color: var(--ink-2); margin: 0 0 var(--s3); }

/* 줄 배치 — 한 줄에 늘어놓기(폼 한 줄·툴바). 부품 사이 간격을 손으로 주지 말 것. */
.row { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }
.row--between { justify-content: space-between; }
.row--end { justify-content: flex-end; }
.stack { display: flex; flex-direction: column; gap: var(--s2); }
/* minmax(0,…) — 「1fr」은 안의 긴 입력칸·글만큼 안 줄어 좁은 칸(.split 오른쪽 등)에서 화면이 옆으로 밀렸다(2026-10-20 신고안내) */
.grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s4); }
@media (max-width: 900px) { .grid-2 { grid-template-columns: 1fr; } }

/* ── 2. 버튼 ──────────────────────────────────────────
   모양은 3가지뿐: 채움(주 동작) · 선(보조) · 조용(취소·토글).
   위치 규칙 = **주 동작은 항상 오른쪽 끝**(.btn-bar), 목록 행에서는 왼쪽부터 자주 쓰는 순. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s1);
  padding: var(--s2) var(--s4); min-height: 34px;
  border: 1px solid var(--brand); border-radius: var(--r-sm);
  background: var(--brand); color: var(--brand-ink);
  font-family: inherit; font-size: var(--fs-md); font-weight: 600;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; filter: none; }
.btn--line { background: var(--surface); color: var(--brand); }
.btn--quiet { background: var(--neutral-bg); color: var(--neutral); border-color: transparent; }
.btn--danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn--sm { padding: var(--s1) var(--s2); min-height: 26px; font-size: var(--fs-xs); font-weight: 700; }
/* 아주 작은 판 — 표 위 도구줄처럼 단추가 여럿 붙는 자리(업무관리 시즌 줄 · 사장님 2026-10-19 「사이즈 줄였으면」) */
.btn--xs { padding: 0 var(--s2); min-height: 24px; height: 24px; font-size: var(--fs-xs); font-weight: 600; }   /* = .pick-group--xs 높이 — 한 줄에 놓으면 들쭉날쭉하지 않게 */
.btn--lg { padding: var(--s3) var(--s4); min-height: var(--tap); font-size: var(--fs-lg); font-weight: 700; }
.btn--block { width: 100%; }
/* 버튼 줄 — 주 동작 오른쪽 끝 고정 */
.btn-bar { display: flex; gap: var(--s2); align-items: center; margin-top: var(--s4); }
.btn-bar > .btn:last-child { margin-left: auto; }
.btn-bar--left > .btn:last-child { margin-left: 0; }

/* ── 3. 배지 · 플래그 ─────────────────────────────────
   상태를 나타내는 알약. 색은 반드시 tone-* 로만 고른다(색을 직접 쓰지 말 것). */
.badge {
  display: inline-block; padding: 2px 10px; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 700; white-space: nowrap;
  background: var(--neutral-bg); color: var(--neutral);
}
.badge--square { border-radius: var(--r-sm); padding: 2px 6px; }
.tone-ok { background: var(--ok-bg); color: var(--ok); }
.tone-warn { background: var(--warn-bg); color: var(--warn); }
.tone-danger { background: var(--danger-bg); color: var(--danger); }
.tone-info { background: var(--info-bg); color: var(--info); }
.tone-accent { background: var(--accent-bg); color: var(--accent); }
.tone-neutral { background: var(--neutral-bg); color: var(--neutral); }

/* ── 4. 표 ────────────────────────────────────────────
   .table = 읽는 표(줄만) / .table--grid = 입력·대조하는 표(칸 테두리).
   ⚠ 넓은 표는 반드시 .table-scroll 로 감싼다 — 포털 원칙 2(모바일 375px 완결). */
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); background: var(--surface); }
.table th { color: var(--ink-2); font-weight: 600; font-size: var(--fs-sm); text-align: left; }
.table th, .table td { padding: var(--s2) var(--s2); border-bottom: 1px solid var(--line-2); }
.table--grid { font-size: var(--fs-sm); }
.table--grid th { background: var(--surface-2); text-align: center; border: 1px solid var(--line); padding: var(--s2) var(--s1); white-space: nowrap; }
.table--grid td { border: 1px solid var(--line-2); padding: var(--s1) var(--s2); vertical-align: middle; }
.table tbody tr:hover { background: var(--gray-100); }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.num--in { color: var(--info); }
.num--out { color: var(--danger); }
.empty { color: var(--muted-2); padding: var(--s5); text-align: center; font-size: var(--fs-md); }

/* ── 5. 입력 · 폼 ─────────────────────────────────────
   ★ 모양이 한 종류다. 크기·테두리·모서리를 화면마다 다시 정하지 않는다.
   ★ 배치도 한 종류: .form-grid(라벨 위, 칸 아래) 또는 .row(한 줄 폼). */
.input, .select, .textarea, input[type=text], input[type=number], input[type=date],
input[type=password], input[type=tel], input[type=email], select, textarea {
  font-family: inherit; font-size: var(--fs-md); color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-3); border-radius: var(--r-sm);
  padding: var(--s2) var(--s2); min-height: 34px; max-width: 100%;
}
textarea { min-height: 80px; line-height: var(--lh); }
/* 고르기 칸은 글자판 높이 때문에 입력칸보다 2px 커서 한 줄에 놓으면 들쭉날쭉했다(사장님 2026-10-19 「입력창 박스 상하 폭이 들쭉날쭉」) — 높이를 못 박는다 */
select { height: 34px; padding-top: 0; padding-bottom: 0; }
.input:disabled, select:disabled, textarea:disabled { background: var(--neutral-bg); color: var(--muted); }
.input--w-sm { width: 80px; } .input--w-md { width: 130px; } .input--w-lg { width: 220px; }
.input--num { text-align: right; font-variant-numeric: tabular-nums; }
.input--err { border-color: var(--danger); background: var(--danger-bg); }

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s3) var(--s4); }
/* 2열 고정 — 세무사랑처럼 칸이 짝으로 선다(사업자번호|법인등록번호 · 업태|종목 · 전화|팩스) · 좁으면 1열 */
.form-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 700px) { .form-grid--2 { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.field > label, .label { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); }
.field .hint, .hint { font-size: var(--fs-xs); color: var(--muted-2); }
.field--err .hint { color: var(--danger); }
.check { display: inline-flex; align-items: center; gap: var(--s1); font-size: var(--fs-sm); cursor: pointer; }
.req::after { content: ' *'; color: var(--danger); }
/* 묶음을 통째로 읽기 전용으로 — <fieldset disabled> 는 안의 입력칸을 전부 잠근다(권한 없는 직원의 목록 · CLAUDE.md §3-2). 테두리는 지운다 */
.fieldset-plain { border: 0; padding: 0; margin: 0; min-width: 0; }

/* ── 6. 탭 · 필터 칩 ─────────────────────────────────── */
.tabs { display: flex; flex-wrap: wrap; gap: var(--s1); }
.tabs a, .tab {
  display: inline-block; font-size: var(--fs-sm); padding: var(--s1) var(--s3);
  border: none; border-radius: var(--r-pill); text-decoration: none;
  color: var(--neutral); background: var(--neutral-bg); cursor: pointer;
}
.tabs a.is-on, .tab.is-on { background: var(--brand); color: var(--brand-ink); }
/* ★ 화면을 옮기는 탭(.tabs--page) ≠ 목록을 거르는 칩(.tabs) — 같은 알약이면 둘을 헷갈린다(사장님 2026-10-17).
     밑줄 탭 = 다른 화면으로 간다 · 알약 칩 = 이 화면의 목록을 거른다. */
.tabs--page { gap: 0; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; border-bottom: 1px solid var(--line); }
.tabs--page a, .tabs--page .tab { background: none; border-radius: 0; padding: var(--s2) var(--s3); margin-bottom: -1px;
  color: var(--ink-2); font-weight: 600; white-space: nowrap; border-bottom: 3px solid transparent; }
.tabs--page a:hover { color: var(--ink); }
.tabs--page a.is-on, .tabs--page .tab.is-on { background: none; color: var(--brand); border-bottom-color: var(--brand); }

/* 포털 하단 탭바 — 엄지가 닿는 자리(포털 원칙 2 「모바일 우선」).
   ★ 메뉴의 정본은 portal/menu.py 표 한 장이다 — 탭을 더하려고 이 CSS·템플릿을 고치지 않는다.
   ⚠ 고정 바가 마지막 카드를 가리지 않게, 탭바가 있는 화면의 몸통은 .page--tabbar 로 아래를 비운다. */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: flex; justify-content: center;
  background: var(--surface); border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar-inner { display: flex; width: 100%; max-width: var(--page-w-portal); }
.tabbar a {
  flex: 1 1 0; min-height: calc(var(--tap) + 10px);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  font-size: var(--fs-xs); color: var(--muted); text-decoration: none; position: relative;
}
.tabbar a .ico { font-size: 18px; line-height: 1; }
.tabbar a.is-on { color: var(--brand); font-weight: 700; }
.tabbar a.is-on::before { content: ''; position: absolute; top: 0; left: 25%; right: 25%;
                          height: 2px; background: var(--brand); }
/* 할 일 건수 — 숫자 배지(0이면 안 그린다) */
.tabbar .count { position: absolute; top: 4px; left: 54%; min-width: 16px; height: 16px;
                 padding: 0 4px; border-radius: var(--r-pill); background: var(--danger);
                 color: #fff; font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; }
.page--tabbar { padding-bottom: calc(var(--tap) + 44px); }

/* 목록 줄 — 눌러서 들어가는 한 줄(왼쪽 글, 오른쪽 배지). 포털 목록의 기본 단위.
   .list-row--action = 「해야 할 일」 줄(테두리가 있는 큰 줄 — 엄지로 누른다). */
.list-row {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s2);
  padding: 11px 4px; border-bottom: 1px solid var(--line-2);
  text-decoration: none; color: var(--ink); font-size: var(--fs-md);
}
.list-row:last-child { border-bottom: none; }
.list-row > :first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-row > .badge { flex-shrink: 0; }
.list-row--action {
  min-height: var(--tap); padding: var(--s2) var(--s3); margin-top: var(--s2);
  border: 1.5px solid var(--line-3); border-radius: var(--r-sm); font-weight: 600;
}
.list-row--action:last-child { border-bottom: 1.5px solid var(--line-3); }

/* ── 7. 지표 (숫자·비율 바) ───────────────────────────── */
.stat { font-size: var(--fs-md); }
.stat b { font-size: 18px; }
.meter { flex: 1 1 220px; min-width: 180px; height: 14px; display: flex;
         border-radius: var(--r-pill); overflow: hidden; background: var(--neutral-bg); }
.meter i { display: block; height: 100%; }
.meter .seg-ok { background: var(--chart-ok); }
.meter .seg-warn { background: var(--chart-warn); }
.meter .seg-danger { background: var(--chart-danger); }
/* 상태가 아니라 「갈래」를 가르는 막대(매출 · 매입 같은) — 좋고 나쁨의 색(ok·warn·danger)을 쓰지 않는다(2026-10-22 · 월간 리포트 매출·매입) */
.meter .seg-brand { background: var(--brand); }
.meter .seg-brand-soft { background: var(--navy-300); }

/* ── 8. 알림 ──────────────────────────────────────────
   messages = 동작 결과(위쪽 자동) / callout = 화면에 상주하는 설명·경고 */
.messages { list-style: none; padding: 0; margin: 0 0 var(--s4); }
.messages li { padding: var(--s2) var(--s3); border-radius: var(--r-sm);
               background: var(--ok-bg); color: var(--ok);
               font-size: var(--fs-md); margin-bottom: var(--s1); }
.messages li.error { background: var(--danger-bg); color: var(--danger); }
.messages li.warning { background: var(--warn-bg); color: var(--warn); }
.callout { border-left: 3px solid var(--muted-2); background: var(--neutral-bg);
           padding: var(--s2) var(--s3); border-radius: var(--r-sm); font-size: var(--fs-sm); }
.callout.tone-warn { border-color: var(--warn); }
.callout.tone-danger { border-color: var(--danger); }
.callout.tone-ok { border-color: var(--ok); }
/* .remark = 세무사 코멘트(사람이 판단했다는 표시 · 기획서 §4-A3) — 시스템 안내(.callout)와 섞이면
   「기계가 쓴 문장」처럼 읽힌다. 골드 줄 + 「세무사 코멘트」 꼬리표로 구분한다(2026-10-03). */
.remark { border-left: 3px solid var(--brand-accent); background: var(--surface-2);
          padding: var(--s2) var(--s3); border-radius: var(--r-sm); font-size: var(--fs-md);
          line-height: var(--lh); white-space: pre-line; }
.remark::before { content: '세무사 코멘트'; display: block; font-size: var(--fs-xs);
                  font-weight: 700; color: var(--muted); margin-bottom: 2px; white-space: normal; }
.remark--lead { font-size: var(--fs-lg); font-weight: 600; }

/* ── 9. 유틸 (딱 이만큼만) ────────────────────────────── */
.muted { color: var(--muted); font-size: var(--fs-sm); }
.muted-xs { color: var(--muted-2); font-size: var(--fs-xs); }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.center { text-align: center; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }

/* ── 10. 모바일 ───────────────────────────────────────
   포털 원칙 2 = 전 화면 375px 완결. 표는 .table-scroll 안에서만 옆으로 흐른다. */
@media (max-width: 480px) {
  .page--narrow { padding: var(--s3) var(--s2) 50px; }
  .card { padding: var(--s4) var(--s3); }
  /* iOS: 입력칸 글자가 16px 미만이면 포커스 때 화면이 확대된다 */
  input, select, textarea { font-size: 16px; }
  .btn { min-height: var(--tap); }
  .appbar { padding: var(--s2) var(--s3); gap: var(--s3); }
}

/* 인쇄 — 계약서·명세서 PDF는 자체 스타일을 쓰므로 여기선 화면 장식만 지운다 */
@media print {
  .appbar, .topbar, .tabbar, .btn, .tabs, .messages { display: none !important; }
  .card { border: none; box-shadow: none; padding: 0; }
}

/* ── 11·11-b·12. 종이 — core/static/core/paper.css 로 옮겼다(2026-10-18 · 셸 밖 종이도 같은 부품을 쓰게) ── */

/* 조문 고치는 자리 */
.art-row { border-bottom: 1px solid var(--line); padding: var(--s2) 0; }
.art-row > summary { cursor: pointer; font-size: var(--fs-sm); display: flex;
                     align-items: center; gap: var(--s2); flex-wrap: wrap; }
.art-row--off > summary { color: var(--muted-2); }
.art-row .art-no { font-weight: 700; color: var(--ink-2); }
.art-row textarea { margin-top: var(--s2); font-size: var(--fs-sm); line-height: 1.6; }


/* 작업 공간 격자 — ⚠ 이름이 .work-area 인 이유: 마이데스크가 .workspace 를 이미 쓴다(.tab 충돌과 같은 사고)
    — 탭 띠(위) + 화면(아래). 창 분할이면 [왼쪽 칸 | 경계선 | 오른쪽 칸].
   ⚠ 모든 화면이 이 격자 하나에 산다 — 칸을 옮겨도 iframe 을 DOM 에서 옮기지 않으려고(옮기면 새로 불러와 입력이 사라진다).
   어느 칸인지는 data-col 하나(workspace.js). */
.work-area { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr);
             grid-template-rows: auto minmax(0, 1fr); }
.work-area.is-split { grid-template-columns: minmax(0, var(--split, 50%)) 6px minmax(0, 1fr); }
.work-area > .tabstrip[data-col="1"] { grid-column: 1; grid-row: 1; }
.work-area > .tabstrip[data-col="2"] { grid-column: 3; grid-row: 1; }
.work-area.is-split > .tabstrip { display: flex; }                 /* 빈 오른쪽 띠도 놓을 자리로 보인다 */
.work-area.is-split > .tabstrip.is-focus { box-shadow: inset 0 2px 0 var(--seal); }   /* 손이 간 칸 = 금색 윗선 */
.work-area.is-split > .tabstrip.is-drop { background-color: var(--navy-900); }
.work-area > .tab-pane { grid-row: 2; grid-column: 1; }
.work-area > .tab-pane[data-col="2"] { grid-column: 3; }
.split-bar { grid-column: 2; grid-row: 1 / span 2; cursor: col-resize; background: var(--line);
             border-left: 1px solid var(--line-3); border-right: 1px solid var(--line-3); touch-action: none; }
.split-bar:hover, .is-dragging .split-bar { background: var(--seal); }
.is-dragging .tab-pane iframe { pointer-events: none; }            /* 끄는 동안 iframe 이 마우스를 삼키지 않게 */
.split-empty { display: none; grid-column: 3; grid-row: 2; align-items: center; justify-content: center;
               color: var(--muted); font-size: var(--fs-md); text-align: center; padding: var(--s5);
               border: 2px dashed var(--line-3); margin: var(--s4); border-radius: var(--r); }
.work-area.col2-empty .split-empty { display: flex; }
.split-empty.is-drop { border-color: var(--seal); color: var(--ink); }
.side-split.is-on { background: var(--label-paper); color: var(--appbar-ink); }
.side-split.is-on .side-ico { border-color: var(--seal); color: var(--seal); }
@media (max-width: 640px) {
  .work-area { display: block; }
  .side-split, .split-bar, .split-empty { display: none !important; }
}
.side-tools { padding: var(--s2) 0 0; }
/* 탭 안(iframe)에서 열린 화면 — 작업 공간 껍데기도 걷는다(이중 창 방지) */
.in-frame .work-area { display: block; }
.in-frame .split-bar, .in-frame .split-empty, .in-frame .side-tools { display: none !important; }

/* ── 14. 로그인 바탕 (2026-10-02 · 사장님 「배경에 디자인을 좀 · 심플하게」) ─────────
   ★ 무늬 = **확정 심볼을 크게 옅게** 두 번(왼쪽 위·오른쪽 아래) + 브랜드 두 색의 옅은 번짐.
     심볼 파일은 화면이 --mark 로 넘긴다(로고 파일을 바꾸면 무늬도 따라 바뀐다).
   ⚠ 글자와 겹쳐 읽기 어려웠던 2판 벽지의 교훈 — 카드 뒤는 비워 두고 무늬는 가장자리에만. */
.auth-backdrop { background:
    radial-gradient(60vmax 60vmax at 0% 0%, color-mix(in srgb, var(--navy-200) 55%, transparent), transparent 70%),
    radial-gradient(55vmax 55vmax at 100% 100%, color-mix(in srgb, var(--gold-soft) 60%, transparent), transparent 70%),
    var(--canvas);
  overflow: hidden; }
.auth-backdrop::before, .auth-backdrop::after {
  content: ''; position: absolute; width: 70vmin; height: 70vmin; pointer-events: none;
  background: var(--mark) center / contain no-repeat; opacity: .07; z-index: 0; }
.auth-backdrop > * { position: relative; z-index: 1; }   /* 무늬가 카드 위로 올라오지 않게 */
.auth-backdrop::before { left: -18vmin; top: -20vmin; transform: rotate(-12deg); }
.auth-backdrop::after { right: -20vmin; bottom: -22vmin; transform: rotate(168deg); }
@media (max-width: 640px) { .auth-backdrop::before, .auth-backdrop::after { width: 60vmin; height: 60vmin; } }
/* 눈에는 안 보이고 화면읽기에만 — 제목을 뺀 화면에도 「여기가 어디인지」는 남긴다 */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
           clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ── 15. 패널 — 대시보드 위젯 한 칸 (2026-10-03 · 마이데스크 이식) ─────────────
   머리(아이콘 + 제목 + 건수 배지) · 몸(목록) · 발(바로가기 한 줄).
   ★ 건수 배지는 .badge.tone-* · 목록은 .list-row(두 줄이면 .lr-main 안에 .lr-t/.lr-s) — 위젯마다 다시 만들지 않는다. */
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
         display: flex; flex-direction: column; overflow: hidden; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
              padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line-2); }
.panel-title { display: flex; align-items: center; gap: var(--s2); margin: 0;
               font-size: var(--fs-md); font-weight: 700; color: var(--ink); }
.panel-title .ico { width: 16px; height: 16px; color: var(--muted); }
.panel-body { padding: var(--s1) var(--s3); max-height: 340px; overflow-y: auto; }
.panel-body .empty { padding: var(--s5) var(--s2); font-size: var(--fs-sm); line-height: 1.6; }
.panel-foot { display: block; text-align: center; padding: var(--s2); border-top: 1px solid var(--line-2);
              font-size: var(--fs-sm); font-weight: 600; color: var(--brand); text-decoration: none; }
.panel-foot:hover { background: var(--surface-2); }
/* 두 줄 목록 줄 — 제목 + 보조 줄 · 오른쪽 끝(.lr-end)에 배지·금액·버튼 */
.lr-main { flex: 1 1 auto; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
a.lr-main { text-decoration: none; color: inherit; }   /* 줄 몸통이 링크일 때 밑줄이 두 줄 다 그어졌다 */
.lr-t { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-decoration: none; }
.lr-s { font-size: var(--fs-xs); color: var(--muted-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lr-end { display: flex; align-items: center; gap: var(--s2); flex-shrink: 0; }
/* 끝까지 읽어야 하는 줄(안내문의 서류 목록) — 말줄임 대신 줄바꿈. 375px 에서 서류 이름이 잘리면 무엇을 내라는지 모른다 */
.list-row--wrap .lr-t, .list-row--wrap .lr-s { white-space: normal; }
a.list-row:hover { background: var(--surface-2); }
/* 단추가 여럿인 줄(직원마다 [카톡으로 보내기][링크 복사][PDF]) — 375px 에서 넘치면 단추 줄이 아래로 내려간다 */
.list-row--btns { flex-wrap: wrap; row-gap: var(--s1); }
.list-row--btns .lr-end { flex-wrap: wrap; margin-left: auto; }
.list-row--total { font-weight: 700; background: var(--surface-2); padding-left: var(--s2); padding-right: var(--s2); }
.list-row.is-done { opacity: .45; } .list-row.is-done .lr-t { text-decoration: line-through; }

/* ── 16. 화면 머리 · 뒤로 · 문서 도구줄 · 인쇄 숨김 · 확인 창 (2026-10-05 · 공용 틀 목록 docs/디자인시스템.md §3-1) ─────
   ★ 왜: 전수 점검(템플릿 95)에서 화면 머리가 8갈래, 뒤로가 3갈래·글 12가지, 문서 도구줄이 5벌이었다 —
     공용에 틀이 없으니 화면마다 조립했다(사장님: "그때그때 만들어서 붙이지 말고 미리 만들어진 틀을 사용하자").
   ★ 버튼 이름은 고정: 인쇄 · PDF 내려받기 · 엑셀 내려받기 · 저장 · 보내기 · 삭제 · 되돌리기 — **그림 글자를 붙이지 않는다**(사장님).
   쓰는 법(카탈로그 /office/ui/ 「16」):
     <div class="page-head">
       <div class="page-head__title"><a class="back" href="…">목록</a><h1>제목</h1><p class="page-head__sub">부제</p></div>
       <div class="btn-bar"><a class="btn btn--line" …>보조</a><button class="btn">주 동작</button></div>
     </div>
     문서 화면: {% include 'core/_print_bar.html' with pdf_url=… %}   ← [PDF 내려받기] [인쇄] 이름·순서가 고정된다 */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap;
             gap: var(--s3) var(--s4); margin-bottom: var(--s4); }
.page-head__title { min-width: 0; }
.page-head h1 { margin: 0; }
.page-head__sub { margin: var(--s1) 0 0; color: var(--muted); font-size: var(--fs-sm); }
.page-head > .btn-bar { margin: 0 0 0 auto; flex-wrap: wrap; }
.page-head > .btn-bar > .btn:last-child { margin-left: 0; }   /* 머리에선 묶음째 오른쪽 — 주 동작은 묶음의 맨 끝 */
/* 뒤로 — 왼쪽 위 작은 글 링크 하나. 화살표는 CSS 가 붙인다(글엔 돌아갈 화면 이름만 — 「← 목록으로」「← 돌아가기」 같은 변주가 생기지 않게) */
.back { display: inline-block; margin-bottom: var(--s1); color: var(--muted); font-size: var(--fs-sm);
        text-decoration: none; }
.back::before { content: "← "; }
.back:hover { color: var(--brand); }
/* 문서 도구줄 — 오른쪽 끝 [PDF 내려받기] [인쇄]. 좁은 화면에서 글자를 쪼개지 않고 버튼째 넘긴다(10-05 수임 서류에서 밟음) */
.print-bar { display: flex; justify-content: flex-end; align-items: center; flex-wrap: wrap; gap: var(--s2);
             margin-bottom: var(--s3); }
.print-bar .btn { white-space: nowrap; }
/* 확인 창 — [취소 왼쪽 · 확인 오른쪽](.btn-bar 의 마지막이 오른쪽 끝). 열기 = .modal-back 에 .is-open */
.modal-back { position: fixed; inset: 0; z-index: 100; display: none; align-items: center; justify-content: center;
              padding: var(--s4); background: rgba(15, 23, 42, .45); }
.modal-back.is-open { display: flex; }
.modal { width: min(480px, 100%); max-height: 90vh; overflow: auto; padding: var(--s5);
         background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--shadow-modal); }
.modal__title { margin: 0 0 var(--s3); font-size: var(--fs-h2); font-weight: 700; }
/* 넓은 창 — 안에 다른 화면(미리보기)을 띄운다(메일 첨부 미리보기 · 2026-10-19) */
.modal--wide { width: min(1100px, 100%); height: 88vh; display: flex; flex-direction: column; gap: var(--s2); }
.modal__frame { flex: 1 1 auto; width: 100%; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
/* 인쇄할 때 숨김 — 종이에 남으면 안 되는 것(버튼 줄·뒤로·도구줄) */
@media print {
  .no-print, .print-bar, .back, .page-head > .btn-bar, .modal-back { display: none !important; }
}

/* ── 17. 올리기 줄 (.uprow) — 사진·파일 받는 한 줄 (2026-10-06 · 기획서 §10 「서류받기 강화」 1) ─────
   ★ 왜: 같은 줄이 **세 벌**이었다 — 신고안내 포털(filing/notice_portal) · 신고대리 손님(filing/public_case) ·
     연말정산 근로자(yearend/public). 셋 다 `<input type="file">` 날것이라 ①폰에서 「사진 찍기」가 바로 안 열리고
     ②무엇을 골랐는지 보이지 않아 빈 채로 [올리기]를 누르는 일이 있었다. ⇒ 틀 하나로 모은다.
   쓰는 법: {% include 'core/_upload_row.html' with row=r up_action='…' %}  (core/templates/core/_upload_row.html)
   ⚠ **자바스크립트 없이도 된다** — 고르기는 <label> 이 하고(네이티브), [올리기]는 늘 보인다.
     upload.js 는 **덤**(미리보기 그림·고른 장수)일 뿐이라 꺼져도 올라간다. */
.uprow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2);
         padding: 11px 4px; border-bottom: 1px solid var(--line-2); }
.uprow:last-of-type { border-bottom: none; }
.uprow__main { flex: 1 1 180px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* 서류 이름은 끝까지 읽혀야 한다 — 375px 에서 잘리면 무엇을 내라는지 모른다(.list-row--wrap 과 같은 판단) */
.uprow__t { font-weight: 600; color: var(--ink); }
.uprow__s { font-size: var(--fs-xs); color: var(--muted-2); }
.uprow__got { font-size: var(--fs-xs); color: var(--ok); }
.uprow__got a { color: inherit; }
/* 고르는 단추 둘 — 「사진 찍기」(폰 카메라 바로) · 「파일 고르기」. 안의 input 은 화면에서만 숨긴다
   (display:none 이면 일부 브라우저가 label 클릭을 전달하지 않는다 — 클립으로 숨긴다) */
.uprow__pick { display: flex; flex-wrap: wrap; gap: var(--s2); margin-left: auto; }
.uprow__pick input[type=file] { position: absolute; width: 1px; height: 1px; padding: 0;
                                clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; }
.uprow__pick label { margin: 0; cursor: pointer; }
.uprow__pick input[type=file]:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 2px; }
/* 고른 것 미리보기 — 그림은 썸네일, 그 밖은 이름. 올리기 전에 「이것 맞나」를 보여 준다 */
.upthumbs { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: var(--s2); }
.upthumbs:empty { display: none; }
.upthumb { display: flex; align-items: center; gap: var(--s1); max-width: 100%;
           padding: 2px var(--s2); border: 1px solid var(--line-3); border-radius: var(--r-sm);
           background: var(--surface-2); font-size: var(--fs-xs); color: var(--ink-2); }
.upthumb img { width: 34px; height: 34px; object-fit: cover; border-radius: 3px; }
.upthumb.is-big { border-color: var(--danger); color: var(--danger); }
/* 사진 찍기는 카메라가 있는 기기에서만 뜻이 있다 — 데스크톱에선 파일 고르기와 똑같이 동작하므로 감춘다 */
@media (hover: hover) and (pointer: fine) { .uprow__pick .pick-cam { display: none; } }

/* ── 18. 표 안에서 바로 고치는 칸 (.input--cell · .is-saved) (2026-10-08 · 거래처 등록 › 업무 설정) ─────
   ★ 업무관리 화면에 따로 있던 `.cl-inp`·`.cl-sel`·`.cl-saved`(그 화면에만 있던 스타일)를 공용으로 올렸다.
     표 한 줄에 칸이 열 개쯤 들어가므로 **평소엔 테두리가 없고** 손을 대면 칸이 보인다.
   ★ 저장되면 그 칸이 **초록으로 한 번** 깜빡인다(.is-saved) — 「저장됐나?」를 사람이 다시 열어 확인하지 않게. */
.input--cell, select.input--cell {
  border-color: transparent; background: transparent; min-height: 28px; height: auto;
  padding: 2px var(--s1); font-size: var(--fs-sm); width: 100%;
}
.input--cell:hover { border-color: var(--line-3); background: var(--surface); }
.input--cell:focus { outline: none; border-color: var(--brand); background: var(--info-bg); }
.is-saved { animation: cellsaved .7s ease; }
@keyframes cellsaved { from { background: var(--ok-bg); } to { background: transparent; } }
.checks-inline { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); }
.checks-inline .check { font-size: var(--fs-xs); color: var(--ink-2); }

/* ── 19. 떠 있는 알림 (.messages--toast) (2026-10-08 · 사장님 「버튼들이 전부 누르면 화면이 움직여」) ─────
   ★ 종전 알림 줄(.messages)은 본문 **위에 끼어들어** 버튼을 누를 때마다 화면 전체를 아래로 밀었다.
     사무소 화면은 알림을 **본문 위에 띄우고**(자리를 차지하지 않는다) 성공 알림은 몇 초 뒤 사라진다
     — 오류·주의는 사람이 누를 때까지 남는다(놓치면 안 된다). 동작 = core/static/core/steady.js.
   ⚠ 로그인·비밀번호 화면은 그대로 둔다(폼 하나뿐이라 밀릴 것이 없다). */
.messages--toast { position: fixed; top: var(--s3); right: var(--s4); z-index: 60; margin: 0;
                   width: min(440px, calc(100vw - 2 * var(--s4))); }
.messages--toast li { box-shadow: var(--shadow-modal); cursor: pointer; transition: opacity var(--dur) var(--ease); }
.messages--toast li.is-gone { opacity: 0; }

/* ── 21. 진행 점 (.pips) — 한 줄에 단계 몇 개를 점으로 (2026-10-11 · 원천세 진행 바) ─────
   ★ 위멤버스 「신고리스트」 6단계(급여자료 → 대장 → 신고 → 납부서 → 지급명세서 → 완료)를 업무관리 그리드 한 칸에.
     표 한 줄에 들어가야 해서 **글자 없이 점**으로 — 이름은 title(마우스) · 범례는 거르기 칩이 맡는다.
   점의 뜻: 채움 = 끝남 · 빈 테두리 = 아직 · 옅은 점선 = 이 거래처엔 없는 단계 · 굵은 테두리 = **다음에 할 단계**. */
.pips { display: inline-flex; align-items: center; gap: 3px; vertical-align: middle; }
.pips i { display: block; width: 10px; height: 10px; border-radius: 50%;
          border: 1.5px solid var(--line-3); background: var(--surface); }
.pips i.is-done { background: var(--ok); border-color: var(--ok); }
.pips i.is-na { border-style: dashed; border-color: var(--line); background: transparent; }
.pips i.is-next { border-color: var(--warn); border-width: 2.5px; }

/* ── 22. 거래처 작업 띠 (.client-band) (2026-10-10 · 사장님 「그 거래처 들어가서 할까」) ─────────────────────
   거래처마다 하는 화면 맨 위 한 줄 — 「작업 중 [거래처 ▾] 사업자번호 · 카드 · 차트 · 통장 대사 · 거래 상대방 …」.
   ★ 고른 거래처는 세션에 기억된다(office/workclient.py) — 탭을 옮겨도 거래처가 유지된다. 카탈로그 22. */
.client-band { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
               padding: var(--s2) var(--s3); margin-bottom: var(--s3);
               background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--brand-accent);
               border-radius: var(--r); }
.client-band__label { font-size: var(--fs-xs); font-weight: 700; color: var(--muted); }
.client-band__pick { font: inherit; font-weight: 700; font-size: var(--fs-lg); color: var(--ink);
                     border: 1px solid var(--line-3); border-radius: var(--r-sm); padding: 2px var(--s2); background: var(--surface); }
.client-band__tabs { margin-left: auto; }
.client-band__year { font: inherit; font-size: var(--fs-sm); font-weight: 700; color: var(--brand);
                     border: 1px solid var(--brand-soft); border-radius: var(--r-sm); padding: 2px var(--s2); background: var(--brand-tint); }
.client-band__sep { width: 1px; align-self: stretch; margin: 0 var(--s1); background: var(--line-3); }   /* 쌓이는 것 | 연도 탭 사이 */
@media print { .client-band { display: none !important; } }   /* 인쇄(예상세금 보고서 등)엔 작업 띠를 안 싣는다 */
/* ── 23. 목록 + 상세 한 화면 (.split) · 기록 머리줄 (.recbar) (2026-10-17 · 거래처 등록 = 세무사랑 회사등록 틀) ─────
   ★ 사장님: 세무사랑 회사등록의 특징은 **틀**이다 — 맨 위 줄에 지금 고른 것(코드·이름·기수) · 왼쪽 주요정보 목록 · 오른쪽 상세.
     페이지를 옮기지 않고 같은 자리에서 바뀐다(↑↓ 로 고른다). 다음에 같은 꼴의 화면(직원·양식함 등)도 이것을 쓴다.
   ⚠ 줄 = 체크칸 + 링크(<a class="split__go">) — 자바스크립트가 없어도 고를 수 있고, 체크칸을 눌러도 화면이 넘어가지 않는다. */
.recbar { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
          padding: var(--s2) var(--s3); margin-bottom: var(--s2);
          background: var(--surface); border: 1px solid var(--line); border-top: 3px solid var(--brand); border-radius: 0; }
.recbar__code { font-variant-numeric: tabular-nums; font-weight: 700; padding: 2px var(--s2);
                background: var(--brand-soft); color: var(--brand); border-radius: var(--r-sm); }
.recbar__name { font-size: var(--fs-lg); font-weight: 700; color: var(--ink); }
.recbar__side { margin-left: auto; text-align: right; font-size: var(--fs-sm); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.recbar__side b { color: var(--ink); }
/* 머리 줄 안에 설 때(거래처 등록) — 제목과 단추 사이를 다 쓴다 */
.page-head .recbar { flex: 1 1 auto; min-width: 0; align-self: center; margin: 0 var(--s4); padding: 0;
                     background: none; border: 0; }
.page-head:has(.recbar) { align-items: center; }
.split { display: grid; grid-template-columns: minmax(380px, 500px) minmax(0, 1fr); gap: var(--s3); align-items: start; }
.split__list { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
               max-height: calc(100vh - 210px); overflow-y: auto; position: sticky; top: var(--s2); }
/* 줄 = 체크 · 코드 · 상호 · 구분 · 담당 · 열기(›) — 세무사랑처럼 **줄에서 바로 입력**(.input--cell · §18) */
.split__head, .split__row { display: grid; grid-template-columns: 22px 62px minmax(0, 1fr) 58px 70px 84px 16px;
                            gap: 2px; align-items: center; padding: 2px var(--s2); font-size: var(--fs-sm); }
.split__head { position: sticky; top: 0; z-index: 1; background: var(--surface-2); color: var(--muted);
               font-size: var(--fs-xs); border-bottom: 1px solid var(--line); padding-top: var(--s2); padding-bottom: var(--s2); }
.split__head button { background: none; border: 0; padding: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.split__head button:hover { color: var(--ink); }
.split__head button.is-asc::after { content: " \25B2"; }
.split__head button.is-desc::after { content: " \25BC"; }
.split__row { border-bottom: 1px solid var(--line-2); color: var(--ink); }
.split__row .input--cell { min-height: 26px; }
.split__row select.input--cell { padding-left: 0; }
.split__row:hover { background: var(--surface-2); }
.split__row.is-on { background: var(--brand-soft); }
/* ⚠ 목록 칸은 고르거나 올려도 **테두리가 바뀌지 않는다** — 테두리가 생겼다 사라지면 칸이 움직이는 것처럼 보인다(사장님 2026-10-17).
     고른 칸은 바탕 + 밑줄로만 표시한다. */
.split__row .input--cell, .split__row .input--cell:hover { border-color: transparent; background: transparent; }
/* ★ 격자처럼(사장님 2026-10-17) — 한 번 누르면 칸이 **진한 색으로 골라지기만** 하고, 두 번 누르면 **입력칸 모양**으로 바뀐다(core/split.js).
     골라진 칸 = :focus(입력은 잠긴 채) · 입력 중 = .is-editing. ⚠ 맨 아래 빈 줄은 새로 치는 자리라 바로 입력된다. */
.split__row .input--cell[readonly] { cursor: default; }
.split__row .input--cell:focus { border-color: transparent; background: color-mix(in srgb, var(--brand) 22%, var(--surface)); box-shadow: none; }
.split__row .input--cell.is-editing,
.split__row--new .input--cell:focus { border: 1px solid var(--brand); background: var(--surface); cursor: text; }
.split__row.is-off .input--cell { color: var(--muted-2); }
.split__row--new { background: var(--canvas); }
.split__row[hidden] { display: none; }
.split__row--new .input--cell { border-style: dashed; border-color: var(--line-3); }
/* 코드는 필수 — 코드 없이 들어와 있던 거래처(옛 자료)는 코드 칸을 빨간 점선으로 세워 채우게 한다 */
.split__row:not(.split__row--new) input[name=semu_code]:placeholder-shown { border: 1px dashed var(--danger); }
.split__row:not(.split__row--new) input[name=semu_code]:placeholder-shown::placeholder { color: var(--danger); }
.split__row .num { font-variant-numeric: tabular-nums; }
/* 코드·담당은 가운데(머리와 칸이 같은 자리에 서게) */
.split__row input[name=semu_code], .split__row select[name=manager], .split__row select[name=biz_type] { text-align: center; text-align-last: center; }
.split__head [data-sort=semu_code], .split__head [data-sort=manager], .split__head [data-sort=biz_type] { text-align: center; }
.split__row.is-err .input--cell.is-bad { border-color: var(--danger); background: var(--danger-bg, transparent); }
.split__warn { color: var(--danger); }
/* 확인 부탁(저장은 됐다) — 빨간 「틀림」과 다른 색으로 말한다(주민·법인번호 검증번호 · 막지 않는다) */
.hint.hint--warn { color: var(--warn); }
.split__list > .tabs .split__unassigned { margin-left: auto; padding: 0; background: none; }
.split__go { color: var(--muted-2); text-decoration: none; text-align: center; }
.split__detail { min-width: 0; }
/* 칸 + 단추 한 줄(주소 [주소 검색] · 주민번호 [보기]) — 칸이 남는 폭을 다 쓴다 */
.input-btn { display: flex; gap: var(--s2); align-items: center; }
.input-btn > input { flex: 1 1 auto; min-width: 0; }
/* 찾기 팝업의 고른 줄(업종코드 찾기 · ↑↓ 로 움직인다) */
.table tr.is-on > td { background: var(--brand-soft); }
.input-btn > input.input--w-sm, .input-btn > input.input--w-md { flex: 0 0 auto; }   /* 우편번호·업종코드처럼 폭이 정해진 칸은 늘지 않는다 */
@media print {
  .split { display: block; }
  .split__list, .page-head, .no-print, .tabs { display: none !important; }
  .recbar { border-top-width: 1px; }
}
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } .split__list { position: static; max-height: 40vh; } }

/* ── 24. 세무 현황 카드 띠 (.status-strip · .scard) (2026-10-18 · 거래처 파트 3-1) ─────
   ★ 포털 홈 맨 위 — 다음 신고 D-day · 도착한 납부서 · 원천세 진행 점 · 예상 부가세 · 지난 신고를 **작은 카드 몇 장**으로.
     ⚠ 옆으로 밀어 보는 띠였다가 **가로 스크롤을 없앴다**(사장님 10-18 「우측이 잘리네 · 가로스크롤 없애」) ⇒ 폭에 맞춰 줄바꿈 · 375px = 한 줄에 두 장.
   ⚠ 읽는 자리다 — 「할 일」(.list-row--action)처럼 테두리 굵게 하지 않는다. 판정 = portal/status.py · 카탈로그 24. */
.status-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--s2);
                margin-bottom: var(--s3); }
.scard { min-width: 0; display: flex; flex-direction: column; gap: 2px;
         padding: var(--s2) var(--s3); background: var(--surface); border: 1px solid var(--line);
         border-radius: var(--r-lg); color: var(--ink); text-decoration: none; }
a.scard:hover { border-color: var(--brand-soft); }
.scard__l { font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scard__v { font-size: var(--fs-lg); font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scard__s { font-size: var(--fs-xs); color: var(--muted-2); line-height: 1.35; }
.scard.tone-warn { border-color: var(--warn); background: var(--surface); }
.scard.tone-warn .scard__v { color: var(--warn); }
.scard.tone-danger { border-color: var(--danger); background: var(--surface); }
.scard.tone-danger .scard__v { color: var(--danger); }
.scard .pips { align-self: flex-start; margin: 2px 0; }
.status-strip__who { font-size: var(--fs-xs); font-weight: 700; color: var(--muted); margin: 0 0 var(--s1); }

/* ── 25. 고르기 펼침 (.pick) — 여럿 중 하나를 골라 복사 (2026-10-18 · 은행별 가상계좌) ─────
   단추 하나(summary)를 누르면 아래로 은행 단추들이 펼쳐진다 · <details> 라 자바스크립트 없어도 열린다 · 카탈로그 25. */
.pick { display: inline-block; }
.pick > summary { list-style: none; cursor: pointer; }
.pick > summary::-webkit-details-marker { display: none; }
.pick[open] > summary { border-color: var(--brand); color: var(--brand); }
.pick__list { display: flex; flex-wrap: wrap; gap: var(--s1); margin-top: var(--s1); }
/* ── 26. 상품 층 표식 (.tier) — 무료 · 유료 · 기장 (2026-10-18 · 사장님 「구분이 되야된다니까」) ─────
   메뉴 줄·화면 머리 옆의 작은 표식 · 색 = tokens.css §4 층 색 · 카탈로그 1. ⚠ 상태 배지(.tone-*)와 섞어 쓰지 않는다. */
.tier { display: inline-block; font-size: var(--fs-xs); font-weight: 700; line-height: 1.4; white-space: nowrap;
        padding: 1px var(--s2); border-radius: var(--r-pill); vertical-align: middle; }
.tier--free { color: var(--tier-free); background: var(--tier-free-bg); }
.tier--paid { color: var(--tier-paid); background: var(--tier-paid-bg); }
.tier--book { color: var(--tier-book); background: var(--tier-book-bg); }
/* ── 27. 새 시즌 만들기 접이 (.season-new) — 업무관리 (2026-10-18 · 순서 카드 넷은 사장님 「없애」로 뺐다) ── */
.season-new { margin-top: var(--s3); }
.season-new > summary { list-style: none; }
.season-new > summary::-webkit-details-marker { display: none; }
/* ── 28. 찾아 고르기 (.pick · .pick-list) — 긴 목록을 글자로 찾아 하나 (2026-10-19 · core/static/core/pick.js) ──
   목록을 우리가 그린다 — 브라우저 datalist 목록은 창 분할·패널 안에서 엉뚱한 자리에 떴다(사장님 「목록이 엉뚱한데 보여」).
   ⚠ 부모가 overflow:hidden 이면 목록이 잘린다 — 담는 틀에서 overflow:visible 로 푼다. */
.pick { position: relative; }
.pick-list {
  position: absolute; top: calc(100% + 2px); left: 0; z-index: 50;
  min-width: 100%; max-height: 18rem; overflow-y: auto;
  margin: 0; padding: var(--s1) 0; list-style: none;
  background: var(--surface); border: 1px solid var(--line-3); border-radius: var(--r-sm);
  box-shadow: var(--shadow-pop);
  font-size: var(--fs-sm); text-align: left;
}
.pick-list[hidden] { display: none; }
.pick-list li { padding: var(--s1) var(--s3); white-space: nowrap; cursor: pointer; }
.pick-list li:hover, .pick-list li.is-on { background: var(--brand-tint); color: var(--brand); }
.pick-list .pick-list__none { color: var(--muted); cursor: default; }
.pick-list .pick-list__none:hover { background: none; color: var(--muted); }

/* ── 29. 접이식 (.fold) — 길게 늘어지는 표·설명을 접어 둔다 (2026-10-19 · 홈택스 확인 대조 표) ──
   <details class="fold"><summary>제목 · 요약 한 줄</summary> … </details> — 접힌 채로도 요약(다른 칸 수 등)이 보이게 summary 에 적는다. */
.fold > summary { cursor: pointer; font-size: var(--fs-sm); color: var(--ink-2); padding: var(--s1) 0; list-style: none; }
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::before { content: '▸ '; color: var(--muted); }
.fold[open] > summary::before { content: '▾ '; }
.fold[open] > summary { margin-bottom: var(--s2); }

/* ── 30. 폴더 나무 (.folders) — 왼쪽 묶음 › 항목 · 오른쪽 그 폴더 내용 (2026-10-19 · 메일 보관함 「거래처별」 — 담당자 › 거래처) ──
   <div class="folders"><nav class="folders__tree"> <a class="folders__item">…<span class="folders__n">n</span></a>
     <details class="folders__group"><summary>묶음 <span class="folders__n">n</span></summary> <a class="folders__item">…</a> </details>
   </nav><section>내용</section></div> — 좁은 화면(폰)에선 나무가 위로 올라간다. */
.folders { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); gap: var(--s3); align-items: start; }
.folders__tree { position: sticky; top: var(--s3); max-height: calc(100vh - 160px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: var(--s2);
  font-size: var(--fs-sm); }
.folders__group > summary { display: flex; justify-content: space-between; gap: var(--s2); padding: var(--s1) var(--s2);
  font-weight: 700; cursor: pointer; list-style: none; border-radius: var(--r-sm); }
.folders__group > summary::-webkit-details-marker { display: none; }
.folders__group > summary:hover { background: var(--surface-2); }
.folders__item { display: flex; justify-content: space-between; gap: var(--s2); padding: 3px var(--s2) 3px var(--s5);
  border-radius: var(--r-sm); color: var(--ink); text-decoration: none; }
.folders__item--top { padding-left: var(--s2); font-weight: 700; margin-bottom: var(--s1); }
.folders__item > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folders__item:hover { background: var(--surface-2); }
.folders__item.is-on { background: var(--brand-tint); color: var(--brand); font-weight: 700; }
.folders__item.is-empty { color: var(--muted-2); }   /* 아직 빈 폴더(0통) — 그래도 끌어 놓을 수 있다 */
/* 끌어 놓는 상자 — 어디에 놓을지 모를 때(사장님 「드래그 앤 드롭 박스」) · 끌기 시작하면 놓을 곳이 전부 점선(.is-dragging-on) */
.folders__dropbox { margin-bottom: var(--s2); padding: var(--s3); text-align: center; font-weight: 700; color: var(--brand);
  border: 2px dashed var(--line-3); border-radius: var(--r); background: var(--canvas); }
.folders__dropbox.is-drop { border-color: var(--brand); background: var(--brand-tint); }
.is-dragging-on .folders__dropbox { border-color: var(--brand); }
.is-dragging-on .folders__item[data-drop-client], .is-dragging-on .folders__item[data-drop-staff] { outline: 1px dashed var(--line-3); outline-offset: -1px; }
.folders__group--ended > summary { color: var(--muted); }
.folders__item.is-found { background: var(--brand-tint); }
.folders__n { color: var(--muted); font-variant-numeric: tabular-nums; flex-shrink: 0; font-weight: 400; }
@media (max-width: 720px) {
  .folders { grid-template-columns: 1fr; }
  .folders__tree { position: static; max-height: none; }
}

/* ── 31. 정렬 머리 (.th-sort) — 쪽으로 나뉜 표의 머리를 눌러 서버 정렬 (2026-10-19 · core/sorting.py · {% sort_th %}) ──
   ⚠ 한 화면에 다 그리는 표는 화면 정렬(split.js data-sort)로 충분하다 — 쪽 나눔 표만 이것(보이는 50줄만 섞이면 안 된다). */
.th-sort { color: inherit; text-decoration: none; white-space: nowrap; cursor: pointer; }
.th-sort:hover { color: var(--brand); }
.th-sort::after { content: ' \2195'; color: var(--muted-2); font-size: .85em; }
.th-sort.is-asc::after { content: ' \25B2'; color: var(--brand); }
.th-sort.is-desc::after { content: ' \25BC'; color: var(--brand); }
/* 폴더 나무에 끌어 놓기(§30 과 짝) — 끌고 있는 줄 · 놓을 수 있는 폴더 */
tr[draggable="true"] { cursor: grab; }
tr.is-dragging { opacity: .45; }
.folders__item.is-drop { background: var(--brand-tint); outline: 2px dashed var(--brand); outline-offset: -2px; }
.folders__item--new { border: 1px dashed var(--line-3); margin: var(--s1) 0; }
.w-check { width: 28px; }
/* 찾아 고르기(§28)를 담은 확인 창 — 목록이 창 밖으로 내려가도 잘리지 않게 */
.modal.pick { overflow: visible; }
/* 첨부 표시 — 메일 표의 클립(사장님 「첨부 클립이 너무 작고 얇아」 — 글자 그림 📎 대신 아이콘 · 굵게) */
.ico--clip { width: 19px; height: 19px; color: var(--brand); }

/* ── 32. 고르기 묶음 (.pick-group) — 남색 머리표 + 고르기(select) 여럿을 한 틀에 (2026-10-19 · 업무관리 「시즌 | 연도 | 세목 | 기수」에서 올렸다) ──
   사장님 「이런 것들은 틀이야?」 — 그때까지 업무관리 화면 <style> 에만 있었다(.season-pick) ⇒ 다른 화면도 같은 모양을 쓰게 공용으로.
   머리표 __tag · 고르기 select · 오른쪽 상태 __state(마감이면 .is-closed) · 글자로 찾기 __find · 작은 판 --sm(28px) */
.pick-group { display: inline-flex !important; align-items: stretch; height: 34px; border: 1px solid var(--line-3);
  border-radius: var(--r-md, 8px); background: var(--surface, #fff); overflow: hidden; }
.pick-group__tag { display: flex; align-items: center; padding: 0 var(--s3); background: var(--brand); color: var(--brand-ink);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .02em; }
.pick-group select { border: 0; border-left: 1px solid var(--line); background: transparent; padding: 0 var(--s5) 0 var(--s3);
  font: inherit; font-size: var(--fs-sm); font-weight: 600; color: var(--ink); cursor: pointer; outline: none; }
.pick-group select:first-of-type { border-left: 0; }
.pick-group select:hover, .pick-group select:focus { background: var(--brand-50, #eef2f8); }
.pick-group__state { display: flex; align-items: center; padding: 0 var(--s3); border-left: 1px solid var(--line);
  font-size: var(--fs-xs); font-weight: 700; color: var(--ok, #1e7a46); }
.pick-group__state.is-closed { color: var(--ink-3, #8a94a6); }
.pick-group__find { border: 0; background: transparent; padding: 0 var(--s3); width: 15rem; font: inherit; font-size: var(--fs-xs); }
.pick-group__find:focus { outline: none; background: var(--brand-50, #eef2f8); }
.pick-group--sm { height: 28px; }
.pick-group--sm select { border-left: 0; font-weight: 500; font-size: var(--fs-xs); }
.pick-group--xs { height: 24px; }
.pick-group--xs .pick-group__tag { padding: 0 var(--s2); }
.pick-group--xs select { padding: 0 var(--s4) 0 var(--s2); font-size: var(--fs-xs); }
.pick-group--sm.pick-group--xs { height: 24px; }   /* 둘을 같이 달면 작은 쪽 */
.pick-group--xs .pick-group__state { padding: 0 var(--s2); }
.pick-group--xs .pick-group__find { width: 11rem; }
.pick-group.pick { overflow: visible; }   /* 찾아 고르기 목록(§28)이 틀 밖으로 내려와야 한다 */
/* ★ 틀 안의 고르기·입력칸은 **틀 높이를 따른다** — 공용 입력 규칙(위 select·input 34px)이 그대로 걸려
   24·28px 틀에서 칸이 삐져나와 글자가 아래로 밀렸다(사장님 2026-10-19 「위아래 중앙이 아니고」 · 「입력창도 위아래 폭이 달라」).
   폭은 가장 긴 선택지(직원 이름)에 끌려가지 않게 상한을 둔다(「쓸데없이 좌우 폭이 넓잖아」). */
.pick-group select, .pick-group input { height: 100%; min-height: 0; margin: 0; border-radius: 0; }
.pick-group select { width: auto; max-width: 8rem; text-overflow: ellipsis; }
.pick-group--wide select { max-width: 24rem; }   /* 긴 이름을 고르는 자리(신고안내 업무 종류·안내문 제목) — 잘리면 어느 장인지 모른다 */

/* ── 33. 옆 패널 (.side-panel) — 화면을 덮지 않고 오른쪽에서 열려 그 자리의 일을 한다 (2026-10-19 · 업무관리 단계 패널) ──
   확인 창(.modal)과 다른 점: 바탕을 어둡게 덮지 않는다 — 옆 표를 보면서 고르고 보낸다(그리드 체크와 같이 쓴다).
   머리 __head(제목 __title · 닫기 __close) · 몸 __body(넘치면 이것만 굴러간다) · 발 __foot(보내기 단추) · 열기 = .is-open · 폰에선 전체 폭 */
.side-panel { position: fixed; top: 0; right: 0; z-index: 90; width: min(420px, 100vw); height: 100vh;
  display: flex; flex-direction: column; background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-modal); transform: translateX(100%); visibility: hidden;
  transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur); }
.side-panel.is-open { transform: none; visibility: visible; transition: transform var(--dur) var(--ease); }
/* 폭 조절 손잡이 — 왼쪽 경계선(core/static/core/sidepanel.js 가 저절로 단다 · 끌기 · 두 번 = 기본 폭 · ←/→) · 2026-10-21 */
.side-panel__grip { position: absolute; top: 0; left: -4px; width: 8px; height: 100%; cursor: col-resize; z-index: 1; touch-action: none; }
.side-panel__grip:hover, .side-panel__grip:focus-visible, .side-panel.is-resizing .side-panel__grip { background: var(--brand-tint); outline: none; }
.side-panel.is-resizing { transition: none; user-select: none; }
@media (max-width: 600px) { .side-panel__grip { display: none; } }
/* 패널이 열려 있으면 **본문은 그대로 넓게** 두고(비키면 표가 좁아진다 · 사장님 10-21) 가로로 굴러가는 표 끝에 패널 폭만큼 여유를 준다 —
   패널 밑에 숨은 오른쪽 칸(청구·입금 등)을 가로 스크롤로 패널 왼쪽까지 끌어낸다(sidepanel.js 가 body.side-open · --sidepanel-w 를 단다) */
body.side-open .table-wrap > table { margin-right: var(--sidepanel-w, 0px); }
.side-panel__head { display: flex; align-items: flex-start; gap: var(--s2); padding: var(--s4); border-bottom: 1px solid var(--line); }
.side-panel__title { flex: 1; margin: 0; font-size: var(--fs-lg); font-weight: 700; color: var(--ink); }
.side-panel__close { border: 0; background: transparent; font-size: var(--fs-lg); line-height: 1; color: var(--muted); cursor: pointer; padding: var(--s1); }
.side-panel__close:hover { color: var(--ink); }
.side-panel__body { flex: 1 1 auto; overflow: auto; padding: var(--s4); display: flex; flex-direction: column; gap: var(--s3); }
.side-panel__foot { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; padding: var(--s3) var(--s4);
  border-top: 1px solid var(--line); background: var(--surface-2); }
/* 패널 안 목록 한 줄 — 체크 · 이름 · 마지막 한 일 */
.side-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: var(--r); }
.side-list li { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); border-top: 1px solid var(--line); font-size: var(--fs-sm); }
.side-list li:first-child { border-top: 0; }
.side-list li.is-done { color: var(--muted); }
.side-list__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-list__meta { font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; }
.side-list__meta.is-bad { color: var(--danger); }
@media (prefers-reduced-motion: reduce) { .side-panel, .side-panel.is-open { transition: none; } }
/* 곁 패널 .side-panel--beside — 열린 옆 패널 **바로 왼쪽**에 붙는 둘째 패널(받는 모습 미리보기 등 · 2026-10-22)
   사장님 「우측패널에 띄워」 — 가운데 팝업은 패널의 표를 가려 거래처를 바꿔 가며 볼 수 없었다 ⇒ 표와 나란히 둔다.
   자리 = 옆 패널 폭(--sidepanel-w · sidepanel.js) 만큼 왼쪽 · 폭 조절 손잡이·본문 여유는 붙지 않는다(sidepanel.js 가 건너뛴다) · 폰은 위에 겹친다 */
.side-panel.side-panel--beside { right: var(--sidepanel-w, 0px); z-index: 89; width: min(400px, 100vw); }
@media (max-width: 600px) { .side-panel.side-panel--beside { right: 0; z-index: 91; } }

/* ── 34. 달력 (.cal) — 한 달 7칸 격자 · 칸마다 날 숫자 + 작은 표 두 개까지 (2026-10-21 · 거래처 「세금·납부 달력」 portal/taxcal.py) ──
   머리 __head(요일) · 칸 __day(일정이 있으면 <a>.has-items → 아래 일정 목록 #앵커) · 다른 달 .is-out · 쉬는 날 .is-off(빨간 숫자) · 오늘 .is-today
   표 __tag(기본 = 기한 · .is-bill 낼 것 · .is-paid 끝) · 넘친 수 __more · 위 이동 줄 .cal-nav · 375px 에서 칸 하나 ≈ 46px */
.cal-nav { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s2); }
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; }
.cal__head { text-align: center; font-size: var(--fs-xs); color: var(--muted); padding: var(--s1) 0; }
.cal__head.is-off { color: var(--danger); }
.cal__day { display: flex; flex-direction: column; align-items: center; gap: 2px; min-height: 52px; padding: 3px 1px;
  border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink); text-decoration: none; overflow: hidden; }
.cal__day.has-items { background: var(--brand-tint); }
.cal__day.is-out { opacity: .4; }
.cal__day.is-today { box-shadow: inset 0 0 0 2px var(--brand); }
.cal__num { font-size: var(--fs-sm); font-weight: 600; }
.cal__day.is-off .cal__num { color: var(--danger); }
.cal__tag { max-width: 100%; font-size: var(--fs-xs); line-height: 1.3; padding: 0 3px; border-radius: var(--r-sm);
  background: var(--neutral-bg); color: var(--neutral); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal__tag.is-bill { background: var(--warn-bg); color: var(--warn); }
.cal__tag.is-paid { background: var(--ok-bg); color: var(--ok); }
.cal__more { font-size: var(--fs-xs); color: var(--muted); }

/* ── 35. 받는 모습 미리보기 (.mock) — 문자·알림톡·카톡·앱은 휴대폰 화면, 메일은 웹메일 화면 (2026-10-21 · 업무관리 공문 「보낼 문구 확인」) ──
   사장님 「실제 디자인으로 · 각자 보는 것처럼 · 앱·문자·알림톡·카톡은 모바일 · 이메일은 네이버」 · 「쏠라피도 그 디자인 색상 그대로」.
   틀 .mock-grid 안에 .mock(머리표 __label) · 휴대폰 .mock-phone > __bar(보낸 사람) + __screen(바탕: --sms · --kakao · --app) ·
   말풍선 .mock-bubble(받은) · .mock-bubble--me(카톡 내가 보냄 = 노랑) · 알림톡 카드 .mock-alim(__head 노랑 띠 + __body) · 메일 .mock-mail(__bar · __subj · __from · __body).
   ⛔ 색은 tokens.css 의 --mock-* 만(남의 앱 색이라 브랜드 토큰과 섞지 않는다). */
.mock-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: var(--s4); align-items: start; }
.mock-grid .mock--wide { grid-column: 1 / -1; }
.mock__label { font-size: var(--fs-sm); font-weight: 700; margin-bottom: var(--s1); }
.mock-phone { width: 230px; border: 8px solid var(--mock-phone); border-radius: 28px; overflow: hidden; background: var(--surface); box-shadow: var(--shadow-card); }
.mock-phone__bar { padding: 6px 10px; font-size: var(--fs-xs); font-weight: 700; text-align: center; background: var(--surface); border-bottom: 1px solid var(--line-2); }
.mock-phone__screen { height: 380px; overflow: auto; padding: 10px; font-size: 12.5px; line-height: 1.5; }
.mock-phone__screen--sms { background: var(--surface); }
.mock-phone__screen--kakao { background: var(--mock-kakao-chat); }
.mock-phone__screen--app { background: var(--bg, var(--surface-2)); padding: 0; overflow: hidden; position: relative; }
/* 앱 화면 = 진짜 화면을 375px 폰 폭으로 그려 틀(214px)에 맞게 줄인다 — 좁은 칸에 그대로 넣으면 글이 세로로 찌그러진다
   ⚠ 창 분할 틀의 `.tab-pane iframe { width:100% }` 가 이기지 않게 두 단계로 집는다(10-21 밤 · 앱 화면이 반 크기로 들어갔다) */
.mock-phone .mock-phone__frame { position: absolute; top: 0; left: 0; width: 375px; max-width: none; height: 666px; border: 0; transform: scale(.5707); transform-origin: 0 0; }
.mock-bubble { display: inline-block; max-width: 88%; padding: 7px 10px; border-radius: 14px; background: var(--mock-sms-bubble); color: var(--ink);
  white-space: pre-wrap; word-break: break-all; }
.mock-bubble--me { float: right; background: var(--mock-kakao); color: var(--mock-kakao-ink); border-radius: 12px; }
.mock-bubble__link { display: block; margin-top: 6px; padding: 6px 8px; border-radius: 8px; background: var(--surface); color: var(--ink); font-size: 11.5px; }
.mock-alim { max-width: 92%; border-radius: 10px; overflow: hidden; background: var(--surface); color: var(--mock-kakao-ink); }
.mock-alim__head { padding: 7px 10px; background: var(--mock-kakao); font-weight: 700; font-size: 12px; }
.mock-alim__body { padding: 10px; white-space: pre-wrap; word-break: break-all; }
.mock-alim__from { font-size: 11.5px; margin-bottom: 4px; color: var(--mock-kakao-ink); }
.mock-time { display: block; clear: both; font-size: 10.5px; color: var(--muted); margin-top: 3px; }
.mock-mail { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.mock-mail__bar { padding: 6px 12px; background: var(--mock-mail); color: var(--surface); font-weight: 700; font-size: var(--fs-sm); }
.mock-mail__subj { padding: 12px 14px 6px; font-size: 16px; font-weight: 700; }
.mock-mail__from { display: flex; align-items: center; gap: 8px; padding: 0 14px 10px; font-size: 12px; color: var(--muted); border-bottom: 1px solid var(--line-2); }
.mock-mail__from b { color: var(--ink); }
.mock-mail__avatar { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  border-radius: 50%; background: var(--mock-mail); color: var(--surface); font-weight: 700; font-size: 13px; }
.mock-mail__body { padding: 12px 14px; white-space: pre-wrap; word-break: break-all; font-size: var(--fs-sm); max-height: 260px; overflow: auto; }

/* ── 36. 패널 표 (.ptable) — 옆 패널 안 「거래처 × 보낼 수단」 표 · 업무관리 격자와 같은 틀 (2026-10-21 · 공문·납부·청구 패널) ──
   사장님 「격자·버튼 일관성 · 브랜드 통일성」 · 「격자에 체크박스 있고 정렬 기능은 틀이야」 ·「50곳이면 카드처럼 넓게 쓰면 계속 내려야 해」.
   틀: 맨 앞 __chk(체크박스 · 머리 = 전체) · 머리 th[data-sort] = 눌러 정렬(__arrow ▲▼↕ · .is-sorted) · 거래처 __name(말줄임) ·
   수단 칸 = 체크박스 / 「꺼짐」·「없음」(__off) / [넣기] · 머리의 __col = 그 열 전부 켜기 · 결과 __res · 줄 .is-done(흐리게) · .is-on(보는 줄) · 까닭 __bad.
   칸이 많은 패널은 .side-panel--wide 로 연다(표가 잘리지 않게). */
/* ⚠ min-width 가 아니라 기본 폭 — min-width 로 두면 손잡이로 넓히기만 되고 **좁히기가 안 됐다**(사장님 2026-10-23) ·
   끌어 둔 폭(sidepanel.js 의 style.width)이 이기고, 두 번 누르면 이 폭으로 돌아온다 */
.side-panel.side-panel--wide { width: min(680px, 92vw); }
.ptable { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); }
.ptable th { position: sticky; top: 0; z-index: 1; background: var(--surface-2); border-bottom: 1px solid var(--line);
  padding: 4px 6px; white-space: nowrap; font-weight: 600; text-align: center; color: var(--ink-2); }
.ptable td { border-bottom: 1px solid var(--line-2); padding: 3px 6px; text-align: center; white-space: nowrap; vertical-align: middle; }
/* 패널 표 안의 입력칸은 줄 높이에 맞춘 작은 칸(사장님 2026-10-24 「금액칸이 너무 커」) — 공용 input[type=text] 규칙(34px · 여백 8px)이
   .input--cell 보다 세서 폼 칸 크기로 그려지고 있었다 ⇒ 패널 표 안에서만 이겨 낸다(다른 화면의 .input--cell 은 그대로) */
.ptable .input--cell, .ptable select.input--cell { min-height: 26px; height: 26px; padding: 0 6px; font-size: var(--fs-sm); }
.ptable th[data-sort] { cursor: pointer; user-select: none; }
.ptable th[data-sort]:hover, .ptable th.is-sorted { color: var(--brand); }
.ptable__arrow { margin-left: 2px; font-size: 9px; color: var(--muted-2); }
.ptable th.is-sorted .ptable__arrow { color: var(--brand); }
.ptable .ptable__chk { width: 26px; }
.ptable .ptable__name { text-align: left; max-width: 12em; overflow: hidden; text-overflow: ellipsis; }
.ptable .ptable__res { text-align: left; }
.ptable__col { border: 0; background: none; padding: 0; font: inherit; font-weight: 600; color: inherit; cursor: pointer; }
.ptable__col:hover:not(:disabled) { color: var(--brand); text-decoration: underline; }
.ptable__col:disabled { color: var(--muted-2); cursor: default; }
.ptable__off { color: var(--muted-2); }
.ptable__bad { font-size: var(--fs-xs); color: var(--danger); }
.ptable tr.is-done td { color: var(--muted); }
.ptable tr.is-on td { background: var(--brand-tint); }

/* 수단 단추(.chan) — 받는 앱의 색 그대로(사장님 10-21 「네이버는 녹색 · 카톡은 노란색」) · 평소 = 그 색 테두리 · 고른 것(.is-on) = 그 색으로 채움 ·
   --email(네이버 메일 초록) · --kakao·--alimtalk(카톡 노랑) · --sms(문자 회색) · --app(우리 남색) — 색은 §35 와 같은 --mock-* 만 */
.chan { display: inline-flex; align-items: center; gap: 3px; height: 24px; padding: 0 10px; border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 700; cursor: pointer; background: var(--surface); color: var(--ink);
  border: 2px solid var(--chan, var(--line)); }
.chan.is-on { background: var(--chan, var(--brand)); color: var(--chan-ink, var(--surface)); }
.chan:disabled { opacity: .5; cursor: default; }
.chan--email, .chan--naver { --chan: var(--mock-mail); --chan-ink: var(--surface); }   /* --naver = 네이버 예약·톡톡·스마트플레이스(같은 초록 · 문의·예약 알림 2026-10-23) */
a.chan { text-decoration: none; }
.chan--kakao, .chan--alimtalk { --chan: var(--mock-kakao); --chan-ink: var(--mock-kakao-ink); }
.chan--sms { --chan: var(--mock-sms-bubble); --chan-ink: var(--ink); }
.chan--app { --chan: var(--brand); --chan-ink: var(--brand-ink); }


/* ── 37. AI 도우미 채팅창 (.aichat) — 화면 위에 떠 있는 창 하나 · 머리 끌기 · 오른쪽 아래 모서리 크기 (2026-10-22 · office/_ai_chat.html · aichat.js) ──
   캐릭터 = 미어캣 「슬기」 한 마리(office/_ai_face.html) — 털·분홍 색은 캐릭터 전용이라 그림 안에서만 쓴다. */
.aichat { position: fixed; right: var(--s6); bottom: var(--s6); z-index: 900; width: 380px; height: 560px;
  min-width: 320px; min-height: 360px; max-width: calc(100vw - 16px); max-height: calc(100vh - 16px);
  display: flex; flex-direction: column; overflow: hidden; resize: both;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-modal); }
/* ★ 10-23 다시 짬(사장님 「심플하게」) — 금 띠·회색 바탕·말풍선마다 얼굴과 이름·늘 보이는 단추 줄·안내 글을 걷었다.
   남은 것 = 머리(얼굴·이름·두 단추) · 대화 · 입력 상자 하나. 색은 내 말 = 옅은 회색 상자 / 슬기 = 바탕 그대로(글만). */
.aichat[hidden] { display: none; }
.in-frame .aichat { display: none !important; }
.aichat.is-dragging { user-select: none; opacity: .96; }
.aichat-head { display: flex; align-items: center; gap: var(--s2); height: 44px; padding: 0 var(--s2) 0 var(--s3); cursor: move;
  border-bottom: 1px solid var(--line); touch-action: none; flex: none;
  background: var(--surface); color: var(--ink); }   /* ⚠ 옛 전역 `header { background: var(--brand) }` 가 칠해 이름 「슬기」가 남색에 묻혔다(10-23) */
.aichat-title { flex: 1; min-width: 0; font-size: var(--fs-md); font-weight: 700; color: var(--ink); }
.aichat-ico { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  border: 0; border-radius: var(--r-sm); background: none; color: var(--muted); }
.aichat-ico:hover { background: var(--surface-2); color: var(--ink); }
.aichat-ico .ico { width: 16px; height: 16px; }
.aichat-feed { flex: 1; overflow-y: auto; padding: var(--s4) var(--s4) var(--s2); display: flex; flex-direction: column; gap: var(--s4); }
.aichat-hello { margin: auto 0; display: flex; flex-direction: column; align-items: center; gap: var(--s2); text-align: center;
  color: var(--ink-2); font-size: var(--fs-md); }
.aichat-hello p { margin: 0; }
.aichat-off { color: var(--warn); font-size: var(--fs-sm); }
.aichat-note { font-size: var(--fs-xs); color: var(--muted); }
.aichat-quick { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: var(--s2) 0; }
.aichat-quick button { height: 30px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--surface); font: inherit; font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer; }
.aichat-quick button:hover { border-color: var(--line-2); background: var(--surface-2); color: var(--ink); }
.aichat-me { display: flex; justify-content: flex-end; }
.aichat-me p { margin: 0; max-width: 85%; padding: var(--s2) var(--s3); background: var(--surface-2); color: var(--ink);
  border-radius: 12px; font-size: var(--fs-md); line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
.aichat-bot { display: flex; flex-direction: column; gap: 4px; }
.aichat-bubble { font-size: var(--fs-md); line-height: 1.65; color: var(--ink); white-space: pre-wrap; word-break: break-word; }
.aichat-bubble.is-error { color: var(--danger); }
/* 답 아래 [복사]·[리포트에 넣기] — 그 답에 마우스를 올렸을 때만(늘 떠 있으면 대화가 지저분하다) · 키보드로 가도 보인다 */
/* 근거 조문(법제처 원문 링크 · 2026-10-24) — 답 바로 아래 · 늘 보인다(단추와 달리 내용이다) */
.aichat-src { display: flex; flex-wrap: wrap; gap: 2px var(--s2); font-size: var(--fs-xs); color: var(--muted); }
.aichat-src[hidden] { display: none; }
.aichat-src > span { font-weight: 600; }
.aichat-src a { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.aichat-acts { display: flex; gap: var(--s3); opacity: 0; transition: opacity .12s; }
.aichat-bot:hover .aichat-acts, .aichat-acts:focus-within, .aichat-bot:last-child .aichat-acts { opacity: 1; }
.aichat-acts button { padding: 0; border: 0; background: none; font: inherit; font-size: var(--fs-xs); color: var(--muted); cursor: pointer; }
.aichat-acts button:hover { color: var(--brand); }
.aichat-acts button.is-saved { color: var(--ok); }
/* 슬기가 띄운 「거래처에 보낼 글」 초안(office/_ai_draft.html · 2026-10-24) — 보내기 전엔 고칠 수 있고, 보낸 뒤엔 잠긴다 */
.aidraft { display: flex; flex-direction: column; gap: 6px; margin-top: var(--s2); padding: var(--s2) var(--s3);
  border: 1px solid var(--line-2); border-left: 3px solid var(--brand); border-radius: var(--r); background: var(--surface); }
.aidraft-head { display: flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--muted); }
.aidraft-head .ico { width: 14px; height: 14px; color: var(--brand); }
.aidraft-head b { color: var(--ink); }
.aidraft-to { margin-left: auto; font-variant-numeric: tabular-nums; }
.aidraft textarea { resize: vertical; min-height: 6em; font-size: var(--fs-sm); line-height: 1.55; }
.aidraft-acts { display: flex; gap: 6px; }
.aidraft-msg { margin: 0; font-size: var(--fs-xs); color: var(--muted); }
.aidraft.is-done { border-left-color: var(--line-2); }
.aidraft.is-done textarea, .aidraft.is-done input { background: var(--surface-2); color: var(--muted); }
.aidraft.is-fail { border-left-color: var(--danger); }
.aidraft.is-fail .aidraft-msg { color: var(--danger); }
.aichat-think { display: flex; align-items: center; gap: var(--s2); }
.aichat-compose { flex: none; display: flex; flex-direction: column; gap: 6px; padding: var(--s2) var(--s3) var(--s3); }
/* 입력 = 보내기 단추가 안에 든 상자 하나 · 글이 길면 위로 자란다(aichat.js · 최대 6줄쯤) */
.aichat-box { display: flex; align-items: flex-end; gap: 6px; padding: 6px 6px 6px var(--s3);
  border: 1px solid var(--line-2); border-radius: 14px; background: var(--surface); }
.aichat-box:focus-within { border-color: var(--brand); }
.aichat-box textarea { flex: 1; min-width: 0; min-height: 0; max-height: 9.5em; resize: none; border: 0; outline: 0; padding: 5px 0; background: none;
  font: inherit; font-size: var(--fs-md); line-height: 1.5; color: var(--ink); }
.aichat-go { flex: none; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: var(--brand); color: var(--brand-ink); cursor: pointer; }
.aichat-go .ico { width: 15px; height: 15px; }
/* 오른쪽 아래 모서리 표시 — 실제로 잡히는 것은 CSS resize 모서리다(이건 눈에 보이게만) */
.aichat-grip { position: absolute; right: 2px; bottom: 2px; width: 10px; height: 10px; pointer-events: none;
  background: linear-gradient(135deg, transparent 55%, var(--line-2) 55%, var(--line-2) 65%, transparent 65%, transparent 80%, var(--line-2) 80%, var(--line-2) 90%, transparent 90%); }
.side-ai.is-on { background: var(--label-paper); color: var(--appbar-ink); }
/* 메뉴의 「슬기」 = 아이콘 자리에 얼굴(사장님 10-23 「캐릭터 이미지 넣고」) — 다른 메뉴 아이콘(18px)보다 조금 크게, 흐리게 하지 않는다 */
.side-ai-face { display: inline-flex; width: 22px; height: 22px; margin-left: 2px; opacity: 1; }
.side-ai-face .ai-face { width: 22px; height: 22px; border-radius: 6px; }
/* 닫혀 있을 때 오른쪽 아래 슬기 단추 — 메뉴를 접어 둬도 부를 수 있게 */
.aichat-fab { position: fixed; right: var(--s6); bottom: var(--s6); z-index: 899; width: 52px; height: 52px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 50%;
  background: var(--surface); box-shadow: var(--shadow-pop); cursor: pointer; transition: transform .15s; }
.aichat-fab:hover { transform: translateY(-2px); }
.aichat-fab[hidden], .in-frame .aichat-fab, .panel-open .aichat-fab { display: none !important; }
@media print { .aichat, .aichat-fab { display: none !important; } }
/* 살아 있게(사장님 「너무 정적이야」) — 가끔 눈을 깜빡이고, 첫 화면에선 천천히 몸을 흔든다 */
.ai-face .ai-eye { transform-box: fill-box; transform-origin: center; animation: ai-blink 5s infinite; }
.ai-face .ai-bob { transform-box: view-box; transform-origin: 60px 112px; }
.aichat-hello .ai-face .ai-bob { animation: ai-run .36s ease-in-out infinite; }
/* 첫 화면 = 달리기 직전 제자리 발 구르기(사장님 10-23 「발을 움직이는 애니 · 달리기 전」) — 두 발이 번갈아 들렸다 내려가고 팔은 반대로 흔든다 */
.ai-face .ai-foot, .ai-face .ai-arm { transform-box: fill-box; transform-origin: center; }
.aichat-hello .ai-foot--l { animation: ai-foot .36s ease-in-out infinite; }
.aichat-hello .ai-foot--r { animation: ai-foot .36s ease-in-out -.18s infinite; }
.aichat-hello .ai-arm--l { animation: ai-arm .36s ease-in-out -.18s infinite; }
.aichat-hello .ai-arm--r { animation: ai-arm .36s ease-in-out infinite; }
/* 첫 화면 슬기 = 달려가는 모습(④) — 통통 뛴다 */
/* 생각하는 동안(사장님 「생각할 때 애니메이션 하나」 · 「미어캣의 동작 있잖아」) — 미어캣 보초 자세:
   벌떡 일어서서(위로 쭉) 눈을 좌우로 두리번 + 옆의 점 세 개가 차례로 뛴다 */
.is-thinking .ai-face .ai-bob { animation: ai-stand 2.4s ease-in-out infinite; }
.is-thinking .ai-face .ai-eye { transform-box: view-box; transform-origin: 60px 60px; animation: ai-look 2.4s ease-in-out infinite; }
.ai-dots { display: inline-flex; gap: 5px; align-items: center; height: 1.6em; }
.ai-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--gold); animation: ai-dot 1s ease-in-out infinite; }
.ai-dots i:nth-child(2) { animation-delay: .15s; }
.ai-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes ai-blink { 0%, 94%, 100% { transform: scaleY(1); } 97% { transform: scaleY(.1); } }
@keyframes ai-foot { 0%, 100% { transform: translate(0, 0) rotate(0); } 25% { transform: translate(-2px, -4px) rotate(-18deg); } 50% { transform: translate(1px, 0) rotate(0); } 75% { transform: translate(2px, -1px) rotate(10deg); } }
@keyframes ai-arm { 0%, 100% { transform: rotate(0); } 50% { transform: rotate(-22deg); } }
@keyframes ai-run { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes ai-stand { 0%, 100% { transform: translateY(0) scaleY(1); } 18%, 82% { transform: translateY(-6px) scaleY(1.05); } }
@keyframes ai-look { 0%, 20%, 100% { transform: translateX(0); } 35%, 48% { transform: translateX(-2.6px); } 62%, 75% { transform: translateX(2.6px); } }
@keyframes ai-dot { 0%, 60%, 100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-5px); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .ai-face .ai-eye, .ai-face .ai-bob, .ai-face .ai-foot, .ai-face .ai-arm, .ai-dots i { animation: none !important; } }
@media (max-width: 640px) { .aichat { left: 8px !important; right: 8px !important; top: auto !important; bottom: 8px !important;
  width: auto !important; height: 75vh !important; resize: none; } }

/* ── 입금 귀퉁이 쪽지 .bank-note (2026-10-24 · billing/static/billing/hana_import.js) ──
   하나은행 빠른조회에 직원이 칠 세 값을 입금 패널 오른쪽 위 귀퉁이에(사장님 「한쪽 귀퉁이에 써 놔」) · 값은 가림 + [보기] */
.bank-quick { position: relative; }
.bank-quick .bank-note { float: right; margin: 0 0 var(--s1) var(--s2); padding: var(--s1) var(--s2);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); font-size: var(--fs-sm); min-width: 190px; }
.bank-note__row { display: flex; gap: var(--s1); align-items: center; justify-content: space-between; }
.bank-note__row b { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.bank-note__set input { display: block; width: 100%; margin: 2px 0; }
@media (max-width: 640px) { .bank-quick .bank-note { float: none; margin: 0 0 var(--s1); } }
