@charset "utf-8";
/* ============================================================================
   components.css: 페이지헤더 · 카드 · 표 · 폼 · 버튼 · 배지 · 모달 · 빈상태 · 페이징
   ============================================================================
   네이밍: BEM-lite + 상태 클래스 (10_CSS.md §2)
     .ie-{block}   .ie-{block}__{elem}   .ie-{block}--{variant}   .is-{state}
   불변 규칙
     1) `ie-` 없는 클래스를 새로 만들지 않는다. 예외는 그누보드가 생성하는 마크업뿐
        (.pg_wrap · .sound_only · #captcha). 이건 **재정의**이지 신규 생성이 아니다.
     2) `.is-*` 는 단독 스타일링 금지. 반드시 블록과 결합한다
        (css/default.css:59~60 의 .is-hidden/.is-visible 과 충돌 방지).
     3) 중첩은 2단까지.
     4) 컴포넌트 CSS 는 **semantic 토큰만** 참조한다. 리터럴 HEX 금지.
   ============================================================================ */

/* ═══ 페이지 헤더 ═══════════════════════════════════════════════════════ */
.ie-pagehead {
  display: flex; align-items: flex-start; gap: var(--ie-sp-4);
  flex-wrap: wrap;
  padding-block-end: var(--ie-sp-4);
  border-block-end: 1px solid var(--ie-c-border);
}
.ie-pagehead__main { flex: 1 1 auto; min-inline-size: 0; }
.ie-pagehead__title { font-size: var(--ie-fs-20); font-weight: var(--ie-fw-semi); color: var(--ie-c-text-title); }
.ie-pagehead__desc  { margin-block-start: var(--ie-sp-1); font-size: var(--ie-fs-13); color: var(--ie-c-text-muted); }
.ie-pagehead__meta  { display: flex; gap: var(--ie-sp-4); margin-block-start: var(--ie-sp-2); }
.ie-pagehead__meta li { font-size: var(--ie-fs-13); color: var(--ie-c-text-muted); }
.ie-pagehead__meta b  { color: var(--ie-c-text-body); font-variant-numeric: tabular-nums; }
.ie-pagehead__meta .is-warn b { color: var(--ie-warning-ink); }
.ie-pagehead__actions { flex: 0 0 auto; display: flex; gap: var(--ie-sp-2); align-items: center; }

/* ═══ 버튼 ═══════════════════════════════════════════════════════════════
   ⚠ `.btn` `.btn01` `.btn_submit` `.btn_b01`… 은 전부 그누보드가 선점한 이름이다
     (css/default.css:262~299). 우리는 `.ie-btn` 만 쓴다. */
.ie-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--ie-sp-2);
  block-size: var(--ie-control-h); padding-inline: var(--ie-sp-4);
  border: 1px solid var(--ie-c-border-field); border-radius: var(--ie-r-md);
  background: var(--ie-c-surface-card); color: var(--ie-c-text-label);
  font-family: inherit; font-size: var(--ie-fs-14); font-weight: var(--ie-fw-semi);
  line-height: 1; white-space: nowrap; cursor: pointer; text-decoration: none;
  transition: background-color var(--ie-dur-fast) var(--ie-ease),
              border-color     var(--ie-dur-fast) var(--ie-ease);
}
.ie-btn:hover { background: var(--ie-c-surface-hover); text-decoration: none; }
.ie-btn:active { background: var(--ie-gray-200); }
.ie-btn[disabled], .ie-btn.is-disabled {
  color: var(--ie-c-text-disabled); background: var(--ie-c-surface-sunken);
  border-color: var(--ie-c-border); cursor: not-allowed;
}
.ie-btn--sm { block-size: var(--ie-control-h-sm); padding-inline: var(--ie-sp-3); font-size: var(--ie-fs-13); }
.ie-btn--primary {
  background: var(--ie-c-action); border-color: var(--ie-c-action); color: var(--ie-c-action-on);
}
.ie-btn--primary:hover  { background: var(--ie-c-action-hover);   border-color: var(--ie-c-action-hover); }
.ie-btn--primary:active { background: var(--ie-c-action-pressed); border-color: var(--ie-c-action-pressed); }
/* ── `--ghost` 재정의 (2026-08-07 · docs/42) ──────────────────────────────
   ★ 바뀐 것: `background: transparent; border-color: transparent` 두 값뿐이다.
     선언 자체는 지우지 않았고 값만 바꿨다. hover 규칙은 아래로 옮겨 확장했다.

   ★ 왜 바꿨나 (어포던스 실패)
     투명 배경 + 투명 테두리 + 링크색 글자였다. 즉 **마우스를 올리기 전에는 텍스트
     링크와 구분되지 않았다.** 표 행에서 `수정`(ghost) 과 `삭제`(danger) 가 나란히
     있으면 삭제만 버튼으로 보이고 수정은 그냥 글자였다. "눌러도 되는지"를 hover
     해 봐야 알 수 있는 상태였고, 사용자가 실제로 이 지점을 지적했다.

   ★ 왜 하필 이 값인가
     · 경계는 **선**으로 준다. `--ie-c-border-field`(gray-500) 는 흰 배경 위 3.75:1 로
       WCAG 1.4.11(비텍스트 대비 3:1) 을 넘는 유일한 기존 경계 토큰이다.
       `--ie-c-border`(gray-200) 는 1.27:1, `--ie-c-border-strong`(gray-300) 은 1.55:1 로
       둘 다 미달이라 쓸 수 없다.
     · **면(채움)은 주 버튼에만 남긴다.** primary 는 brand-600 면, ghost 는 선.
       그래서 위계가 뒤집히지 않는다. 나란히 놓으면 primary 가 항상 더 세다.
     · 글자는 링크색(brand-700, 8.38:1) 을 유지해 중립 `.ie-btn`(gray-700) 과 구분한다.
       "보조 행동"이라는 원래 의미가 색으로 남는다.

   ★ 08 §9.1 의 Ghost 정의(배경 투명·테두리 없음)와 어긋난다. 그 표는 "hover 전에도
     눌린다는 것이 보여야 한다"를 만족하지 못한다. 어포던스를 우선한다(docs/42 §2).

   ★ 새 색을 만들지 않았다. 전부 기존 토큰이다. */
.ie-btn--ghost {
  background: var(--ie-c-surface-card);
  border-color: var(--ie-c-border-field);
  color: var(--ie-c-text-link);
}
.ie-btn--ghost:hover {
  background: var(--ie-c-action-subtle-bg);
  border-color: var(--ie-c-border-brand);
  color: var(--ie-c-action-hover);
}
/* `--ie-brand-100` 는 1계층이다. 바로 위 `.ie-btn:active` 가 이미 `--ie-gray-200` 를
   같은 방식으로 참조하고 있어 표기를 맞췄다. 눌린 순간에만 쓰는 한 단계 짙은 틴트로,
   이 용도의 semantic 토큰은 아직 없다. */
.ie-btn--ghost:active {
  background: var(--ie-brand-100);
  border-color: var(--ie-c-action-pressed);
  color: var(--ie-c-action-pressed);
}
.ie-btn--danger {
  background: var(--ie-danger); border-color: var(--ie-danger); color: var(--ie-white);
}
.ie-btn--danger:hover { background: var(--ie-danger-ink); border-color: var(--ie-danger-ink); }
.ie-btn--danger:active { background: var(--ie-danger-ink); border-color: var(--ie-danger-ink); }

/* ── 비활성: 변형(variant)보다 **반드시 뒤에, 반드시 더 높은 특이도로** ──────
   ★ 이것도 같은 계열의 어포던스 버그다. 위쪽 `.ie-btn[disabled]`(0,2,0) 는
     `.ie-btn--primary`/`--danger`/`--ghost`(전부 0,2,0) 보다 **앞에** 있어서 진다.
     그래서 `<button class="ie-btn ie-btn--danger" disabled>` 가 지금까지 **멀쩡한
     빨간 버튼으로 보였다**(partner_form.php:222 · asset_form.php:176 실제 사용 중).
     못 누르는데 눌릴 것처럼 보이는 것도 어포던스 실패다. 여기서 못 박는다.
   ★ 위쪽 원래 규칙은 지우지 않았다. 이 블록은 덧셈이다. */
.ie-btn[disabled],                 .ie-btn.is-disabled,
.ie-btn--primary[disabled],        .ie-btn--primary.is-disabled,
.ie-btn--ghost[disabled],          .ie-btn--ghost.is-disabled,
.ie-btn--danger[disabled],         .ie-btn--danger.is-disabled,
.ie-btn[disabled]:hover,           .ie-btn.is-disabled:hover,
.ie-btn--primary[disabled]:hover,  .ie-btn--primary.is-disabled:hover,
.ie-btn--ghost[disabled]:hover,    .ie-btn--ghost.is-disabled:hover,
.ie-btn--danger[disabled]:hover,   .ie-btn--danger.is-disabled:hover,
.ie-btn[disabled]:active,          .ie-btn.is-disabled:active,
.ie-btn--primary[disabled]:active, .ie-btn--primary.is-disabled:active,
.ie-btn--ghost[disabled]:active,   .ie-btn--ghost.is-disabled:active,
.ie-btn--danger[disabled]:active,  .ie-btn--danger.is-disabled:active {
  color: var(--ie-c-text-disabled);
  background: var(--ie-c-surface-sunken);
  border-color: var(--ie-c-border);
  cursor: not-allowed;
}

/* ── 포커스 링 ────────────────────────────────────────────────────────────
   ★ `default.css` 의 `@layer in-force` 는 `.ie-shell :focus-visible` 로 스코프돼 있는데,
     모달은 `#ie-modal-root`(tail.php:30) 로 **셸 밖에** 렌더된다. 그래서 모달 안 버튼은
     그 규칙에 걸리지 않고 브라우저 기본 링에만 의존했다. 여기서 셸 안팎을 모두 덮는다.
   ★ 값은 in-force 것과 같다(2px `--ie-c-focus` + offset 1px). 셸 안에서는 in-force 의
     `!important` 가 같은 값으로 덮으므로 보이는 결과가 달라지지 않는다.
   ★ `outline: none` 을 쓰지 않는다(base.css 규칙 3). */
.ie-btn:focus-visible {
  outline: 2px solid var(--ie-c-focus);
  outline-offset: 1px;
}

/* ═══ 링크 (2026-08-07 신규 · docs/42) ═══════════════════════════════════
   ★ 버튼을 버튼으로 보이게 만들면, 그 반대쪽도 같이 정해야 한다.
     "다른 화면으로 데려갈 뿐인 것"까지 `.ie-btn--ghost` 를 달고 있으면 화면 안에
     버튼이 너무 많아져 결국 아무것도 눈에 안 띈다. 그런 곳은 `.ie-link` 로 내린다.
   ★ 판정 기준 (docs/42 §3 분류표)
       행동을 일으킨다(저장·삭제·필터·토글·업로드) → 버튼
       다른 화면으로 데려간다                      → 링크
       단 표 행의 액션 열·페이지헤더 액션 바에 놓인 것은 화면 이동이라도 **버튼**
         (그 자리에 있는 것들끼리 같은 모양이어야 열이 읽힌다)
   ★ 밑줄을 기본값으로 둔다. `base.css:64` 가 `:where(.ie-shell a){text-decoration:none}`
     이라 밑줄이 없으면 링크도 그냥 색 있는 글자가 되고, 그러면 버튼과 같은 문제가
     반대편에서 반복된다. `:where()` 라 특이도 0 이므로 여기서 이긴다. */
.ie-link {
  display: inline-flex; align-items: center; gap: var(--ie-sp-1);
  padding: 0; border: 0; background: none;
  color: var(--ie-c-text-link);
  font-family: inherit; font-size: var(--ie-fs-13); font-weight: var(--ie-fw-semi);
  line-height: var(--ie-lh-ui);
  text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer;
}
.ie-link:hover { color: var(--ie-c-action-pressed); text-decoration: underline; }
.ie-link:focus-visible { outline: 2px solid var(--ie-c-focus); outline-offset: 2px; border-radius: var(--ie-r-sm); }
.ie-link[disabled], .ie-link.is-disabled { color: var(--ie-c-text-disabled); text-decoration: none; cursor: not-allowed; }

/* ═══ 카드 ═══════════════════════════════════════════════════════════════
   그림자 없음. 테두리 1px + radius 6px 만 (08 §1.3, 카드마다 다른 그림자 깊이 금지) */
.ie-card {
  background: var(--ie-c-surface-card);
  border: 1px solid var(--ie-c-border);
  border-radius: var(--ie-r-md);
}
.ie-card__head {
  display: flex; align-items: center; gap: var(--ie-sp-3);
  padding: var(--ie-sp-4) var(--ie-sp-5);
  border-block-end: 1px solid var(--ie-c-border);
}
.ie-card__title { font-size: var(--ie-fs-18); font-weight: var(--ie-fw-semi); }
.ie-card__more  { margin-inline-start: auto; font-size: var(--ie-fs-13); }
/* ── 카드 헤더 우측 슬롯 (2026-08-07 · docs/42) ────────────────────────────
   ★ `a.ie-card__more` 만 링크로 표시한다. `.ie-card__more` 는 `<span>` 캡션으로도
     쓰이고 있어서(asset_view.php:109 `총 12건`, grant_form.php:93 `공고문에 적힌 그대로`)
     요소를 안 가르면 **캡션에 밑줄이 그어진다.** 이 파일이 먼 곳을 깨뜨리는 전형적 지점이다.
   ★ `.ie-card__act` 는 "카드 헤더 오른쪽에 놓이는 **버튼**" 자리다. `.ie-card__more` 는
     margin-inline-start:auto 를 갖고 있는데 버튼에 그 클래스를 같이 붙이면 font-size 13px
     까지 따라와 `--sm` 과 싸운다. 정렬만 필요하므로 분리한다. */
a.ie-card__more { text-decoration: underline; text-underline-offset: 2px; }
a.ie-card__more:hover { color: var(--ie-c-action-pressed); }
.ie-card__act { margin-inline-start: auto; }
.ie-card__body  { padding: var(--ie-sp-5); }
.ie-card__body--flush { padding: 0; }

.ie-note {
  font-size: var(--ie-fs-14); line-height: var(--ie-lh-ui); color: var(--ie-c-text-muted);
}

/* ═══ 바로가기 (대시보드) ═══════════════════════════════════════════════
   ⚠ **이 블록은 현재 마크업에서 아무 데도 쓰이지 않는다.** 2026-08-07 전수 확인 결과
     `src/**` 에 `ie-quick` 은 이 파일 5줄뿐이고, 렌더된 대시보드의
     `document.querySelectorAll('.ie-quick__item').length` 는 **0** 이다(실측).
     docs/42 §6-3 이 "대시보드 바로가기 타일"이라 적은 것은 실제로는
     `pages/dashboard.css` 의 **`a.ie-kpi`** 다. 그쪽도 같은 날 같은 근거로 고쳤다.
     이 블록은 지우지 않고 **경계 규칙만 맞춰 둔다.** 언젠가 마크업이 붙었을 때
     1.27:1 경계가 되살아나는 것을 막기 위해서다.

   ★ 2026-08-07 (docs/43) 바꾼 것: `border` 의 색 토큰 1개 + `:focus-visible` 1줄 추가.
     `--ie-c-border`(gray-200)는 흰 배경 위 **1.27:1** 이라 "누를 수 있는 카드"의 경계로는
     WCAG 1.4.11(비텍스트 대비 3:1) 미달이다. 기존 경계 토큰 중 3:1 을 넘는 것은
     `--ie-c-border-field`(gray-500) 하나뿐이다: 흰 면 위 **3.75:1**, 페이지 배경(gray-50)
     위 3.52:1, hover 배경(brand-50) 위 3.35:1. gray-300 은 1.55:1, gray-400 은 2.32:1 로 미달.
   ★ **선은 1px 그대로 두고 색만 올린다.** 굵기·반경·여백을 건드리면 첫 화면 인상이
     통째로 바뀐다. 바뀌는 것은 "선이 보이느냐"뿐이다.
   ★ docs/42 가 보조 버튼·입력의 경계를 전부 `--ie-c-border-field` 로 정리했으므로,
     이제 앱 전체에서 **누를 수 있는 것 = gray-500 선**으로 읽힌다. 새 색은 0개다. */
.ie-quick { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--ie-sp-3); }
.ie-quick__item {
  display: flex; align-items: center; gap: var(--ie-sp-3);
  padding: var(--ie-sp-4);
  border: 1px solid var(--ie-c-border-field); border-radius: var(--ie-r-md);
  color: var(--ie-c-text-body); font-size: var(--ie-fs-14); font-weight: var(--ie-fw-semi);
  transition: border-color var(--ie-dur-fast) var(--ie-ease), background-color var(--ie-dur-fast) var(--ie-ease);
}
.ie-quick__item:hover { border-color: var(--ie-c-border-brand); background: var(--ie-c-action-subtle-bg); text-decoration: none; }
.ie-quick__item:focus-visible { outline: 2px solid var(--ie-c-focus); outline-offset: 1px; }
.ie-quick__icon { color: var(--ie-c-action); }
.ie-quick__label { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ═══ 표 ═══════════════════════════════════════════════════════════════════
   ERP 표는 항상 넘친다. **가로 스크롤은 이 래퍼 안에서만** 발생한다 (10_CSS.md §5.1).
     ① .ie-shell     { overflow: hidden }      ← 셸 밖으로 못 나감
     ② .ie-main-wrap { min-inline-size: 0 }    ← 진짜 원인 차단
     ③ .ie-main      { overflow-x: hidden }    ← 보험
     ④ .ie-table-scroll { overflow: auto }     ← 가로 스크롤이 발생하는 유일한 지점 */
.ie-table-scroll {
  overflow: auto;
  min-inline-size: 0;                          /* ★ 필수 */
  max-block-size: none;
  border: 1px solid var(--ie-c-border);
  border-radius: var(--ie-r-md);
  background: var(--ie-c-surface-card);
}
.ie-table {
  inline-size: 100%;
  /* ★ separate 필수. border-collapse:collapse 는 position:sticky 인 th 에서 테두리가 사라진다. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--ie-fs-14);
  font-variant-numeric: tabular-nums;
}
.ie-table caption { text-align: start; }
.ie-table thead th {
  position: sticky; inset-block-start: 0; z-index: 2;
  block-size: var(--ie-thead-h);
  padding: 0 var(--ie-sp-3);
  background: var(--ie-c-surface-header);
  color: var(--ie-c-text-label);
  font-size: var(--ie-fs-13); font-weight: var(--ie-fw-semi);
  text-align: start; white-space: nowrap;
  border-block-end: 1px solid var(--ie-c-border-strong);
}
.ie-table tbody td {
  block-size: var(--ie-row-h);
  padding: var(--ie-sp-2) var(--ie-sp-3);
  border-block-end: 1px solid var(--ie-c-border);   /* 세로선 없음 */
  color: var(--ie-c-text-body);
  vertical-align: middle;
}
.ie-table tbody tr:last-child td { border-block-end: 0; }
.ie-table--hover tbody tr:hover td { background: var(--ie-c-surface-hover); }
.ie-table tbody tr.is-selected td { background: var(--ie-c-surface-selected); }
.ie-table--compact tbody td { block-size: var(--ie-row-h-compact); font-size: var(--ie-fs-13); padding-inline: 10px; }
.ie-table--compact thead th { block-size: var(--ie-row-h-compact); }
.ie-table--nowrap td { white-space: nowrap; }
.ie-td--num, .ie-th--num       { text-align: right; }
.ie-td--center, .ie-th--center { text-align: center; }
.ie-td--primary a { color: var(--ie-c-text-body); font-weight: var(--ie-fw-semi); }
.ie-td--primary small { display: block; color: var(--ie-c-text-muted); font-size: var(--ie-fs-12); }

/* ── 표 행의 액션 열 (2026-08-07 · docs/42 §4) ─────────────────────────────
   ★ 문제: 행 액션은 대부분 `<a>수정</a>` + `<form><button>삭제</button></form>` 이다.
     `<form>` 은 블록이라 아무 것도 안 하면 **수정과 삭제가 위아래로 쪼개진다.**
   ★ 지금까지는 모듈마다 같은 한 줄을 각자 복사해 두고 있었다. 전수 확인 결과 5벌이다.
       pages/grant.css:162    `.ie-grt__rowact form { display: inline }`
       pages/account.css:130  `.ie-acc__inline  { display: inline }`
       pages/finance.css:35   `.ie-fin__inline  { display: inline-flex }`
       pages/asset.css:34     `.ie-ast__inline  { display: inline-flex }`
       pages/calendar.css:433 `.ie-inlineform   { display: inline }`
     모듈이 하나 늘 때마다 여섯 번째를 복사하거나, 잊고 행이 쪼개진 채 나간다.
     성질이 모듈에 있지 않으므로 여기서 한 번만 정한다.
   ★ 기존 5벌은 지우지 않았다. 같은 값이라 결과가 바뀌지 않고, 지우는 순간 그 화면들이
     이 규칙 하나에 전부 매달리게 된다. 중복은 지금 시점에서 더 싼 쪽이다.
   ★ 대상을 `td > form` 직계로 좁힌 이유: 표 전체를 감싼 폼(`<form><table>…`)이나
     셀 안의 중첩 폼까지 inline 으로 만들면 레이아웃이 엉뚱한 데서 무너진다. */
.ie-table td > form { display: inline-flex; align-items: center; gap: var(--ie-sp-2); margin: 0; vertical-align: middle; }
/* `<a class="ie-btn">` 은 baseline, `<form>` 은 위에서 middle 이라 둘이 1px 어긋난다.
   실측으로 잡았다(top 407 vs 408). 기준을 맞춘다. */
.ie-table td > .ie-btn { vertical-align: middle; }
/* 버튼끼리 붙지 않게. 테두리가 생겼으므로 공백문자 하나로는 두 버튼이 한 덩어리로 보인다. */
.ie-table td > .ie-btn + .ie-btn,
.ie-table td > .ie-btn + form,
.ie-table td > form + .ie-btn,
.ie-table td > form + form { margin-inline-start: var(--ie-sp-1); }

/* ═══ 배지 (08 §7.5) ══════════════════════════════════════════════════════
   ★ 배지에 반드시 한글 라벨. 색만 있는 도트 배지는 금지 (원칙 4). */
.ie-badge {
  display: inline-flex; align-items: center; gap: var(--ie-sp-1);
  block-size: 22px; padding-inline: var(--ie-sp-2);
  border: 1px solid transparent; border-radius: var(--ie-r-sm);
  font-size: var(--ie-fs-12); font-weight: var(--ie-fw-semi);
  line-height: 1; white-space: nowrap;
}
.ie-badge__dot { inline-size: 6px; block-size: 6px; border-radius: var(--ie-r-full); background: currentColor; }
.ie-badge--success { background: var(--ie-success-tint); color: var(--ie-success-ink); border-color: var(--ie-success-border); }
.ie-badge--warning { background: var(--ie-warning-tint); color: var(--ie-warning-ink); border-color: var(--ie-warning-border); }
.ie-badge--danger  { background: var(--ie-danger-tint);  color: var(--ie-danger-ink);  border-color: var(--ie-danger-border); }
.ie-badge--info    { background: var(--ie-info-tint);    color: var(--ie-info-ink);    border-color: var(--ie-info-border); }
.ie-badge--neutral { background: var(--ie-gray-100);     color: var(--ie-gray-700);    border-color: var(--ie-gray-200); }
.ie-badge--count {
  min-inline-size: 20px; block-size: 20px; justify-content: center;
  background: var(--ie-c-action); color: var(--ie-c-action-on); border-radius: var(--ie-r-full);
  font-size: var(--ie-fs-11); padding-inline: 6px;
}

/* ═══ 폼 ═══════════════════════════════════════════════════════════════════
   ⚠ `.frm_input` `.required` `.full_input` 은 그누보드 선점 이름이다. 재사용 금지. */
.ie-form { display: flex; flex-direction: column; gap: var(--ie-sp-4); }
.ie-field { display: flex; flex-direction: column; gap: var(--ie-sp-2); }
.ie-field__label { font-size: var(--ie-fs-13); font-weight: var(--ie-fw-semi); color: var(--ie-c-text-label); }
.ie-req { color: var(--ie-danger); text-decoration: none; margin-inline-start: 2px; }
.ie-input, .ie-select, .ie-textarea {
  inline-size: 100%; box-sizing: border-box;
  block-size: var(--ie-control-h);
  padding-inline: var(--ie-sp-3);
  border: 1px solid var(--ie-c-border-field);   /* UI 컴포넌트 경계 3:1, gray-300 금지 */
  border-radius: var(--ie-r-md);
  background: var(--ie-c-surface-card);
  font-family: inherit; font-size: var(--ie-fs-14); color: var(--ie-c-text-body);
}
.ie-textarea { block-size: auto; min-block-size: 120px; padding-block: var(--ie-sp-2); line-height: var(--ie-lh-ui); }
.ie-input::placeholder, .ie-textarea::placeholder { color: var(--ie-c-text-placeholder); }
.ie-input[disabled], .ie-select[disabled], .ie-textarea[disabled] {
  background: var(--ie-c-surface-sunken); color: var(--ie-c-text-disabled);
}
.ie-field.is-error .ie-input,
.ie-field.is-error .ie-select,
.ie-field.is-error .ie-textarea { border-color: var(--ie-danger); }
.ie-field__hint  { font-size: var(--ie-fs-12); color: var(--ie-c-text-muted); }
.ie-field__error { font-size: var(--ie-fs-12); color: var(--ie-danger-ink); font-weight: var(--ie-fw-semi); }

/* ═══ 필터바 ═══════════════════════════════════════════════════════════ */
.ie-filterbar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--ie-sp-3);
  padding: var(--ie-sp-3) var(--ie-sp-4);
  background: var(--ie-c-surface-card);
  border: 1px solid var(--ie-c-border); border-radius: var(--ie-r-md);
}
.ie-filterbar .ie-field { flex: 0 0 auto; min-inline-size: 140px; }
.ie-filterbar__btns { margin-inline-start: auto; display: flex; gap: var(--ie-sp-2); }

.ie-list__bar {
  display: flex; align-items: center; gap: var(--ie-sp-3);
  font-size: var(--ie-fs-13); color: var(--ie-c-text-muted);
}
.ie-list__total b { color: var(--ie-c-text-body); font-variant-numeric: tabular-nums; }
.ie-list__foot { display: flex; align-items: center; justify-content: center; }

/* ═══ 페이징: get_paging() 산출물을 재정의한다 (신규 생성이 아니다) ═══════
   그누보드 마크업: <nav class="pg_wrap"><span class="pg">…<a class="pg_page">…
   css/default.css:443 `.pg_wrap{clear:both;float:left}` 의 float 은 flex 레이아웃에서 깨진다. */
.ie-shell .pg_wrap { clear: none; float: none; display: flex; justify-content: center; margin-block-start: var(--ie-sp-5); }
.ie-shell .pg      { display: inline-flex; align-items: center; gap: 2px; }
.ie-shell .pg_page,
.ie-shell .pg_current,
.ie-shell .pg_start, .ie-shell .pg_prev, .ie-shell .pg_next, .ie-shell .pg_end {
  display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: 32px; block-size: 32px; padding-inline: var(--ie-sp-2);
  border: 1px solid var(--ie-c-border); border-radius: var(--ie-r-md);
  background: var(--ie-c-surface-card); color: var(--ie-c-text-label);
  font-size: var(--ie-fs-13); text-decoration: none;
}
.ie-shell .pg_page:hover { background: var(--ie-c-surface-hover); text-decoration: none; }
.ie-shell .pg_current {
  background: var(--ie-c-action); border-color: var(--ie-c-action);
  color: var(--ie-c-action-on); font-weight: var(--ie-fw-semi);
}

/* ═══ 빈 상태 (08 §7.6): 3종을 구분한다 ════════════════════════════════ */
.ie-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--ie-sp-2);
  min-block-size: 240px; padding-block: var(--ie-sp-12);
  background: var(--ie-c-surface-card);
  border: 1px solid var(--ie-c-border); border-radius: var(--ie-r-md);
  text-align: center;
}
.ie-empty__icon  { color: var(--ie-gray-300); }
.ie-empty--error .ie-empty__icon { color: var(--ie-danger); }
.ie-empty__title { font-size: var(--ie-fs-15); color: var(--ie-c-text-body); font-weight: var(--ie-fw-semi); }
.ie-empty__desc  { font-size: var(--ie-fs-13); color: var(--ie-c-text-muted); }
.ie-empty__act   { margin-block-start: var(--ie-sp-3); }

/* 그누보드가 내는 빈 목록 (css/default.css:367~368 은 padding 만 !important) */
.ie-content .empty_table,
.ie-content .empty_list {
  color: var(--ie-c-text-muted); font-size: var(--ie-fs-14); text-align: center;
}

/* ═══ 알림 배너 ═══════════════════════════════════════════════════════════ */
.ie-alert {
  display: flex; align-items: flex-start; gap: var(--ie-sp-2);
  padding: var(--ie-sp-3) var(--ie-sp-4);
  border: 1px solid var(--ie-c-border); border-radius: var(--ie-r-md);
  font-size: var(--ie-fs-14);
}
.ie-alert--info    { background: var(--ie-info-tint);    color: var(--ie-info-ink);    border-color: var(--ie-info-border); }
.ie-alert--warning { background: var(--ie-warning-tint); color: var(--ie-warning-ink); border-color: var(--ie-warning-border); }
.ie-alert--danger  { background: var(--ie-danger-tint);  color: var(--ie-danger-ink);  border-color: var(--ie-danger-border); }
.ie-alert--success { background: var(--ie-success-tint); color: var(--ie-success-ink); border-color: var(--ie-success-border); }

/* ═══ 모달 ═══════════════════════════════════════════════════════════════
   ★ 마크업은 항상 #ie-modal-root 로 옮겨 렌더한다. 표 안에 두면 overflow 컨테이너에 잘린다. */
.ie-modal-root:empty { display: none; }
.ie-modal-back {
  position: fixed; inset: 0; z-index: var(--ie-z-modal);
  background: rgba(18, 34, 42, .45);
  display: flex; align-items: center; justify-content: center;
  padding: var(--ie-sp-4);
}
.ie-modal {
  inline-size: 100%; max-inline-size: 520px; max-block-size: 86vh;
  display: flex; flex-direction: column;
  background: var(--ie-c-surface-card);
  border-radius: var(--ie-r-lg);
  box-shadow: var(--ie-shadow-modal);
  overflow: hidden;
}
.ie-modal--lg { max-inline-size: 820px; }
.ie-modal__head {
  display: flex; align-items: center; gap: var(--ie-sp-3);
  padding: var(--ie-sp-4) var(--ie-sp-5);
  border-block-end: 1px solid var(--ie-c-border);
}
.ie-modal__title { font-size: var(--ie-fs-18); font-weight: var(--ie-fw-semi); }
.ie-modal__close {
  margin-inline-start: auto; inline-size: 32px; block-size: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: var(--ie-r-md);
  color: var(--ie-c-text-muted); cursor: pointer;
}
.ie-modal__close:hover { background: var(--ie-c-surface-hover); }
.ie-modal__body { padding: var(--ie-sp-5); overflow-y: auto; font-size: var(--ie-fs-14); line-height: var(--ie-lh-ui); }
.ie-modal__foot {
  display: flex; justify-content: flex-end; gap: var(--ie-sp-2);
  padding: var(--ie-sp-4) var(--ie-sp-5);
  border-block-start: 1px solid var(--ie-c-border);
  background: var(--ie-c-surface-page);
}

/* ═══ 토스트 ═════════════════════════════════════════════════════════════ */
.ie-toast-root {
  position: fixed; inset-block-end: var(--ie-sp-6); inset-inline-end: var(--ie-sp-6);
  z-index: var(--ie-z-toast);
  display: flex; flex-direction: column; gap: var(--ie-sp-2);
  pointer-events: none;
}
.ie-toast {
  pointer-events: auto;
  min-inline-size: 240px; max-inline-size: 380px;
  padding: var(--ie-sp-3) var(--ie-sp-4);
  border-radius: var(--ie-r-md);
  box-shadow: var(--ie-shadow-pop);
  background: var(--ie-gray-900); color: var(--ie-white);
  font-size: var(--ie-fs-14);
}
.ie-toast--ok    { background: var(--ie-success); }
.ie-toast--warn  { background: var(--ie-warning); }
.ie-toast--error { background: var(--ie-danger); }

/* ═══ 읽기 본문 (게시글): 720px, 16px/1.7 (08 §3.2) ════════════════════ */
.ie-prose {
  max-inline-size: var(--ie-content-max-read);
  font-size: var(--ie-fs-16); line-height: var(--ie-lh-read); color: var(--ie-c-text-body);
}
.ie-prose p { margin: 0 0 var(--ie-sp-4); }
.ie-prose a { text-decoration: underline; }

/* ── 라디오 · 체크박스 그룹 ────────────────────────────────────────────────
   `.ie-radios` / `.ie-check` 는 캘린더 등록폼·공휴일·목록 화면이 쓰는데 공용 정의가 없어
   `pages/calendar.css` 안에 `.ie-cal-quick` 스코프로만 있었다. 그 스코프 밖에서는
   라디오와 라벨이 줄바꿈되어 흩어진다. 여기로 올려 전 화면이 같은 모양을 쓰게 한다. */
.ie-radios {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--ie-sp-2) var(--ie-sp-4);
}
.ie-check {
  display: inline-flex; align-items: center; gap: var(--ie-sp-1);
  font-size: var(--ie-fs-13); line-height: 1.4;
  cursor: pointer; user-select: none;
}
.ie-check input[type="radio"],
.ie-check input[type="checkbox"] {
  margin: 0; flex: none; accent-color: var(--ie-brand-600);
}
.ie-check:has(input:disabled) { color: var(--ie-c-text-disabled); cursor: not-allowed; }

/* `.ie-radio`: `.ie-radios` 안의 개별 항목. `.ie-check` 와 형제 규칙이다.
   `pages/calendar.css` 안에 `.ie-cal-quick .ie-radio` / `.ie-cal-form__types .ie-radio` 로만
   있어서 그 스코프 밖(캘린더 수정 폼의 반복 3지선다)에서는 라벨이 줄바꿈되어 흩어졌다.
   docs/25 §9 No.5 의 공용화 요청이다. 페이지 CSS 에는 **밀도 차이만** 남긴다. */
.ie-radio {
  display: inline-flex; align-items: center; gap: var(--ie-sp-1);
  font-size: var(--ie-fs-13); line-height: 1.4;
  cursor: pointer; user-select: none;
}
.ie-radio input[type="radio"],
.ie-radio input[type="checkbox"] {
  margin: 0; flex: none; accent-color: var(--ie-brand-600);
}
.ie-radio:has(input:disabled) { color: var(--ie-c-text-disabled); cursor: not-allowed; }

/* ═══ 모달 (승격분) ══════════════════════════════════════════════════════════
   ★ 아래는 `pages/calendar.css` 에 캘린더 전용으로 있던 규칙과, 공용 `IERP.modal`
     (`js/inerp.js`)이 새로 쓰는 상태 블록이다. docs/26 §2 가 정본이다.
     위쪽 `═══ 모달 ═══` 블록의 기존 규칙은 **한 줄도 고치지 않았다**. 여기는 덧셈뿐이다. */

/* 모달 안에서 스크롤이 끝에 닿아도 뒤 페이지가 따라 움직이지 않게 한다.
   (`pages/calendar.css` 의 `.ie-cal-modal-back` 에서 옮겨 왔다. 캘린더만의 성질이 아니다.) */
.ie-modal-back { overscroll-behavior: contain; }

/* 크기 변형. `--lg`(820px)는 위에 이미 있고, 확인창처럼 짧은 모달용 `--sm` 을 더한다. */
.ie-modal--sm { max-inline-size: 420px; }

/* 로딩 · 오류 상태. 원격 로드(`IERP.modal.load`)가 본문 자리에 넣는다.
   ★ 스피너를 만들지 않는다. 애니메이션 1개를 위해 라이브러리를 들이는 것이 D-74 가
     막으려는 바로 그 흐름이고, 사내망에서 이 조회는 대개 한 프레임 안에 끝난다. */
.ie-modal__state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--ie-sp-3);
  min-block-size: 120px; padding-block: var(--ie-sp-8);
  color: var(--ie-c-text-muted); font-size: var(--ie-fs-14); text-align: center;
}
.ie-modal__state--error { color: var(--ie-danger-ink); }
.ie-modal__state-msg { margin: 0; }
/* 확인창의 기본 본문 한 줄 */
.ie-modal__msg { margin: 0; font-size: var(--ie-fs-14); line-height: var(--ie-lh-ui); color: var(--ie-c-text-body); }
