/* COOPLINK admin console — tokens from docs/design_handoff_cooplink_admin/README.md */
:root {
    --brand: #21A377;
    --brand-strong: #1B8F68;
    --brand-heavy: #167E5B;
    --brand-light: #4CC79A;
    --header: #171719;

    --bg: #F7F7F8;
    --surface: #FFFFFF;
    --thead: #F4F4F5;
    --tray: #EEEEF0;

    /* 표 머리 — 행이 적어 ag-grid 없이 표로 그리는 화면(관리자·메뉴·공지·알림톡·카드·타코·
       월별총계·임금명세서·계산 시트)이 그리드와 같은 머리를 쓰게 한다. 그리드 쪽 값은
       taxi-grid.js 의 headerBackgroundColor 다 — 색을 바꾸면 두 곳을 같이 고친다. */
    --thead-strong: #14503C;
    --thead-strong-ink: rgba(255, 255, 255, 0.86);
    --thead-strong-line: rgba(255, 255, 255, 0.16);
    /* 표 머리 높이 — taxi-grid.js 의 headerHeight 와 한 쌍이다(색과 같은 규칙: 두 곳을 같이 고친다).
       이 여섯 표는 그리드와 한 화면에 같이 놓이므로(카드관리 좌·중 표 + 우 그리드가 그 예다)
       높이가 다르면 같은 머리 띠가 두 단으로 보인다. 머리 글자가 두 줄인 그리드(출근부·월간배차의
       날짜+요일)만 화면에서 headerHeight 를 44 로 올린다 — 글자가 두 줄이라 그런 것이다. */
    --thead-h: 38px;
    /* 행 높이 — taxi-grid.js 의 rowHeight 와 한 쌍이다(머리와 같은 규칙). 화면마다 36·32·30·28·26 으로
       제각각이라 탭을 옮기면 행간이 달라 보였다. 그리드도 화면에서 rowHeight 를 다시 주지 않는다.
       칸이 두 줄인 표(공지 제목+요약, 알림톡 본문)만 내용이 더 키운다 — height 는 최소값이다. */
    --row-h: 30px;

    --label-strong: #000000;
    --label-normal: #171719;
    --label-neutral: rgba(46, 47, 51, 0.88);
    --label-alt: rgba(55, 56, 60, 0.61);
    --label-assistive: rgba(55, 56, 60, 0.28);

    --line-neutral: rgba(112, 115, 124, 0.16);
    --line-normal: rgba(112, 115, 124, 0.22);
    --fill-alt: rgba(112, 115, 124, 0.08);

    --positive-bg: rgba(0, 191, 64, 0.10);
    --positive: #00963C;
    --negative-bg: rgba(255, 66, 66, 0.10);
    --negative: #E02222;
    --caution-bg: rgba(255, 150, 0, 0.14);
    --caution: #C76A00;
    --done-bg: rgba(112, 115, 124, 0.08);
    --done: rgba(55, 56, 60, 0.61);

    --ease: cubic-bezier(0.4, 0, 0.2, 1);

    /* ---- 컴포넌트 시안 A "원장밀도" (docs/mockups/2026-09-26-components.html)
       한 높이 · 반경 4 · 경계는 1px 실선(inset ring 아님) · 그림자는 띄우는 것에만 ·
       브랜드색은 선택된 상태에만. 채운 면은 --brand-heavy(흰 글자 5.04) 부터다 — --brand 는 3.20 이라 못 쓴다. */
    --ctl-h: 32px;
    --ctl-h-sm: 24px;
    --r: 4px;
    --bd: var(--line-normal);
    --bd-hov: rgba(112, 115, 124, 0.38);
    --ring: rgba(22, 126, 91, 0.30);
    --pop: 0 6px 18px rgba(23, 23, 25, 0.16);
    /* --positive(3.87)·--caution(3.83) 은 흰 바탕에서 4.5 를 못 넘긴다 — 글자용 진한 짝 */
    --ok: #0A7A34;
    --warn: #9A5200;
    --bad: #C81E1E;
    --mute: #55565B;
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

/* 표 머리는 띠로 읽힌다 — 그리드(taxi-grid.js 의 wrapperBorderRadius)처럼 위 두 모서리만 둥글다.
   `border-collapse: collapse` 이면 칸의 radius 가 무시되므로 separate + spacing 0 으로 둔다 — 이 표들은
   칸마다 한쪽 변만 그어서 합칠 선이 없어 모양은 그대로다. 이미 둥근 통이 잘라 주는 표(.cap-sched-wrap ·
   .rule-sheet)는 빼 두었다: 두 번 깎으면 모서리에 흰 틈이 보인다. */
:is(.card-table, .pay-table, .slip-table, .income-sheet:not(.cap-sched), .side-panel table) {
    border-collapse: separate;
    border-spacing: 0;
}
:is(.card-table, .pay-table, .slip-table, .income-sheet:not(.cap-sched), .side-panel table) thead tr:first-child > th:first-child {
    border-top-left-radius: 8px;
}
:is(.card-table, .pay-table, .slip-table, .income-sheet:not(.cap-sched), .side-panel table) thead tr:first-child > th:last-child {
    border-top-right-radius: 8px;
}

/* hidden 속성의 기본 display:none 은 UA 규칙이라 .btn·.flash 같은 author 의 display 에 진다.
   화면마다 .x[hidden] 을 다시 적는 대신 여기서 한 번 이긴다. */
[hidden] {
    display: none !important;
}
/* 단 ag-grid 를 품은 hidden 은 크기를 둔 채 감춘다 — 셸 탭 프레임이 visibility:hidden 인 것과 같은 이유다.
   그려진 그리드가 크기 0 이 되면 ag-grid 36 이 높이를 매 프레임 다시 재는 루프(rAF 120/s)에 빠지고 숨은 탭이 돼도 안 멈춘다
   (2026-11-01 실측: 월간배차 기사별 · 카드관리 전월 이월에서 돌아온 뒤). 화면 코드는 hidden 을 그대로 쓰면 된다. */
[hidden]:has(.ag-root-wrapper) {
    display: block !important;
    visibility: hidden;
    position: absolute;
    inset: 0;
    pointer-events: none;
}

body {
    margin: 0;
    min-height: 100vh;
    background: var(--bg);
    color: var(--label-normal);
    font-family: "Pretendard Variable JP", "Pretendard JP", Pretendard, -apple-system,
        "Apple SD Gothic Neo", "Malgun Gothic", sans-serif;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.0096em;
}

a {
    color: var(--brand);
    text-decoration: none;
}

a:hover {
    color: var(--brand-strong);
}

input::placeholder {
    color: var(--label-assistive);
}

/* ---------- app shell ---------- */

.app {
    display: flex;
    flex-direction: column;
    height: 100vh;
    min-width: 900px;
}

.app-header {
    flex: none;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    background: var(--header);
    box-shadow: inset 0 -3px 0 var(--brand);
    z-index: 2;
}

.app-header .brand,
.app-header .account {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.app-header .account {
    gap: 14px;
    flex: none;
}

.app-header img {
    height: 28px;
    flex: none;
}

.app-header .badge-admin {
    flex: none;
    padding: 3px 7px;
    border-radius: 6px;
    background: rgba(76, 199, 154, 0.18);
    color: var(--brand-light);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.app-header .divider {
    width: 1px;
    height: 14px;
    background: rgba(255, 255, 255, 0.2);
    flex: none;
}

.app-header .tagline,
.app-header .who {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.64);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-header .logout {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.64);
    cursor: pointer;
    white-space: nowrap;
    transition: color 120ms var(--ease);
}

.app-header .logout:hover {
    color: #FFFFFF;
}

.app-body {
    display: flex;
    flex: 1;
    min-height: 0;
}

/* ---------- sidebar ---------- */

.app-side {
    --w: 248px;
    width: var(--w);
    flex: none;
    overflow-y: auto;
    padding: 16px 12px 24px;
    background: var(--surface);
    box-shadow: inset -1px 0 0 var(--line-neutral);
    transition: margin-left 200ms var(--ease);
}

/* 접힘: 폭을 줄이면 메뉴 글자가 줄바꿈하며 찌그러지므로 제 폭만큼 왼쪽으로 밀어낸다 */
html.side-collapsed .app-side {
    margin-left: calc(-1 * var(--w));
}

.app-side details {
    margin-bottom: 2px;
}

/* 그룹 없이 최상위에 놓이는 고정 메뉴(대시보드) */
.app-side .home-group {
    margin: 0 0 10px;
    padding-left: 0;
    border-left: 0;
}

.app-side summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 9px 8px 9px 10px;
    border-radius: 8px;
    cursor: pointer;
    list-style: none;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--label-strong);
}

.app-side summary::-webkit-details-marker {
    display: none;
}

.app-side summary:hover {
    background: var(--fill-alt);
}

.app-side summary::after {
    content: "";
    width: 8px;
    height: 8px;
    margin-right: 4px;
    border-right: 1.6px solid var(--label-assistive);
    border-bottom: 1.6px solid var(--label-assistive);
    transform: rotate(-135deg);
    transition: transform 200ms var(--ease);
}

.app-side details[open] summary::after {
    transform: rotate(45deg) translate(-2px, -2px);
}

.app-side .group-items {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin: 2px 0 10px 14px;
    padding-left: 14px;
    border-left: 2px solid var(--line-neutral);
}

.app-side details.has-active .group-items {
    border-left-color: var(--brand);
}

.app-side .group-items a {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 500;
    color: var(--label-alt);
    transition: background 120ms var(--ease);
}

.app-side .group-items a:hover {
    background: var(--fill-alt);
    color: var(--label-alt);
}

.app-side .group-items a.active,
.app-side .group-items a.active:hover {
    background: rgba(33, 163, 119, 0.10);
    color: var(--brand-strong);
    font-weight: 600;
}

/* ---------- main ---------- */

/* 셸: 탭별 iframe 을 겹쳐 쌓고 활성 프레임만 보인다(비활성 탭도 살아 있어 상태가 유지된다)
   비활성은 display:none 이 아니라 visibility:hidden 이다 — 크기가 0 이 되면 고정행(합계 줄)이 있는 ag-grid 가
   행 높이를 매 프레임 다시 재는 루프에 빠진다(36.1 의 pinnedHeightChanged 무조건 발화). 숨은 탭 하나가 초당 rAF 60번이라
   탭·브라우저 창이 늘수록 보는 화면의 클릭이 밀렸다. 크기를 유지하면 숨은 탭 비용이 0 이고, 올라온 탭이 0 을 재는 일도 없다. */
.frame-stack {
    position: relative;
    flex: 1;
    min-height: 0;
}

/* 프레임 요소 배경의 스피너는 새 탭이 첫 화면을 그리기 전까지만 보인다 — 첫 문서가 뜨면 셸이 .loaded 를 달아 뗀다(admin-workspace.js frameFor).
   문서가 덮는다고 멈추지 않는다: SMIL 회전이 뒤에서 계속 돌아 보는 탭을 매 프레임 다시 그렸다(2026-11-01 실측: 가만히 있어도 메인스레드 2.5% → 0).
   이미 뜬 화면 안의 이동·저장은 화면 쪽 딤(.tx-dim)이 맡는다. */
.frame-stack .frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    visibility: hidden;
    background: var(--bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='13' fill='none' stroke='%2370737C' stroke-opacity='.2' stroke-width='3'/%3E%3Cpath d='M16 3a13 13 0 0 1 13 13' fill='none' stroke='%23167E5B' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 16 16' to='360 16 16' dur='.8s' repeatCount='indefinite'/%3E%3C/path%3E%3C/svg%3E") center / 32px no-repeat;
}
.frame-stack .frame.loaded {
    background-image: none;
}

/* 서버와 통신 중(taxi-util.js) — 클릭은 바로 막고 모양은 200ms 뒤에 나타난다. 프레임 안이라 그 화면만 덮는다 */
.tx-dim { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; background: rgba(23, 23, 25, 0.28); cursor: progress; opacity: 0; animation: tx-dim-in 160ms var(--ease) 200ms forwards; }
.tx-dim i { width: 32px; height: 32px; border: 3px solid rgba(255, 255, 255, 0.35); border-top-color: #FFFFFF; border-radius: 50%; animation: tx-spin 0.8s linear infinite; }
@keyframes tx-dim-in { to { opacity: 1; } }
@keyframes tx-spin { to { transform: rotate(360deg); } }

.frame-stack .frame.active {
    visibility: visible;
}

/* 화면(프레임) 페이지: 셸이 없으므로 body 가 곧 스크롤 컨테이너다 */
.frame-page {
    min-height: 100vh;
    background: var(--bg);
}

.frame-body {
    padding: 24px 28px 48px;
}

.crumb {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.032em;
    color: var(--label-assistive);
}

.page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 8px 0 18px;
}

.page-head .titles {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.page-head h1 {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.023em;
    line-height: 1.34;
    color: var(--label-strong);
    white-space: nowrap;
}

.page-head .count {
    font-size: 13px;
    font-weight: 500;
    color: var(--label-alt);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.page-head .actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
}

/* ---------- buttons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: var(--ctl-h);
    padding: 0 12px;
    border: 1px solid var(--brand-heavy);
    border-radius: var(--r);
    background: var(--brand-heavy);
    color: #FFFFFF;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
    transition: background 120ms var(--ease), border-color 120ms var(--ease);
}

.btn:hover {
    background: #10684B;
    border-color: #10684B;
    color: #FFFFFF;
}

.btn:active {
    background: #0C5540;
    border-color: #0C5540;
}

.btn:focus-visible {
    outline: 2px solid var(--brand-heavy);
    outline-offset: 2px;
}

.btn.outlined {
    background: var(--surface);
    border-color: var(--bd);
    color: var(--label-normal);
}

.btn.outlined:hover {
    background: var(--fill-alt);
    border-color: var(--bd-hov);
    color: var(--label-normal);
}

.btn.outlined:active {
    background: var(--tray);
}

/* 취소처럼 되돌리는 동작 — 경계도 면도 없이 글자만 */
.btn.ghost {
    background: transparent;
    border-color: transparent;
    color: var(--label-alt);
    font-weight: 500;
}

.btn.ghost:hover {
    background: var(--fill-alt);
    color: var(--label-normal);
}

.btn.lg {
    height: 40px;
    padding: 0 18px;
    font-size: 14px;
}

.btn.danger {
    background: var(--surface);
    border-color: rgba(200, 30, 30, 0.34);
    color: var(--bad);
    height: var(--ctl-h-sm);
    padding: 0 8px;
    font-size: 12px;
}

.btn.danger:hover {
    background: var(--negative-bg);
    border-color: rgba(200, 30, 30, 0.50);
    color: var(--bad);
}

.btn.sm,
.btn.sm-link {
    height: var(--ctl-h-sm);
    padding: 0 8px;
    font-size: 12px;
}

.btn[disabled],
.btn:disabled {
    background: var(--fill-alt);
    border-color: var(--line-neutral);
    color: var(--label-assistive);
    cursor: not-allowed;
}

/* ---------- cards / fields ---------- */

.card {
    background: var(--surface);
    border: 1px solid var(--line-neutral);
    border-radius: 6px;
    padding: 16px;
}

.card-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--label-normal);
}

.field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.field > span,
.field > label {
    font-size: 13px;
    font-weight: 500;
    color: var(--label-alt);
}

input[type="text"],
input[type="tel"],
input[type="search"],
input[type="password"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="file"],
textarea,
select {
    height: var(--ctl-h);
    max-width: 100%;
    padding: 0 8px;
    border: 1px solid var(--bd);
    outline: 0;
    border-radius: var(--r);
    background: var(--surface);
    font: inherit;
    font-size: 13px;
    color: var(--label-normal);
}

input:hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) {
    border-color: var(--bd-hov);
}

textarea {
    height: auto;
    min-height: 56px;
    padding: 6px 8px;
    line-height: 1.55;
    resize: vertical;
}

/* 포커스는 경계를 브랜드로 바꾸고 바깥에 옅은 링 — inset ring 은 A 언어가 아니다 */
input:focus,
textarea:focus,
select:focus {
    border-color: var(--brand-heavy);
    box-shadow: none;
    outline: 2px solid var(--ring);
    outline-offset: 0;
}

input[readonly] {
    background: var(--fill-alt);
    border-color: var(--line-neutral);
    color: var(--label-neutral);
}

input:disabled,
select:disabled,
textarea:disabled {
    background: var(--fill-alt);
    border-color: var(--line-neutral);
    color: var(--label-assistive);
}

/* 체크·라디오도 브라우저 기본을 쓰지 않는다 — accent-color 로는 크기도 모양도 못 맞춘다 */
input[type="checkbox"],
input[type="radio"] {
    position: relative;
    flex: none;
    width: 16px;
    height: 16px;
    margin: 0;
    padding: 0;
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid var(--line-normal);
    background: var(--surface);
    cursor: pointer;
    transition: background 120ms var(--ease), border-color 120ms var(--ease);
}

input[type="checkbox"] {
    border-radius: 3px;
}

input[type="radio"] {
    border-radius: 50%;
}

input[type="checkbox"]:hover:not(:disabled),
input[type="radio"]:hover:not(:disabled) {
    border-color: rgba(112, 115, 124, 0.42);
}

input[type="checkbox"]:checked {
    background: var(--brand-heavy);
    border-color: var(--brand-heavy);
}

input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    left: 5px;
    top: 2px;
    width: 4px;
    height: 8px;
    border: solid #FFFFFF;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* 일부만 고른 머리 체크박스(JS 의 indeterminate) — 채운 칸에 가로줄 */
input[type="checkbox"]:indeterminate {
    background: var(--brand-heavy);
    border-color: var(--brand-heavy);
}

input[type="checkbox"]:indeterminate::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 6px;
    width: 8px;
    height: 2px;
    background: #FFFFFF;
}

input[type="radio"]:checked {
    border-color: var(--brand-heavy);
}

input[type="radio"]:checked::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 3px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--brand-heavy);
}

input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
    background: var(--fill-alt);
    border-color: var(--line-neutral);
    cursor: not-allowed;
}

/* 표 머리(짙은 띠) 위의 잠긴 체크박스는 ag-grid 머리 체크박스와 같은 모양 — 흰 칸 반투명.
   위의 기본 :disabled(옅은 회색 면)는 짙은 머리에서 거의 안 보여 두 그리드가 달라 보였다 */
th input[type="checkbox"]:disabled {
    background: var(--surface);
    border-color: var(--line-normal);
    opacity: .5;
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: 2px solid var(--brand-heavy);
    outline-offset: 2px;
}

/* ---------- filter bar ---------- */
/* 컨트롤이 한 높이(--ctl-h)라 한 줄에 여섯이 서도 밑선이 어긋나지 않는다 */

.filter-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    background: var(--surface);
    border: 1px solid var(--line-neutral);
    border-radius: var(--r);
    padding: 8px 10px;
    margin-bottom: 10px;
}

.filter-bar .chip {
    display: flex;
    align-items: center;
    gap: 6px;
    height: var(--ctl-h);
    padding: 0 8px;
    border: 1px solid var(--bd);
    border-radius: var(--r);
    font-size: 12.5px;
    color: var(--label-neutral);
    white-space: nowrap;
}

/* 칩이 컨트롤을 감싸기만 하는 자리(원장 날짜칸)는 테두리가 두 겹이 된다 — 바깥을 없앤다 */
.filter-bar .chip:has(> input, > select) {
    height: auto;
    padding: 0;
    border: 0;
}

.filter-bar .chip > span {
    color: var(--label-assistive);
}

.filter-bar input[type="date"],
.filter-bar input[type="month"],
.filter-bar input[type="search"],
.filter-bar input[type="file"],
.filter-bar select {
    height: var(--ctl-h);
    font-size: 13px;
}

.filter-bar input[type="date"] {
    width: 130px;
}

.filter-bar input[type="month"] {
    width: 120px;
}

.filter-bar .search {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--ctl-h);
    flex: 0 1 280px;
    max-width: 280px;
    padding: 0 8px;
    border: 1px solid var(--bd);
    border-radius: var(--r);
    background: var(--surface);
}

.filter-bar .search:hover {
    border-color: var(--bd-hov);
}

.filter-bar .search:focus-within {
    border-color: var(--brand-heavy);
    outline: 2px solid var(--ring);
}

.filter-bar .search input {
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: 0;
    outline: 0;
    background: transparent;
}

.filter-bar .search input:hover,
.filter-bar .search input:focus {
    border: 0;
    outline: 0;
}

.filter-bar .spacer {
    flex: 1;
}

/* ---------- badges / flash ---------- */

.badge {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 6px;
    border-radius: 3px;
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
    background: var(--done-bg);
    color: var(--mute);
}

.badge.positive {
    background: var(--positive-bg);
    color: var(--ok);
}

.badge.caution {
    background: var(--caution-bg);
    color: var(--warn);
}

.badge.negative {
    background: var(--negative-bg);
    color: var(--bad);
}

/* 알림줄은 왼쪽 세로 막대로 좋고 나쁨을 알린다 — 면을 채우면 원장 위에서 너무 큰 소리가 된다 */
.flash {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    margin-bottom: 10px;
    border: 1px solid rgba(0, 191, 64, 0.34);
    border-left: 3px solid var(--ok);
    border-radius: var(--r);
    font-size: 12.5px;
    color: var(--label-normal);
    background: var(--positive-bg);
    box-shadow: none;
}

.flash.bad {
    background: var(--negative-bg);
    border-color: rgba(200, 30, 30, 0.34);
    border-left-color: var(--bad);
    box-shadow: none;
}

.flash.caution {
    background: var(--caution-bg);
    border-color: rgba(255, 150, 0, 0.40);
    border-left-color: var(--warn);
    box-shadow: none;
}

.flash::before {
    content: "";
    width: 5px;
    height: 5px;
    flex: none;
    border-radius: 99px;
    background: currentColor;
    color: var(--ok);
}

.flash.bad::before {
    color: var(--bad);
}

.flash.caution::before {
    color: var(--warn);
}

/* ---------- grid ---------- */

/* 좌우 두 그리드(공통코드관리) — 좌측에서 고른 그룹이 우측 목록을 좁힌다. */
.split-grids {
    display: grid;
    grid-template-columns: 380px 1fr;
    gap: 12px;
    align-items: start;
}

@media (max-width: 1100px) {
    .split-grids {
        grid-template-columns: 1fr;
    }
}

.split-grids .pane-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
}

.split-grids .pane-head h2 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--label-normal);
}

.split-grids .sub {
    font-size: 12px;
    color: var(--label-alt);
}

.admin-grid .ag-row.row-picked {
    box-shadow: inset 3px 0 0 var(--brand);
}

/* 그리드에서 바로 고치는 화면(공통코드관리) — 아직 저장하지 않은 변경을 눈에 보이게 한다.
   저장하면 화면이 다시 그려지므로 이 표시는 미저장 상태에서만 남는다. */
.admin-grid .ag-row.row-new {
    background: var(--positive-bg);
}

.admin-grid .ag-row.row-deleted {
    background: var(--done-bg);
}

.admin-grid .ag-row.row-deleted .ag-cell {
    color: var(--done);
    text-decoration: line-through;
}

.admin-grid .ag-row.row-deleted .btn {
    text-decoration: none;
}

.admin-grid .ag-cell.cell-dirty {
    background: var(--caution-bg);
    box-shadow: inset 2px 0 0 var(--caution);
}

.grid-legend {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 0 0 0 auto;
    font-size: 12px;
    color: var(--label-alt);
}

.grid-legend .dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-right: 5px;
    border-radius: 3px;
    vertical-align: -1px;
}

.grid-legend .dot.new {
    background: var(--positive);
}

.grid-legend .dot.edited {
    background: var(--caution);
}

.grid-legend .dot.deleted {
    background: var(--done);
}

.grid-legend .dot.neg {
    background: var(--negative);
}

.admin-grid {
    width: 100%;
    border-radius: 12px;
    overflow: hidden;
    background: var(--surface);
    box-shadow: inset 0 0 0 1px var(--line-neutral);
}

/* 시안 "B 원장" — docs/mockups/2026-09-25-grid-design.html. 머리 색·행 높이는 테마
   한 덩어리(taxi-grid.js)가 정하고, 여기는 그 머리 위에서 읽혀야 하는 것들이다. */

/* 자릿수가 세로로 맞아야 금액이 눈으로 비교된다 */
.admin-grid .ag-cell {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* 고정열은 떠 있고 숫자가 그 밑을 흐른다 */
.admin-grid .ag-pinned-left-header {
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.22);
}

.admin-grid .ag-pinned-left-cols-container {
    box-shadow: 1px 0 0 rgba(112, 115, 124, 0.3);
}

/* 묶음이 시작하는 열에만 세로선 — 컬럼 전체에 그으면 32칸이 창살이 된다.
   colDef 의 headerClass·cellClass 로 붙인다(수입금 원장 income-daily.js). */
.admin-grid .ag-cell.col-edge {
    box-shadow: inset 1px 0 0 rgba(112, 115, 124, 0.28);
}

.admin-grid .ag-header-cell.col-edge {
    box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.22);
}

/* 차량 한 대가 두 줄인 그리드(원장 주·야, 월간배차·고정기사 1부·2부)는
   묶음 끝에만 진한 선을 둔다 — 행 사이가 옅어야 두 줄이 한 덩어리로 읽힌다.
   .row-night 는 세 화면이 이미 붙이고 있다(income-daily · dispatch-month · dispatch-drivers). */
.admin-grid .ag-row.row-night {
    border-bottom-color: rgba(112, 115, 124, 0.34);
}

.grid-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 100%;
}

.grid-actions form {
    margin: 0;
}

/* ---------- dashboard ---------- */
/* 시안 두 벌(A 경영 요약 · B 마감 보드)이 같은 조각을 쓴다 — home.jsp + fragments/dash-a.jsp · dash-b.jsp.
   패널은 .card, 제목은 .card-title, 버튼은 .btn, 칩은 .badge 를 그대로 쓰고 여기서는 크기만 맞춘다.
   tone 은 넷(ok · warn · bad · idle)이고 색은 클래스가 입힌다 — 글자는 --ok/--warn/--bad/--mute, 옅은 면과 점은 아래 변수다.
   인라인 style 은 데이터가 정하는 치수(막대 높이·폭 %, 스파크라인 점)뿐이다. */

.dash { display: flex; flex-direction: column; gap: 16px; font-variant-numeric: tabular-nums;
    --dash-axis: #C9CACD; --dash-bar: #8FCDB6; --dash-prev: #8E8F94; --dash-track: #CDEBDD; }

.dash .tone-ok   { color: var(--ok);   --tone-bg: #E5F8EB; --tone-dot: var(--ok); }
.dash .tone-warn { color: var(--warn); --tone-bg: #FFF0DB; --tone-dot: #E08A00; }
.dash .tone-bad  { color: var(--bad);  --tone-bg: #FFECEC; --tone-dot: var(--bad); }
.dash .tone-idle { color: var(--mute); --tone-bg: #F1F1F2; --tone-dot: var(--dash-axis); }
.dash .tone-info { color: #0058D6; --tone-bg: #E9F1FF; }
.dash .badge { background: var(--tone-bg, var(--done-bg)); font-weight: 700; }
.dash .btn { height: 28px; padding: 0 10px; font-size: 12.5px; }
.dash-ink { color: var(--label-normal); }
.dash-sp { flex: 1; }
.dash-note { font-size: 12px; color: var(--mute); }

/* 머리 — 날짜 · 조합 · 권한 줄 + 시안별 제목, 오른쪽에 바로가기(B) / 시안 선택(본사만) */
.dash-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 24px; }
.dash-head-main { min-width: 0; }
.dash-meta { font-size: 12.5px; color: var(--mute); }
.dash-meta span + span::before { content: " · "; }
.dash-head h1 { margin: 4px 0 0; font-size: 24px; font-weight: 700; line-height: 1.36; letter-spacing: -0.02em; color: var(--label-strong); }
.dash-head-side { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; font-size: 12.5px; color: var(--mute); }
.dash-head .btn { height: 30px; padding: 0 12px; }
/* 시안 선택 + 기준일(로컬 전용). .filter-bar 는 날짜 칸의 Enter 조회 표식으로만 붙였다 — 그 상자 모양(면·테두리·여백)은 지운다 */
.dash-view { margin: 0; padding: 0; border: 0; background: none; }
.dash-view :is(select, input[type="date"]) { height: 30px; font-size: 12.5px; font-weight: 600; }

/* 얇은 진행 막대 — 출자금 납입률(A). 폭 % 는 인라인 */
.dash-track { flex: 1; height: 8px; border-radius: 4px; background: var(--dash-track); overflow: hidden; }
.dash-track i { display: block; width: 0; height: 100%; background: var(--brand-heavy); }

/* 패널 — .card 위에 얹는다. 기본은 머리·줄이 테두리까지 닿고(.pad 만 안쪽 여백), 아래 목록 셋은 꼬리줄이 바닥에 붙는다 */
.dash-row { display: flex; flex-wrap: wrap; align-items: stretch; gap: 12px; }
.dash-panel { min-width: 0; padding: 0; overflow: hidden; }
.dash-panel.pad { padding: 14px 16px; }
.dash-ph { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 12px 16px; }
.dash-panel.pad > .dash-ph { padding: 0; }
.dash-empty { margin: 0; padding: 14px 16px; border-top: 1px solid var(--line-neutral); font-size: 12.5px; color: var(--mute); }
.dash-panel.pad > .dash-empty { padding: 12px 0 0; border-top: 0; }
.dash-foot { margin-top: auto; padding: 10px 14px; background: var(--thead); font-size: 12px; color: var(--mute); }
.dash-foot-line { margin: auto 0 0; padding-top: 10px; border-top: 1px solid var(--line-neutral); font-size: 12px; color: var(--mute); }
.dash-legend { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--mute); }
.dash-legend i { flex: none; width: 10px; height: 10px; border-radius: 2px; background: var(--dash-bar); }
.dash-legend i.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--tone-dot); }
.dash-legend i.line { width: 12px; height: 2px; border-radius: 0; background: var(--label-normal); }
.dash-legend i.cur { background: var(--brand-heavy); }
.dash-legend i.prev { background: var(--dash-prev); }

/* 지표 타일 — 한 줄 띠(230px 부터 접힌다). 스파크라인은 B 가 최근 14일, A 가 최근 6개월 */
.dash-tiles { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-tile { flex: 1 1 230px; min-width: 0; padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.dash-tile .l { font-size: 12.5px; color: var(--mute); }
.dash-tile .d { font-size: 12px; color: var(--mute); }
.dash-tile .vr { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
.dash-tile .v { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: normal; color: var(--label-strong); white-space: nowrap; }
.dash-spark { position: relative; flex: 0 1 88px; min-width: 40px; height: 26px; margin-right: 5px; }
.dash-spark svg { display: block; width: 100%; height: 100%; overflow: visible; }
.dash-spark polyline { fill: none; stroke: var(--dash-prev); stroke-width: 1.5px; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.dash-spark i { position: absolute; left: 100%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: var(--brand-heavy); box-shadow: 0 0 0 2px var(--surface); }

/* 막대 차트 — pct 100 이 --scale 높이다(그 위 --head 는 막대 위 값 글자 자리). 월별(A, .months) · 요일별(B, .tall) 이 같이 쓴다 */
.dash-chart { --scale: 120px; --head: 12px; display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 4px 6px; margin: 14px 0 10px; }
.dash-chart.tall { --scale: 160px; --head: 16px; margin-top: 16px; }
.dash-axis { position: relative; height: calc(var(--scale) + var(--head)); font-size: 10.5px; color: var(--mute); }
.dash-axis span { position: absolute; right: 0; bottom: -6px; white-space: nowrap; }
.dash-axis .top { bottom: calc(var(--scale) - 7px); }
.dash-axis .mid { bottom: calc(var(--scale) / 2 - 7px); }
.dash-plot { position: relative; height: calc(var(--scale) + var(--head)); border-bottom: 1px solid var(--dash-axis); }
.dash-plot::before, .dash-plot::after { content: ""; position: absolute; left: 0; right: 0; bottom: var(--scale); border-top: 1px solid var(--line-neutral); }
.dash-plot::after { bottom: calc(var(--scale) / 2); }
.dash-bars { position: absolute; left: 0; right: 0; bottom: 0; height: var(--scale); display: flex; align-items: flex-end; gap: 2px; }
.dash-bars > div { position: relative; flex: 1; min-width: 0; height: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.dash-bars i { flex: none; width: 100%; max-width: 22px; border-radius: 4px 4px 0 0; background: var(--dash-bar); }
.dash-bars b { position: absolute; left: 50%; font-size: 11px; font-weight: 700; white-space: nowrap; transform: translateX(-50%); }
.dash-chart.tall .dash-bars { gap: 0; }
.dash-chart.tall .dash-bars i { width: 14px; background: var(--brand-heavy); }
.dash-chart.tall .dash-bars i + i { background: var(--dash-prev); }
.dash-x { display: flex; gap: 2px; font-size: 10.5px; color: var(--mute); }
.dash-x span { flex: 1; min-width: 0; text-align: center; white-space: nowrap; }
.dash-x b { display: block; font-size: 10.5px; font-weight: 600; }
.dash-chart.tall .dash-x { gap: 0; font-size: 11.5px; }

/* 목록 넷(일자별 마감 · 오늘 미배차 · 카드 확인 필요 · 미입금 잔액)은 그리드다(dashboard.js) — 패널이 이미 카드라 그리드 테두리는 뗀다.
   .go 는 칸 전체가 링크다: a::after 가 칸을 덮는다(ag-cell 이 position:absolute 라 그 상자다) */
.dash-grid { border-radius: 0; box-shadow: none; border-top: 1px solid var(--line-neutral); }
.dash-grid .k { font-weight: 600; }
.dash-grid .m { color: var(--mute); }
.dash-grid .c { text-align: center; }
.dash-grid .ag-row.today { background: #F2FAF6; }
.dash-grid .ag-cell.go:hover { background: var(--fill-alt); }
.dash-grid .ag-cell.go a { display: inline-flex; align-items: center; gap: 6px; }
.dash-grid .ag-cell.go a::after { content: ""; position: absolute; inset: 0; }
.dash-grid .ag-cell.go a:focus-visible { outline: 0; }
.dash-grid .ag-cell.go a:focus-visible::after { outline: 2px solid var(--brand-heavy); outline-offset: -2px; }
.dash-grid .ag-cell.go a:is(.tone-warn, .tone-bad) { font-weight: 700; }
.dash-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--tone-dot); }
.dash-grid .ag-row-pinned { background: var(--thead); font-weight: 600; }
.dash-grid .ag-row-pinned .note { font-size: 12px; font-weight: 500; color: var(--mute); }

/* B — 일자별 마감(넓다: 좁은 프레임에서는 자기 상자 안에서 가로 스크롤) + 요일별 평균, 아래 목록 셋 */
.dash-board { flex: 1.8 1 900px; }
.dash-weekday { flex: 1 1 420px; display: flex; flex-direction: column; }
.dash-list { flex: 1 1 380px; display: flex; flex-direction: column; }
.dash-list.wide { flex: 1.5 1 520px; }
.dash-list > .dash-ph { gap: 8px; padding: 10px 14px; }
.dash-list > .dash-empty { padding: 12px 14px; }
.dash-buckets { padding: 2px 14px 10px; }
.dash-stack { display: flex; gap: 2px; height: 14px; border-radius: 3px; overflow: hidden; }
.dash-legends { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 6px; }
.dash i.s0 { background: #E58C8C; }
.dash i.s1 { background: #D04A4A; }
.dash i.s2 { background: #A81212; }

/* A — 대표의 경영 요약: 월별 막대 | 7일 평균 흐름, 그 아래 확인할 것 | 조합 현황 */
.dash-half { flex: 1 1 520px; display: flex; flex-direction: column; }
.dash-chart.months { --scale: 150px; --head: 18px; margin-top: 18px; }
.dash-chart.months .dash-bars { gap: 0; }
.dash-chart.months .dash-bars i { width: 24px; max-width: none; }
.dash-bars .cur i { background: var(--brand-heavy); }
.dash-bars .now i { background: var(--dash-track); }
.dash-chart.months .dash-x { gap: 0; font-size: 11.5px; font-weight: 600; color: var(--label-normal); }
.dash-chart.months .dash-x b { font-weight: 500; color: var(--mute); }
/* 흐름 — 선 두 줄. 점·끝 라벨의 자리(left·top %)는 인라인이고 오른쪽 76px 칸이 끝 라벨 자리다 */
.dash-flow { display: grid; grid-template-columns: 44px minmax(0, 1fr) 76px; gap: 4px 6px; margin: 18px 0 10px; }
.dash-flow-axis { position: relative; height: 164px; font-size: 10.5px; color: var(--mute); }
.dash-flow-axis span { position: absolute; right: 0; white-space: nowrap; transform: translateY(-50%); }
.dash-flow-plot { position: relative; height: 164px; border-bottom: 1px solid var(--line-neutral);
    background: linear-gradient(var(--line-neutral), var(--line-neutral)) 0 25% / 100% 1px no-repeat,
                linear-gradient(var(--line-neutral), var(--line-neutral)) 0 50% / 100% 1px no-repeat,
                linear-gradient(var(--line-neutral), var(--line-neutral)) 0 75% / 100% 1px no-repeat; }
.dash-flow-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.dash-flow-plot polyline { fill: none; stroke: var(--dash-prev); stroke-width: 2px; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.dash-flow-plot polyline.cur { stroke: var(--brand-heavy); }
.dash-flow-plot i { position: absolute; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: var(--dash-prev); box-shadow: 0 0 0 2px var(--surface); }
.dash-flow-plot i.cur { background: var(--brand-heavy); }
.dash-flow-plot b { position: absolute; left: 100%; margin-left: 10px; font-size: 11.5px; font-weight: 700; white-space: nowrap; transform: translateY(-50%); }
.dash-flow-x { position: relative; height: 16px; font-size: 10.5px; color: var(--mute); }
.dash-flow-x span { position: absolute; white-space: nowrap; transform: translateX(-50%); }
.dash-flow-x span:first-child { transform: none; }
.dash-checks { flex: 1.5 1 620px; }
.dash-check { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 50px; padding: 7px 16px; border-top: 1px solid var(--line-neutral); }
.dash-check .badge { flex: none; justify-content: center; min-width: 40px; height: 22px; padding: 0 8px; font-size: 12px; }
.dash-check .b { flex: 1 1 320px; min-width: 0; }
.dash-check .t { font-weight: 600; }
.dash-check .d { margin-top: 1px; font-size: 12.5px; color: var(--mute); }
.dash-check .dash-go { flex: none; width: 104px; padding: 0 8px; }
.dash-coop { flex: 1 1 420px; display: flex; flex-direction: column; gap: 12px; }
.dash-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.dash-kv .l { font-size: 12.5px; color: var(--mute); }
.dash-kv .v { margin-top: 2px; font-size: 20px; font-weight: 700; font-variant-numeric: normal; color: var(--label-strong); }
.dash-kv .d { font-size: 12px; color: var(--mute); }
.dash-sub { padding-top: 12px; border-top: 1px solid var(--line-neutral); }
.dash-sub .dash-note { margin-top: 4px; }
.dash-line { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 8px; margin-bottom: 6px; font-size: 12.5px; color: var(--mute); }
.dash-steps { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 6px; margin-top: 8px; font-size: 12px; }
.dash-step i { display: block; height: 4px; margin-bottom: 6px; border-radius: 2px; background: var(--tone-dot); }
.dash-step.tone-ok i { background: var(--brand-heavy); }
.dash-step.tone-idle i { background: var(--line-normal); }
.dash-step b { display: block; font-weight: 600; color: var(--label-normal); }
.dash-step.tone-idle b { font-weight: 500; color: var(--mute); }
.dash-step:is(.tone-warn, .tone-bad) span { font-weight: 600; }

/* ---------- 옛 대시보드(home-legacy.jsp) ----------
   새 대시보드는 아직 로컬에서만 연다 — 개발서버·운영은 이 화면을 본다(AdminHomeController.dashboardOpen).
   새 화면을 공개하면 home-legacy.jsp 와 이 절을 같이 지운다. 뿌리만 .dash → .dash-legacy 로 바꿨다(새 화면의 .dash 와 겹친다). */
.dash-legacy {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.dash-hello {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    padding: 8px 0 4px;
}

.dash-hello h1 {
    margin: 0 0 6px;
    font-size: 28px;
    font-weight: 700;
    line-height: 1.36;
    letter-spacing: -0.024em;
    color: var(--label-strong);
}

.dash-hello p {
    margin: 0;
    font-size: 15px;
    line-height: 1.47;
    color: var(--label-alt);
}

.dash-hello .today {
    font-size: 13px;
    font-weight: 500;
    color: var(--label-assistive);
    padding-bottom: 4px;
    white-space: nowrap;
}

.stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
}

.stat {
    display: flex;
    flex-direction: column;
    padding: 22px 22px 20px;
}

.stat .label {
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.0194em;
    color: var(--label-alt);
}

.stat .value {
    margin-top: 8px;
    font-size: 28px;
    font-weight: 700;
    line-height: 1.36;
    letter-spacing: -0.024em;
    color: var(--label-strong);
    font-variant-numeric: tabular-nums;
}

.stat .sub {
    margin-top: 5px;
    font-size: 12px;
    font-weight: 600;
    color: var(--label-assistive);
}

.stat .sub.positive {
    color: var(--positive);
}

.stat .sub.caution {
    color: var(--caution);
}

.dash-cols {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 12px;
}

.bars {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.bars .bar {
    display: flex;
    align-items: center;
    gap: 10px;
}

.bars .bar .day {
    width: 44px;
    flex: none;
    font-size: 12px;
    color: var(--label-alt);
}

.bars .bar .track {
    flex: 1;
    height: 8px;
    border-radius: 99px;
    background: var(--fill-alt);
    overflow: hidden;
}

.bars .bar .fill {
    height: 100%;
    border-radius: 99px;
    background: var(--brand);
    transition: width 320ms var(--ease);
}

.bars .bar .amount {
    width: 96px;
    flex: none;
    text-align: right;
    font-size: 12px;
    font-weight: 600;
    color: var(--label-neutral);
    font-variant-numeric: tabular-nums;
}

.feed .row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 0;
}

.feed .row .name {
    font-size: 14px;
    font-weight: 500;
    color: var(--label-normal);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.feed .row .meta {
    font-size: 12px;
    color: var(--label-alt);
}

.feed .empty {
    font-size: 13px;
    color: var(--label-assistive);
    padding: 9px 0;
}

.quick {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.quick a {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 14px;
    border-radius: 10px;
    background: var(--surface);
    box-shadow: inset 0 0 0 1px var(--line-normal);
    font-size: 14px;
    font-weight: 500;
    color: var(--label-neutral);
}

.quick a:hover {
    background: var(--fill-alt);
    color: var(--label-neutral);
}

.quick a::after {
    content: "";
    width: 6px;
    height: 6px;
    border-right: 1.6px solid var(--label-assistive);
    border-top: 1.6px solid var(--label-assistive);
    transform: rotate(45deg);
}

/* .card-head 는 옛 대시보드(home-legacy.jsp)가 쓴다 */
.card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 14px;
}

.card-head a {
    font-size: 13px;
    font-weight: 500;
    color: var(--label-alt);
}

.card-head a:hover {
    color: var(--label-normal);
}

/* ---------- login ---------- */

.login-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: var(--surface);
    padding: 24px;
}

.login-card {
    display: flex;
    width: 880px;
    max-width: 100%;
    border-radius: 24px;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 20px 56px rgba(0, 0, 0, 0.14),
        inset 0 0 0 1px var(--line-neutral);
}

.login-card .pitch {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 32px;
    padding: 44px 40px;
    background: var(--brand);
}

.login-card .pitch img {
    height: 44px;
    align-self: flex-start;
}

.login-card .pitch h1 {
    margin: 0 0 12px;
    font-size: 28px;
    font-weight: 700;
    line-height: 1.36;
    letter-spacing: -0.024em;
    color: #FFFFFF;
}

.login-card .pitch p {
    margin: 0;
    font-size: 14px;
    line-height: 1.57;
    color: rgba(255, 255, 255, 0.72);
}

.login-card .pitch .org {
    font-size: 12px;
    color: rgba(255, 255, 255, 0.56);
}

.login-card .form {
    flex: 1.15;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 22px;
    padding: 44px;
    background: var(--surface);
}

.login-card .form h2 {
    margin: 0 0 5px;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.023em;
    color: var(--label-strong);
}

.login-card .form .lead {
    margin: 0;
    font-size: 14px;
    color: var(--label-alt);
}

.login-card form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.login-card form input[type="text"],
.login-card form input[type="password"] {
    height: 48px;
}

.login-card .remember-row {
    display: flex;
    gap: 20px;
}

.login-card .remember {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
    font-size: 14px;
    color: var(--label-neutral);
}

.login-card .submit {
    height: 48px;
    border-radius: 12px;
    font-size: 16px;
}

.login-card .links {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    font-size: 13px;
    color: var(--label-alt);
}

.login-card .links .divider {
    width: 1px;
    height: 12px;
    background: var(--line-normal);
}

.login-foot {
    margin-top: 20px;
    font-size: 12px;
    color: var(--label-assistive);
}

.login-error {
    border-radius: 12px;
    padding: 12px 14px;
    font-size: 13px;
    color: var(--negative);
    background: var(--negative-bg);
}

/* ---------- form page ---------- */

.form-card {
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-width: 720px;
}

.form-card .foot {
    display: flex;
    gap: 8px;
    padding-top: 14px;
    box-shadow: inset 0 1px 0 var(--line-neutral);
}

.form-card .foot .btn {
    width: 140px;
    height: 40px;
}

/* ---------- 상세 슬라이드 패널 ---------- */

.detail-dim {
    position: fixed;
    inset: 0;
    z-index: 20;
    background: rgba(23, 23, 25, 0.52);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms cubic-bezier(0, 0, 0.2, 1);
}

.detail-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 460px;
    max-width: 100vw;
    z-index: 21;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.24);
    transform: translateX(105%);
    transition: transform 240ms cubic-bezier(0, 0, 0.2, 1);
}

.detail-open .detail-dim {
    opacity: 1;
    pointer-events: auto;
}

.detail-open .detail-panel {
    transform: translateX(0);
}

.detail-panel .panel-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 18px 24px 16px;
    background: var(--brand);
}

.detail-panel .panel-head .crumb {
    display: block;
    color: rgba(255, 255, 255, 0.64);
}

.detail-panel .panel-head h2 {
    margin: 3px 0 0;
    font-size: 20px;
    font-weight: 600;
    letter-spacing: -0.012em;
    color: #FFFFFF;
    white-space: nowrap;
}

.detail-panel .panel-close {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: rgba(255, 255, 255, 0.8);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    transition: background 120ms var(--ease);
}

.detail-panel .panel-close:hover {
    background: rgba(255, 255, 255, 0.16);
}

.detail-panel .panel-body {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 20px 24px 24px;
}

/* 항목이 많은 상세(월정산)는 2단. 대분류(가.~사.) 합계는 한 줄을 다 쓰고 색으로 강조한다. */
.detail-panel .panel-body.two-col,
.detail-panel .panel-section .section-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px 16px;
    align-items: end;
}

.detail-panel .panel-body.two-col > .panel-section,
.detail-panel .panel-body.two-col > .panel-hint,
.detail-panel .panel-body.two-col > .field-top,
.detail-panel .section-body > .field-top {
    grid-column: 1 / -1;
}

.detail-panel .panel-body .field-top {
    background: rgba(33, 163, 119, 0.08);
    border-left: 3px solid var(--brand);
    border-radius: 8px;
    padding: 10px 12px;
}

.detail-panel .panel-body .field-top > span {
    color: var(--brand-heavy);
    font-size: 14px;
    font-weight: 700;
}

/* 접기 그룹 — <details>/<summary> 라 여닫는 스크립트가 없다 */
.detail-panel .panel-section {
    border: 1px solid var(--line-neutral);
    border-radius: 12px;
    background: var(--surface);
}

.detail-panel .panel-section > summary {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 12px;
    cursor: pointer;
    list-style: none;
    color: var(--brand-heavy);
    font-size: 15px;
    font-weight: 700;
}

.detail-panel .panel-section > summary::-webkit-details-marker {
    display: none;
}

.detail-panel .panel-section > summary::before {
    content: "";
    width: 7px;
    height: 7px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(-45deg);
    transition: transform 0.15s var(--ease);
}

.detail-panel .panel-section[open] > summary::before {
    transform: rotate(45deg);
}

.detail-panel .panel-section > summary:hover {
    background: var(--fill-alt);
}

.detail-panel .panel-section .section-sum {
    margin-left: auto;
    color: var(--label-normal);
    font-variant-numeric: tabular-nums;
}

.detail-panel .panel-section .section-body {
    padding: 4px 14px 16px;
}

/* 패널은 항목이 세로로 길게 쌓이므로 폼(44px)보다 낮게 — 한 화면에 더 많은 칸이 보인다 */
.detail-panel .panel-body input,
.detail-panel .panel-body textarea,
.detail-panel .panel-body select {
    height: 34px;
    padding: 0 10px;
    font-size: 14px;
}

.detail-panel .panel-body textarea {
    height: auto;
}

.detail-panel .panel-body input:disabled,
.detail-panel .panel-body textarea:disabled,
.detail-panel .panel-body select:disabled,
.detail-panel .panel-body input[readonly] {
    background-color: var(--fill-alt);   /* background 단축이면 셀렉트 화살표(아래 전역 규칙)가 지워진다 */
    color: var(--label-neutral);
    -webkit-text-fill-color: var(--label-neutral);
    opacity: 1;
}

.detail-panel .panel-hint {
    font-size: 12px;
    color: var(--label-assistive);
}

.detail-panel .panel-foot {
    display: flex;
    justify-content: center;
    gap: 8px;
    flex: none;
    padding: 14px 24px 20px;
    box-shadow: inset 0 1px 0 var(--line-neutral);
}

.detail-panel .panel-foot .btn {
    width: 140px;
    height: 40px;
    flex: none;
}

/* ---------- 탭 바 ---------- */

.app-content {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

/* 사이드바 토글 — 탭바 왼쪽 끝, 경계선 바로 옆의 둥근 셰브론(‹ / 접히면 ›).
   경계선에 걸치지 않고 본문 쪽에만 있어 열리든 접히든 자리가 같다(탭바 왼쪽 여백이 그 자리다) */
.side-toggle {
    position: absolute;
    top: 11px;
    left: 4px;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--line-normal);
    border-radius: 50%;
    background: var(--surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    color: var(--label-alt);
    cursor: pointer;
    transition: color 120ms var(--ease), border-color 120ms var(--ease);
}

.side-toggle::before {
    content: "";
    width: 7px;
    height: 7px;
    border-left: 1.6px solid currentColor;
    border-bottom: 1.6px solid currentColor;
    transform: translateX(2px) rotate(45deg);
    transition: transform 200ms var(--ease);
}

.side-toggle:hover {
    border-color: var(--brand);
    color: var(--brand);
}

.side-toggle:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

html.side-collapsed .side-toggle::before {
    transform: translateX(-2px) rotate(-135deg);
}

.tab-bar {
    display: flex;
    align-items: flex-end;
    flex: none;
    gap: 4px;
    height: 46px;
    padding: 8px 12px 0 36px;   /* 왼쪽 여백은 사이드바 토글 자리(4px + 24px + 8px) */
    background: var(--tray, #EEEEF0);
    box-shadow: inset 0 -2px 0 var(--brand);
    overflow-x: auto;
}

/* 셸의 한 줄 알림 — 탭 상한으로 탭이 저절로 닫힌 것처럼 "사용자가 안 한 일"을 설명한다.
   셸은 프레임 밖이라 position:fixed 가 화면 기준으로 뜬다(프레임 안이면 프레임 박스에 갇힌다). */
.admin-note {
    position: fixed;
    left: 50%;
    bottom: 24px;
    z-index: 60;
    transform: translate(-50%, 8px);
    padding: 10px 16px;
    border-radius: 10px;
    background: rgba(23, 23, 25, 0.92);
    color: #fff;
    font-size: 13px;
    font-weight: 500;
    box-shadow: 0 8px 24px rgba(23, 23, 25, 0.22);
    opacity: 0;
    pointer-events: none;
    transition: opacity .16s var(--ease), transform .16s var(--ease);
}

.admin-note.on {
    opacity: 1;
    transform: translate(-50%, 0);
}

.tab-bar:empty {
    display: none;
}

.tab-bar .tab {
    display: flex;
    align-items: center;
    gap: 7px;
    height: 38px;
    padding: 0 14px;
    border-radius: 8px 8px 0 0;
    background: transparent;
    color: var(--label-alt);
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    transition: background 120ms var(--ease), color 120ms var(--ease);
}

.tab-bar .tab:hover {
    background: rgba(112, 115, 124, 0.08);
    color: var(--label-alt);
}

.tab-bar .tab.active,
.tab-bar .tab.active:hover {
    background: var(--brand);
    color: #FFFFFF;
    font-weight: 600;
}

.tab-bar .tab .pin {
    width: 12px;
    height: 12px;
    flex: none;
    border-radius: 50% 50% 50% 0;
    background: currentColor;
    opacity: 0.55;
}

.tab-bar .tab.active .pin {
    opacity: 0.9;
}

.tab-bar .tab-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex: none;
    border: 0;
    border-radius: 5px;
    background: transparent;
    color: var(--label-assistive);
    font: inherit;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}

.tab-bar .tab.active .tab-close {
    color: rgba(255, 255, 255, 0.72);
}

.tab-bar .tab-close:hover {
    background: rgba(112, 115, 124, 0.08);
}

.tab-bar .tab.active .tab-close:hover {
    background: rgba(255, 255, 255, 0.16);
}

/* ---------- 목록+상세 워크스페이스 (인사관리·차량관리 공용) (FHD 1920×1080 한 장) ---------- */

/* 좌: 사원리스트 300px 고정, 우: 상세 프레임이 남는 폭을 다 먹는다 */
.rec-workspace {
    display: flex;
    gap: 10px;
    height: 100%;
    min-height: 0;
}

.rec-list {
    flex: 0 0 300px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 0;
}

.rec-list-head {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rec-list .seg {
    display: flex;
    gap: 4px;
}

.rec-list .seg-btn {
    flex: 1;
    height: 26px;
    line-height: 26px;
    text-align: center;
    font-size: 12px;
    border-radius: 6px;
    background: var(--fill-alt);
    color: var(--label-alt);
    text-decoration: none;
}

.rec-list .seg-btn.on {
    background: var(--brand);
    color: #fff;
    font-weight: 600;
}

/* 조합 셀렉트(GET 폼)와 검색칸(그리드 필터)이 따로라 세로로 쌓는다 */
.rec-list .rec-search {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rec-list .rec-search input,
.rec-list .rec-search select {
    width: 100%;
    height: 28px;
    font-size: 12px;
    padding: 0 10px;
}

.rec-list .admin-grid {
    flex: 1;
    min-height: 0;
}

.rec-list-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 12px;
    color: var(--label-alt);
}

.btn.sm {
    height: 26px;
    padding: 0 10px;
    font-size: 12px;
}

/* 좌우 폭 조절자. 잡기 쉬우라고 6px 을 두되, 평소엔 보이지 않고 hover·드래그일 때만 물든다. */
.rec-split {
    flex: 0 0 6px;
    align-self: stretch;
    border-radius: 3px;
    cursor: col-resize;
    background: transparent;
    transition: background 120ms var(--ease);
}

.rec-split:hover,
.rec-workspace.resizing .rec-split {
    background: var(--line-normal);
}

.rec-split:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 0;
}

/* 드래그 중에는 양쪽 글자가 선택되지 않게 한다 — 커서가 목록 위를 지나며 긁힌다. */
.rec-workspace.resizing {
    user-select: none;
    cursor: col-resize;
}

/* 드래그가 iframe 위를 지날 때 프레임이 포인터를 먹지 않도록 잠깐 통과시킨다.
   포인터 캡처만으로는 커서 모양이 프레임 것으로 바뀐다. */
.rec-workspace.resizing .rec-detail-frame {
    pointer-events: none;
}

.rec-detail-frame {
    flex: 1;
    min-width: 0;
    border: 0;
    border-radius: 8px;
    background: var(--surface);
}

/* ---------- 상세 폼 (인사관리·차량관리 공용) (조밀 · FHD 한 장) ---------- */

/* 기본 폼 스타일(입력 44px, 라벨을 위에 쌓는 .field)로는 70항목이 안 들어간다.
   이 화면은 라벨을 왼쪽에 두고 행 높이를 26px 로 줄인다. */
.rec-form {
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: 12px;
}

.rec-form .band {
    display: flex;
    gap: 8px;
    align-items: stretch;
}

.rec-form .box {
    border: 1px solid var(--line-neutral);
    border-radius: 6px;
    padding: 6px 10px 8px;
    margin: 0;
    min-width: 0;
}

.rec-form .box.flex1 {
    flex: 1;
}

.rec-form .band-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rec-form legend {
    font-size: 12px;
    font-weight: 600;
    color: var(--label-normal);
    padding: 0 4px;
}

.rec-form .grid4 {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px 12px;
}

.rec-form .grid2 {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 4px 12px;
}

.rec-form .f {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.rec-form .f.span2 {
    grid-column: span 2;
}

.rec-form .f > label {
    flex: 0 0 88px;
    font-size: 12px;
    color: var(--label-alt);
    text-align: right;
}

/* 이 화면 안에서만 입력 높이를 26px 로 줄인다 */
.rec-form input,
.rec-form select {
    flex: 1;
    min-width: 0;
    height: 26px;
    padding: 0 8px;
    font-size: 12px;
    border: 1px solid var(--line-normal);
    border-radius: 4px;
    background: var(--surface);
}

.rec-form input.amount {
    text-align: right;
}

/* 중복된 사원번호·이메일 — 저장 때 뜨는 경고와 같은 뜻이다 */
.rec-form input.dup {
    border-color: var(--negative);
    background: var(--negative-bg);
}

.rec-form .photo-cell {
    flex: 0 0 176px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rec-form .photo-cell input[type=file] {
    display: none;
}

.rec-form .photo-actions {
    display: flex;
    gap: 4px;
}

.rec-form .photo-actions .btn {
    flex: 1;
    height: 26px;
    padding: 0 8px;
    font-size: 12px;
}

/* 증명사진 3:4 */
.rec-form .photo-box {
    aspect-ratio: 3 / 4;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--line-neutral);
    border-radius: 6px;
    background: var(--fill-alt);
    overflow: hidden;
}

.rec-form .photo-box img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rec-form .photo-empty {
    font-size: 12px;
    color: var(--label-assistive);
}

.rec-form .form-foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

.rec-form .form-foot .btn {
    height: 30px;
    padding: 0 20px;
    font-size: 12px;
}

/* 반복 블록 표 — 행 24px, 폰트 11px. 넘치면 그 표만 세로로 스크롤한다. */
.rec-form .rowbox {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.rec-form .rowtable {
    width: 100%;
    border-collapse: collapse;
    font-size: 11px;
}

.rec-form .rowtable th {
    height: 22px;
    padding: 0 4px;
    text-align: left;
    font-weight: 600;
    color: var(--label-alt);
    background: var(--thead);
    white-space: nowrap;
}

.rec-form .rowtable td {
    padding: 1px 2px;
}

.rec-form .rowtable input,
.rec-form .rowtable select {
    height: 24px;
    width: 100%;
    font-size: 11px;
    padding: 0 6px;
}

.rec-form .rowbox .row-add {
    align-self: flex-start;
}

.rec-form .readonly-box {
    flex: 0 0 220px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.rec-form .ro {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: var(--label-alt);
}

.rec-form .ro b {
    color: var(--label-normal);
}

/* 폭을 고정한다(인사관리 .rec-tabbed 래퍼 · 차량관리 폼): 프레임이 좁아지면 칸이 찌그러지는 대신
   가로 스크롤이 생긴다(프레임 문서의 body 가 스크롤한다).
   1280 = FHD 에서 좌측 목록 300px 을 뺀 상세 폭의 안쪽 — grid4 한 칸이 라벨 88 + 입력 180 은 된다. */
.rec-wide {
    min-width: 1280px;
}

/* ---------- 인사관리 상세 — 요약 헤더 + 탭 (member-form.jsp · member-form.js) ---------- */

/* 요약 헤더 — 누구를 보고 있는지 + [저장]. 탭이 바뀌어도 자리를 지킨다(sticky). */
.rec-head {
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 14px;
    height: 56px;
    padding: 0 12px;
    background: var(--surface);
    border: 1px solid var(--line-neutral);
    border-radius: 8px 8px 0 0;
}

.rec-head .thumb {
    flex: none;
    width: 38px;
    height: 38px;
    border-radius: 9px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--fill-alt);
    color: var(--label-alt);
    font-size: 14px;
    font-weight: 700;
}

.rec-head .thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rec-head .who {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}

.rec-head .who small {
    font-size: 13px;
    color: var(--label-alt);
    font-variant-numeric: tabular-nums;
}

.rec-head .who b {
    font-size: 16px;
    letter-spacing: -0.01em;
}

.rec-head .meta {
    display: flex;
    font-size: 12px;
    color: var(--label-alt);
    white-space: nowrap;
}

.rec-head .meta span {
    padding: 0 10px;
    border-left: 1px solid var(--line-neutral);
}

.rec-head .meta span:first-child {
    padding-left: 0;
    border-left: 0;
}

.rec-head .meta b {
    color: var(--label-normal);
    font-weight: 600;
}

.rec-head .spacer {
    flex: 1;
}

.rec-head .btn {
    height: 30px;
    padding: 0 20px;
    font-size: 12px;
}

.rec-head .last {
    font-size: 12px;
    color: var(--label-alt);
    white-space: nowrap;
}

.rec-head .last b {
    color: var(--label-neutral);
    font-weight: 600;
}

/* 탭바 — 헤더 바로 아래 붙는다. 표시: .dirty(고친 탭, 파란 점) · .tab-mark.bd(필수 n · 계좌 없음 · 잔액) */
.rec-tabs {
    position: sticky;
    top: 56px;
    z-index: 3;
    display: flex;
    gap: 2px;
    padding: 0 8px;
    margin-bottom: 8px;
    background: var(--surface);
    border: 1px solid var(--line-neutral);
    border-top: 0;
    border-radius: 0 0 8px 8px;
}

.rec-tabs button {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 10px 14px 9px;
    margin-bottom: -1px;
    border: 0;
    border-bottom: 2px solid transparent;
    background: none;
    font: inherit;
    font-size: 13px;
    color: var(--label-alt);
    cursor: pointer;
}

.rec-tabs button.on {
    color: var(--brand-strong);
    font-weight: 700;
    border-bottom-color: var(--brand);
}

.rec-tabs button:disabled {
    color: var(--label-assistive);
    cursor: not-allowed;
}

.rec-tabs button:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

.rec-tabs button.dirty::after {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #0058D6;
}

/* 면허·자격 만료 확인할 것 — 주황 점(앞), 고친 표시는 파란 점(뒤) */
.rec-tabs button.warn::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--caution);
}

.rec-tabs .tab-mark:empty {
    display: none;
}

.rec-tabs .bd {
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.6;
    font-variant-numeric: tabular-nums;
    background: var(--fill-alt);
    color: var(--label-alt);
}

.rec-tabs .bd.neg { background: var(--negative-bg); color: var(--negative); }
.rec-tabs .bd.cau { background: var(--caution-bg); color: var(--caution); }
.rec-tabs .bd.pos { background: var(--positive-bg); color: var(--positive); }

/* 탭 본문 — 보기만 바꾼다. 폼은 하나라 숨긴 탭의 값도 같이 저장된다. */
.rec-pane {
    display: none;
    flex-direction: column;
    gap: 8px;
}

.rec-pane.on {
    display: flex;
}

/* 급여·보험 탭 — 박스 넷을 2×2 로. 한 줄에 다섯을 깔면 칸 하나가 60px 이었다. */
.rec-form .grid-boxes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}

.rec-form .grid1 {
    display: grid;
    grid-template-columns: 1fr;
    gap: 4px;
}

/* 공제·가족 탭 — 인적공제 박스는 폭을 정하고 가족 표가 나머지를 먹는다 */
.rec-form .dedc-box {
    flex: 0 0 560px;
}

/* 인적공제 인원 옆 칩 — 가족관계 표에서 센 값. ok = 같다, diff = 다르다(손으로 적은 값을 둔다) */
.rec-form .f .chip {
    flex: none;
    padding: 1px 6px;
    border-radius: 5px;
    font-size: 10.5px;
    white-space: nowrap;
    background: var(--fill-alt);
    color: var(--label-alt);
}

.rec-form .f .chip.ok {
    background: var(--positive-bg);
    color: var(--positive);
}

.rec-form .f .chip.diff {
    background: var(--caution-bg);
    color: var(--caution);
}

/* 면허·자격 마감 D-day — 표의 "갱신" 열(JS 가 붙인다)과 사원리스트 행 앞의 점 */
.rec-form .rowtable th.dd,
.rec-form .rowtable td.dd {
    width: 64px;
    text-align: center;
}

.dday {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 5px;
    font-size: 10.5px;
    font-weight: 700;
    white-space: nowrap;
}

.dday:empty {
    display: none;
}

.dday.cau {
    background: var(--caution-bg);
    color: var(--caution);
}

.dday.neg {
    background: var(--negative-bg);
    color: var(--negative);
}

.warn-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--caution);
}

/* 채우기 제안 — 퇴사일 → 상실일자, 입사일 → 취득일자. fieldset 아래 한 줄. */
.rec-hint {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 12px;
    background: rgba(0, 102, 255, 0.09);
    color: #0058D6;
}

.rec-hint .btn {
    height: 22px;
    padding: 0 10px;
    font-size: 11px;
    background: #0058D6;
}

.rec-hint .x {
    margin-left: auto;
    border: 0;
    background: none;
    font: inherit;
    font-size: 14px;
    color: var(--label-alt);
    cursor: pointer;
}

/* 출자금 탭 — 요약 타일 여섯 + 좌 약정·수기 납입 / 우 회차표. 타일·회차표 모양은 옛 [내역] 레이어(.cap-*)를 그대로 쓴다. */
.cap-pane .cap-sum {
    grid-template-columns: repeat(6, 1fr);
}

.cap-pane .cap-sum .tile.neg b {
    color: var(--negative);
}

.cap-pane .cap-empty {
    grid-column: 1 / -1;
    padding: 12px 14px;
    border: 1px dashed var(--line-normal);
    border-radius: 9px;
}

.cap-pane .cap-cols {
    display: grid;
    grid-template-columns: 440px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
}

.cap-pane .cap-side {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.cap-pane .cap-side .form-foot {
    margin-top: 6px;
}

/* 월분납금은 계산 칸 — 편집칸처럼 보이지 않게 */
.cap-pane input[readonly] {
    background: var(--fill-alt);
    color: var(--label-neutral);
}

.cap-pane .cap-side .crumb {
    margin: 6px 0 0;
    line-height: 1.6;
}

.cap-pane .cap-main .crumb {
    margin: 6px 0 0;
}

.cap-pane .cap-sched-wrap {
    max-height: 560px;
}

.cap-pane .cap-sched tr.k-manual td {
    background: rgba(0, 102, 255, 0.05);
}

.cap-pane .cap-sched a {
    font-size: 11px;
    color: var(--negative);
}

/* ── 레이어 팝업 (공통) ──────────────────────────────────────────────────── */
/* 셸이 그리므로 화면 중앙이다. 프레임 안에서 fixed 를 쓰면 프레임 박스에 갇힌다. */
.layer-dim {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(23, 23, 25, 0.52);
}

.layer-box {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 41;
    width: 500px;
    max-width: calc(100vw - 32px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 6px;
    background: var(--surface);
    box-shadow: 0 12px 32px rgba(23, 23, 25, 0.20);
}

/* 머리를 잡아 옮긴다. touch-action 이 없으면 터치에서 브라우저가 스크롤로 가져간다. */
.layer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 10px 8px 12px;
    background: var(--brand-heavy);
    cursor: move;
    touch-action: none;
    user-select: none;
}

.layer-head h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: -0.012em;
    color: #FFFFFF;
    white-space: nowrap;
}

.layer-close {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: var(--r);
    background: transparent;
    color: #FFFFFF;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    transition: background 120ms var(--ease);
}

.layer-close:hover {
    background: rgba(255, 255, 255, 0.16);
}

.postcode-embed {
    height: 470px;
}

/* ---------- 기준·요율 레이어 (급여계산, 시안 B "대조 시트" — payroll.js) ----------
   이 달 값(입력) | 직전 달 | 룰 기본값 을 한 줄에 둔다. 표 머리·행 높이는 그리드와 같은 토큰이다.
   직전 달과 다른 줄은 주황 테두리(.diff), 이번에 고친 줄은 노란 바탕(.dirty). */
.rates-body {
    display: grid;
    grid-template-columns: minmax(340px, 400px) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
    padding: 16px 20px;
    max-height: calc(100vh - 200px);
    overflow: auto;
}
.rates-side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.rates-table { width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; }
.rates-table caption { padding: 0 0 6px; text-align: left; font-size: 13px; font-weight: 700; color: var(--thead-strong); }
.rates-table caption span { margin-left: 6px; font-size: 11px; font-weight: 400; color: var(--mute); }
.rates-table thead th {
    height: var(--thead-h);
    padding: 0 10px;
    background: var(--thead-strong);
    color: var(--thead-strong-ink);
    font-size: 12px;
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
}
.rates-table tbody tr { height: calc(var(--row-h) + 4px); box-shadow: inset 0 -1px 0 var(--line-neutral); }
.rates-table tbody th { padding: 0 10px; font-weight: 500; text-align: left; white-space: nowrap; }
.rates-table tbody th .badge { margin-left: 6px; }
.rates-table td { padding: 2px 10px; color: var(--mute); }
.rates-table td:nth-child(2) { width: 160px; padding: 2px 4px; }
.rates-table .num { width: 96px; text-align: right; }
.rates-table thead th.num { text-align: right; }
.rates-table.rule { table-layout: fixed; }
.rates-table.rule thead th:nth-child(1) { width: 140px; }
.rates-table.rule thead th.num { width: 96px; }
.rates-table.rule thead th:nth-child(2) { width: 160px; }   /* 이것도 .num 이다 — 뒤에 둬야 이긴다 */
.rates-table td.desc { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rates-cell {
    display: flex;
    align-items: center;
    height: 28px;
    box-sizing: border-box;
    border: 1px solid var(--bd);
    border-radius: var(--r);
    background: var(--surface);
}
.rates-cell:focus-within { border-color: var(--brand-heavy); box-shadow: 0 0 0 3px var(--ring); }
.rates-cell input {
    flex: 1;
    min-width: 0;
    height: 26px;
    padding: 0 4px 0 8px;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: right;
    color: var(--label-normal);
    outline: none;
}
.rates-cell input:disabled { color: var(--mute); }
.rates-cell span { flex: none; width: 34px; font-size: 11px; color: var(--mute); }
.rates-table tr.diff .rates-cell { border-color: #E0A040; }
.rates-table tr.diff td.prev { color: var(--warn); }
.rates-table tr.dirty .rates-cell { background: var(--caution-bg); }
.rates-summary { margin: 0; padding: 10px 12px; border-radius: var(--r); background: var(--caution-bg); font-size: 12px; font-weight: 700; color: var(--warn); }
.rates-tools { display: flex; flex-wrap: wrap; gap: 8px; }
.rates-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 20px;
    background: var(--bg);
    box-shadow: inset 0 1px 0 var(--line-normal);
}
.rates-foot p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--mute); }
.rates-foot small { display: block; font-size: 12px; }
.rates-buttons { display: flex; flex: none; gap: 8px; }

/* ---------- 확인 레이어 (AdminFrame.confirm) ---------- */
/*
  .layer-body 자체에는 여백이 없다 — 주소검색은 iframe 이 가장자리까지 차야 하기 때문이다.
  그래서 여백은 확인 팝업 쪽에만 준다.
  푸터는 상세 패널과 같은 규칙이다(핸드오프: 상단 1px 라인 + 버튼 140×40 중앙 정렬) —
  콘솔 안에서 확인·저장 버튼이 늘 같은 자리·같은 크기로 보이게 한다.
*/

.layer-confirm .layer-msg {
    margin: 0;
    padding: 26px 24px 22px;
    font-size: 15px;
    line-height: 1.6;
    text-align: center;
    color: var(--label-normal);
    /* 한국어는 단어 안에서 끊기면 읽기 나쁘다. 긴 토큰만 예외로 끊는다. */
    word-break: keep-all;
    overflow-wrap: anywhere;
    white-space: pre-line;
}

.layer-confirm .layer-foot {
    display: flex;
    justify-content: center;
    gap: 8px;
    padding: 14px 24px 20px;
    box-shadow: inset 0 1px 0 var(--line-neutral);
}

.layer-confirm .layer-foot .btn {
    width: 140px;
    height: 40px;
    flex: none;
}

/* 주소검색으로 채우는 칸 — 오른쪽 끝 돋보기. 인사관리 폼과 셸 상세 패널이 같은 클래스를 단다(JS 가 붙인다).
   readonly 배경(background 단축 속성)과 .rec-form 의 padding 을 이기려고 파일 끝 + 같은 특이도로 둔다. */
input.postcode-input,
.rec-form input.postcode-input,
.detail-panel .panel-body input.postcode-input {
    padding-right: 32px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7684' stroke-width='2.2' stroke-linecap='round'><circle cx='11' cy='11' r='7'/><line x1='16.5' y1='16.5' x2='21' y2='21'/></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px 16px;
}

/* 모든 셀렉트의 화살표 — 브라우저 기본은 오른쪽 끝에 붙어 날짜칸의 달력 아이콘과 어긋난다.
   오른쪽 8px 안쪽에 같은 꺾쇠를 그린다. 화면별 규칙이 padding 단축으로 오른쪽 여백을 되돌리지 못하게
   그 선택자들을 여기 나열하고 파일 끝에 둔다(같은 특이도면 뒤가 이긴다). */
select,
.rec-form select,
.rec-form .rowtable select,
.detail-panel .panel-body select,
.rec-list .rec-search select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 26px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7684' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px 12px;
}

/* 필수 표시 — 라벨 뒤 빨간 별표. 폼 프래그먼트·상세 패널·반복 블록 헤더·공지 폼이 같은 클래스를 쓴다 */
.req {
    color: var(--bad);
    font-style: normal;
    font-weight: 700;
    margin-left: 3px;
}

/* 공통코드처럼 그리드에서 직접 고치는 화면은 헤더에 별표 (colDef.headerClass).
   머리가 딥그린이라 --negative 로는 안 읽힌다 — 밝은 쪽 빨강이다. */
.ag-header-cell.req-head .ag-header-cell-text::after {
    content: " *";
    color: #FF9C9C;
    font-weight: 700;
}

/* ---------- 월간 배차 ---------- */

.month-grid { height: calc(100vh - 256px); min-height: 360px; }
/* 그리드(또는 그리드를 품은 판)가 .frame-body 바로 밑 마지막 칸이면 창 바닥까지 채운다 — 가로 스크롤바가 그리드 바닥에 있는데
   위의 calc(100vh - 256px) 는 위 띠가 그보다 두꺼우면(필터바가 두 줄로 접히면 338px) 바닥을 창 밖으로 밀어 열이 넘쳐도 스크롤바가 안 보였다.
   flex 라 필터바가 나중에 접히거나(카드사 버튼·◀ ▶) 알림 줄이 붙어도 따라간다. 새 화면은 그리드를 그 자리에 .month-grid 로 두면 된다. */
.frame-body:has(> :is(.month-grid, .log-layout, .cap-layout, .dlg-layout, .card-layout, .income-split, .pay-layout)) { display: flex; flex-direction: column; height: 100vh; }
.frame-body:has(> :is(.month-grid, .log-layout, .cap-layout, .dlg-layout, .card-layout, .income-split, .pay-layout)) > * { flex-shrink: 0; }
.frame-body:has(> :is(.month-grid, .log-layout, .cap-layout, .dlg-layout, .card-layout, .income-split, .pay-layout)) > .page-head { margin-top: 0; }   /* flex 는 마진을 겹치지 않는다 — 위 .crumb 의 12px 가 대신한다 */
.frame-body > :is(.month-grid, .log-layout, .cap-layout, .dlg-layout, .card-layout, .income-split, .pay-layout) { flex: 1 1 0; height: auto; min-height: 240px; }
.frame-body > .log-layout > * { height: auto; min-height: 0; }   /* 배차일지 — 그리드·이달 배차 판이 줄 높이를 따른다 */
/* 카드·유류·과태료·타코(.card-layout) · 미수·후입금(.income-split) · 월마감·연간급여(.pay-layout)도 같은 열이다(2026-11-02) —
   전에는 calc(100vh - 330px) 같은 고정 뺄셈이라 필터바가 두 줄로 접히면 바닥이 창 밖으로 밀렸다. 안쪽 그리드는 flex 로 남은 높이를 받는다. */
.frame-body > .pay-layout .pay-main .month-grid, .frame-body > .pay-layout #annual-drivers, .frame-body > .pay-layout .pay-main #annual-grid { flex: 1 1 0; height: auto; min-height: 200px; }
.pay-main > .income-head, .pay-main > .pay-close-bar, .rec-list-foot { flex: none; }
.month-grid .ag-header-cell-text { white-space: pre-line; text-align: center; line-height: 1.15; }
.month-grid .ag-header-cell-label { justify-content: center; }
/* 일·토·오늘 — 딥그린 머리 위라 어두운 쪽 색은 안 읽힌다. 밝은 쪽으로 뒤집었다. */
.month-grid .ag-header-cell.head-sun .ag-header-cell-text { color: #FF9C9C; }
.month-grid .ag-header-cell.head-sat .ag-header-cell-text { color: #9DC0FF; }
.month-grid .ag-header-cell.head-today { box-shadow: inset 0 -3px 0 var(--brand-light); }
.month-grid .ag-cell { padding: 0 4px; text-align: center; font-size: 12px; }
.month-grid .ag-cell.cell-day   { background: rgba(33,163,119,.12); }
.month-grid .ag-cell.cell-night { background: rgba(63,76,143,.12); }
.month-grid .ag-cell.cell-work  { background: var(--caution-bg); color: var(--caution); font-weight: 600; }
.month-grid .ag-cell.cell-off   { background: repeating-linear-gradient(135deg, transparent 0 3px, rgba(112,115,124,.14) 3px 4px); color: var(--label-assistive); }
.month-grid .ag-cell.cell-conf  { background: var(--negative-bg); color: var(--negative); font-weight: 700; box-shadow: inset 0 0 0 1px var(--negative); }
.month-grid .ag-cell.cell-past  { opacity: .72; }
.month-grid .ag-cell.cell-dirty { background: rgba(255,214,0,.38); box-shadow: inset 2px 0 0 #A88A00; }
.month-grid .ag-floating-bottom .ag-cell { font-weight: 600; color: var(--label-alt); background: var(--thead); }
.month-grid .ag-cell-inline-editing { padding: 0; border: 0; box-shadow: none; background: transparent; }
.month-editor { width: 100%; height: 100%; border: 0; border-radius: 0; outline: 2px solid var(--brand); outline-offset: -2px; padding: 0 4px; font: inherit; font-size: 12px; text-align: center; background: var(--surface); box-shadow: none; }
.month-ac { position: fixed; z-index: 20; min-width: 170px; padding: 3px 0; background: var(--surface); border: 1px solid var(--line-normal); border-radius: 6px; box-shadow: 0 8px 24px rgba(23,23,25,.14); font-size: 12px; }
.month-ac div { padding: 5px 10px; display: flex; gap: 10px; cursor: pointer; }
.month-ac div.on { background: var(--positive-bg); color: var(--brand-strong); }
.month-ac div.clear { color: var(--bad); border-bottom: 1px solid var(--line-alt, var(--line-normal)); }
.month-ac div span:first-child { min-width: 34px; font-variant-numeric: tabular-nums; color: var(--label-alt); }
.badge.night { background: rgba(63,76,143,.12); color: #3F4C8F; }
.month-bar form { display: contents; }
.month-hint { margin: 0 0 8px; }
/* 하나만 고르는 세그 — 붙은 한 덩어리에 채운 칸 하나 */
.seg-tabs { display: inline-flex; border: 1px solid var(--bd); border-radius: var(--r); background: var(--surface); overflow: hidden; }
.seg-tabs button { height: 30px; min-width: 52px; padding: 0 12px; border: 0; border-left: 1px solid var(--line-neutral); background: transparent; font: inherit; font-size: 12.5px; line-height: 1; color: var(--label-alt); cursor: pointer; transition: background 120ms var(--ease), color 120ms var(--ease); }
.seg-tabs button:first-child { border-left: 0; }
.seg-tabs button:hover { background: var(--fill-alt); color: var(--label-normal); }
.seg-tabs button[aria-pressed="true"] { background: var(--brand-heavy); color: #FFFFFF; font-weight: 700; }
.seg-tabs button:focus-visible { outline: 2px solid var(--brand-heavy); outline-offset: -2px; }
/* 여럿이 동시에 켜지는 세그(원장의 "보일 카드사")는 모양부터 다르다 — 떨어진 상자 + 체크표시.
   흐리게만 하면 "하나만 고르는 것"과 구분이 안 된다. */
#card-cols { display: inline-flex; flex-wrap: wrap; gap: 4px; border: 0; background: transparent; overflow: visible; }
#card-cols button { position: relative; display: inline-flex; align-items: center; gap: 6px; height: 30px; min-width: 0; padding: 0 8px 0 6px; border: 1px solid var(--bd); border-radius: var(--r); background: var(--surface); }
#card-cols button::before { content: ""; flex: none; width: 12px; height: 12px; border: 1px solid var(--line-normal); border-radius: 2px; background: var(--surface); }
#card-cols button[aria-pressed="true"] { background: var(--surface); border-color: var(--label-alt); }
#card-cols button[aria-pressed="true"]::before { background: var(--brand-heavy); border-color: var(--brand-heavy); }
#card-cols button[aria-pressed="true"]::after { content: ""; position: absolute; left: 11px; top: 50%; width: 3px; height: 6px; margin-top: -4px; border: solid #FFFFFF; border-width: 0 2px 2px 0; transform: rotate(45deg); }
#card-cols button[aria-pressed="false"] .chn { background: var(--fill-alt); color: var(--label-assistive); }
.dirty-count { font-size: 12px; color: var(--label-alt); font-variant-numeric: tabular-nums; }
.dirty-count.has { color: #A88A00; font-weight: 600; }
.grid-legend .dot.day   { background: rgba(33,163,119,.45); }
.grid-legend .dot.night { background: rgba(63,76,143,.45); }
.grid-legend .dot.work  { background: var(--caution); }
.grid-legend .dot.off   { background: repeating-linear-gradient(135deg, transparent 0 2px, rgba(112,115,124,.5) 2px 3px); box-shadow: inset 0 0 0 1px var(--line-normal); }
.grid-legend .dot.dirty { background: rgba(255,214,0,.8); }

/* ---------- 수입금관리 ---------- */

/* 원장 · 월계 · 출근부 그리드는 월간배차의 셀 편집 규칙(.month-grid)을 그대로 쓴다 — 여기서는 숫자 칸만 더한다 */
.income-grid .ag-cell { text-align: right; }
.income-grid .ag-cell.cell-text { text-align: left; }
.income-grid .ag-cell.cell-center { text-align: center; }
/* 저장하지 않는 파생칸은 옅은 청록 — 회색 배경보다 "계산해서 보여주는 칸"이 눈에 띈다 */
.income-grid .ag-cell.cell-derived { background: rgba(20,80,60,.06); color: rgba(23,32,29,.74); }
.income-grid .ag-cell.cell-derived.col-edge { box-shadow: inset 1px 0 0 rgba(20,80,60,.28); }
.income-grid .ag-cell.cell-locked { color: var(--label-assistive); background: repeating-linear-gradient(135deg, transparent 0 4px, rgba(112,115,124,.10) 4px 5px); }
.income-grid .ag-cell.cell-neg { color: var(--negative); font-weight: 600; }
.income-grid .ag-cell.cell-strong { font-weight: 700; color: #0B2C21; }
.income-grid .ag-header-cell.head-derived { background: #0F3F2F; }
/* 원장(기사별) — 줄이 일자다. 요일은 흰 바탕 위라 헤더용 밝은 색(#FF9C9C·#9DC0FF)이 아니라 글자용 짝을 쓴다 */
.income-grid .dow { color: var(--mute); }
.income-grid .dow.sun { color: var(--bad); }
.income-grid .dow.sat { color: #1F55B5; }
/* 배차일지에서 깔아 둔 차 — 아직 원장 행이 아니다(금액을 넣으면 행이 된다) */
.income-grid .ag-cell.cell-plan { color: #0058D6; }
.grid-legend .dot.plan { background: #0058D6; }
#member-select { width: var(--w-name); }
/* 합계는 머리 바로 밑 짙은 띠 */
/* 합계 줄(고정행) — ag-grid 33 부터 통의 이름이 .ag-floating-top 이 아니라 .ag-grid-pinned-top-rows-container 다
   (옛 이름으로 적혀 있어 월계의 합계·평균 띠와 기사별 원장의 합계 줄이 칠해지지 않았다) */
.income-grid .ag-grid-pinned-top-rows-container .ag-cell { font-weight: 700; color: #0B2C21; background: #EAF1EE; }
.income-grid .ag-grid-pinned-top-rows-container { border-bottom: 1px solid rgba(20,80,60,.28); }
.income-grid .ag-grid-pinned-top-rows-container .ag-row:nth-child(2) .ag-cell { font-weight: 500; color: var(--label-alt); }
.income-stats { display: flex; gap: 8px; margin: 0 0 10px; }
.income-stats .stat { flex: 1; display: flex; flex-direction: column; gap: 2px; padding: 10px 14px; background: var(--surface); border-radius: 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); }
.income-stats .stat .k { font-size: 12px; color: var(--label-alt); }
.income-stats .stat .n { font-size: 18px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--label-strong); }
.income-stats .stat .n small { font-size: 12px; font-weight: 500; color: var(--label-alt); margin-left: 4px; }
.income-stats .stat.neg .n { color: var(--negative); }
.income-stats .stat.pos .n { color: var(--brand-strong); }
/* 레이어 팝업 안의 명세 표(월계 상세 · 출근부 달력 · 미수 후입 폼) */
.income-sheet { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.income-sheet th { height: var(--thead-h); padding: 0 8px; background: var(--thead-strong); color: var(--thead-strong-ink); font-weight: 600; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--thead-strong-line); }
.income-sheet td { height: var(--row-h); padding: 0 8px; border-bottom: 1px solid var(--line-neutral); text-align: right; white-space: nowrap; }
.income-sheet th.l, .income-sheet td.l { text-align: left; }
.income-sheet tr.sum td { background: var(--thead); font-weight: 700; }
.income-sheet td.neg { color: var(--negative); }
.income-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; font-size: 11px; text-align: center; }
.income-cal .h { color: var(--label-alt); font-weight: 600; padding: 2px 0; }
.income-cal .h.sun { color: var(--negative); } .income-cal .h.sat { color: #2F5FC4; }
.income-cal .d { height: 36px; border-radius: 6px; display: flex; flex-direction: column; justify-content: center; gap: 1px; }
.income-cal .d b { font-weight: 600; } .income-cal .d span { color: var(--label-alt); }
.income-cal .d.day { background: rgba(33,163,119,.16); } .income-cal .d.night { background: rgba(63,76,143,.14); } .income-cal .d.work { background: var(--caution-bg); color: var(--caution); }
.income-rcgn { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; font-size: 12px; }
.income-rcgn div { display: flex; justify-content: space-between; padding: 6px 8px; border-radius: 6px; background: var(--fill-alt); }
.income-form { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)) auto; gap: 8px; align-items: end; }
.income-form label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--label-alt); }
.income-form input, .income-form select { height: 34px; padding: 0 10px; border-radius: 8px; border: 0; box-shadow: inset 0 0 0 1px var(--line-normal); font: inherit; font-size: 13px; background: var(--surface); }
.income-form input[readonly] { background: var(--fill-alt); color: var(--label-alt); }
.income-split { display: flex; gap: 10px; min-height: 0; }
.income-split > .left { flex: 0 0 560px; min-width: 0; display: flex; flex-direction: column; }   /* 기사별 그리드(.tall)가 남은 높이를 받는 열 */
.income-split > .right { flex: 1; min-width: 0; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 10px; }   /* 창이 낮으면(1440×900) 열 안에서 스크롤 — 문서는 안 넘친다 */
.income-head { display: flex; align-items: center; gap: 14px; padding: 12px 16px; background: var(--surface); border-radius: 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); }
.income-head b { font-size: 16px; }
.income-box { padding: 14px 16px; background: var(--surface); border-radius: 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); display: flex; flex-direction: column; gap: 10px; }
.income-grid.short { height: 260px; min-height: 200px; }
.income-grid.tall { flex: 1 1 0; height: auto; min-height: 240px; }   /* .income-split 이 창 바닥까지 채우는 flex 열이라(위 .frame-body:has) 고정 뺄셈이 아니다 */
/* 미입 행 · 후입금 내역 두 그리드가 오른쪽 열의 남은 높이를 나눠 받는다 — 각각 160 · 120 아래로는 안 줄고 그때는 열이 스크롤한다 */
.income-split .income-grid.short { flex: 1 1 260px; height: auto; min-height: 160px; }
.income-split .income-box:last-child { flex: 1 1 auto; }
.income-split .income-box:last-child .income-grid.short { flex: 1 1 0; min-height: 120px; }

/* 고정기사 · 배차일지 — 월간배차의 셀 편집 규칙(.month-grid)을 그대로 쓰고, 여기서는 그 둘만의 칸을 더한다 */
.month-grid .ag-cell.cell-text { text-align: left; }
.month-grid .ag-cell.cell-idle { color: var(--label-assistive); }
.month-grid .ag-cell.cell-retired { color: var(--negative); }
.month-grid .ag-header-group-cell.head-day .ag-header-group-text { color: #7FD3B0; }
.month-grid .ag-header-group-cell.head-night .ag-header-group-text { color: #A8B5F0; }
.grid-legend .dot.idle { background: var(--line-normal); }
/* 고정기사는 컬럼이 6개뿐이라 화면 폭을 다 쓰면 칸 하나가 900px 이 된다 — 레거시처럼 좁게 둔다 */
.fixed-grid { max-width: 940px; }

/* 날짜 ◀ □ ▶ — 세 컨트롤이 한 덩어리로 붙어 보이게 */
.date-step { display: inline-flex; align-items: center; gap: 4px; }
/* .tx-step 은 taxi-date.js 가 상단 필터의 날짜·월 칸 양쪽에 붙이는 ◀ ▶ 다 — 화면이 직접 적은 .date-step 과 같은 모양 */
.date-step .btn, .filter-bar .btn.tx-step { padding: 6px 9px; font-size: 12px; line-height: 1; }
.date-step input[type="number"] { width: 84px; }   /* 연간급여의 연도 칸 — 같은 ◀ ▶ 사이에 선다 */
.date-step input[type="date"], .date-step input[type="number"] { padding: 6px 8px; border: 1px solid var(--line-normal); border-radius: 8px; font: inherit; font-size: 13px; background: var(--surface); color: inherit; }

/* 배차일지 = 좌 사원조회 + 그리드 + 우 이달 달력 (레거시 "사 원 조 회" · "배차예정") */
/* 배차일지: 그리드 + 우측 "이달 배차" 달력. 좌측 사원조회 패널은 뺐다(필터바 검색·[미배차만]과 겹쳤다). */
.log-layout { display: flex; gap: 12px; align-items: stretch; }
.log-layout .month-grid { flex: 1; min-width: 0; }

.side-panel { flex: none; display: flex; flex-direction: column; height: calc(100vh - 256px); min-height: 360px; background: var(--surface); border-radius: 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); }
.side-panel .side-head { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px; border-bottom: 1px solid var(--line-neutral); }
.side-panel .side-head b { font-size: 12px; color: var(--label-alt); }
.side-panel .side-scroll { flex: 1; overflow-y: auto; }
.side-panel table { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.side-panel th { position: sticky; top: 0; z-index: 1; height: var(--thead-h); padding: 0 4px; background: var(--thead-strong); color: var(--thead-strong-ink); font-weight: 600; }
.side-panel td { height: var(--row-h); padding: 0 4px; text-align: center; border-top: 1px solid var(--line-neutral); }
.side-panel tbody tr { cursor: pointer; }
.side-panel tbody tr:hover { background: rgba(33,163,119,.06); }

.day-cal { width: 210px; }
.day-cal tr.sun td:nth-child(-n+2) { color: var(--negative); }
.day-cal tr.sat td:nth-child(-n+2) { color: #2F5FC4; }
.day-cal tr.today td { font-weight: 700; }

/* 사원조회에서 고른 기사가 탄 줄 */

/* 급여계산 — 집계 칸(잠금) · 손입력 칸(흰 칸) · 확인 필요 줄. 셀 편집 규칙은 .month-grid 를 그대로 쓴다 */
.month-grid .ag-cell.cell-agg   { background: #FAFAFB; color: rgba(55,56,60,.75); }
.month-grid .ag-cell.cell-input { background: #FFFDF5; box-shadow: inset 0 0 0 1px rgba(112,115,124,.16); }
.month-grid .ag-row.row-issue .ag-cell { background: rgba(255,66,42,.06); }

/* 월마감 — 단계줄 4칸 · 왼쪽 확인 필요 카드 400px */
.pay-steps { display: flex; padding: 0; margin-bottom: 10px; overflow: hidden; }
.pay-steps > div { flex: 1; display: flex; align-items: center; gap: 12px; padding: 12px 18px; }
.pay-steps > div + div { box-shadow: inset 1px 0 0 var(--line-neutral); }
.pay-steps > div.cur { background: var(--positive-bg); }
.pay-steps .n { width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; background: #EEEEF0; color: var(--label-alt); }
.pay-steps .done .n { background: var(--brand); color: #fff; }
.pay-steps .cur .n { background: #fff; color: var(--brand-strong); box-shadow: inset 0 0 0 2px var(--brand); }
.pay-steps .t { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pay-steps .t strong { font-size: 13px; font-weight: 600; color: var(--label-normal); }
.pay-steps .t span { font-size: 12px; color: var(--label-alt); }
.pay-issues { flex: 0 0 400px; display: flex; flex-direction: column; gap: 8px; min-width: 0; min-height: 0; overflow: auto; }   /* 카드가 많으면 열 안에서 스크롤 — .pay-layout 이 창 높이에 고정이다 */
.pay-issues .card { padding: 12px 14px; }
.pay-issues .card.clear { opacity: .55; }
.pay-issues .head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pay-issues .who { margin: 6px 0 0; padding-left: 16px; font-size: 12px; color: var(--label-normal); }
.pay-issues .who .more { color: var(--label-alt); list-style: none; margin-left: -16px; }
.pay-issues .crumb { margin: 6px 0 8px; }
.pay-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.pay-main .month-grid { min-height: 300px; }   /* 높이는 .pay-layout flex 열이 준다(월간 배차 절의 .frame-body:has) */
.pay-close-bar { display: flex; align-items: center; gap: 10px; }
.pay-close-bar .spacer { flex: 1; }
.pay-close-bar .btn:disabled { background: var(--fill-alt); color: var(--label-assistive); cursor: not-allowed; }

/* ---------- 급여관리 — 월별총계 · 연간급여 ---------- */
.pay-summary { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px; align-items: start; }
.pay-summary > .card { padding: 16px 18px; min-width: 0; }
.pay-kv, .pay-table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 12px; font-variant-numeric: tabular-nums; }
.pay-kv td { padding: 7px 0; border-bottom: 1px solid var(--line-neutral); color: var(--label-alt); }
.pay-kv td.v { text-align: right; color: var(--label-strong); font-weight: 600; }
.pay-kv tr.sum td { border-bottom: 0; color: var(--brand-strong); font-size: 14px; font-weight: 700; }
.pay-table th { height: var(--thead-h); padding: 0 8px; background: var(--thead-strong); color: var(--thead-strong-ink); font-weight: 600; text-align: right; }
.pay-table td { height: var(--row-h); padding: 0 8px; border-bottom: 1px solid var(--line-neutral); text-align: right; }
.pay-table th.l, .pay-table td.l { text-align: left; }
.pay-table tr.sum td { background: var(--thead); font-weight: 700; color: var(--label-strong); }
.pay-main .income-head { padding: 10px 16px; }
.pay-main .income-head .spacer { flex: 1; }
.pay-table th:first-child, .pay-table td:first-child { width: 44%; }
/* 연간급여의 두 그리드 높이는 .pay-layout flex 열이 준다(월간 배차 절의 .frame-body:has) — 여기는 바닥만 */
#annual-drivers, .pay-main #annual-grid { min-height: 300px; }

/* ---------- 급여계산 룰 — 세 탭 · 칩 · 편집기. 묶음은 N개라 열이 자동으로 늘고, 색은 묶음 키가 아니라 부호(.sign-pay/.sign-dedc/.sign-info) ---------- */

.rule-bar select { height: 34px; padding: 0 8px; font-size: 13px; border-radius: 8px; background: transparent; box-shadow: inset 0 0 0 1px var(--line-normal); }
.rule-bar .chip select { box-shadow: none; }
.rule-bar .btn.small { height: 34px; padding: 0 12px; font-size: 13px; }
.rule-body .btn.small { height: 28px; padding: 0 10px; font-size: 12px; }
.rule-body { display: grid; gap: 12px; align-items: start; }
.rule-body.buckets { grid-template-columns: 296px minmax(0, 1fr); }
.rule-body.sheet, .rule-body.slip { grid-template-columns: minmax(0, 1fr) 420px; }
/* 계산 시트·명세서의 오른쪽 슬롯 — 편집 패널(#rule-panel, 두 탭 공용) + 계산 시트는 그 아래 검산 */
.rule-slot { display: flex; flex-direction: column; gap: 12px; position: sticky; top: 12px; min-width: 0; }
/* 계산 시트·명세서 — 표와 오른쪽 패널을 fitPanes 가 창 높이에 맞춰 각자 세로 스크롤한다(항목 묶음의 열 판과 같다) */
#slot-sheet, #slot-slip, .rule-slip { overflow-y: auto; }
#slot-sheet > .card, #slot-slip > .card { flex: none; }
.rule-palette { padding: 16px; }
.rule-body .grp { font-size: 11.5px; font-weight: 600; letter-spacing: .032em; color: var(--label-assistive); margin: 14px 0 7px; }
.rule-body .grp:first-child { margin-top: 0; }
.rule-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip-var { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 9px; border-radius: 8px; background: var(--fill-alt);
    box-shadow: inset 0 0 0 1px var(--line-neutral); font-size: 12.5px; white-space: nowrap; cursor: grab; user-select: none; }
.chip-var.disabled { opacity: .38; cursor: not-allowed; }
.chip-var .tag { width: 16px; height: 16px; border-radius: 4px; font-size: 10px; font-weight: 700; color: #fff; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.tag.agg { background: var(--brand); } .tag.month { background: #2F5FC4; } .tag.member { background: #6B4FC4; } .tag.capital { background: #B8652B; }
.tag.item { background: var(--caution); } .tag.sum { background: #4A5568; }
.chip-var.op { background: transparent; box-shadow: none; padding: 0 3px; font-weight: 600; color: var(--label-alt); cursor: default; }
.chip-var.fn { background: rgba(47,95,196,.10); box-shadow: inset 0 0 0 1px rgba(47,95,196,.30); }
.chip-var.num { font-variant-numeric: tabular-nums; }
.chip-var .x { margin-left: 2px; color: var(--label-assistive); cursor: pointer; }
.chip-var .x:hover { color: var(--negative); }
.rule-tokens { min-height: 40px; display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 6px; border-radius: 10px; background: #FAFAFB; box-shadow: inset 0 0 0 1px var(--line-neutral); flex: 1; cursor: text; }
.rule-tokens:focus-within { box-shadow: inset 0 0 0 1.5px var(--brand); background: var(--surface); }
.rule-tokens.over { box-shadow: inset 0 0 0 2px var(--brand); }
.rule-tokens.mini { min-height: 0; padding: 0; background: transparent; box-shadow: none; gap: 3px; }
.rule-tokens.mini .chip-var { height: 24px; padding: 0 7px; font-size: 12px; cursor: default; }
.rule-tokens .slot { width: 8px; height: 26px; border-radius: 3px; cursor: text; }
.rule-tokens .slot:hover { background: var(--fill-alt); }
/* 커서 슬롯 — 입력 칸(.rule-type)이 커서다. 팔레트 칩을 끌어 놓는 자리도 같다 */
.rule-tokens .slot.on { width: auto; display: inline-flex; align-items: center; background: transparent; }
.rule-typewrap { position: relative; display: inline-flex; }
.rule-tokens input.rule-type { width: 150px; height: 26px; margin: 0 2px; border: 0; border-bottom: 2px solid var(--brand); border-radius: 0; background: transparent; box-shadow: none; font: inherit; font-size: 12.5px; padding: 0 4px; outline: 0; }
.rule-tokens input.rule-type:focus { box-shadow: none; }
.rule-tokens input.rule-type::placeholder { font-size: 12px; }
/* 후보 목록 — 커서 밑에 뜬다. 그룹 색 태그 · 이름 · 키 · 미리보기 값 */
.rule-ac { position: absolute; left: 0; top: 30px; width: 340px; z-index: 6; background: var(--surface); border-radius: 9px; box-shadow: 0 12px 32px rgba(23,23,25,.18), inset 0 0 0 1px var(--line-normal); padding: 4px; font-size: 12.5px; cursor: default; }
.rule-ac .row { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; cursor: pointer; }
.rule-ac .row.on, .rule-ac .row:hover { background: rgba(33,163,119,.10); }
.rule-ac .row .tag { width: 16px; height: 16px; border-radius: 4px; font-size: 10px; font-weight: 700; color: #fff; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.rule-ac .row .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rule-ac .row code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--label-assistive); }
.rule-ac .row .v { font-variant-numeric: tabular-nums; color: var(--label-alt); font-size: 12px; white-space: nowrap; }
.rule-ac .hint { padding: 5px 8px 3px; font-size: 11px; color: var(--label-assistive); border-top: 1px solid var(--line-neutral); margin-top: 2px; }
/* 풀이줄 — 토큰을 한글 이름 + 미리보기 값으로, "= 값", 그 항목의 오류 */
.rule-read { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; flex: 1; font-size: 12.5px; color: var(--label-alt); padding: 7px 2px 0; }
.rule-read b { color: var(--label-strong); font-weight: 600; }
.rule-read b small { font-size: 12px; font-weight: 500; color: var(--label-alt); font-variant-numeric: tabular-nums; }
.rule-read .opl { font-weight: 700; }
.rule-read .fnl { color: #2F5FC4; font-weight: 600; }
.rule-read .eq { color: var(--brand-strong); font-weight: 700; font-variant-numeric: tabular-nums; }
.rule-read .err { color: var(--negative); font-weight: 600; margin-left: auto; }
.rule-empty { font-size: 12.5px; color: var(--label-assistive); padding: 0 6px; }
.chip-num-input, .rule-num { width: 90px; height: 28px !important; font-size: 12.5px; padding: 0 8px; }
.rule-editor { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line-neutral); cursor: default; }
.rule-row { display: flex; align-items: flex-start; gap: 8px; }
.rule-row > label { flex: none; width: 72px; padding-top: 7px; font-size: 12.5px; color: var(--label-alt); }
.rule-row input[type=text], .rule-row select { height: 32px; font-size: 13px; padding: 0 8px; border-radius: 8px; }
.rule-row input[type=text] { flex: 1; min-width: 0; }
/* 적요 — 여러 줄. 라벨이 위인 칸(카드·패널)에서 flex:1 이 높이를 0 으로 눌러 버리지 않게 flex:none */
.rule-row textarea.rule-desc { width: 100%; min-height: 72px; height: auto; padding: 8px 10px; font-size: 13px; line-height: 1.5; border-radius: 8px; resize: vertical; }
.rule-card .rule-row > input, .rule-panel .rule-row > input { flex: none; }
.rule-inline { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: 1; }
.rule-inline .muted, .rule-body .muted { font-size: 12px; color: var(--label-alt); }
.rule-check-box { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.rule-key, .rule-row input.key, .rule-sheet td.key, .rule-col .head .key, .rule-add input.key { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.rule-key { color: var(--label-assistive); }
.rule-editor .del-row { display: flex; justify-content: flex-end; }
.rule-badge { display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border-radius: 5px; font-size: 11px; font-weight: 600; background: var(--fill-alt); color: var(--label-alt); white-space: nowrap; }
.rule-badge.sign-pay { background: var(--positive-bg); color: var(--positive); } .rule-badge.sign-dedc { background: var(--caution-bg); color: var(--caution); }
.rule-badge.sign-info { background: rgba(107,114,128,.12); color: #6B7280; } .rule-badge.input { background: var(--caution-bg); color: var(--caution); }
.rule-badge.const, .rule-badge.lvl2 { background: rgba(47,95,196,.10); color: #2F5FC4; }
/* 묶음 열 — 묶음 수만큼 자동으로 늘어난다(3 고정이 아니다). 열 폭은 345px 고정이고 넘치면 가로 스크롤.
   팔레트와 열 판은 payroll-rules.js fitPanes 가 창 높이에 맞춰 각자 세로 스크롤한다 — 가로 스크롤바가 화면 아래에 늘 보인다 */
.rule-cols { display: grid; grid-auto-flow: column; grid-auto-columns: 345px; gap: 12px; overflow: auto; padding-bottom: 4px; }
.rule-body.buckets .rule-palette { overflow-y: auto; }
/* 스크롤바를 늘 그린다 — macOS 오버레이 스크롤바는 움직일 때만 보여서 넘친 열이 있는지 모른다.
   그리드 화면(.has-grid)도 같다: ag-grid 는 body 에 붙인 div 로 스크롤바 폭을 재고 0 이면 가로 스크롤바를
   마우스를 올릴 때까지 숨긴다. 그 div 까지 폭이 생기도록 body 아래 전부에 건다. */
.rule-cols::-webkit-scrollbar, .rule-body.buckets .rule-palette::-webkit-scrollbar, .rule-sheet::-webkit-scrollbar, #slot-sheet::-webkit-scrollbar, #slot-slip::-webkit-scrollbar, .rule-slip::-webkit-scrollbar, .has-grid ::-webkit-scrollbar { width: 10px; height: 10px; }
.rule-cols::-webkit-scrollbar-track, .rule-body.buckets .rule-palette::-webkit-scrollbar-track, .rule-sheet::-webkit-scrollbar-track, #slot-sheet::-webkit-scrollbar-track, #slot-slip::-webkit-scrollbar-track, .rule-slip::-webkit-scrollbar-track, .has-grid ::-webkit-scrollbar-track { background: var(--fill-alt); border-radius: 5px; }
.rule-cols::-webkit-scrollbar-thumb, .rule-body.buckets .rule-palette::-webkit-scrollbar-thumb, .rule-sheet::-webkit-scrollbar-thumb, #slot-sheet::-webkit-scrollbar-thumb, #slot-slip::-webkit-scrollbar-thumb, .rule-slip::-webkit-scrollbar-thumb, .has-grid ::-webkit-scrollbar-thumb { background: rgba(112,115,124,.4); border-radius: 5px; border: 2px solid transparent; background-clip: padding-box; }
.rule-cols::-webkit-scrollbar-thumb:hover, .rule-body.buckets .rule-palette::-webkit-scrollbar-thumb:hover, .rule-sheet::-webkit-scrollbar-thumb:hover, #slot-sheet::-webkit-scrollbar-thumb:hover, #slot-slip::-webkit-scrollbar-thumb:hover, .rule-slip::-webkit-scrollbar-thumb:hover, .has-grid ::-webkit-scrollbar-thumb:hover { background: rgba(112,115,124,.6); background-clip: padding-box; }
.rule-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; padding: 14px 18px; margin-top: 24px; }   /* 위 탭 본문과 띄운다 — 항목 묶음의 열 판은 fitBuckets 가 이 여백을 읽는다 */
.rule-foot .grp { margin: 0; } .rule-foot .sum { font-size: 13px; font-variant-numeric: tabular-nums; }
.rule-foot .sum.sign-pay b { color: var(--positive); } .rule-foot .sum.sign-dedc b { color: var(--caution); } .rule-foot .sum.sign-info b { color: #6B7280; }
.rule-foot .sum.net b { font-size: 15px; }
.rule-col { background: var(--surface); border-radius: 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); display: flex; flex-direction: column; min-height: 320px; }
.rule-col .head { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-bottom: 1px solid var(--line-neutral); }
.rule-col .head .row { display: flex; align-items: center; gap: 6px; }
.rule-col .head input, .rule-col .head select { height: 28px; font-size: 12.5px; padding: 0 7px; border-radius: 6px; min-width: 0; }
.rule-col .head input.nm { flex: 1; font-weight: 700; font-size: 13.5px; }
.rule-col .head input.desc { flex: 1; color: var(--label-alt); }
.rule-col .head .n { font-size: 12px; color: var(--label-alt); }
.rule-col .head .key { flex: 1; color: var(--label-assistive); }
.rule-col .head .del { margin-left: auto; height: 26px; padding: 0 8px; font-size: 12px; }
.rule-col.sign-pay .head { box-shadow: inset 0 3px 0 var(--positive); } .rule-col.sign-pay .head input.nm { color: var(--positive); }
.rule-col.sign-dedc .head { box-shadow: inset 0 3px 0 var(--caution); } .rule-col.sign-dedc .head input.nm { color: var(--caution); }
.rule-col.sign-info .head { box-shadow: inset 0 3px 0 #6B7280; } .rule-col.sign-info .head input.nm { color: #6B7280; }
.rule-col .list { padding: 12px; display: flex; flex-direction: column; gap: 8px; background: #FAFAFB; border-radius: 0 0 12px 12px; flex: 1; }
.rule-col .list.over { box-shadow: inset 0 0 0 2px var(--brand); }
.rule-card { background: var(--surface); border-radius: 10px; padding: 11px 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); cursor: pointer; }
.rule-card.on { box-shadow: inset 0 0 0 2px var(--brand); }
.rule-card.dirty { background: #FFFDF5; }
.rule-card.lvl2 { margin-left: 18px; }
.rule-card.bad { box-shadow: inset 0 0 0 2px var(--negative); }
.rule-card.drag-over { box-shadow: inset 0 3px 0 var(--brand); }
.rule-card .top { display: flex; justify-content: space-between; gap: 8px; font-weight: 600; font-size: 13px; }
.rule-card .amt { font-variant-numeric: tabular-nums; color: var(--label-alt); font-weight: 500; }
.rule-card .fx { margin-top: 6px; } .rule-card .meta { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
/* 카드 안 편집기 — 열이 좁아(≈230px) 라벨을 위에 얹어 계산식 칸이 카드 폭을 다 쓴다 */
.rule-card .rule-row { flex-direction: column; gap: 4px; }
.rule-card .rule-row > label { width: auto; padding-top: 0; font-size: 11.5px; font-weight: 600; letter-spacing: .02em; }
.rule-card .rule-tokens input.rule-type { width: 96px; }
.rule-card .rule-ac { width: 300px; }
.rule-sheet { padding: 0; overflow: auto; }
.rule-sheet table { width: 100%; border-collapse: collapse; }
.rule-sheet th { height: var(--thead-h); padding: 0 8px; text-align: left; font-size: 12px; font-weight: 600; color: var(--thead-strong-ink); background: var(--thead-strong); border-bottom: 1px solid var(--thead-strong-line); white-space: nowrap; }
.rule-sheet thead th { position: sticky; top: 0; z-index: 1; }   /* 표가 자기 안에서 세로 스크롤하므로 머리는 붙들어 둔다 */
/* 앞 열 고정(stickCols) — 뒤 열이 밑으로 비치지 않게 불투명 배경, 경계에 그림자 */
.rule-sheet .stick { position: sticky; z-index: 1; background-color: var(--surface); }
.rule-sheet thead th.stick { z-index: 3; background-color: var(--thead-strong); }
.rule-sheet .stick-edge { box-shadow: 6px 0 6px -4px rgba(23,23,25,.12); }
.rule-sheet tr.on td.stick { background: linear-gradient(rgba(33,163,119,.06), rgba(33,163,119,.06)), var(--surface); }
.rule-sheet tr.rule-fixed td.stick { background-color: #FAFAFB; }
.rule-sheet tr.dirty td.nm.stick { background-color: #FFFDF5; }
.rule-sheet .sect-label { position: sticky; left: 8px; display: inline-block; }
/* 표는 내용 폭 그대로 — 좁은 칸을 찌그러뜨리지 않고 넘치면 가로 스크롤. 항목 이름 열은 200px 고정 */
.rule-sheet table { width: max-content; min-width: 100%; }
.rule-sheet tr[data-key] td.nm, .rule-sheet tr.rule-fixed td.nm { width: 200px; min-width: 200px; max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rule-sheet td { height: var(--row-h); padding: 0 8px; border-bottom: 1px solid var(--line-neutral); font-size: 13px; vertical-align: middle; }
.rule-sheet td.num, .rule-check .num { text-align: right; font-variant-numeric: tabular-nums; }
.rule-sheet td.c { text-align: center; }
.rule-sheet td.handle { width: 28px; color: var(--label-assistive); cursor: grab; text-align: center; }
.rule-sheet td.key { color: var(--label-assistive); }
.rule-sheet td.desc { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--label-alt); font-size: 12px; }
.rule-sheet tbody tr:not(.rule-fixed):not(.rule-sect) { cursor: pointer; }
.rule-sheet tr.on td { background: rgba(33,163,119,.06); box-shadow: inset 3px 0 0 var(--brand); }
.rule-sheet tr.dirty td.nm { background: #FFFDF5; }
.rule-sheet tr.bad td.nm { color: var(--negative); }
.rule-sheet tr.drag-over td { box-shadow: inset 0 3px 0 var(--brand); }
.rule-sheet tr.lvl2 td.nm { padding-left: 30px; }
.rule-sheet tr.rule-sect td { background: var(--thead); font-weight: 700; }
.rule-sheet tr.rule-sect.sign-pay td.nm { color: var(--positive); } .rule-sheet tr.rule-sect.sign-dedc td.nm { color: var(--caution); } .rule-sheet tr.rule-sect.sign-info td.nm { color: #6B7280; }
.rule-sheet tr.rule-sect td .desc { font-weight: 400; color: var(--label-alt); margin-left: 8px; font-size: 12px; }
.rule-lvl { height: 22px; min-width: 24px; padding: 0 5px; border: 0; border-radius: 5px; font-size: 11px; font-weight: 700; background: var(--fill-alt); color: var(--label-alt); cursor: pointer; }
.rule-lvl.l2 { background: rgba(47,95,196,.12); color: #2F5FC4; } .rule-lvl:disabled { cursor: default; }
.rule-sheet tr.rule-fixed td { background: #FAFAFB; } .rule-sheet tr.rule-fixed.sign-pay td.nm { color: var(--positive); font-weight: 600; }
.rule-sheet tr.rule-fixed.sign-dedc td.nm { color: var(--caution); font-weight: 600; } .rule-sheet tr.rule-fixed.net td.nm { font-weight: 700; }
.rule-check { padding: 18px; display: flex; flex-direction: column; gap: 10px; }
.rule-inputs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px 14px; }
.rule-check .kv { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; }
.rule-values { display: flex; flex-direction: column; gap: 6px; }
.rule-values .kv { font-size: 13px; } .rule-values .kv.muted span:first-child { color: var(--label-alt); }
.rule-values .kv.l2 span:first-child { padding-left: 14px; color: var(--label-alt); }
.rule-values .kv.sum { border-top: 1px solid var(--line-neutral); padding-top: 6px; }
.rule-values .kv.sum.sign-pay b { color: var(--positive); } .rule-values .kv.sum.sign-dedc b { color: var(--caution); } .rule-values .kv.sum.sign-info b { color: #6B7280; }
.rule-values .kv.sum.net { font-size: 15px; }
.rule-slip { padding: 22px 24px; }
.slip-head { display: flex; justify-content: space-between; align-items: baseline; padding-bottom: 14px; border-bottom: 2px solid var(--label-normal); font-size: 17px; }
/* 세로 명세서 — 묶음 줄 → lvl 1 → lvl 2(들여쓰기) → 실지급액. 비고 = 적요 · 산출방식(서버 notes) */
.slip-table { width: 100%; border-collapse: collapse; margin-top: 16px; font-size: 13px; }
.slip-table th { height: var(--thead-h); padding: 0 12px; background: var(--thead-strong); color: var(--thead-strong-ink); font-weight: 600; text-align: left; }
.slip-table th.num, .slip-table td.num { text-align: right; font-variant-numeric: tabular-nums; width: 150px; white-space: nowrap; }
.slip-table td { height: var(--row-h); padding: 0 12px; border-bottom: 1px solid var(--line-neutral); }
.slip-table td.note { color: var(--label-alt); font-size: 12px; line-height: 1.5; padding: 6px 12px; }   /* 적요+산출방식이 두 줄로 접히는 칸 — 인쇄 명세서(payroll-slip.jsp)와 같은 행간 */
.slip-table tr.sect td { background: var(--thead); font-weight: 700; }
.slip-table tr.sect.sign-pay td:first-child { color: var(--positive); } .slip-table tr.sect.sign-dedc td:first-child { color: var(--caution); } .slip-table tr.sect.sign-info td:first-child { color: #6B7280; }
.slip-table tr.line { cursor: pointer; }
.slip-table tr.l2 td:first-child { padding-left: 34px; color: var(--label-alt); }
.slip-table tr.on td { background: rgba(33,163,119,.06); box-shadow: inset 3px 0 0 var(--brand); font-weight: 600; }
.slip-table tr.net td { background: var(--header); color: #fff; font-weight: 700; font-size: 15px; border-bottom: 0; }
.slip-table tr.net td.note { color: rgba(255,255,255,.75); font-weight: 400; }
/* 오른쪽 편집 패널(계산 시트·명세서) — 머리(이름·키·출처·묶음) + 2열 속성. 계산식·풀이·조건·적요·서랍은 전폭(.wide) */
.rule-panel { padding: 14px 16px; }
.rule-panel-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--line-neutral); }
.rule-panel-head h2 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.01em; }
.rule-panel-head code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--label-assistive); }
.rule-panel .rule-editor { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; margin-top: 0; padding-top: 0; border-top: 0; }
.rule-panel .rule-row { flex-direction: column; gap: 4px; min-width: 0; }
.rule-panel .rule-row > label { width: auto; padding-top: 0; font-size: 11.5px; font-weight: 600; letter-spacing: .02em; }
.rule-panel .rule-row.wide, .rule-panel .rule-drawer, .rule-panel .rule-keys, .rule-panel .del-row { grid-column: 1 / -1; }
.rule-panel .rule-read { padding-top: 0; }
.rule-drawer { border: 1px dashed var(--line-normal); border-radius: 9px; padding: 8px 12px; }
.rule-drawer summary { cursor: pointer; font-size: 12.5px; list-style: none; display: flex; gap: 8px; align-items: baseline; }
.rule-drawer summary::-webkit-details-marker { display: none; }
.rule-drawer summary::before { content: "▸"; color: var(--label-assistive); font-size: 11px; }
.rule-drawer[open] summary::before { content: "▾"; }
.rule-drawer[open] summary { margin-bottom: 8px; }
.rule-drawer .rule-palette { padding: 0; }
.rule-keys { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 11.5px; color: var(--label-assistive); }
.rule-keys kbd { font-family: inherit; font-size: 11px; border: 1px solid var(--line-normal); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px; background: #fff; color: var(--label-alt); }
/* 항목 추가 레이어(셸 openLayer 안) — .layer-body 는 여백이 없어(주소검색 iframe) 폼이 자기 여백을 가진다 */
.rule-add { display: flex; flex-direction: column; gap: 10px; padding: 16px 20px 14px; }
.rule-add label { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--label-alt); }
.rule-add input, .rule-add select { height: 32px; font-size: 13px; padding: 0 8px; border-radius: 8px; }
.rule-add .msg { min-height: 16px; font-size: 12px; color: var(--negative); }
.rule-add .foot { display: flex; justify-content: flex-end; gap: 8px; }

/* ---------- 카드관리 (시안 A · 3단 대조판) — 표 3개, 셀 편집 없음 ---------- */
/* 우측(미입력)만 그리드다 — 주야·기사를 여기서 고르므로 3단 중 제일 좁으면 안 된다.
   가운데(붙은 승인건)는 6열짜리 표라 줄어도 견딘다. */
.card-layout { display: grid; grid-template-columns: minmax(360px, 580px) minmax(260px, 1fr) minmax(560px, 640px); grid-auto-rows: minmax(0, 1fr); gap: 10px; height: calc(100vh - 330px); min-height: 480px; }
/* 유류비관리 — 카드관리 3단과 같은 패널, 폭만 다르다(좌 차량별 대조 9열 · 우 미입력 7열) */
/* 우 패널 상한 568 — 미입력 표가 충전소를 줄임(stnShort)으로 48px 에 담아 1920 의 가운데가 428px 이 된다(가맹점사용량 두 열을 풀네임으로) */
.card-layout.fuel-layout { grid-template-columns: minmax(420px, 600px) minmax(320px, 1fr) minmax(460px, 568px); }
/* 과태료관리 — 같은 3단, 우 패널이 통지서 미리보기라 가장 넓다. 1920 에서 가운데 위반 8열(통지서 열까지)이 가로 스크롤 없이 보이는 폭이다 */
.card-layout.fine-layout { grid-template-columns: minmax(340px, 460px) minmax(300px, 1fr) minmax(460px, 600px); }
.fine-legend { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--label-alt); white-space: nowrap; }
.fine-legend i, .fine-bar i { display: inline-block; height: 8px; background: var(--fill-alt); }
.fine-legend i { width: 8px; border-radius: 2px; margin-left: 4px; }
.fine-bar { display: flex; width: 100%; height: 8px; margin-top: 11px; border-radius: 2px; overflow: hidden; background: var(--fill-alt); }
:is(.fine-legend, .fine-bar) i.d { background: var(--brand-heavy); } :is(.fine-legend, .fine-bar) i.x { background: #E3A23B; }
:is(.fine-legend, .fine-bar) i.m { background: #2F5FC4; } :is(.fine-legend, .fine-bar) i.q { background: var(--negative); }
.fine-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; }
#right-tabs em { font-style: normal; font-weight: 700; margin-left: 2px; }
#pane-notice { overflow: auto; }   /* 낮은 창(1440×900)에서는 미리보기·놓기·대기열이 한 통으로 스크롤된다 — 대기열이 0 으로 눌리지 않게 */
.income-grid .cell-sub { color: var(--label-alt); }
.admin-grid .ag-row.row-drop { background: rgba(0, 102, 255, .10); box-shadow: inset 0 0 0 2px #0058D6; }
.month-hint.bad { color: var(--warn, #9A5200); font-weight: 600; }
/* 통지서 — 고른 건의 미리보기(왼쪽 종이 · 오른쪽 정보) */
.fine-view { flex: none; display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 12px; padding: 12px; border-bottom: 1px solid var(--line-neutral); }
.fine-doc { min-width: 0; }
.fine-paper { width: 100%; height: clamp(200px, 30vh, 280px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 12px; border: 1.5px dashed var(--line-normal); border-radius: 6px; background: var(--tray); color: var(--label-alt); font: inherit; font-size: 12px; text-align: center; }
.fine-paper b { color: var(--label-normal); font-size: 13px; }
.fine-paper.has { padding: 0; border: 1px solid var(--line-normal); background: #fff; cursor: zoom-in; overflow: hidden; }
.fine-paper.has img { width: 100%; height: 100%; object-fit: contain; }
.fine-paper.has iframe { width: 100%; height: 100%; border: 0; pointer-events: none; }   /* 누름은 버튼이 받아 크게 보기를 연다 */
.fine-meta { min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.fine-meta h3 { margin: 0; font-size: 14px; font-weight: 700; }
.fine-meta dl { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 4px 8px; margin: 0; font-size: 12px; }
.fine-meta dt { color: var(--label-alt); font-weight: 600; }
.fine-meta dd { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fine-file { display: flex; justify-content: space-between; gap: 8px; padding: 6px 8px; border-radius: 4px; background: var(--thead); font-size: 12px; }
.fine-file b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fine-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.fine-big { height: 76vh; }
.fine-big img { width: 100%; height: 100%; object-fit: contain; }
.fine-big iframe { width: 100%; height: 100%; border: 0; }
/* 여러 장 놓기 칸 — 파일 입력은 보이지 않게만 두고(라벨이 연다) 키보드 포커스는 칸 테두리로 보인다 */
.fine-drop { flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px; margin: 10px 12px 0; padding: 12px; border: 1.5px dashed rgba(0, 88, 214, .45); border-radius: 6px; background: rgba(0, 102, 255, .04); color: #173D7A; font-size: 13px; text-align: center; cursor: pointer; }
.fine-drop small { color: var(--label-alt); font-size: 12px; }
.fine-drop.over, .fine-drop:focus-within { background: rgba(0, 102, 255, .10); border-color: #0058D6; }
.fine-drop input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.fine-tray-head { flex: none; display: flex; align-items: baseline; gap: 8px; padding: 10px 12px 6px; }
.fine-tray-head b { font-size: 13px; }
.fine-tray-head .sub { font-size: 12px; color: var(--label-alt); }
.fine-tray { flex: 1 0 140px; min-height: 140px; overflow: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); align-content: start; gap: 8px; padding: 0 12px 10px; }
.fine-thumb { display: flex; flex-direction: column; gap: 4px; padding: 6px; border: 1px solid var(--line-neutral); border-radius: 4px; background: var(--surface); font: inherit; text-align: left; cursor: grab; }
.fine-thumb.on { border-color: #0058D6; box-shadow: 0 0 0 2px rgba(0, 88, 214, .2); }
.fine-thumb .pg { height: 72px; display: flex; align-items: center; justify-content: center; overflow: hidden; border-radius: 2px; background: var(--tray); }
.fine-thumb .pg img { width: 100%; height: 100%; object-fit: cover; }
.fine-thumb .pdf { padding: 2px 6px; border-radius: 3px; background: rgba(200, 30, 30, .10); color: #C81E1E; font-size: 11px; font-weight: 700; }
.fine-thumb .nm { font-size: 11.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fine-thumb .sz { font-size: 11px; color: var(--label-alt); }
.fine-empty { margin: 0; padding: 12px; color: var(--label-alt); font-size: 12px; }
/* 직접 등록 팝업 — 레거시 과태료입력과 같은 두 묶음, 한 줄 두 칸 */
.fine-form h4 { margin: 4px 0 0; padding-bottom: 6px; border-bottom: 1px solid var(--line-neutral); font-size: 13px; color: var(--label-normal); }
.fine-form .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; }
.fine-form .grid > label { display: grid; grid-template-columns: 82px minmax(0, 1fr); align-items: center; gap: 8px; }
.fine-form .grid > label.w { grid-column: 1 / -1; }
.fine-form .grid > label > span { font-weight: 600; color: var(--label-alt); }
.fine-form .grid :is(input, select) { width: 100%; max-width: none; height: var(--ctl-h); }
.fine-form [data-amount], .fine-form #fine-bal { text-align: right; font-variant-numeric: tabular-nums; }
.fine-form #fine-bal.neg { color: var(--negative); font-weight: 700; }
.fine-form .grid > .file-row { grid-column: 1 / -1; display: grid; grid-template-columns: 82px minmax(0, 1fr); align-items: start; gap: 6px 8px; }
.fine-form .file-row > span { padding-top: 12px; font-size: 12px; font-weight: 600; color: var(--label-alt); }
.fine-form .file-row > :is(label.file-drop, .file-list) { grid-column: 2; }
.fine-form label.file-drop { flex-direction: row; justify-content: center; gap: 10px; padding: 10px 14px; }   /* 팝업 안이라 한 줄로 낮게 */
.fine-form .foot .hint { margin-right: auto; align-self: center; font-size: 12px; color: var(--label-alt); }
.card-panel { display: flex; flex-direction: column; min-height: 0; overflow: hidden; background: var(--surface); border-radius: 12px; box-shadow: inset 0 0 0 1px var(--line-neutral); }
.card-ph { flex: none; display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--line-neutral); }
.card-ph b { font-size: 14px; font-weight: 600; white-space: nowrap; }
.card-ph .sub { font-size: 12px; color: var(--label-alt); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-ph .spacer { flex: 1; }
.card-ph .seg-tabs button { padding: 4px 10px; font-size: 12px; }
#left-tabs, #detach-day { flex: none; }   /* 좁은 패널에서는 설명글(.sub)이 줄어든다 — 탭·버튼이 찌그러지지 않게 */
.card-ph input[type="search"] { flex: 0 1 200px; min-width: 0; height: 28px; padding: 0 10px; font-size: 12px; }
.card-scroll { flex: 1; min-height: 0; overflow: auto; }
.card-pf { flex: none; display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-top: 1px solid var(--line-neutral); background: var(--thead); font-size: 12px; font-variant-numeric: tabular-nums; }
.card-pf .spacer { flex: 1; }
.card-table { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.card-table th { position: sticky; top: 0; height: var(--thead-h); padding: 0 6px; background: var(--thead-strong); color: var(--thead-strong-ink); font-weight: 600; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--thead-strong-line); }
.card-table td { height: var(--row-h); padding: 0 6px; border-bottom: 1px solid var(--line-neutral); text-align: right; white-space: nowrap; }
.card-table th.l, .card-table td.l { text-align: left; } .card-table th.c, .card-table td.c { text-align: center; }
.card-table tr.picked td { background: rgba(0,191,64,.07); } .card-table tr.picked td:first-child { box-shadow: inset 3px 0 0 var(--brand); }
.card-table tr.bad td { background: rgba(255,66,66,.06); }
.card-table tr.click { cursor: pointer; }
/* 남는 폭만 쓰고 넘치면 말줄임 — 카드관리 가운데 카드명. max-width:0 이 있어야 표가 이 칸을 줄인다 */
.card-table th.fill, .card-table td.fill { width: 100%; max-width: 0; overflow: hidden; text-overflow: ellipsis; }
.card-table td.neg { color: var(--negative); font-weight: 600; } .card-table td.pos { color: var(--brand-strong); font-weight: 600; } .card-table td.mute { color: var(--label-assistive); }
.chn { display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 18px; padding: 0 5px; border-radius: 3px; font-size: 11px; font-weight: 700; letter-spacing: .02em; background: var(--fill-alt); color: var(--mute); }
/* 브랜드 초록은 "고른 것" 에만 쓴다 — 카드사 여섯은 서로 구분되기만 하면 되고 초록이면 선택으로 읽힌다 */
.chn.TM { background: rgba(47,95,196,.12); color: #1F55B5; } .chn.CS { background: rgba(168,52,126,.12); color: #9B2F72; } .chn.UT { background: rgba(23,23,25,.09); color: #37383C; }
.chn.IM { background: rgba(255,150,0,.16); color: #8A5200; } .chn.UP { background: rgba(106,59,176,.12); color: #5E36A0; } .chn.KN { background: rgba(0,122,122,.12); color: #00676B; }
/* 패널 안에 그리드를 넣을 때 — 스크롤은 그리드가 스스로 하고, 둥근 모서리·테두리는 패널이 이미 갖고 있다 */
.card-scroll.grid-host { overflow: hidden; }
/* 카드관리 미입력 "전월 이월" 탭 머리 안내 */
.carry-note { flex: none; margin: 0; padding: 8px 12px; border-bottom: 1px solid var(--line-neutral); font-size: 12px; line-height: 1.55; color: var(--label-alt); }
.carry-note.warn { background: rgba(255, 146, 0, 0.08); }
.admin-grid.flush { height: 100%; border-radius: 0; box-shadow: none; }

/* 미입력 승인건 — 차번을 못 알아본 줄(붙일 곳이 없다) · 기사를 아직 안 고른 칸 · 교대 경계 안내 */
.admin-grid .ag-row.row-bad { background: rgba(255, 66, 66, 0.05); }
/* 눌러서 골라야 하는 칸이다 — 가장 흐리게 두면 안 된다(대비 1.7:1 이었다) */
.income-grid .ag-cell.cell-empty { color: var(--label-alt); font-style: italic; }
/* 교대 경계 안내. 색만으로 알리지 않는다 — 앞에 표시를 붙이고 자릿수 정렬은 그대로 둔다 */
.income-grid .ag-cell.cell-near { color: var(--caution); font-weight: 600; }
/* 좁은 열(카드관리 미입력 — 사번·승인시각·채널·카드금)은 좌우 여백을 줄여 말줄임 없이 담는다 */
.income-grid .ag-cell.cell-tight { padding-left: 4px; padding-right: 4px; }
/* 그 열의 머리도 — 유류비관리 가운데 가맹 L · (구) L · 단가 */
.income-grid .ag-header-cell.head-tight { padding-left: 4px; padding-right: 4px; }
/* 대체카드 표시 — 배지(좌우 여백)는 48px 충전소 칸을 잘라 먹어 글자 하나만 붙인다 */
.income-grid .alt-mark { margin-left: 2px; font-size: 10px; font-weight: 700; color: var(--warn); }
.income-grid .ag-cell.cell-near::before { content: "⚠ "; font-weight: 400; }
/* 차량별 대조 · 붙은 승인건 — 차이 + 는 초록 · 원장 행 없는 차번 · 0 · 배차에서 온 기사 · 카드명 없음은 흐리게 */
.income-grid .ag-cell.cell-pos { color: var(--brand-strong); font-weight: 600; }
.income-grid .ag-cell.cell-mute { color: var(--label-assistive); }

.card-item { display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 10px; border-bottom: 1px solid var(--line-neutral); font-size: 12px; font-variant-numeric: tabular-nums; }
.card-item.bad { background: rgba(255,66,66,.05); }
.card-item b { font-size: 13px; width: 40px; } .card-item .t { color: var(--label-alt); width: 80px; } .card-item .amt { font-size: 13px; font-weight: 600; width: 60px; text-align: right; }
.card-item select, .card-item input { flex: 1; min-width: 0; height: 26px; padding: 0 6px; border-radius: 6px; font-size: 12px; }
.card-item .near { font-size: 11px; color: var(--caution); white-space: nowrap; }
.card-form { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px; font-size: 13px; }
.card-form label { display: flex; flex-direction: column; gap: 4px; color: var(--label-alt); font-size: 12px; }
.card-form input, .card-form select { height: 34px; padding: 0 10px; border-radius: 8px; font-size: 13px; }
.card-form .row { display: flex; gap: 8px; } .card-form .row > label { flex: 1; }
.card-form .foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.card-form table { font-size: 11px; } .card-form td, .card-form th { padding: 2px 6px; white-space: nowrap; }
.card-busy { display: flex; flex-direction: column; gap: 6px; margin: 0; color: var(--label-alt); font-size: 12px; }
.card-busy progress { width: 100%; height: 6px; accent-color: var(--brand-heavy); }

/* 파일 선택(taxi-util.js TaxiGrid.fileDrop — 카드·타코 올리기) — 끌어 놓는 상자 + 고른 파일 목록. 네이티브 input 은 상자 안에 숨어 포커스·files 를 맡는다.
   label 이라 .card-form label 과 겹친다 — 뒤에 두어 이긴다. */
label.file-drop { position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 18px 16px; border: 1px dashed var(--bd-hov); border-radius: var(--r); background: var(--bg); color: var(--label-alt); font-size: 12px; text-align: center; cursor: pointer; transition: border-color 120ms var(--ease), background 120ms var(--ease), color 120ms var(--ease); }
label.file-drop b { font-weight: 600; font-size: 13px; color: var(--label-normal); }
label.file-drop u { color: var(--brand-heavy); text-decoration: none; }
label.file-drop .sub { color: var(--label-assistive); }
label.file-drop:hover, label.file-drop.over { border-color: var(--brand-heavy); background: rgba(22, 126, 91, 0.05); color: var(--brand-heavy); }
label.file-drop.over { border-style: solid; }
label.file-drop:focus-within { border-color: var(--brand-heavy); box-shadow: 0 0 0 3px var(--ring); }
label.file-drop:has(input:disabled) { opacity: .5; cursor: default; pointer-events: none; }
label.file-drop input[type=file] { position: absolute; width: 1px; height: 1px; padding: 0; border: 0; opacity: 0; pointer-events: none; }
.file-list { margin: 0; padding: 0; list-style: none; }
.file-list:empty { display: none; }
.file-list li { display: flex; align-items: center; gap: 8px; height: var(--row-h); border-bottom: 1px solid var(--line-neutral); font-size: 12.5px; }
.file-list .ext { flex: none; min-width: 36px; padding: 1px 4px; border-radius: 3px; background: rgba(22, 126, 91, 0.10); color: var(--brand-heavy); font-size: 10px; font-weight: 700; text-align: center; text-transform: uppercase; }
.file-list .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--label-normal); }
.file-list .sz { flex: none; color: var(--label-alt); font-variant-numeric: tabular-nums; }

/* ---------- 푸시발송 ---------- */

/* 좌 대상 380px + 우(보내기 · 이력). 인사관리처럼 FHD 한 장이라 프레임 패딩을 줄인 화면(push.jsp)이다. */
.push-layout { display: grid; grid-template-columns: 380px minmax(0, 1fr); gap: 10px; height: calc(100vh - 110px); min-height: 520px; }
.push-right { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.push-ctl { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--line-neutral); }
.push-ctl form { display: contents; }
.push-ctl .seg { display: flex; gap: 4px; }
.push-ctl .seg-btn { flex: 1; height: 26px; line-height: 26px; text-align: center; font-size: 12px; border-radius: 6px; background: var(--fill-alt); color: var(--label-alt); }
.push-ctl .seg-btn.on { background: var(--brand); color: #fff; font-weight: 600; }
.push-ctl input[type="search"], .push-ctl select { height: 28px; font-size: 12px; padding: 0 10px; border-radius: 8px; width: 100%; }
.push-list label { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 10px; border-bottom: 1px solid var(--line-neutral); font-size: 13px; font-variant-numeric: tabular-nums; cursor: pointer; }
.push-list label.on { background: rgba(33, 163, 119, .06); }
.push-list label.off { color: var(--label-assistive); cursor: default; }
.push-list .no { width: 44px; color: var(--label-alt); } .push-list .nm { flex: 1; } .push-list .dv { font-size: 12px; color: var(--label-alt); }
.push-list label.off .no, .push-list label.off .dv { color: var(--label-assistive); }
.push-list .coop-nm { flex: 1; font-weight: 600; } .push-list .coop-sub { font-size: 12px; color: var(--label-alt); }
.push-compose { display: grid; grid-template-columns: 120px 1fr; gap: 10px 12px; align-items: center; padding: 14px 16px; }
.push-compose .lbl { font-size: 12px; color: var(--label-alt); }
.push-compose .lbl.top { align-self: start; padding-top: 8px; }
.push-compose input[type="text"], .push-compose input[type="month"], .push-compose select { height: 32px; font-size: 13px; border-radius: 8px; padding: 0 12px; }
.push-compose textarea { min-height: 88px; font-size: 13px; border-radius: 8px; padding: 10px 12px; }
.push-compose .inline { display: flex; align-items: center; gap: 12px; }
.push-compose .chip { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: 6px; background: var(--fill-alt); font-size: 12px; color: var(--label-alt); }
.push-compose .chip b { color: var(--label-normal); font-weight: 600; }
.push-compose .hint { font-size: 12px; color: var(--label-alt); } .push-compose .hint b { color: var(--label-normal); font-weight: 600; }
.push-compose .btn:disabled { background: var(--fill-alt); color: var(--label-assistive); cursor: not-allowed; }
.push-detail-stats { margin: 0 0 12px; }

/* ---- 타코관리 (/admin/tacho) — 카드관리의 .card-* 위에 지표 칸 · 그래프만 더한다 ---- */
.tacho-layout { grid-template-columns: 560px minmax(0, 1fr) 430px; }   /* 좌 대조 7열(그리드, 2026-11-02)이 가로 스크롤 없이 서는 폭 · 우 영업건 7열 */
.tacho-center { display: flex; flex-direction: column; overflow: hidden; }
.tacho-metrics { flex: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line-neutral); border-bottom: 1px solid var(--line-neutral); }
.tacho-metrics div { background: var(--surface); padding: 9px 12px 8px; min-width: 0; }
.tacho-metrics small { display: block; font-size: 11px; color: var(--label-alt); white-space: nowrap; }
.tacho-metrics b { font-size: 16px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.tacho-metrics b i { font-style: normal; font-size: 11px; font-weight: 500; color: var(--label-alt); margin-left: 3px; }
.tacho-metrics em { font-style: normal; font-size: 11px; margin-left: 6px; font-weight: 600; color: var(--label-alt); }
.tacho-metrics em.neg { color: var(--negative); } .tacho-metrics em.cau { color: var(--caution); } .tacho-metrics em.pos { color: var(--positive); }
.tacho-chart-head { flex: none; display: flex; align-items: center; gap: 14px; padding: 10px 14px 0; font-size: 11px; color: var(--label-alt); }
.tacho-chart-head b { color: var(--label-normal); font-weight: 600; font-size: 12px; margin-right: auto; }
.tacho-chart-head i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
canvas.tacho-speed { display: block; flex: 1; width: 100%; min-height: 160px; }
.card-table tr.hl td { background: rgba(33,163,119,.08); }
.income-stats .stat.cau .n { color: var(--caution); }

/* ---------- 셸 헤더 · 현재 조합 선택기 ---------- */

/* 접근 가능한 조합이 여럿일 때만 셀렉트다. 하나면 글자만 찍는다(.one). */
.coop-picker { display: flex; align-items: center; gap: 7px; padding: 4px 10px; border-radius: 8px; background: rgba(255, 255, 255, .09); border: 1px solid rgba(255, 255, 255, .18); }
.coop-picker label { font-size: 11px; color: rgba(255, 255, 255, .55); white-space: nowrap; }
.coop-picker b { font-size: 13px; color: #fff; }
.coop-picker select { height: 24px; padding: 0 22px 0 6px; border: 0; border-radius: 6px; background: transparent; color: #fff; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.coop-picker select option { color: var(--label-normal); }
.coop-picker select:focus-visible { outline: 2px solid var(--brand-light); outline-offset: 1px; }

/* ---------- 관리자관리 ---------- */

/* 좌 목록 520px + 우 상세 3단. 행이 적어 ag-grid 없이 표로 그린다(카드관리와 같다). */
.adm-layout { display: grid; grid-template-columns: 520px minmax(0, 1fr); gap: 10px; height: calc(100vh - 130px); min-height: 520px; }
.adm-right { display: flex; flex-direction: column; gap: 10px; min-height: 0; overflow: auto; }
.adm-ctl { flex: none; display: flex; gap: 8px; align-items: center; padding: 8px 12px; border-bottom: 1px solid var(--line-neutral); }
.adm-ctl form { display: contents; }
.adm-ctl input[type="search"] { flex: 1; height: 28px; padding: 0 10px; border-radius: 8px; font-size: 12px; }
.adm-ctl label { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--label-alt); white-space: nowrap; cursor: pointer; }

.adm-badge { display: inline-block; min-width: 38px; padding: 2px 8px; border-radius: 6px; font-size: 11px; font-weight: 700; }
.adm-badge.SUPER { background: var(--header); color: #fff; }
.adm-badge.GENR { background: rgba(33, 163, 119, .13); color: var(--brand-strong); }
.adm-badge.CEO { background: var(--caution-bg); color: var(--caution); }
.adm-badge.STLM { background: var(--done-bg); color: var(--done); }
.st-on { padding: 2px 8px; border-radius: 6px; font-size: 11px; background: var(--positive-bg); color: var(--positive); }
.st-lock { padding: 2px 8px; border-radius: 6px; font-size: 11px; background: var(--negative-bg); color: var(--negative); }
.st-temp { padding: 2px 8px; border-radius: 6px; font-size: 11px; background: var(--caution-bg); color: var(--caution); }

.adm-form { display: grid; grid-template-columns: 92px minmax(0, 1fr) 92px minmax(0, 1fr); gap: 8px 10px; padding: 12px 14px; align-items: center; }
.adm-form .lbl { font-size: 12px; color: var(--label-alt); text-align: right; }
.adm-form .req { color: var(--negative); font-style: normal; margin-left: 2px; }
.adm-form input, .adm-form select { width: 100%; height: 30px; padding: 0 8px; border: 1px solid var(--line-normal); border-radius: 7px; font: inherit; font-size: 13px; background: var(--surface); }
.adm-form input:disabled, .adm-form select:disabled { background: var(--fill-alt); color: var(--label-alt); }

.adm-scope { padding: 12px 14px; }
.adm-scope-all { margin: 0; padding: 14px; border: 1px dashed var(--line-normal); border-radius: 9px; background: var(--fill-alt); color: var(--label-alt); font-size: 13px; text-align: center; }
.adm-scope .adm-one { width: 100%; height: 32px; padding: 0 8px; border: 1px solid var(--line-normal); border-radius: 8px; font: inherit; font-size: 13px; }
.adm-coops { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.adm-coop { display: flex; align-items: center; gap: 7px; padding: 7px 9px; border: 1px solid var(--line-neutral); border-radius: 8px; font-size: 13px; cursor: pointer; }
.adm-coop.on { border-color: var(--brand); background: rgba(33, 163, 119, .07); }

.adm-acct { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; padding: 11px 14px; background: var(--tray); }
.adm-acct .kv { font-size: 12px; color: var(--label-alt); font-variant-numeric: tabular-nums; }
.adm-acct .kv b { color: var(--label-normal); font-weight: 600; }
.adm-acct .spacer { flex: 1; }

/* 등록 레이어 — 셸이 그리므로 폼 전송이 아니라 프레임에서 postForm 으로 나간다 */
.adm-new { display: flex; flex-direction: column; gap: 9px; padding: 14px 16px; }
.adm-new label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--label-alt); }
.adm-new input, .adm-new select { height: 32px; padding: 0 9px; border: 1px solid var(--line-normal); border-radius: 8px; font: inherit; font-size: 13px; }
.adm-new select[multiple] { height: 96px; padding: 4px; }
.adm-new .adm-hint { margin: 0; font-size: 12px; line-height: 1.6; color: var(--caution); background: var(--caution-bg); border-radius: 8px; padding: 9px 11px; }
.adm-new .foot { display: flex; justify-content: flex-end; gap: 7px; margin-top: 4px; }

/* 임시 비밀번호는 받아적는 값이다 — 한 번만 보이므로 눈에 띄게 */
.temp-pw { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 17px; letter-spacing: .08em; }

/* ---------- 메뉴관리 ---------- */

.card-table tr.mute td { color: var(--label-assistive); }
.menu-child { padding-left: 16px; }
.card-table code { font-size: 11.5px; color: var(--label-alt); }
.adm-badge.off { background: var(--fill-alt); color: var(--label-assistive); }
.ord { border: 0; background: none; color: var(--label-assistive); font-size: 10px; cursor: pointer; padding: 0 2px; line-height: 1; }
.ord:hover { color: var(--brand); }
.adm-form .span3 { grid-column: 2 / 5; }

/* ---------- 공지관리 ---------- */

/* 좌 목록 + 중 편집 + 우 앱 미리보기. 행이 적어 ag-grid 없이 표로 그린다(관리자관리와 같다). */
.ntc-layout { display: grid; grid-template-columns: minmax(380px, 460px) minmax(0, 1fr) 340px; gap: 10px; height: calc(100vh - 130px); min-height: 520px; }
.ntc-layout .card-panel.preview .card-scroll { background: var(--tray); }
.ntc-ttl { font-weight: 600; line-height: 1.35; white-space: normal; }
.ntc-ttl small { display: block; font-weight: 400; color: var(--label-alt); font-size: 11.5px; margin-top: 2px; max-width: 34ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-table tr.mute .ntc-ttl { color: var(--label-assistive); }
.ntc-all { display: inline-block; margin-left: 4px; padding: 1px 6px; border-radius: 5px; font-size: 10.5px; font-weight: 700; background: var(--header); color: #fff; }
.st-off { padding: 2px 8px; border-radius: 6px; font-size: 11px; background: var(--fill-alt); color: var(--label-alt); }

/* 구분 배지 — 앱 CategoryBadge 와 같은 색 (news_data.dart NoticeCategory) */
.ntc-cat { display: inline-flex; align-items: center; border-radius: 6px; padding: 2px 8px; font-size: 11px; font-weight: 700; white-space: nowrap; line-height: 1.65; }
.ntc-cat.NOTI { background: rgba(112, 115, 124, .10); color: rgba(46, 47, 51, .88); }
.ntc-cat.STLM { background: rgba(33, 163, 119, .12); color: var(--brand); }
.ntc-cat.WLFR { background: rgba(123, 91, 214, .12); color: #7B5BD6; }
.ntc-cat.EDUC { background: rgba(232, 118, 13, .12); color: #E8760D; }
#ntc-tabs button { display: inline-flex; align-items: center; gap: 6px; }
#ntc-tabs button[aria-pressed="true"] .ntc-cat { background: rgba(255, 255, 255, .22); color: #fff; }
#ntc-tabs .n { font-size: 11px; opacity: .75; }

.ntc-form { display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 10px; padding: 13px 14px; align-items: center; }
.ntc-form .lbl { font-size: 12px; color: var(--label-alt); text-align: right; }
.ntc-form .lbl.top { align-self: start; padding-top: 8px; }
.ntc-form .req { color: var(--negative); font-style: normal; margin-left: 2px; }
.ntc-form input[type="text"], .ntc-form textarea { width: 100%; border: 1px solid var(--line-normal); border-radius: 7px; padding: 6px 9px; font: inherit; font-size: 13px; background: var(--surface); }
.ntc-form textarea { line-height: 1.6; resize: vertical; }
.ntc-form input:disabled, .ntc-form textarea:disabled { background: var(--fill-alt); color: var(--label-alt); }
.ntc-form .hint { margin: 6px 0 0; font-size: 11.5px; color: var(--label-alt); line-height: 1.6; }
.ntc-form .hint.ntc-locked { color: var(--caution); margin: 0; }
.ntc-form .chk { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.ntc-catpick { display: flex; gap: 6px; flex-wrap: wrap; }
.ntc-catpick .ntc-cat { padding: 6px 12px; font-size: 12.5px; cursor: pointer; border: 1px solid transparent; opacity: .5; }
.ntc-catpick .ntc-cat.sel { opacity: 1; border-color: currentColor; }
.ntc-catpick .ntc-cat.sel::before { content: "✓ "; }
.ntc-scope button { font-size: 12px; padding: 5px 12px; }

/* 앱 미리보기 — 폰 프레임. 여백·글자 크기는 앱 NoticeTile 규격을 옮긴 것이다 */
.ntc-phone { margin: 12px auto; width: 290px; border-radius: 30px; background: #111; padding: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, .18); }
.ntc-screen { background: #fff; border-radius: 22px; overflow: hidden; font-size: 12.5px; }
.ntc-screen .sbar { display: flex; justify-content: space-between; padding: 8px 16px 0; font-size: 10.5px; font-weight: 600; color: #111; }
.ntc-screen .app-search { margin: 10px 12px 4px; border: 1px solid var(--line-normal); border-radius: 9px; padding: 7px 10px; font-size: 11.5px; color: var(--label-alt); }
.ntc-screen .app-tabs { display: flex; border-bottom: 1px solid var(--line-normal); }
.ntc-screen .app-tabs span { flex: 1; text-align: center; padding: 9px 0; font-size: 12px; color: var(--label-alt); }
.ntc-screen .app-tabs span.on { color: var(--brand); font-weight: 700; box-shadow: inset 0 -2px 0 var(--brand); }
.ntc-tile { display: flex; gap: 10px; padding: 11px 14px; border-bottom: 1px solid var(--line-normal); }
.ntc-tile.live { background: rgba(33, 163, 119, .06); box-shadow: inset 3px 0 0 var(--brand); }
.ntc-tile.off { color: var(--label-alt); font-size: 11.5px; justify-content: center; background: var(--fill-alt); }
.ntc-tile .body { flex: 1; min-width: 0; }
.ntc-tile .t1, .ntc-detail .t1 { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.ntc-tile .t1 .ntc-cat, .ntc-detail .t1 .ntc-cat { font-size: 10.5px; padding: 1px 7px; }
.ntc-tile .d, .ntc-detail .d { font-size: 10.5px; color: var(--label-alt); }
.ntc-tile .ttl { font-size: 13px; font-weight: 600; line-height: 1.35; margin-bottom: 3px; color: #171719; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ntc-tile .ex { font-size: 11.5px; color: var(--label-alt); line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ntc-tile .chev { color: var(--label-assistive); font-size: 14px; align-self: flex-start; margin-top: 2px; }
.ntc-detail { padding: 14px 16px 18px; border-top: 6px solid var(--tray); }
.ntc-detail h4 { margin: 8px 0 10px; font-size: 15px; font-weight: 700; line-height: 1.35; letter-spacing: -.01em; color: #171719; }
.ntc-detail p { margin: 0 0 10px; font-size: 12px; line-height: 1.65; color: #2e2f33; }
.ntc-detail p.dim { color: var(--label-assistive); }

/* ---------- FAQ관리 ---------- */

/* 공지관리와 같은 3단이고 .ntc-form · .ntc-phone 을 같이 쓴다. 더한 것은 끌기 손잡이 · 구분 묶음 줄 · 펼침 미리보기다 */
.faq-layout { display: grid; grid-template-columns: minmax(440px, 780px) minmax(360px, 1fr) 404px; gap: 10px; height: calc(100vh - 130px); min-height: 520px; }
.faq-layout .card-panel.preview .card-scroll { background: var(--tray); }
#faq-tabs button { display: inline-flex; align-items: center; gap: 5px; }
#faq-tabs .n { font-size: 11px; opacity: .75; }
.faq-hd { display: inline-grid; grid-template-columns: repeat(2, 3px); gap: 2px 3px; vertical-align: middle; opacity: .55; cursor: grab; }
.faq-hd i { width: 3px; height: 3px; border-radius: 50%; background: var(--label-alt); }
.faq-hd.no { opacity: .15; cursor: default; }
.faq-coop { font-size: 11.5px; color: var(--label-alt); }
.card-table tr.faq-grp td { height: 28px; background: var(--thead); text-align: left; font-weight: 700; color: var(--label-neutral); }
.card-table tr.faq-grp td em { font-style: normal; font-weight: 500; color: var(--label-alt); margin-left: 6px; }
.card-table tr.dragging td { opacity: .4; }
.card-table tr.drop-before td { box-shadow: inset 0 2px 0 var(--brand); }
.card-table tr.drop-after td { box-shadow: inset 0 -2px 0 var(--brand); }
#faq-form select { width: var(--w-name); }
#faq-form .faq-cnt { display: flex; gap: 10px; font-variant-numeric: tabular-nums; }
#faq-form .faq-cnt .spacer { flex: 1; }
#faq-form .faq-meta { grid-column: 1 / -1; margin: 6px 0 0; padding-top: 12px; border-top: 1px solid var(--line-neutral); font-size: 12px; color: var(--label-alt); font-variant-numeric: tabular-nums; }
.faq-phone { width: 380px; }
.faq-phone .faq-bar { padding: 12px 14px 4px; font-size: 15px; font-weight: 600; color: #171719; }
.faq-item { border-bottom: 1px solid var(--line-normal); }
.faq-item.open { box-shadow: inset 3px 0 0 var(--brand); }
.faq-q { display: flex; gap: 10px; padding: 13px 14px 13px 18px; font-size: 13.5px; line-height: 1.45; font-weight: 600; color: #171719; }
.faq-q b { flex: none; width: 16px; color: var(--brand); font-size: 15px; }
.faq-q span { flex: 1; min-width: 0; }
.faq-q i { font-style: normal; color: var(--label-assistive); }
.faq-a { margin: 0 14px 14px; padding: 12px 14px; border-radius: 12px; background: rgba(112, 115, 124, .05); }
.faq-a p { margin: 0; font-size: 13px; line-height: 1.6; color: #2e2f33; }
.faq-a p + p { margin-top: 8px; }
.faq-a p.dim { color: var(--label-assistive); }

/* ---------- 출자금 — 요약 타일 + 회차표(인사관리 출자금 탭, .cap-pane 이 위에 얹는다) ---------- */

.cap-sum { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.cap-sum .tile { border: 1px solid var(--line-neutral); border-radius: 9px; padding: 9px 11px; }
.cap-sum .tile small { display: block; font-size: 11px; color: var(--label-alt); margin-bottom: 3px; }
.cap-sum .tile b { font-size: 15px; font-weight: 700; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.cap-sum .tile.hi { border-color: var(--brand); background: rgba(33, 163, 119, .06); }
.cap-sched-wrap { max-height: 380px; overflow: auto; border: 1px solid var(--line-neutral); border-radius: 8px; }
.cap-sched-wrap thead th { position: sticky; top: 0; z-index: 1; }
.cap-sched tr.k-paid td, .cap-sched tr.k-prepay td { color: var(--label-alt); }
.cap-sched tr.k-now td { background: rgba(33, 163, 119, .08); font-weight: 600; }
.cap-sched tr.k-plan td { color: var(--label-assistive); }
.cap-sched tr.k-missed td { background: rgba(255, 66, 66, .05); }
.cap-sched tr.k-open td { color: var(--warn); }
.cap-sched tr.k-stop td { background: rgba(255, 150, 0, .07); }

/* ---------- 출자금관리 화면(급여관리 > 출자금관리) — 패널은 카드관리의 .card-panel, 오른쪽 안쪽은 인사관리 출자금 탭의 .cap-pane 그대로 ----------
   높이는 .month-grid 와 같은 채우기 규칙(.frame-body flex)이 정한다. 여기 적는 것은 두 칸 배치와 좁은 패널에 맞춘 두 줄뿐이다. */
.cap-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(480px, 600px); grid-auto-rows: minmax(0, 1fr); gap: 10px; }
.cap-layout .cap-pane { display: flex; flex-direction: column; gap: 10px; padding: 12px; }
.cap-layout .cap-pane .cap-sum { grid-template-columns: repeat(3, 1fr); }   /* 탭은 여섯 칸 한 줄 — 패널 폭에선 세 칸 두 줄 */


/* ---------- 알림톡 (/admin/alimtalk · /admin/alimtalk/templates) ---------- */

/* 푸시발송의 .push-* · .card-* 위에 템플릿 카드 · 카카오톡 미리보기만 더한다. 카카오 노랑은 이 화면에서만 쓴다. */
:root { --kakao: #FEE500; --kakao-ink: #191600; --kakao-chat: #B2C7D9; --kakao-sub: #55606C; }
.atlk-layout { display: grid; grid-template-columns: 360px minmax(0, 1fr) 400px; gap: 10px; height: calc(100vh - 110px); min-height: 520px; }
.atlk-sender { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--label-alt); white-space: nowrap; }
.atlk-sender b { color: var(--label-normal); font-weight: 600; }
.atlk-channel { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px 0 6px; border-radius: 14px; background: var(--kakao); color: var(--kakao-ink); font-weight: 700; font-size: 12px; }
.atlk-channel i { width: 18px; height: 18px; border-radius: 50%; background: var(--kakao-ink); color: var(--kakao); font-style: normal; font-size: 9px; display: inline-flex; align-items: center; justify-content: center; }
.atlk-channel.off { padding: 0 10px; background: var(--fill-alt); color: var(--label-alt); }
.atlk-muted { font-size: 12px; color: var(--label-alt); }
.atlk-err { font-size: 12px; color: var(--negative); }
.atlk-empty { margin: 0; font-size: 13px; color: var(--label-alt); line-height: 1.6; }
.atlk-sms { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--label-alt); white-space: nowrap; cursor: pointer; }
.badge.info { background: rgba(0, 102, 255, .09); color: #0058D6; }

.atlk-tpls { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; padding: 12px 16px 0; }
.atlk-tpl { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding: 9px 12px; border: 0; border-radius: 10px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line-normal); font: inherit; text-align: left; color: inherit; cursor: pointer; }
.atlk-tpl .t { font-size: 13px; font-weight: 700; } .atlk-tpl .s { font-size: 11px; color: var(--label-alt); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.atlk-tpl.on { box-shadow: inset 0 0 0 2px var(--brand); background: rgba(33, 163, 119, .05); }
.atlk-tpl:focus-visible, .atlk-row:focus-visible, .card-table tr.click:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.push-compose input[type="date"] { height: 32px; font-size: 13px; border-radius: 8px; padding: 0 12px; }
.push-compose .atlk-err { font-weight: 600; }

.atlk-row { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 10px; border-bottom: 1px solid var(--line-neutral); font-size: 13px; font-variant-numeric: tabular-nums; cursor: pointer; }
.atlk-row.on { background: rgba(33, 163, 119, .06); }
.atlk-row.off { color: var(--label-assistive); }
.atlk-row.cur { box-shadow: inset 3px 0 0 var(--kakao-ink); background: rgba(254, 229, 0, .16); }
.atlk-row .no { width: 40px; color: var(--label-alt); }
.atlk-row .nm { width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.atlk-row .tel { flex: 1; font-size: 12px; color: var(--label-alt); }
.atlk-row .val { font-size: 12px; color: var(--label-neutral); }
.atlk-row .why { font-size: 11px; padding: 1px 6px; border-radius: 4px; background: var(--fill-alt); color: var(--label-alt); white-space: nowrap; }
.atlk-row.off .no, .atlk-row.off .tel { color: var(--label-assistive); }

/* 카카오톡 미리보기 — 채팅방 바탕 · 노란 띠 말풍선 · 회색 버튼. 딜러사 미리보기 모양을 옮겼다 */
.atlk-phone { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--kakao-chat); overflow: auto; }
.atlk-chat-top { padding: 10px 14px; background: rgba(255, 255, 255, .2); font-size: 14px; font-weight: 700; color: #1D2833; }
.atlk-chat { display: flex; gap: 8px; align-items: flex-start; padding: 16px 14px; }
.atlk-pf { width: 38px; height: 38px; border-radius: 14px; background: var(--kakao); flex: none; }
.atlk-msg { display: flex; flex-direction: column; gap: 4px; max-width: 290px; min-width: 0; }
.atlk-who { font-size: 12px; color: var(--kakao-sub); }
.atlk-bubble { border-radius: 4px 14px 14px 14px; background: #fff; overflow: hidden; }
.atlk-band { display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; background: var(--kakao); font-size: 12.5px; font-weight: 700; color: var(--kakao-ink); }
.atlk-band small { font-size: 10px; font-weight: 700; padding: 1px 5px; border-radius: 3px; background: var(--kakao-ink); color: var(--kakao); }
.atlk-body { padding: 14px 12px; font-size: 13.5px; line-height: 1.6; color: #111; white-space: pre-wrap; word-break: break-word; }
.atlk-body mark { background: rgba(254, 229, 0, .55); color: inherit; border-radius: 3px; padding: 0 2px; }
.atlk-body mark.miss { background: var(--negative-bg); color: var(--negative); }
.atlk-kbtn { margin: 0 12px 8px; min-height: 36px; padding: 6px 10px; display: flex; align-items: center; justify-content: center; border-radius: 6px; background: #F2F2F2; font-size: 13px; color: #111; text-align: center; }
.atlk-kbtn:last-child { margin-bottom: 12px; }
.atlk-fallback { margin: 0 14px 14px; padding: 10px 12px; border-radius: 8px; background: rgba(255, 255, 255, .55); font-size: 12px; line-height: 1.5; color: #2C3640; }
.atlk-fallback:empty { display: none; }

/* 템플릿 화면 — 좌 목록 + 우 상세 */
.atlk-tw { display: grid; grid-template-columns: minmax(0, 1fr) 560px; gap: 10px; height: calc(100vh - 110px); min-height: 520px; }
.atlk-wrap { white-space: normal !important; line-height: 1.8; padding-top: 4px !important; padding-bottom: 4px !important; }
.atlk-var { display: inline-block; padding: 0 6px; margin: 0 2px 0 0; border-radius: 5px; font-size: 11.5px; font-weight: 600; line-height: 1.7; background: rgba(254, 229, 0, .38); color: var(--kakao-ink); white-space: nowrap; }
.atlk-var.input { background: var(--fill-alt); color: var(--label-neutral); }
.atlk-var.wrong { background: var(--negative-bg); color: var(--negative); }
.atlk-form { display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 12px; align-items: center; align-content: start; padding: 14px 16px; }
.atlk-form .lbl { font-size: 12px; color: var(--label-alt); } .atlk-form .lbl.top { align-self: start; padding-top: 8px; }
.atlk-form select { height: 32px; font-size: 13px; border-radius: 8px; padding: 0 10px; width: 200px; }
.atlk-text { padding: 10px 12px; border-radius: 8px; background: var(--fill-alt); font-size: 13px; line-height: 1.8; white-space: pre-wrap; word-break: break-word; color: var(--label-neutral); }
.atlk-btnline { font-size: 12px; line-height: 1.8; color: var(--label-alt); word-break: break-all; } .atlk-btnline b { color: var(--label-normal); font-weight: 600; }
.atlk-guide { font-size: 12px; color: var(--label-alt); line-height: 2; }
.atlk-layout .push-ctl .seg-btn { border: 0; font: inherit; font-size: 12px; cursor: pointer; }

/* 인쇄 — 딥그린 머리는 배경을 안 찍는 기본 설정에서 흰 글자만 남아 백지가 된다.
   화면 대비를 위한 색이라 종이에서는 회색 머리로 되돌린다(임금명세서는 자기 style 을 갖고 있어 별개다). */
@media print {
    .admin-grid .ag-header-row,
    .admin-grid .ag-header-cell,
    .income-sheet th,
    .side-panel th,
    .pay-table th,
    .rule-sheet th,
    .slip-table th,
    .card-table th {
        background: #EEEEF0 !important;
        color: #171719 !important;
    }

    .admin-grid .ag-header-cell-text,
    .month-grid .ag-header-group-cell .ag-header-group-text {
        color: #171719 !important;
    }

    .admin-note { display: none !important; }
}


/* ── 셀렉트 드롭 (taxi-select.js) · 시안 A ────────────────────────────────
   닫힌 칸은 네이티브 <select> 그대로다 — 위의 공통 규칙(height var(--ctl-h) · 1px 실선 ·
   반경 var(--r) · 파일 끝의 꺾쇠 SVG)이 이미 A 이고, 화면마다 걸어 둔 높이
   (.rec-form 26 · .rowtable 24 · 패널 34 · .adm-form 30 · .push-ctl 28 · .atlk-form 32)도
   그 자리에 그대로 남는다. 여기서 새로 그리는 것은 "열었을 때의 목록" 하나다.
   목록은 그 문서의 body 에 position:fixed 로 붙는다 — 프레임 안의 스크롤 상자
   (.panel-body · .card-scroll · .rule-cols · .layer-box)가 absolute 를 잘라 먹기 때문이다. */

.tx-sel-pop {
    position: fixed;
    z-index: 200;                /* 상세 패널 21 · 레이어 41 · 셸 알림 60 위 */
    display: flex;
    flex-direction: column;
    min-width: 0;
    max-width: 480px;            /* 1920 에서 칸 폭을 그대로 따르면 13px 글자가 왼쪽 끝에 고립된다 */
    border: 1px solid var(--line-normal);
    border-radius: var(--r);
    background: var(--surface);
    box-shadow: var(--pop);      /* 그림자는 띄우는 것에만 */
    overflow: hidden;
    font-size: 13px;
    color: var(--label-normal);
}

.tx-sel-pop[hidden] {
    display: none;
}

.tx-sel-head {
    flex: none;
    padding: 6px;
    border-bottom: 1px solid var(--line-neutral);
}

.tx-sel-head[hidden] {
    display: none;
}

/* 읽기전용 표시칸이다 — 포커스는 늘 select 에 있고 타이핑이 여기 비친다 */
.tx-sel-search {
    width: 100%;
    height: 26px;
    padding: 0 8px;
    border: 1px solid var(--bd);
    border-radius: 3px;
    background: var(--surface);
    font: inherit;
    font-size: 12.5px;
    color: var(--label-normal);
    cursor: default;
}

.tx-sel-search::placeholder {
    color: var(--label-alt);
}

.tx-sel-list {
    position: relative;          /* 줄의 offsetTop 기준 — 커서를 따라 스크롤한다 */
    flex: 1 1 auto;
    min-height: 0;
    max-height: 232px;
    padding: 2px 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(112, 115, 124, 0.34) transparent;
}

.tx-sel-list::-webkit-scrollbar {
    width: 10px;
}

.tx-sel-list::-webkit-scrollbar-track {
    background: transparent;
}

.tx-sel-list::-webkit-scrollbar-thumb {
    background: rgba(112, 115, 124, 0.32);
    border: 3px solid var(--surface);
    border-radius: 99px;
}

.tx-sel-opt {
    position: relative;
    display: flex;
    align-items: center;
    height: 28px;
    padding: 0 8px 0 24px;
    color: var(--label-neutral);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
}

.tx-sel-opt.on {                 /* 커서 — 무채색이다, 브랜드색은 고른 것에만 */
    background: var(--fill-alt);
    color: var(--label-normal);
}

.tx-sel-opt.sel {
    background: rgba(33, 163, 119, 0.08);
    color: var(--brand-heavy);
    font-weight: 600;
}

.tx-sel-opt.sel.on {
    background: rgba(33, 163, 119, 0.14);
}

.tx-sel-opt.sel::before {        /* 체크표시 — 두 변만 남긴 사각형 */
    content: "";
    position: absolute;
    left: 9px;
    top: 9px;
    width: 4px;
    height: 8px;
    border: solid var(--brand-heavy);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.tx-sel-opt.off {
    color: var(--label-assistive);
    cursor: not-allowed;
}

.tx-sel-opt.off.on {
    background: transparent;
}

.tx-sel-none {
    display: flex;
    align-items: center;
    height: 28px;
    padding: 0 8px 0 24px;
    color: var(--label-assistive);
}

/* 열려 있는 칸 — 브랜드색은 "지금 열려 있다"는 상태에만 쓴다.
   .rec-form .rowtable select (0,2,1) 를 이기려고 같은 특이도로 파일 끝에 둔다(꺾쇠 규칙과 같은 이유). */
select.tx-sel.open {
    border-color: var(--brand-heavy);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23167E5B' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 15 12 9 18 15'/></svg>");
}

/* ---------- 날짜 · 달력 (taxi-date.js · 시안 A) ---------- */

:root {
    /* 달력 요일색. 흰 바탕이라 진한 쪽이다 — 딥그린 표머리 위의 #FF9C9C·#9DC0FF 와 짝이고
       값은 콘솔이 이미 쓰던 것과 같다(.income-cal .h.sun = --negative, .h.sat = #2F5FC4).
       A 패스가 위 토큰 블록에 --sun/--sat 을 넣으면 이 블록은 지운다. */
    --sun: #E02222;
    --sat: #2F5FC4;
}

/* 날짜칸은 네이티브 input 그대로다 — 직접 입력되고 높이·폭·글자는 그 자리 규칙을 따른다(셀렉트와 같은 방식).
   브라우저 달력 단추를 숨기고 오른쪽 8px 안쪽에 셀렉트 꺾쇠와 같은 자리·크기로 달력 아이콘을 그린다.
   그 자리(padding-right)를 누르면 taxi-date.js 가 우리 달력을 연다(ICON_HIT 28 = 26 + 테두리).
   화면별 규칙이 padding 단축으로 오른쪽 여백을 되돌리지 못하게 그 선택자들을 같이 적는다(셀렉트 꺾쇠 규칙과 같은 이유). */
input.tx-date,
.rec-form input.tx-date,
.rec-form .rowtable input.tx-date,
.detail-panel .panel-body input.tx-date,
.filter-bar input.tx-date,
.date-step input.tx-date,
.push-compose input.tx-date {
    padding-right: 26px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7684' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='5' width='18' height='16' rx='2'/><line x1='3' y1='10' x2='21' y2='10'/><line x1='8' y1='3' x2='8' y2='7'/><line x1='16' y1='3' x2='16' y2='7'/></svg>");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px 12px;
}

input.tx-date::-webkit-calendar-picker-indicator { display: none; }

/* 열려 있는 칸 — 브랜드색은 "지금 열려 있다"는 상태에만 쓴다(select.tx-sel.open 과 짝) */
input.tx-date.open {
    border-color: var(--brand-heavy);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23167E5B' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='5' width='18' height='16' rx='2'/><line x1='3' y1='10' x2='21' y2='10'/><line x1='8' y1='3' x2='8' y2='7'/><line x1='16' y1='3' x2='16' y2='7'/></svg>");
}

/* 달력은 프레임 문서의 <body> 에 붙는 fixed 다 — 스크롤 통(.card-scroll·.rec-*)의 overflow 에 안 잘린다 */
.tx-cal {
    position: fixed;
    z-index: 70;
    width: 240px;
    padding: 8px;
    border: 1px solid var(--line-normal);
    border-radius: var(--r, 4px);
    background: var(--surface);
    box-shadow: var(--pop, 0 6px 18px rgba(23, 23, 25, 0.16));
    color: var(--label-normal);
    font-size: 13px;
}

.tx-cal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
    height: 28px;
    margin-bottom: 4px;
}

.tx-cal-title { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }

.tx-cal-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--bd, var(--line-normal));
    border-radius: 3px;
    background: var(--surface);
    cursor: pointer;
}

.tx-cal-nav:hover { background: var(--fill-alt); }
.tx-cal-nav:focus-visible { outline: 2px solid var(--brand-heavy); outline-offset: 1px; }
.tx-cal-nav::before { content: ""; width: 0; height: 0; border: 4px solid transparent; }
.tx-cal-nav[data-mv="-1"]::before { border-right-color: var(--label-neutral); transform: translateX(2px); }
.tx-cal-nav[data-mv="1"]::before { border-left-color: var(--label-neutral); transform: translateX(-2px); }

.tx-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.tx-cal.is-month .tx-cal-grid { grid-template-columns: repeat(3, 1fr); gap: 4px; }

.tx-cal-dow {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 20px;
    font-size: 11px;
    font-weight: 600;
    color: var(--label-alt);
}

.tx-cal-dow.sun { color: var(--sun); }
.tx-cal-dow.sat { color: var(--sat); }

.tx-cal-day,
.tx-cal-mon {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 26px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    font: inherit;
    font-size: 12.5px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--label-normal);
    cursor: pointer;
    transition: background 120ms var(--ease);
}

.tx-cal-mon { height: 32px; }
.tx-cal-day.sun { color: var(--sun); }
.tx-cal-day.sat { color: var(--sat); }
.tx-cal-day:hover:not([disabled]),
.tx-cal-mon:hover:not([disabled]) { background: var(--fill-alt); }
.tx-cal-day.out { color: var(--label-assistive); cursor: default; }
.tx-cal-day.today,
.tx-cal-mon.today { border-color: var(--brand); }

/* 고른 칸만 브랜드색으로 채운다 — 흰 글자는 --brand-heavy(5.04) 부터다 */
.tx-cal-day.sel,
.tx-cal-day.sel:hover,
.tx-cal-mon.sel,
.tx-cal-mon.sel:hover {
    background: var(--brand-heavy);
    border-color: var(--brand-heavy);
    color: #FFFFFF;
    font-weight: 700;
}

.tx-cal-day[disabled],
.tx-cal-mon[disabled] { color: var(--label-assistive); cursor: not-allowed; }

/* 키보드 이동은 포커스를 옮기는 것이라 :focus-visible 이 아니라 :focus 로 늘 보이게 둔다 */
.tx-cal-day:focus,
.tx-cal-mon:focus { outline: 2px solid var(--brand-heavy); outline-offset: -1px; }

.tx-cal-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--line-neutral);
}

.tx-cal-today {
    height: var(--ctl-h-sm, 24px);
    padding: 0 8px;
    border: 1px solid var(--bd, var(--line-normal));
    border-radius: 3px;
    background: var(--surface);
    color: var(--label-neutral);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

.tx-cal-today:hover:not([disabled]) { background: var(--fill-alt); color: var(--label-normal); }
.tx-cal-today[disabled] { color: var(--label-assistive); cursor: not-allowed; }
.tx-cal-today:focus-visible { outline: 2px solid var(--brand-heavy); outline-offset: 1px; }
.tx-cal-pick { font-size: 12px; color: var(--label-alt); font-variant-numeric: tabular-nums; }

/* ---------- 컨트롤 폭 상한 (A 시안 4px 격자) — admin.css 맨 끝에 얹는다 ----------
   FHD 1920 에서 프레임 본문은 1616px(기본 여백) ~ 1648px(여백을 줄인 화면)이다.
   width:100% · flex:1 · 그리드 1fr 인 컨트롤은 그 폭을 그대로 먹어 제목 한 칸이 1094px,
   "9월 25일" 을 치는 칸이 704px 이 된다. 칸의 "내용 종류"가 폭을 정하게 한다.

   기존 선택자는 하나도 건드리지 않는다 — max-width 로 멈춰 세우기만 한다.
   칸(그리드·flex)은 그대로라 남는 자리는 컨트롤 오른쪽에 빈자리로 남는다(왼쪽 정렬).
   셸이 그리는 것(.detail-panel 460 · .layer-box 500)은 이 문서가 아니라 닿지 않는다 —
   이미 상한이 있어 손댈 것이 없다. 로그인·비밀번호(.login-card 880)도 같다. */
:root {
    --w-code:  96px;    /* 코드 · 연도 · 인원 · 횟수 · 요율 · 예/아니오 */
    --w-date: 128px;    /* 날짜 · 월 · 시각 */
    --w-name: 176px;    /* 성명 · 사번 · 전화 · 금액 · 공통코드 셀렉트 */
    --w-text: 280px;    /* 일반 텍스트 · 검색 (= .filter-bar .search) */
    --w-addr: 440px;    /* 주소 · 이메일 · 긴 셀렉트 — 기본 상한 (= .cap-cols 왼쪽 칸) */
    --w-prose: 640px;   /* 비고 · 본문 — 읽기 좋은 줄길이(13px 로마자 약 80자 · 한글 약 45자) */
}

/* 기본 상한. 특이도가 (0,1,1) 이고 아래 규칙들이 전부 뒤에 오므로 화면별 규칙이 이긴다.
   새 화면은 아무것도 안 해도 여기 걸린다 — 그게 이 두 줄의 값어치다.
   체크·라디오는 16px 고정이고 그리드 셀 편집기(.month-editor)는 칸이 이미 좁아 걸리지 않는다. */
.frame-body :is(input, select) { max-width: var(--w-addr); }
.frame-body textarea           { max-width: var(--w-prose); }

/* ── 카탈로그 폼(인사관리·차량관리) — 폭을 FormColumn.type 이 정한다.
      form-fields.jsp 가 .f 에 data-t="${col.type}" 를 찍어야 한다(아래 notes 참고). ── */
.rec-form .f[data-t="DATE"] input,
.rec-form .f[data-t="MONTH"] input,
.rec-form .f[data-t="TIME"] input   { max-width: var(--w-date); }
.rec-form .f[data-t="YN"]   select,
.rec-form .f[data-t="NUM"]  input   { max-width: var(--w-code); }
.rec-form .f[data-t="TEL"]  input,
.rec-form .f[data-t="AMT"]  input,
.rec-form .f[data-t="RRN"]  input,
.rec-form .f[data-t="CODE"] select,
.rec-form .f[data-t="SEL"]  select,
.rec-form .f[data-t="REF"]  select  { max-width: var(--w-name); }
.rec-form .f[data-t="TEXT"] input   { max-width: var(--w-text); }
/* 도로명주소는 한 줄 두 칸을 쓰는 자리다 — 기본 상한 440 이 그대로 맞다 */
.rec-form .f.span2 input            { max-width: var(--w-addr); }

/* ── 반복 블록 표 — 표는 width:100% 로 둔 채(칸을 줄이면 표가 박스를 넘친다, notes 참고)
      입력칸만 멈춘다. form-rows.jsp 가 <td data-t="${rc[2]}"> 를 찍어야 한다. ── */
.rec-form .rowtable td[data-t="date"]   input  { max-width: var(--w-date); }
.rec-form .rowtable td[data-t="amount"] input  { max-width: var(--w-name); }
.rec-form .rowtable td[data-t="sel"]    select { max-width: var(--w-name); }
.rec-form .rowtable td[data-t="text"]   input  { max-width: var(--w-text); }

/* ── 손으로 짠 폼 — 1fr 칸을 그대로 먹던 곳. 칸은 그대로 두고 컨트롤만 멈춘다 ── */
/* 관리자관리 · 메뉴관리 — 셀렉트(권한 · 경로)는 라벨이 길어 기본 상한 440 을 그대로 쓴다 */
.adm-form input               { max-width: var(--w-text); }
.adm-form input[name="phone"] { max-width: var(--w-name); }

/* 공지관리 — 제목은 앱 타일 두 줄 분량, 본문은 backstop 의 --w-prose 가 이미 잡는다 */
.ntc-form input[type="text"]  { max-width: var(--w-prose); }

/* 푸시발송 · 알림톡발송(같은 .push-compose) — 제목 · 직접 입력 칸 */
.push-compose input[type="text"]  { max-width: var(--w-prose); }
.push-compose input[type="month"],
.push-compose input[type="date"]  { max-width: var(--w-date); }

/* 미수관리 후입금 — 비고만 한 줄 전체를 쓴다(나머지 6칸은 146px 라 안 걸린다) */
.income-form input               { max-width: var(--w-text); }
.income-form input[name="remark"] { max-width: var(--w-prose); }

/* ---- 외부접근관리 (/admin/access) — 시안 B "경로 지도 + 로그에서 차단". 좌 경로 · 중 정책 · 우 막힌 접근 + 블랙리스트.
   바닥까지 채운다: .frame-body 를 100vh flex 열로 두고 3단이 남은 높이를 갖는다(필터바가 접혀도 따라간다). */
.frame-body:has(> .acs-layout) { display: flex; flex-direction: column; height: 100vh; }
.frame-body:has(> .acs-layout) > * { flex-shrink: 0; }
.acs-layout { flex: 1 1 0; min-height: 420px; display: grid; grid-template-columns: minmax(240px, 300px) minmax(440px, 1fr) minmax(380px, 480px); gap: 10px; }
.acs-right { display: grid; grid-template-rows: minmax(0, 3fr) minmax(0, 2fr); gap: 10px; min-height: 0; }
.acs-mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12px; }
.acs-me { font-size: 12.5px; color: var(--label-neutral); border: 1px solid var(--bd); border-radius: var(--r); background: var(--surface); padding: 5px 10px; }
.acs-empty { margin: 0; padding: 16px 12px; font-size: 12.5px; color: var(--label-alt); }
.acs-search { flex: none; padding: 8px 10px; border-bottom: 1px solid var(--line-neutral); }
.acs-search input { width: 100%; max-width: none; height: 28px; font-size: 12px; }

.acs-dot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%; }
.acs-dot.allow { background: var(--brand-heavy); }
.acs-dot.block { background: var(--negative); }
.acs-dot.inh { background: rgba(22, 126, 91, .35); }
.acs-dot.inh-block { background: rgba(224, 34, 34, .35); }
.acs-dot.none { box-sizing: border-box; border: 1.5px solid rgba(112, 115, 124, .45); }
.acs-legend { gap: 12px; color: var(--label-alt); font-size: 11.5px; flex-wrap: wrap; }
.acs-legend span { display: inline-flex; align-items: center; gap: 4px; }

.acs-tree { padding: 4px 0 8px; }
.acs-tree button { display: flex; width: 100%; align-items: center; gap: 7px; border: 0; background: none; font: inherit; font-size: 12.5px; text-align: left; padding: 5px 10px; cursor: pointer; color: var(--label-normal); }
.acs-tree button:hover { background: var(--fill-alt); }
.acs-tree button.on { background: rgba(33, 163, 119, .10); box-shadow: inset 3px 0 0 var(--brand-heavy); font-weight: 700; }
.acs-tree button.d1 { padding-left: 24px; }
.acs-tree button.d2 { padding-left: 40px; }
.acs-tree button.inh .acs-mono { color: var(--label-alt); }
.acs-tree .acs-mono { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acs-tree .tag { margin-left: auto; flex: none; font-size: 11px; font-weight: 500; color: var(--label-alt); }

.acs-policy { padding: 14px 16px; display: flex; flex-direction: column; gap: 16px; }
.acs-policy .flash { margin: 0; }
.acs-field { display: flex; flex-direction: column; gap: 6px; }
.acs-field .lbl { font-size: 12px; font-weight: 700; color: var(--label-alt); }
.acs-field .seg-tabs { align-self: flex-start; }
.acs-field select, .acs-field input[type="text"] { max-width: var(--w-text); }
.acs-field #acs-memo { max-width: var(--w-prose); }
.acs-policy .hint, .acs-form .hint { font-size: 12px; font-weight: 400; color: var(--label-alt); }
.acs-policy .hint.ok { color: var(--ok); }
.acs-policy .hint.warn { color: var(--warn); }
.acs-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.acs-ips { border: 1px solid var(--line-neutral); }
.acs-ips td.mute { color: var(--label-alt); }
.acs-add { display: flex; flex-wrap: wrap; gap: 6px; }
.acs-add #acs-ip { width: 180px; }
.acs-add #acs-ip-name { width: 180px; }

.acs-ev { display: grid; grid-template-columns: 70px minmax(0, 1fr) auto; gap: 2px 8px; padding: 8px 12px; border-bottom: 1px solid var(--line-neutral); align-items: center; font-size: 12.5px; }
.acs-ev.hot { background: rgba(224, 34, 34, .04); }
.acs-ev .tm { color: var(--label-alt); font-size: 12px; font-variant-numeric: tabular-nums; }
.acs-ev .who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acs-ev .who .mute { color: var(--label-alt); }
.acs-ev .act { display: inline-flex; gap: 4px; }
.acs-ev .sub { grid-column: 2 / 4; color: var(--label-alt); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#acs-blocks td .mute { color: var(--label-alt); font-size: 11px; }
#acs-blocks td { height: auto; min-height: var(--row-h); padding-top: 4px; padding-bottom: 4px; }
.acs-cfg { flex-wrap: wrap; gap: 6px; color: var(--label-alt); }
.acs-cfg b { color: var(--label-normal); }
.acs-cfg input { width: 48px; height: 24px; padding: 0 6px; font-size: 12px; text-align: right; }

/* 레이어 폼(직접 입력 · 블랙리스트 추가) — .layer-body 는 여백이 없어(주소검색 iframe) 폼이 자기 여백을 가진다(.rule-add 와 같다) */
.acs-form { display: flex; flex-direction: column; gap: 12px; padding: 16px 20px 16px; }
.acs-form label { display: flex; flex-direction: column; gap: 6px; font-size: 12px; font-weight: 700; color: var(--label-alt); }
.acs-form label .req { color: var(--negative); font-style: normal; margin-left: 2px; }
.acs-form input, .acs-form select { height: var(--ctl-h); font-weight: 500; }
.acs-form .hint { margin: 0; }
.acs-form-foot { display: flex; justify-content: flex-end; }

/* ---- 기사 로그인 이력 (/admin/driver-logins) — 시안 A. 좌 기사 그리드(320 고정) + 우 고른 기사(머리 · 사실 다섯 칸 · 30일 띠 / 접속 기록 그리드).
   패널은 카드관리의 .card-panel, 높이는 .month-grid 와 같은 채우기 규칙(.frame-body flex)이다. 여기 적는 것은 배치 · 상태 점 · 띠뿐이다. */
.dlg-layout { display: grid; grid-template-columns: 320px minmax(0, 1fr); grid-auto-rows: minmax(0, 1fr); gap: 10px; }
.dlg-right { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 10px; min-height: 0; min-width: 0; }
.dlg-legend { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 12px; font-size: 12px; color: var(--label-alt); }
.dlg-legend span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.dlg-tools { flex-direction: column; align-items: stretch; }
.dlg-tools .seg-tabs { align-self: flex-start; }
.dlg-tools .seg-tabs button { padding: 4px 8px; }
.card-ph.dlg-tools input[type="search"] { flex: none; width: 100%; max-width: none; height: 30px; }
.dlg-layout .card-pf b.warn { color: var(--warn); }
.dlg-period.filter-bar { flex-wrap: nowrap; gap: 4px; margin: 0; padding: 0; border: 0; background: none; font-size: 12px; color: var(--label-alt); }
.dlg-period.filter-bar input[type="date"] { height: 28px; font-size: 12px; }
.dlg-mute { color: var(--label-alt); }
.dlg-empty { margin: 0; padding: 16px; font-size: 13px; color: var(--label-alt); }

.dlg-dot { display: inline-block; flex: none; box-sizing: border-box; width: 9px; height: 9px; border-radius: 50%; vertical-align: middle; }
.dlg-dot.live { background: var(--brand-heavy); box-shadow: 0 0 0 3px rgba(22, 126, 91, .18); }
.dlg-dot.on { border: 2px solid var(--brand-heavy); background: var(--surface); }
.dlg-dot.out { background: #9A9BA0; }
.dlg-dot.exp { border: 2px solid #B5B6BA; background: var(--surface); }
.dlg-dot.none { border: 1.5px dashed #B5B6BA; background: var(--surface); }
.dlg-pill { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px; border-radius: 11px; font-size: 12px; font-weight: 600; background: rgba(112, 115, 124, .08); color: var(--label-alt); }
.dlg-pill:is(.live, .on) { background: rgba(22, 126, 91, .10); color: var(--ok); }

.dlg-head { gap: 14px; padding: 14px 16px; }
.dlg-who { display: flex; align-items: center; gap: 10px; }
.dlg-who strong { font-size: 17px; }
.dlg-who .sub { font-size: 13px; color: var(--label-alt); font-variant-numeric: tabular-nums; }
.dlg-who .spacer { flex: 1; }
.dlg-who a { font-size: 13px; }
.dlg-facts { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 16px; }
.dlg-fact { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dlg-fact .k { font-size: 11px; color: var(--label-alt); }
.dlg-fact .v { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dlg-fact .s { font-size: 12px; color: var(--label-alt); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dlg-strip { display: flex; align-items: flex-end; gap: 3px; }
.dlg-day { flex: none; width: 14px; height: 22px; border-radius: 2px; background: rgba(112, 115, 124, .10); }
.dlg-day.use { background: var(--brand-heavy); }
.dlg-day.fail { background: var(--surface); box-shadow: inset 0 0 0 2px var(--negative); }
.dlg-strip .note { margin-left: 8px; font-size: 11px; color: var(--label-alt); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
