/* ======================================================================
   gridkit.css — 관리자 목록 그리드 키트 스타일 (colon-grid 정본)

   여기에는 **그리드가 쓰는 것만** 둔다. 사이드바·로그인·대시보드처럼
   앱마다 다른 껍데기는 app.css 로 나갔다 — 섞여 있으면 키트만 떼어낼 수 없다.

   ⚠️ Tailwind 없이도 표가 제대로 보이도록 정렬/굵기 유틸을 자체 정의한다(맨 아래).
      Tailwind 가 있는 프로젝트에서는 같은 뜻이라 충돌하지 않는다.
   ====================================================================== */
/* ============================================================
   COLON MONEY ADMIN 공용 컴포넌트
   출처: postring admin.css (canonical) — ADMIN_PAGE_RULE 공통 규칙 구현체
   테마: 블랙앤화이트 (primary=black, accent=gray)
   ============================================================ */
:root {
    --primary: #111827;          /* 블랙(주 강조) */
    --primary-dark: #000000;
    --primary-light: #f3f4f6;    /* 연한 회색(호버/선택 배경) */
    --primary-border: #d1d5db;
    --secondary: #64748b;
    --success: #10b981;
    --danger: #ef4444;
    --warning: #f59e0b;
    --bg: #f1f5f9;
    --card-bg: #ffffff;
    --text-primary: #1e293b;
    --text-secondary: #64748b;
    --border: #e2e8f0;
    --control-border: #f0f0f0;   /* 폼 컨트롤·버튼 공통 보더(연한 회색) — 모든 인풋/셀렉트/버튼 통일 */
    --radius: 12px;
    --radius-sm: 8px;
}

/* ---------- 로딩 FOUC 방지: 향상(admin-grid.js) 전 원본 숨김 + 자리 확보 ---------- */
table[data-grid]:not(.grid-ready) { visibility: hidden; }          /* 향상 전 원본 테이블 숨김 */
[data-grid-actions] { display: none; }                              /* JS가 툴바로 이전 후 노출 */
.bg-white:has(> table[data-grid]:not(.grid-ready)),
.bg-white:has([data-grid-actions]) { position: relative; min-height: 360px; }   /* 그리드 영역 자리 확보 */
.bg-white:has(> table[data-grid]:not(.grid-ready))::after {        /* 로딩 shimmer 플레이스홀더 */
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: linear-gradient(100deg, #eef2f7 30%, #f7fafc 50%, #eef2f7 70%);
    background-size: 200% 100%; animation: gridShimmer 1.25s linear infinite;
}
@keyframes gridShimmer { to { background-position: -200% 0; } }
/* 상세/수정 모달이 목록 위로 함께 로드될 때: 목록은 배경이므로 FOUC shimmer·자리확보 생략(모달 뒤 스켈레톤 깜빡임 방지) */
body:has([data-admin-modal]) .bg-white:has(> table[data-grid]:not(.grid-ready))::after { content: none !important; animation: none !important; }
body:has([data-admin-modal]) .bg-white:has(> table[data-grid]:not(.grid-ready)),
body:has([data-admin-modal]) .bg-white:has([data-grid-actions]) { min-height: 0 !important; }

/* ---------- 체크박스(진담) ---------- */
input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--primary);
    cursor: pointer;
    vertical-align: middle;
}

/* ---------- 검색/필터 영역 (진담 filter-bar) ---------- */
/* 검색카드 — 예전엔 Tailwind 유틸로 만들던 껍데기. 키트가 자립하도록 여기서 정의한다. */
.admin-search-card { display: flex; gap: 16px; align-items: stretch; padding: 16px; margin-bottom: 16px; }
.filter-bar { display: flex; align-items: flex-end; gap: 10px 14px; flex-wrap: wrap; flex: 1 1 auto; }
.filter-group { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 6px; flex: 0 0 auto; }
.filter-group > label { font-size: 13px; color: var(--text-primary); font-weight: 600; margin: 0; white-space: nowrap; }
.filter-row { display: inline-flex; align-items: center; gap: 6px; }
.filter-input {
    border: 1.5px solid var(--control-border);
    border-radius: var(--radius-sm);
    padding: 0 0.6rem;
    height: 34px;                 /* 툴바/검색 컨트롤 공통 높이 */
    font-size: 13px;
    line-height: 1.4;
    outline: none;
    background-color: #fff;
    color: var(--text-primary);
    transition: border-color .15s, box-shadow .15s;
}
.filter-input:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(17, 24, 39, .12); }
/* 모달 폼 컨트롤(인풋/셀렉트/텍스트영역) 보더 = 짙은 회색 통일 (콤보 input 제외 — filter-input로 이미 통일) */
[data-admin-modal] input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not(.combobox-input),
[data-admin-modal] textarea { border-color: var(--control-border); }
/* 모달 폼 컨트롤 포커스 = 검색창과 동일 통일 */
[data-admin-modal] input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):focus,
[data-admin-modal] textarea:focus,
[data-admin-modal] select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(17, 24, 39, .12); outline: none; }
select.filter-input {
    -webkit-appearance: none; -moz-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%2364748b' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 10px center; background-size: 13px 9px; padding-right: 30px;
}

/* ---------- 버튼 (진담 btn) ---------- */
.btn {
    border-radius: var(--radius-sm); font-size: 13px; font-weight: 600; padding: 8px 16px;
    transition: all .15s; border: 1.5px solid var(--control-border); cursor: pointer;   /* 공통 보더(짙은 회색) */
    display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;   /* 좁은 폭에서 글자 세로 쪼개짐 방지(§2.12) */
    user-select: none;   /* 그리드 드래그 중 버튼 글자가 파랗게 잡히지 않게 */
}
.btn svg { flex-shrink: 0; }
/* hover = 색상반전(검흰↔흰검, 파흰↔흰파)으로 통일 — 그림자 없음 */
/* 기본 버튼 = 흰 바탕·검은 글씨. 보더는 전부 짙은 회색(--control-border) 통일. hover 시 색상반전 */
.btn-primary { background: #fff; border-color: var(--control-border); color: var(--primary); }
.btn-primary:hover { background: var(--primary); color: #fff; border-color: var(--primary); }   /* hover 반전: 흰검 → 검흰 */
.btn-light { background: #fff; border-color: var(--control-border); color: var(--text-primary); }
.btn-light:hover { background: var(--primary); color: #fff; border-color: var(--primary); }       /* 흰검 → 검흰 */
.btn-outline { background: #fff; border-color: var(--control-border); color: var(--primary); }   /* §2.3 초기화 */
.btn-outline:hover { background: var(--primary); color: #fff; border-color: var(--primary); }     /* 흰검 → 검흰 */
.btn-danger-outline { background: #fff; border-color: var(--control-border); color: var(--danger); }
.btn-danger-outline:hover { background: var(--danger); color: #fff; border-color: var(--danger); } /* 흰빨 → 빨흰 */
.btn-sm { padding: 0 14px; height: 34px; font-size: 13px; }   /* 셀렉트/툴바 컨트롤과 높이 통일 */

/* ---------- 데이터 테이블 (진담 data-table) ---------- */
/* 가로 오버플로우(컬럼 합이 넓어질 때)는 카드 안에서 스크롤 — 밖으로 안 나가게 */
.table-wrap { overflow-x: auto; }
/* §2.5 table-layout: auto — 고정폭이 텍스트 컬럼을 뭉개지 않게 내용 사이징(컬럼 리사이즈는 드래그 시 px 고정으로 동작). */
.data-table { width: 100%; border-collapse: collapse; table-layout: auto; }
.data-table thead th { text-align: center; }   /* §450 헤더 전부 중앙정렬 */
.data-table th {
    background: #f8fafc !important; border-bottom: 2px solid var(--border) !important;
    border-right: 1px solid var(--border);   /* 컬럼 구분선(리사이즈 위치 가시화) */
    padding: 10px 14px !important; font-size: 12px !important; font-weight: 600 !important;
    color: var(--text-secondary) !important; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; position: relative;
}
.data-table td {
    padding: 11px 14px !important; border-bottom: 1px solid var(--border) !important;
    border-right: 1px solid var(--border);   /* 컬럼 구분선 */
    font-size: 13px; color: var(--text-primary); vertical-align: middle;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;   /* 넘치면 ... */
}
.data-table th:last-child, .data-table td:last-child { border-right: none; }
.data-table td.seq-cell { font-size: 11px; color: #64748b; }   /* §2.10 순번=보조정보(작은 폰트+흐린 slate-500, 데이터처럼 안 읽히게) */
.data-table td .truncate, .data-table td > div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 컬럼 너비 조절 핸들(임시) — 우측 경계 위 */
.col-resizer { position: absolute; top: 0; right: -1px; width: 7px; height: 100%; cursor: col-resize; user-select: none; z-index: 2; }
.col-resizer:hover { background: var(--primary); opacity: .5; }
/* 컬럼 위치 변경(임시, 드래그) 피드백 */
.data-table th.col-dragging { opacity: .5; }
.data-table th.col-dragover { box-shadow: inset 3px 0 0 0 var(--primary); }
/* 빈 상태(데이터 0건) — 고정 높이 200px. (.data-table td 의 padding !important 를 이기려 특정도↑) */
.data-table td.grid-empty-cell { height: 200px; padding: 0 !important; text-align: center; vertical-align: middle; color: var(--text-secondary); font-size: 14px; border-right: none !important; }
.data-table tbody tr:last-child td { border-bottom: none !important; }
.data-table tbody tr:hover td { background: var(--primary-light); }
.data-table tbody tr.row-clickable { cursor: pointer; }
/* 로우 hover = 색상반전(흰 배경 → 검정, 글자 흰색). 배지(bg-* 보유)는 자체 색 유지 */
.data-table tbody tr.row-clickable:hover td { background: var(--primary); color: #fff; }

/* ---------- 정렬 헤더 (다중정렬: 1개=화살표만, 2개+=순서 숫자) ---------- */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--primary) !important; }
.sort-ind { display: inline-flex; align-items: center; gap: 2px; margin-left: 4px; vertical-align: middle; }
.sort-ind .sort-ar { font-size: 10px; opacity: .3; }
th.sortable.sorted .sort-ind .sort-ar { opacity: 1; color: var(--primary); }
.sort-ind .sort-pri {
    display: none; min-width: 15px; height: 15px; line-height: 15px; text-align: center;
    font-size: 9px; font-weight: 700; color: #fff; background: var(--primary); border-radius: 9999px; padding: 0 3px;
}
.sort-ind .sort-pri:not(:empty) { display: inline-block; }   /* 번호 있을 때(2개+)만 표시 */

/* 전체건수 (진담: 세로 바 + "전체 N건") */
.grid-count { font-size: 13px; color: var(--text-primary); display: inline-flex; align-items: center; gap: 8px; }
.grid-count::before { content: ""; width: 5px; height: 16px; border-radius: 2px; background: var(--primary); display: inline-block; }
.grid-count b { color: var(--primary); }

/* ---------- 페이징 (진담 pagination) ---------- */
.grid-pager-area { margin-top: 16px; }   /* 그리드 카드와 별개 하위 영역 */
.pagination-wrapper { display: flex; justify-content: center; align-items: center; gap: 6px; }
.grid-page-status { margin-left: 10px; font-size: 13px; color: var(--text-secondary); }
.page-gap { padding: 0 2px; color: var(--text-secondary); font-size: 13px; user-select: none; align-self: center; }

/* 컬럼 표시/숨김 팝오버(§2.11) — 버튼 기준 툴팁식 팝업(모달 아님) */
.col-pop { position: fixed; z-index: 250; width: 300px; max-width: calc(100vw - 16px); padding: 12px;
    background: #fff; border: 1px solid var(--control-border); border-radius: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, .16); }
.col-pop-title { font-size: 12px; font-weight: 700; color: var(--text-secondary); margin-bottom: 8px; }
.col-pop-list { display: flex; flex-wrap: wrap; gap: 6px; }
.col-badge { font-size: 12px; font-weight: 600; padding: 5px 11px; border-radius: 999px; cursor: pointer; transition: all .12s;
    background: var(--primary); border: 1px solid var(--primary); color: #fff; }                 /* 활성(표시) */
.col-badge:hover { opacity: .85; }
.col-badge.off { background: #f1f5f9; border-color: var(--border); color: #94a3b8; }            /* 비활성(숨김) */
.page-btn {
    min-width: 34px; height: 34px; padding: 0 8px; border: 1.5px solid var(--control-border); border-radius: var(--radius-sm);
    background: #f1f5f9; display: inline-flex; align-items: center; justify-content: center; font-size: 13px;
    cursor: pointer; color: var(--text-primary); transition: all .15s;
}
.page-btn:hover { background: var(--primary); border-color: var(--primary); color: #fff; }   /* 색상반전 통일 */
.page-btn.active { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600; }
.page-btn:disabled { opacity: .45; cursor: not-allowed; }

/* ---------- 로딩 스켈레톤 ---------- */
@keyframes skel-shimmer { 0% { background-position: -180px 0; } 100% { background-position: calc(180px + 100%) 0; } }
.skeleton-bar {
    display: inline-block; height: 12px; border-radius: 6px; width: 100%;
    background: #e9edf2;
    background-image: linear-gradient(90deg, #e9edf2 0, #f5f7fa 60px, #e9edf2 120px);
    background-size: 180px 100%; background-repeat: no-repeat;
    animation: skel-shimmer 1.15s ease-in-out infinite;
}
.grid-skeleton td { padding: 11px 14px !important; border-bottom: 1px solid var(--border) !important; }

/* ---------- 콤보박스 (input + dropdown, 전체목록 노출) ---------- */
.combobox { position: relative; display: inline-flex; align-items: center; }
.combobox.cb-block { display: flex; width: 100%; }
.combobox.cb-block .combobox-input { flex: 1 1 auto; width: 100%; }
.combobox.cb-compact { width: 6.5rem; flex: 0 0 auto; }   /* 페이지당 개수 등 컴팩트 콤보 */
.combobox.cb-compact .combobox-input { width: 100%; }
.combobox-input {
    cursor: pointer; padding-right: 30px !important;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%2364748b' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 10px center; background-size: 13px 9px;
}
.combobox.combobox-open .combobox-input { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(17, 24, 39, .12); outline: none; }
.combobox-dropdown {
    display: none; position: absolute; top: calc(100% + 4px); left: 0; right: 0; min-width: 100%;
    background: #fff; border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, .10);
    max-height: 280px; overflow-y: auto; z-index: 1100; padding: 4px 0;
}
.combobox.combobox-open .combobox-dropdown { display: block; }
.combobox-item { padding: 8px 12px; font-size: 14px; cursor: pointer; color: #334155; white-space: nowrap; line-height: 1.4; }
.combobox-item:hover, .combobox-item.combobox-item-active { background: var(--primary-light); }
.combobox-item.combobox-item-selected { background: rgba(17, 24, 39, .08); color: var(--primary); font-weight: 600; }
.combobox-empty { padding: 10px 12px; font-size: 13px; color: #94a3b8; text-align: center; }

/* ---------- 모달 ---------- */
body.modal-open { overflow: hidden; }

/* ============================================================
   §2.12 반응형 / 모바일 (≤768px) — 공통 CSS가 자동 처리(화면별 마크업 X)
   ============================================================ */

@media (max-width: 768px) {
    /* ----- 그리드 = 카드형(행=카드, 라벨 좌 / 값 우) ----- */
    /* 그리드 카드 래퍼는 투명하게 → 카드 사이 간격에 흰 배경 안 보이고 페이지 배경 노출 */
    .bg-white:has(> .table-wrap) { background: transparent !important; border: none !important; border-radius: 0 !important; overflow: visible !important; }
    .data-table, .data-table tbody, .data-table tr { display: block; width: 100%; }
    .data-table thead { display: none; }
    .data-table tbody tr { border: 1px solid var(--border); border-radius: 10px; margin-bottom: 10px; overflow: hidden; background: #fff; }
    .data-table td {
        display: flex; justify-content: flex-end; align-items: center; gap: 6px;     /* 값(들)은 우측에 모음 */
        width: auto !important; max-width: none;
        text-align: right !important;                                  /* 값 우측(컬럼 inline align 덮기) */
        white-space: normal; overflow: visible; text-overflow: clip;
        border: none; border-bottom: 1px solid var(--border); padding: 9px 14px;
    }
    .data-table td:last-child { border-bottom: none; }
    .data-table td::before {
        content: attr(data-label); flex: 0 0 auto; margin-right: auto;             /* 라벨은 좌측으로 밀고 값은 우측 그룹 */
        font-size: 12px; font-weight: 600; color: var(--text-secondary); text-align: left; white-space: nowrap;
    }
    .data-table td:empty { display: none; }                            /* 값 없는 셀은 카드에서 숨김 */
    .data-table td:has(img) { justify-content: flex-end; }
    .data-table td.grid-empty-cell { display: flex !important; align-items: center; justify-content: center; height: 100px; min-height: 100px; text-align: center !important; }   /* 빈상태 모바일=100px·세로중앙 */
    .data-table td.grid-empty-cell::before { content: none; }
    .data-table .col-resizer { display: none; }
    .table-wrap { overflow-x: visible; }
    .data-table tbody tr.row-clickable:hover td { background: transparent; color: inherit; }   /* 카드에선 로우 반전 완화 */

    /* ----- 검색영역 세로화 ----- */
    .admin-search-card { flex-direction: column; }
    .filter-bar { flex-direction: column; align-items: stretch; }
    .filter-group { width: 100%; }
    .filter-row { width: 100% !important; }                            /* 검색유형(7rem 고정)+검색값(흡수) 한 줄 유지 */
    .admin-search-actions { flex-direction: row !important; align-self: auto; }   /* 초기화/조회 가로 한 줄(둘 다 flex:1) */

}

/* ---------- 기간(부터~까지) 필터 (admin-grid.js data-range) ---------- */
.filter-dash { color: var(--text-secondary); font-size: 12px; padding: 0 2px; user-select: none; }
.filter-row > input[type="month"], .filter-row > input[type="date"] { width: 9.5rem; }

/* ---------- 그리드 합계행 (admin-grid.js data-sum) ---------- */
.data-table tfoot .grid-foot-row td {
    background: #f8fafc !important; border-top: 2px solid var(--border) !important; border-bottom: none !important;
    font-size: 13px; font-weight: 700; color: var(--primary); text-align: right; white-space: nowrap;
}
.data-table tfoot .grid-foot-row td.foot-label { text-align: center; font-size: 11px; color: var(--text-secondary); }
.data-table tbody tr:last-child td { border-bottom: 1px solid var(--border) !important; }   /* 합계행이 붙으므로 마지막 행 선 유지 */

/* ---------- 콤보 자유입력(creatable) 항목 ---------- */
.combobox-item-create { color: var(--primary); font-weight: 600; border-top: 1px solid var(--border); }

/* ---------- 폼 필드 (molecule: 라벨 + 컨트롤) — 모달 폼 공통 ---------- */
.form-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 16px; }
.form-grid .col-2 { grid-column: span 2; }
.form-grid .col-full { grid-column: 1 / -1; }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* footgun(§2.4): 콤보를 <label> 안에 넣으면 항목 클릭이 label 기본동작으로 드롭다운을 다시 연다 → 라벨은 형제 span 으로 */
.field-label { font-size: 13px; font-weight: 600; color: var(--text-primary); white-space: nowrap; }
.field-label .req { color: var(--danger); margin-left: 2px; }
.field .filter-input, .field textarea { width: 100%; }
.field textarea { padding: 8px 10px; height: auto; min-height: 72px; resize: vertical; font-family: inherit; }
.field-hint { font-size: 11px; color: var(--text-secondary); }
/* 자동계산 결과 칸 — 읽기전용임을 색으로 알린다(수정하려면 직접 입력 가능) */
.field .calc-out { background: #f8fafc; font-weight: 600; }
.form-error { background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c; font-size: 13px; padding: 9px 12px; border-radius: 8px; }
.form-section { font-size: 12px; font-weight: 700; color: var(--text-secondary); letter-spacing: .02em; margin: 4px 0 -4px; }

@media (max-width: 768px) {
    .form-grid { grid-template-columns: 1fr; }
    .form-grid .col-2, .form-grid .col-full { grid-column: auto; }
}

/* ---------- 상태 배지 ---------- */
.badge { display: inline-block; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.badge-done { background: #111827; color: #fff; }
.badge-wait { background: #f1f5f9; color: #64748b; }
.badge-mid { background: #e2e8f0; color: #1e293b; }

/* ---------- 그리드 수정모드 (ADMIN_PAGE_RULE §2.15) ---------- */
/* 체크박스 컬럼: 항상 존재하고 수정모드에서만 보인다(컬럼 수를 흔들지 않으려고) */
.data-table .col-check { display: none; width: 40px; }
.data-table.grid-edit-mode .col-check { display: table-cell; }
.data-table.grid-edit-mode { --edit-accent: #111827; }

/* 수정모드에선 행 클릭(상세 모달)이 막히므로 커서/호버 반전도 끈다 */
.data-table.grid-edit-mode tbody tr.row-clickable { cursor: default; }
.data-table.grid-edit-mode tbody tr.row-clickable:hover td { background: #f8fafc; color: inherit; }

/* 편집 가능한 칸 — 수정모드에서만 점선으로 알린다(보기모드에선 아무 표시 없음) */
.data-table.grid-edit-mode td.cell-editable { cursor: text; position: relative; }
/* 편집 가능 표식 = **헤더에 컬럼 유형 아이콘**.
   연필 하나로 통일하면 "고칠 수 있다"만 알 뿐, 무엇으로 고치는지(텍스트/숫자/선택/날짜) 를 모른다.
   셀마다 찍지 않는 이유: 표 전체가 표식으로 뒤덮여 정작 데이터가 안 읽힌다. */
.data-table.grid-edit-mode th.col-editable::before {
    content: ""; display: inline-block; width: 11px; height: 11px; margin-right: 5px;
    vertical-align: middle; opacity: .6; background-color: currentColor;
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center; mask-position: center;
}
.data-table.grid-edit-mode th.col-editable[data-edit="text"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 6h14'/%3E%3Cpath d='M12 6v13'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 6h14'/%3E%3Cpath d='M12 6v13'/%3E%3C/svg%3E");
}
.data-table.grid-edit-mode th.col-editable[data-edit="number"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 4l-1.5 16M16.5 4L15 20M4 9.5h16M3.5 15h16'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 4l-1.5 16M16.5 4L15 20M4 9.5h16M3.5 15h16'/%3E%3C/svg%3E");
}
.data-table.grid-edit-mode th.col-editable[data-edit="select"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='M8.5 11l3.5 3.5 3.5-3.5'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='M8.5 11l3.5 3.5 3.5-3.5'/%3E%3C/svg%3E");
}
.data-table.grid-edit-mode th.col-editable[data-edit="date"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
}
.data-table.grid-edit-mode th.col-editable[data-edit="month"]::before {
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4M7.5 15h9'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4M7.5 15h9'/%3E%3C/svg%3E");
}
.data-table.grid-edit-mode td.cell-editable:hover { background: #fff !important; box-shadow: inset 0 0 0 2px var(--primary); }
/* 편집 중인 셀 = 엑셀처럼 "셀이 선택된" 모양. 셀 안에 인풋 UI(보더·배경·라운드)를 그리지 않는다.
   패딩도 일반 셀과 같게 둬서 편집을 시작해도 값이 튀지 않는다. */
.data-table td.cell-editing { overflow: visible; background: #fff !important; box-shadow: inset 0 0 0 2px var(--primary); }
.data-table td.cell-editing::after { content: none; }
.data-table td .cell-editor {
    width: 100%; min-width: 0; height: auto; line-height: inherit;
    border: none !important; background: transparent !important; box-shadow: none !important;
    border-radius: 0; padding: 0; margin: 0; outline: none;
    font: inherit; color: inherit; text-align: inherit;   /* 금액 우측정렬 등 컬럼 정렬을 그대로 따른다 */
}
.data-table td .combobox { width: 100%; }
/* 날짜/년월 = 텍스트 입력(숫자만 쳐도 자동 정형) + 우측 달력 버튼.
   네이티브 date/month 는 로케일 표기(2026년 08월)를 강제해 목록 표기와 어긋나고 타이핑도 느리다.
   달력이 필요할 때만 숨겨둔 네이티브 입력의 피커를 띄운다. */
.data-table td.cell-picker { position: relative; }
.data-table td.cell-picker .cell-editor { padding-right: 20px; }
.cell-picker-src { position: absolute; right: 4px; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; border: 0; padding: 0; }
.cell-cal {
    position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
    width: 18px; height: 18px; padding: 0; border: 0; background: transparent; cursor: pointer;
    color: #64748b; display: inline-flex; align-items: center; justify-content: center;
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
    -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    background-color: currentColor;
}
.cell-cal:hover { color: var(--primary); }
/* 잘못된 날짜 — 셀 강조 + 말풍선 */
.data-table td.cell-invalid { box-shadow: inset 0 0 0 2px var(--danger) !important; }
.cell-error-tip {
    position: fixed; z-index: 300; background: #fff; color: var(--danger);
    border: 1px solid var(--danger); border-radius: 6px; padding: 5px 10px;
    font-size: 12px; font-weight: 600; white-space: nowrap; pointer-events: none;
    opacity: 0; transition: opacity .1s; box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.cell-error-tip.show { opacity: 1; }
/* 셀 안 날짜 입력의 네이티브 달력 버튼 — 나타났다 사라지며 열 너비를 흔든다. 숨기고 JS 가 showPicker() 로 연다 */
.data-table td .cell-editor::-webkit-calendar-picker-indicator { display: none; }
.data-table td .cell-editor::-webkit-inner-spin-button { display: none; }
/* 콤보는 무엇을 고를 수 있는지 알아야 하므로 꺽쇠만 작게 남긴다 */
.data-table td .combobox-input { padding-right: 14px !important; background-size: 9px 6px; background-position: right 0 center; }
/* 편집 중에는 셀 툴팁이 값 위를 덮는다 → 숨김 */
body.cell-editing-open .admin-celltip { display: none !important; }

/* 변경된 칸 / 저장 시 재계산될 파생 칸 */
.data-table td.cell-changed { background: #fef9c3 !important; font-weight: 600; }
.data-table td.cell-stale { color: #94a3b8; font-style: italic; }
.data-table td.cell-stale::before { content: "↻ "; font-style: normal; }

/* 상태 컬럼 — 맨 왼쪽, 수정모드에서만 (§2.15) */
.data-table .col-state { display: none; width: 56px; }
.data-table.grid-edit-mode .col-state { display: table-cell; }

/* 행 상태 — 수정/삭제 표시 (§2.15) */
.data-table tbody tr.row-edited > td { background: #fffbeb; }
.data-table tbody tr.row-edited > td:first-child { box-shadow: inset 3px 0 0 0 #f59e0b; }
.data-table tbody tr.row-removed > td { background: #fef2f2; color: #b91c1c; text-decoration: line-through; opacity: .8; }
.data-table tbody tr.row-removed > td:first-child { box-shadow: inset 3px 0 0 0 var(--danger); text-decoration: none; }
.data-table tbody tr.row-removed > td.col-state, .data-table tbody tr.row-removed > td.col-check { text-decoration: none; }
.row-state {
    display: inline-flex; align-items: center; justify-content: center; gap: 3px;
    padding: 2px 7px; border-radius: 999px; font-size: 10px; font-weight: 700; line-height: 1.6;
    cursor: pointer; text-decoration: none; vertical-align: middle; transition: opacity .12s;
}
.row-state.is-edited { background: #f59e0b; color: #fff; }
/* 삭제 = 휴지통 아이콘 (행 자체는 빨간 표시 유지) */
.row-state.is-removed { background: var(--danger); color: #fff; width: 24px; height: 24px; padding: 0; border-radius: 7px; }
.row-state.is-removed svg { width: 13px; height: 13px; }
.row-state:hover { opacity: .75; }
.seq-num { vertical-align: middle; }

/* ---------- 그리드 도구 그룹 (이 표에 딸린 조작이라는 걸 시각적으로 묶는다) ---------- */
/* 도구 그룹 = 그리드 상단에 맞붙은 "탭" (§2.13 탭 바가 본문과 이어지는 것과 같은 방식).
   상단 모서리만 라운드 + 하단 보더 제거 + 카드와 1px 겹침 → 표에 속한 도구로 읽힌다. */
.grid-toolbar { margin-bottom: 0; align-items: flex-end; }
/* ⚠️ .grid-tools 는 툴바 직속이 아니라 우측 컨테이너 안에 있다.
   우측 컨테이너에 아래 여백을 주면 탭이 통째로 떠서 이음새가 깨진다 → 여백은 개별 요소에만. */
.grid-toolbar > div { align-items: flex-end; }
.grid-toolbar .grid-count { margin-bottom: 10px; }                /* 카드에 붙지 않게 */
.grid-toolbar .grid-actions { margin-bottom: 10px; }              /* 화면 액션(등록 등) */
.grid-tools {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 8px 7px;
    background: #fff;
    border: 1px solid var(--border);
    border-bottom: none;
    border-radius: 10px 10px 0 0;
    margin-bottom: -1px;          /* 카드 상단 보더와 겹쳐 이음새를 지운다 */
    position: relative; z-index: 1;
}
.grid-card { border-top-right-radius: 0 !important; }             /* 탭이 붙는 쪽 모서리를 편다 */
.grid-tools-icon { display: inline-flex; align-items: center; color: #94a3b8; padding: 0 2px; }
.grid-tools-icon svg { width: 15px; height: 15px; }
/* 수정모드 = 탭과 표가 함께 편집 상태임을 알린다 */
/* 수정모드 강조는 은은하게 — 밑줄이 도드라지면 표보다 버튼이 먼저 읽힌다 */
.grid-tools.is-editing { background: #fffbeb; border-color: #fcd34d; }

/* ---------- 범위 선택 · 채우기 (엑셀식, §2.15) ---------- */
.data-table td.cell-sel { background: rgba(17, 24, 39, .07) !important; }
.data-table td.cell-sel-edge { position: relative; box-shadow: inset 0 0 0 2px var(--primary); }
.data-table td.cell-fill { background: rgba(245, 158, 11, .13) !important; outline: 1px dashed #f59e0b; outline-offset: -1px; }
/* 채우기 핸들 = 선택 범위 우하단 작은 사각형(엑셀과 같은 위치) */
.fill-handle {
    position: absolute; right: -4px; bottom: -4px; width: 8px; height: 8px;
    background: var(--primary); border: 1.5px solid #fff; border-radius: 2px;
    cursor: crosshair; z-index: 3;
}
/* 드래그 중엔 텍스트 선택이 따라붙지 않게 */
body.grid-dragging, body.grid-dragging .data-table { user-select: none; -webkit-user-select: none; }
body.grid-dragging { cursor: cell; }

/* 콤보 드롭다운 portal — 셀 overflow 에 잘리지 않게 body 로 띄운 상태 */
.combobox-dropdown-portal { display: block !important; z-index: 1200; }

@media (max-width: 768px) {
    .data-table.grid-edit-mode .col-check, .data-table.grid-edit-mode .col-state { display: flex; justify-content: flex-end; }
    .grid-tools { flex-wrap: wrap; border-bottom: 1px solid var(--border); border-radius: 10px; margin-bottom: 10px; }
    .grid-card { border-top-right-radius: 12px !important; }
    .grid-toolbar .grid-count, .grid-toolbar .grid-actions { margin-bottom: 6px; }
    .data-table td.cell-editing { display: flex; }
    .data-table td .cell-editor { max-width: 60%; }
}

/* ---------- 셀 안 상세 열기(돋보기) — 연결된 다른 화면으로 (§2.13 탭으로 열림) ---------- */
/* ===== 토스트(§1.4) — 가벼운 결과 알림. 다이얼로그와 달리 아무것도 막지 않는다 ===== */
.toast-host {
    position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
    z-index: 300;                                   /* 모달(200) 위 — 모달 안에서 한 조작도 보여야 한다 */
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    pointer-events: none;                           /* 토스트가 없는 자리는 아래 화면을 그대로 쓴다 */
    width: max-content; max-width: min(92vw, 520px);
}
.toast {
    pointer-events: auto; cursor: pointer;
    background: #0f172a; color: #fff;
    border-radius: 10px; padding: 10px 16px;
    font-size: 13px; line-height: 1.5; text-align: center;
    box-shadow: 0 8px 24px rgba(15, 23, 42, .28);
    opacity: 0; transform: translateY(8px);
    transition: opacity .18s ease, transform .18s ease;
}
.toast-in { opacity: 1; transform: translateY(0); }
.toast-out { opacity: 0; transform: translateY(8px); }
.toast-warn { background: #7c2d12; }
.toast-line + .toast-line { color: #cbd5e1; font-size: 12px; }
@media (prefers-reduced-motion: reduce) {
    .toast { transition: none; opacity: 1; transform: none; }
}
@media (max-width: 768px) { .toast-host { bottom: 16px; } }

/* 다른 화면으로 넘어가는 셀 — **셀 전체**가 클릭 대상이다.
   아이콘(16px)만 누를 수 있으면 사실상 못 누른다. 음수 마진으로 td 안쪽 여백까지 덮는다
   (.data-table td 의 padding: 11px 14px 와 짝을 맞춘 값 — 한쪽만 바꾸면 클릭 영역에 틈이 생긴다). */
.cell-goto {
    display: flex; align-items: center; justify-content: center; gap: 5px;
    margin: -11px -14px; padding: 11px 14px;
    text-decoration: none; cursor: pointer;
}
.cell-goto:hover .cell-zoom { background-color: var(--primary); }
.cell-zoom {
    width: 16px; height: 16px; flex-shrink: 0; cursor: pointer; display: inline-block;
    background-color: #94a3b8;
    -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3'/%3E%3C/svg%3E");
    -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.data-table tbody tr.row-clickable:hover .cell-zoom { background-color: #fff; }
.data-table tbody tr.row-clickable:hover .cell-goto:hover .cell-zoom { background-color: #cbd5e1; }

/* ======================================================================
   Tailwind 없이도 성립하게 — 키트 마크업이 쓰는 최소 유틸만 자체 정의한다.
   Tailwind 가 있는 프로젝트에서는 같은 뜻이라 충돌하지 않는다.
   (여기 없는 유틸을 키트 JS 가 쓰기 시작하면 그 순간 Tailwind 의존이 되살아난다)
   ====================================================================== */
.gk-row      { display: flex; align-items: center; gap: 8px; }
.gk-row-wrap { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.gk-col      { display: flex; flex-direction: column; gap: 8px; align-items: stretch; align-self: stretch; flex-shrink: 0; }
.gk-grow     { flex: 1 1 0%; min-height: 0; justify-content: center; }
.gk-push     { margin-left: auto; }
.gk-icon     { width: 1rem; height: 1rem; }
.gk-card     { background: #fff; border: 1px solid var(--border); border-radius: 12px; }

/* 표 정렬·강조 — Tailwind 의 text-*/font-* 와 같은 값 */
.data-table .text-left,   td.text-left,   th.text-left   { text-align: left; }
.data-table .text-center, td.text-center, th.text-center { text-align: center; }
.data-table .text-right,  td.text-right,  th.text-right  { text-align: right; }
.font-medium   { font-weight: 500; }
.font-semibold { font-weight: 600; }
