/* ===== CSS Reset & Variables ===== */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* hidden 속성은 항상 우선 — display 명시 클래스(.view-toggle/.badge 등)가 [hidden]을 무시하는 문제 방지 */
[hidden] {
  display: none !important;
}

:root {
  --gnb-height: 64px;
  /* clay(전자결재)의 유리 상단바 — 반투명 + 블러 (2026-09-02 봉길님: 전 화면 clay 톤) */
  --gnb-bg: rgba(255, 255, 255, 0.62);

  /* 좌측(레일·패널)은 전자결재 clay 스킨의 크림·라벤더 톤 (2026-09-02 봉길님 지시).
     approval/css/clay.css 의 --base #fcfaf9 · --accA #a48fd4 과 같은 계열이다 */
  --sidebar-bg: rgba(255, 255, 255, 0.42);

  /* 메인메뉴(두 번째 열) 자리의 바탕 — **흰색 계통**이다 (2026-09-04 봉길님:
     「메인 메뉴 쪽 배경 색은 기존의 흰색 계통으로 — 지금은 배경 색이 없는 것처럼 보인다」).
     ⚠ 옅으면 본문과 구분이 안 된다. 실측: 0.42 는 rgb(253,252,252) 로 본문 바탕
       rgb(252,250,249) 과 **1~3 차이**였다 — 있으나 마나였다.
     ⚠ **--sidebar-bg 를 쓰지 않는다.** clay.css 가 `html[data-skin="clay"]` 로 그것을
       transparent 로 덮어써, 메일·게시판·결재에서는 띠 색이 아예 사라졌다(실측
       rgba(0,0,0,0)). clay 가 모르는 이름을 따로 둬야 모든 모듈이 같은 색을 쓴다.
     ⚠ 모듈메뉴(레일) 색과 짝이다 — 함께 고칠 것 (--shell-rail-bg). */
  --shell-panel-bg: rgba(255, 255, 255, 0.92);
  --shell-rail-bg: #f7f3ef;
  --sidebar-hover: #f4efe9;
  --sidebar-active: rgba(164, 143, 212, 0.16);
  --sidebar-text: #55505e;
  --sidebar-text-active: #453764;
  --sidebar-width: 240px;
  --rail-w: 68px;   /* 최좌측 레일 — 아이콘 아래 이름까지 (메일플러그식) */
  /* 레일과 패널이 같은 격자를 타게 하는 값 — 한 곳에서 정한다 (B안, 2026-09-02) */
  /* 46/6 으로 줄였다가 「모듈메뉴가 다닥다닥 붙어 답답하다」는 지적을 받고 되돌렸다
     (2026-09-02 봉길님). 정렬은 두 열이 같은 값을 보는 것으로 지켜지지, 값을 줄여서
     지켜지는 게 아니다 */
  --nav-item-h: 54px;
  --nav-item-gap: 14px;
  --nav-top: 16px;
  /* ⚠ **용어 주의 — 봉길님의 「메인메뉴」는 두 번째 열(기안작성·결재대기…)이다.**
     맨 왼쪽 아이콘 줄(메일·일정·결재…)은 봉길님이 「모듈메뉴」라 부르신다.
     2026-09-03 이 둘을 반대로 알아듣고 **아이콘 줄을 좁혔다가** 지적받았다
     (「모듈 간격 말고 메인메뉴 간격」→「기안작성과 결재대기 메뉴 사이 간격이 너무 넓다」).
     코드에서 아이콘 줄은 .gnb-rail, 두 번째 열은 .sidebar-nav 다.

     두 번째 열의 항목 높이만 따로 둔다. 아이콘 줄은 아이콘+라벨 2줄이라 54px 가 필요하지만,
     두 번째 열은 **글자 한 줄(20px)** 뿐이라 54px 상자에 넣으면 위아래 17px 씩 떠서
     「간격이 너무 넓다」로 보인다. 실측(결재 패널):
       보이는 여백 = 상자높이(54) − 글자(20) + 아래여백(14) = **48px**
       54 → 48px    42 → 36px    36 → 30px
     42px(36px 여백)까지 줄이고 「조금만 더」를 받아 **36px(여백 30px, 원래의 62%)** 로 왔다.
     ⚠ 아래여백(--nav-item-gap 14px)은 손대지 않는다 — 그 변수는 **모듈메뉴(레일)와 공용**이라
       건드리면 아이콘 줄까지 같이 움직인다. 메인메뉴만 바꾸려면 이 높이 변수만 만진다.
     ⚠ 더 줄일 여지: 글자 20px + 위아래 8px 씩 = 36px 이 지금이다. 32px 아래로는
       글자가 상자에 닿아 누를 곳이 좁아진다 */
  --panel-item-h: 36px;

  /* 떠 있는 창(모달)의 바탕 — **불투명 고정**. clay 스킨이 --bg-primary 를 반투명으로
     바꾸기 때문에 그 변수를 쓰면 모달 뒤가 비친다 (2026-09-03 봉길님) */
  --modal-bg: #ffffff;

  /* 자기소개·올해 목표의 글이 **흐르는 폭**. 「내 정보」의 입력칸과 구성원 화면의 문단이
     이 한 값을 같이 본다 — 그래야 같은 글이 두 화면에서 같은 자리에서 끊긴다
     (2026-09-03 봉길님). ⚠ 여백을 더하고 빼서 맞추려 하면 두 화면의 여백 구조가 달라
     번번이 어긋난다(실측 298 vs 327, 324 vs 327). 폭 자체를 못박는 편이 확실하다. */
  --note-line-width: 300px;

  --bg-primary: #ffffff;
  /* 배경은 아주 옅게. 면 구분은 테두리가 아니라 여백과 흰 카드로 한다 (2026-08-16 플렉스형) */
  --bg-secondary: #f7f8f9;
  --bg-tertiary: #f2f4f6;

  --text-primary: #111827;
  --text-secondary: #6b7280;
  --text-tertiary: #9ca3af;

  /* 선은 최소한만. 구분은 여백이 한다 */
  --border-color: #e8eaed;
  --border-light: #f2f4f6;

  --accent: #a48fd4;
  /* ===== 데이브레이크(clay) 버튼 색 — 2026-09-03 봉길님: 「전체 버튼 색상도 데이브레이크로」
     ⚠ clay.css 의 --ink 와 같은 값이지만 그 토큰은 clay 를 싣는 화면에서만 산다.
       버튼은 모든 화면에 있으므로 전역에도 같은 값을 둔다. */
  --btn-ink: #2b2a33;
  --btn-ink-soft: rgba(43, 42, 51, 0.92);
  --btn-ink-tint: rgba(43, 42, 51, 0.06);
  --accent-hover: #8b74c4;
  --accent-light: #f4f0fc;

  /* 상태색은 강조색과 다른 축이다 — 데이브레이크에서 완료·정상은 민트다 (clay --accB #8fbfa6).
     라벤더로 칠하면 「완료」와 「선택됨」이 같은 색이 되어 구분이 사라진다 (2026-09-04) */
  --success: #3f7a5c;
  --success-bg: #eef6f1;
  --warning: #f59e0b;
  --warning-bg: #fffbeb;
  --danger: #ef4444;
  --danger-bg: #fef2f2;
  --gray-badge: #9ca3af;
  --gray-badge-bg: #f3f4f6;

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.08);

  --transition: 0.15s ease;

  /* 날짜칸(YYYY-MM-DD) 표기 폭 — 전역 규칙과 폼 안 규칙이 같은 값을 본다 */
  --date-input-w: 120px;

  /* GNB 로고 「틀」 — 로고가 놓일 자리. 사이드바 폭(240) - 왼쪽 정렬 여백(32).
     ⚠ 이 틀은 고정이다. 로고를 크게 하고 싶으면 틀을 넓히는 게 아니라
       **틀 안에서 이미지를 확대(--gnb-logo-zoom)** 한다. 틀을 넓히면 사이드바와
       경계선이 어긋난다 (2026-09-02 봉길님). */
  --gnb-logo-box-w: 208px;
  --gnb-logo-box-h: 64px;

  --accent-rgb: 164, 143, 212;

  --font-stack: -apple-system, 'Pretendard', 'Segoe UI', Roboto, sans-serif;

  --gradient-teal: linear-gradient(135deg, #a48fd4 0%, #8b74c4 100%);
  --gradient-blue-purple: linear-gradient(135deg, #a48fd4 0%, #6b5a91 100%);
  --gradient-cyan-mint: linear-gradient(135deg, #c0aee6 0%, #a48fd4 100%);
  --gradient-pink-orange: linear-gradient(135deg, #f43f5e 0%, #f97316 100%);
  --gradient-light: linear-gradient(135deg, rgba(164,143,212,0.05) 0%, rgba(139,116,196,0.05) 100%);
  --shadow-teal: 0 8px 24px rgba(164, 143, 212, 0.15);
  --shadow-blue: 0 8px 24px rgba(139, 116, 196, 0.12);

  --accent-blue: #8b74c4;
  --accent-blue-hover: #6b5a91;
  --gradient-teal-hover: linear-gradient(135deg, #8b74c4 0%, #6b5a91 100%);
}

html {
  font-size: 15px;
}

body {
  font-family: var(--font-stack);
  color: var(--text-primary);
  background: #fcfaf9;   /* clay --base — 전 화면이 전자결재와 같은 바탕 (2026-09-02) */
  line-height: 1.5;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.body-wrap {
  display: flex;
  flex: 1;
  min-height: calc(100vh - var(--gnb-height));
  overflow-x: clip;
}

/* ===== 셸(상단바 · 모듈메뉴 · 메인메뉴)의 글꼴을 **한 값으로 못박는다** =====
   2026-09-03 봉길님: 「인사관리 모듈을 선택했을 때와 다른 모듈에서 텍스트 사이즈가 달라진다」

   ⚠ 크기는 어디서나 같았다(레일 라벨 10.5px). **글꼴이 갈려 있었다.**
     clay.css 를 싣는 화면(결재·게시판·근태·구성원)은 `--font-stack` 을 Pretendard 우선으로
     **다시 정의**하고 자간(-0.005em)까지 준다. 안 싣는 화면(인사관리·급여·설정)은
     -apple-system 우선이라 한글이 다른 글꼴로 그려진다 —
     실측: 같은 「메일」 라벨이 **19px vs 21px**. 그래서 크기가 달라 보였다.
   ⚠ clay.css 는 비유바움 운영 화면이 함께 쓰므로 건드리지 않는다. 대신 셸 요소에만
     글꼴·자간을 여기서 정한다. 본문(카드·표)의 clay 룩은 그대로 둔다.
   ⚠ 자기소개·올해 목표는 .note-text 가 자기 글꼴을 따로 정한다(더 안쪽이라 영향 없다). */
.gnb,
.gnb-rail,
.sidebar,
.gnb-profile-menu {
  font-family: -apple-system, 'Pretendard', 'Segoe UI', Roboto, sans-serif;
  letter-spacing: normal;
}

/* ===== GNB (Global Navigation Bar) ===== */
.gnb {
  position: sticky;
  top: 0;
  z-index: 200;
  width: 100%;
  height: var(--gnb-height);
  background: var(--gnb-bg);
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  display: flex;
  align-items: center;
  padding: 0;
  gap: 0;
  flex-shrink: 0;
  /* 구분선 없이 배경색 차이만으로 가른다 (2026-09-02 봉길님: 「상단에 구분선은 없는게 좋을 것 같은데」) */
  border-bottom: none;
  box-shadow: none;
}

.gnb-logo {
  display: flex;
  align-items: center;
  /* ⚠ 사이드바와 경계선을 맞춘다. 한때 로고를 키우려고 min-width 로 풀어 칸이
     늘어나게 했었는데, 봉길님이 「로고칸을 키우는 게 아니라 로고칸 영역에서
     이미지를 확대할 수 있도록」이라고 바로잡으셨다 (2026-09-02). 칸은 고정이다. */
  width: var(--sidebar-width);
  height: 100%;
  /* 좌측 정렬 기준선 32px — 사이드바 메뉴 아이콘 SVG가 그려지기 시작하는 x와 일치
     (메뉴 a: margin 8 + nav 패딩 8 + padding-left 14 = 30, .nav-icon 20 안에 svg 16 중앙 → 32) */
  padding-left: 32px;
  gap: 8px;
  flex-shrink: 0;
  /* 상단이 전체 한 줄이 되면서 로고칸 오른쪽 세로선도 뺐다 — 선 없이 한 판이다 */
  border-right: none;
  text-decoration: none;
}

.gnb-logo:hover {
  text-decoration: none;
}

.gnb-logo .gnb-logo-icon {
  width: 36px;
  height: 36px;
  background: linear-gradient(135deg, #c0aee6, #a48fd4, #8b74c4);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  box-shadow: none;
}

.gnb-logo .gnb-logo-icon svg {
  width: 20px;
  height: 20px;
}

/* 회사 로고 자동 맞춤 — 원본 비율 그대로 높이 박스에 맞춰 축소(2026-07-24 봉길님 시안 ⑪).
   height 고정이면 정사각·세로형 로고가 GNB(64px)를 꽉 채우고 작은 로고는 강제 확대돼 흐려짐.
   max-width는 극단적으로 가로가 긴 로고만 걸러내는 안전장치.

   ⚠ 2026-09-02: 높이를 법인설정에서 정할 수 있게 변수로 뺐다 (봉길님: 로고가 너무 작다).
   ⚠ 2026-09-02: 크기를 법인설정에서 정한다 (봉길님: 로고가 너무 작다 → 40px 도 작다 →
     「좌측 상단 사이즈 영역만큼 표시되게 해서 로고를 채우든가. 기업마다 다 적용가능하게
     해야지 제품같지」). **px 을 찍는 방식을 버리고 로고칸 대비 비율로 바꿨다** —
     px 은 로고 비율마다 결과가 달라서 회사마다 다시 맞춰야 하고, 그건 제품이 아니다.

   ⚠⚠ 높이만으로는 안 된다. 가로가 긴 로고는 **폭 상한에 먼저 걸려** 높이를 올려도 안 커진다
     (6:1 로고를 40px 로 올려도 176px 폭에 걸려 실제 높이 29px — 실측).
     그래서 높이·폭 두 상한을 **같은 비율로 함께** 움직인다. 그러면 가로형은 폭이,
     세로형은 높이가 먼저 차서 어떤 비율이든 칸을 최대로 쓴다.

   ⚠ 여기 기본값(18px/176px)은 **설정을 안 한 법인의 종전 모습**이다. 건드리지 말 것.
     설정이 있으면 js/data.js 가 인라인으로 덮어쓴다. */
.gnb-logo .gnb-logo-img {
  height: auto;
  width: auto;
  max-height: var(--gnb-logo-h, 18px);
  max-width: var(--gnb-logo-w, 176px);
  object-fit: contain;
  display: block;
}

/* ===== 로고 틀 — 칸 안에서 확대·이동 (2026-09-02 봉길님) =====
   봉길님: 「로고칸을 키우는 게 아니라 로고칸 영역에서 이미지를 확대할 수 있도록,
   위치 조절해서 등록시킬 수 있도록」.

   왜 필요한가 — 로고 이미지에 **여백이 들어 있으면** 칸에 꽉 맞춰도(contain) 실제 그림은
   작게 보인다. 그 경우 칸을 넓혀도 소용없다. 틀 밖으로 넘치게 **확대**하고 보고 싶은
   부분으로 **옮기는** 것만이 답이다. 프로필 사진 자르기와 같은 조작이다.

   ⚠ `object-fit: contain` 이 배율 1 의 기준이다. 그래서 zoom 1 은 지금까지의 「칸에 맞춤」과
     같고, 2 면 두 배로 커지며 틀 밖은 잘린다(overflow: hidden).
   ⚠ 틀은 고정이다. 넘치는 그림이 메뉴를 덮지 않게 잘라내는 것이 이 틀의 역할이다. */
.gnb-logo-frame {
  display: block;
  flex: none;
  width: var(--gnb-logo-box-w);
  height: var(--gnb-logo-box-h);
  overflow: hidden;
}

.gnb-logo-frame .gnb-logo-img {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: contain;
  transform-origin: center center;
  transform: scale(var(--gnb-logo-zoom, 1))
    translate(var(--gnb-logo-x, 0%), var(--gnb-logo-y, 0%));
}

.gnb-logo .gnb-logo-text {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.5px;
  color: #111827;
}

/* 로고의 「4U」 — 데이브레이크 라벤더. --accent(에메랄드)를 쓰면 로그인 화면(라벤더)과
   상단바가 색이 달라진다. 이름을 START4U 로 바꾸면서 한 값으로 맞췄다 (2026-09-04).
   ⚠ --accent 자체는 바꾸지 않는다 — 배지·성공 표시 등 다른 자리가 같이 물든다 */
.gnb-logo .gnb-logo-text .brand-accent {
  color: #a48fd4;
}

.gnb-menu {
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 16px;
  gap: 2px;
  flex: 1;
  min-width: 0;
  /* ⚠ overflow 를 걸면 안 된다. 예전에는 모듈 10개가 한 줄이라 가로 스크롤(overflow-x:auto)을
     걸어 뒀는데, 그 상태로 펼침 메뉴를 달면 **드롭다운이 GNB 높이에서 잘린다**
     (overflow-x:auto 는 overflow-y 도 visible 이 아니게 만든다).
     2026-09-02 상단 항목이 홈·업무·인사관리·설정 넷으로 줄어 스크롤이 필요없어졌다 */
  overflow: visible;
}

.gnb-menu-item {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 100%;
  padding: 0 16px;
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--transition), background var(--transition), opacity var(--transition);
  white-space: nowrap;
  user-select: none;
  flex-shrink: 0;
}

.gnb-menu-item:hover {
  color: var(--text-primary);
  background: rgba(0, 0, 0, 0.03);
  text-decoration: none;
}

.gnb-menu-item.active {
  color: var(--text-primary);
  background: transparent;
}

.gnb-menu-item.gnb-menu-disabled {
  color: var(--text-secondary);
  opacity: 0.4;
  cursor: not-allowed;
}

.gnb-menu-item.gnb-menu-disabled:hover {
  color: var(--text-secondary);
  background: none;
}

.gnb-menu-external {
  color: #8b74c4;
}

.gnb-menu-external:hover {
  color: #6b5a91;
  background: rgba(164, 143, 212, 0.06);
}

/* 활성 메뉴 아래 밑줄(::after)은 걷어냈다 (2026-09-02 봉길님 「하단 표시는 빼자」).
   아이콘이 붙은 뒤로는 밑줄까지 있으면 표시가 두 겹이 된다.
   지금 어디인지는 아래 색·굵기로만 알린다 — 표시를 없앤 게 아니라 하나로 줄인 것이다. */
.gnb-menu-item.active {
  color: var(--text-primary);
  font-weight: 700;
}

.gnb-menu-item.active .gnb-menu-icon {
  opacity: 1;
  color: var(--accent);
}

.gnb-menu::-webkit-scrollbar {
  display: none;
}

/* 상단 아이콘 — 글자만 여섯 개 늘어서면 눈이 잡을 곳이 없다 (2026-09-02).
   기본은 흐리게 두고 지금 자리에서만 또렷해진다 */
.gnb-menu-icon {
  width: 15px;
  height: 15px;
  flex: none;
  opacity: 0.65;
  transition: opacity var(--transition), color var(--transition);
}

.gnb-menu-item:hover .gnb-menu-icon { opacity: 1; }

.gnb-menu-label {
  line-height: 1;
}

.gnb-user {
  margin-left: auto;
  padding-right: 24px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: #4a5568;
  font-size: 13px;
  font-weight: 500;
}

.gnb-user-icon {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.8);
}

a,
a.link {
  color: var(--accent);
  text-decoration: none;
}

a:hover,
a.link:hover {
  text-decoration: underline;
}

/* ===== GNB 펼침 메뉴 =====
   상단은 「누가 쓰는가」로 넷(홈·업무·인사관리·설정), 모듈은 그 아래로 편다.
   ⚠ 마우스를 올려서가 아니라 **눌러서** 연다. hover 로 열면 터치 화면에서 첫 탭이
     「열기」에 먹혀 항목을 한 번에 못 고른다 */

.gnb-group {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 100%;
  flex-shrink: 0;
}

.gnb-group-btn {
  border: 0;
  background: transparent;
  font-family: inherit;
}

.gnb-caret {
  width: 11px;
  height: 11px;
  opacity: 0.55;
  transition: transform var(--transition);
}

.gnb-group[data-open="true"] .gnb-caret { transform: rotate(180deg); }
.gnb-group[data-open="true"] .gnb-group-btn { color: var(--text-primary); }

.gnb-dropdown {
  position: absolute;
  top: calc(100% - 8px);
  left: 8px;
  min-width: 172px;
  padding: 6px;
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  display: none;
  z-index: 300;
}

.gnb-group[data-open="true"] .gnb-dropdown { display: block; }

.gnb-dd-item {
  display: block;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--transition), color var(--transition);
}

.gnb-dd-item:hover {
  background: var(--bg-tertiary);
  color: var(--text-primary);
  text-decoration: none;
}

.gnb-dd-item.active {
  background: var(--accent-light);
  color: var(--accent-hover);
  font-weight: 600;
}

/* 미완성 모듈 — 감추지 않는다. 있는데 아직 못 쓰는 것과 아예 없는 것은 다르다 */
.gnb-dd-item.gnb-dd-disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.gnb-dd-item.gnb-dd-disabled:hover {
  background: transparent;
  color: var(--text-secondary);
}

/* ===== Sidebar ===== */
/* 모듈메뉴 판 — 상단바 아래에 **항상 붙어 있는다** (2026-09-03 봉길님:
   「상단, 모듈메뉴, 메인메뉴는 모두 화면에 고정되어 표시되도록」).

   ⚠ 종전에는 min-height 만 있어서, 메뉴가 많으면 판이 창보다 커졌고 sticky 가 붙잡지 못해
     본문과 함께 밀려 올라갔다 (2026-09-03 1280x560 실측: 스크롤 후 판 top −438).
     **height 를 창 높이에 못박아야** sticky 가 제자리를 지킨다. 넘치는 메뉴는 안에서 굴린다. */
.sidebar {
  width: var(--sidebar-width);
  height: calc(100vh - var(--gnb-height));
  min-height: calc(100vh - var(--gnb-height));
  background: var(--sidebar-bg);
  border-right: 1px solid var(--border-light);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: var(--gnb-height);
  align-self: flex-start;
  z-index: 100;
  flex-shrink: 0;
  border-right: 1px solid var(--border-color);
}

.sidebar-logo {
  padding: 24px 20px 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.sidebar-logo .logo-icon {
  width: 32px;
  height: 32px;
  background: var(--accent);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 14px;
}

.sidebar-logo .logo-text {
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.3px;
}

.sidebar-category {
  margin: 0 20px 4px;
  padding: 12px 14px 8px;
  background: none;
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 700;
  border: none;
  border-radius: 0;
  letter-spacing: -0.2px;
}

.sidebar-category:first-child {
  margin-top: 24px;
}

.sidebar-nav {
  flex: 1;
  /* 위 여백은 레일과 **같은 변수**를 쓴다 — 값을 따로 적으면 한쪽을 고칠 때 또 어긋난다
     (B안, 2026-09-02 봉길님) */
  padding: var(--nav-top) 8px 8px;
  /* 넘치는 메뉴는 **여기서** 굴린다. 판(.sidebar)이 아니라 목록이 스크롤해야
     나중에 하단 고정 영역(.sidebar-footer)을 붙여도 같이 밀려 올라가지 않는다.
     ⚠ flex 자식은 min-height:auto 라 내용만큼 부풀어 overflow 가 안 걸린다 — 0 으로 눌러야 한다 */
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;   /* 레일과 같은 이유 — 세로바가 폭을 먹어 가로바가 따라 생기는 걸 막는다 */
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.sidebar-nav::-webkit-scrollbar {
  width: 6px;
}

.sidebar-nav::-webkit-scrollbar-thumb {
  background: rgba(120, 110, 130, 0.28);
  border-radius: 3px;
}

/* ===== 메인메뉴(2열) — 결재 화면과 같은 모습으로 통일 (2026-09-03 봉길님)
   「인사관리 모듈에서 메인메뉴 텍스트 스타일이라든지 활성화 표시라든지
     이런 부분은 결재 모듈의 메인메뉴 스타일을 적용하자」

   ⚠ 아래 색·모서리·그림자는 **approval/css/clay.css 의 값과 같아야 한다.**
     clay.css 는 비유바움 운영 화면이 함께 쓰므로 건드리지 않고, 여기(기본)를 그쪽에 맞췄다.
     clay 화면은 clay.css 가 뒤에 실려 덮지만 **값이 같아서 결과가 같다.**
     한쪽을 바꾸면 다른 쪽도 같이 바꿀 것 — 안 그러면 화면마다 또 달라진다.
   실측 근거(2026-09-03, 라이브): 결재는 모서리 12 / 활성 배경 흰색 .8 / 굵기 500,
     인사관리는 모서리 8 / 활성 배경 보라 .16 / 굵기 700 이었다. */
.sidebar-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  color: rgba(93, 91, 105, 1);
  border-radius: 12px;
  font-size: 13.5px;
  font-weight: 400;
  transition: all var(--transition);
  text-decoration: none;
  /* 글자 한 줄짜리라 아이콘 줄(54px)보다 낮다 — 그대로 두면 위아래 17px 씩 떠서
     「기안작성과 결재대기 사이가 너무 넓다」가 된다 (2026-09-03 봉길님).
     아래여백은 아이콘 줄과 같은 변수를 계속 쓴다 */
  height: var(--panel-item-h);
  box-sizing: border-box;
  margin: 0 8px var(--nav-item-gap);
}

/* 메뉴 아래에 딸린 항목(게시판 이름 등)은 한 칸 들여 쓴다 — 소속이 눈에 보여야 한다.
   ⚠ 페이지마다 prefix 클래스를 새로 만들지 않는다. 메일의 하위 폴더(.mail-subbox)도
     같은 34px 을 쓰고 있어, 다음에 손댈 때 이 이름으로 합칠 수 있다 */
.sidebar-nav a.sidebar-subitem { padding-left: 34px; }

/* 메뉴 안의 구분선 — 성격이 다른 묶음 사이에 한 줄 긋는다.
   (게시판: 「게시판 이름들」과 「찾아보기(필독·안읽은·내가쓴)」가 붙어 있어 경계가 흐렸다) */
.sidebar-nav .sidebar-sep {
  height: 1px;
  background: rgba(0, 0, 0, 0.06);
  margin: 4px 4px 14px;   /* 아래 여백은 메뉴 항목끼리의 간격(14)과 같게 */
}

.sidebar-nav a:hover {
  background: rgba(255, 255, 255, 0.55);
  color: rgba(43, 42, 51, 1);
  text-decoration: none;
}

/* 활성 표시 — 색을 칠하는 게 아니라 **흰 알약이 떠 있는** 모양이다(결재 화면 방식).
   굵기는 700 이 아니라 500 이다. 700 은 글자가 번져 보여 다른 줄과 폭이 달라진다 */
.sidebar-nav a.active {
  background: rgba(255, 255, 255, 0.8);
  color: rgba(43, 42, 51, 1);
  font-weight: 500;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.85) inset,
              0 10px 22px -16px rgba(70, 60, 100, 0.5);
}

/* 하위 묶음을 거느린 상위 항목은 알약을 쓰지 않는다 — 실제 위치는 하위가 말한다.
   둘 다 알약이면 인사관리처럼 「인사정보」와 「직원현황」에 **흰 알약이 두 개** 떠서
   지금 어디인지 두 번 말하게 된다 (2026-09-03 화면에서 확인). 상위는 글자만 진하게. */
.sidebar-nav a.active:has(+ .sidebar-sub) {
  background: none;
  box-shadow: none;
  color: rgba(43, 42, 51, 1);
  font-weight: 600;
}

/* 메인메뉴는 **글자만** 쓴다 (2026-09-03 봉길님: 「메인메뉴에서는 아이콘을 빼버리고
   텍스트만 사용하자」). 왼쪽 모듈메뉴가 아이콘 줄이라 여기까지 아이콘을 두면 두 번 말하는 셈이다.

   ⚠ 마크업이 아니라 **CSS 로 숨긴다.** 이 줄을 만드는 곳이 세 군데(js/data.js 공통,
     payroll-sidebar.js, payroll.js)라 마크업을 고치면 한 곳을 빠뜨려 화면마다 갈린다.
     하단 로그아웃 버튼의 아이콘은 .sidebar-footer 안이라 여기 걸리지 않는다. */
.sidebar-nav a > .nav-icon,
.sidebar-nav .sidebar-pending > .nav-icon {
  display: none;
}

/* 메뉴 옆 건수 — 「지금 나를 기다리는 것」이 있을 때만 나타난다.
   값이 비면 빈 요소라 :empty 로 사라진다 */
.nav-count {
  margin-left: auto;
  min-width: 19px;
  height: 19px;
  padding: 0 6px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  flex: none;
}

.nav-count:empty { display: none; }

.nav-icon {
  width: 20px;
  min-width: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.nav-icon svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  stroke-width: 1.5;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sidebar-group-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  margin: 0 8px 1px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  cursor: default;
  letter-spacing: -0.2px;
}

.sidebar-group-items a {
  padding-left: 40px !important;
  font-size: 12.5px;
}

.sidebar-footer {
  margin-top: auto;
  padding: 14px 16px 18px;
  border-top: 1px solid var(--border-color);
  color: var(--sidebar-text);
  font-size: 11px;
}

.sidebar-account {
  display: grid;
  gap: 8px;
}

.sidebar-user-email {
  /* 글자 시작 x = footer padding 16 + 16 = 32 — 메뉴 아이콘 SVG 기준선과 정렬 */
  padding: 0 16px;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-logout-btn {
  width: 100%;
  display: flex;
  align-items: center;
  /* 아이콘 SVG 32 · 글자 60 — 메뉴 항목과 동일 기준선(테두리 1px 포함해 padding 13) */
  gap: 10px;
  padding: 9px 13px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-primary);
  color: var(--sidebar-text);
  font-family: var(--font-stack);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
}

.sidebar-logout-btn:hover {
  background: var(--sidebar-hover);
  border-color: var(--border-color);
  color: var(--sidebar-text-active);
}

.sidebar-logout-btn .nav-icon {
  width: 20px;
  min-width: 20px;
}

.sidebar-logout-btn svg {
  width: 16px;
  height: 16px;
}

/* ===== Main Content ===== */
.main-content {
  flex: 1;
  padding: 24px 24px 48px;
  min-height: calc(100vh - var(--gnb-height));
  min-width: 0;
  overflow: hidden;
}

main.main-content {
  /* ⚠ max-width 1600 을 **두지 않는다** (2026-09-07 봉길님: 「굳이 왜 여백을 두냐고」
     「조직 많을 경우는 생각 안하냐?」). 2560 모니터에서 왼쪽 24 · 오른쪽 676 으로 어긋났고,
     조직도처럼 옆으로 자라는 화면이 폭을 못 쓴다. 본문은 창을 다 쓴다 — 여백은 padding 이 준다.
     읽는 폭을 좁혀야 하는 화면(결재 문서·양식)은 제 자리에서 max-width 를 갖는다 */
  width: 100%;
  margin-left: 0;
  margin-right: auto;
}

/* ===== Rank Management Layout ===== */
.rank-management-shell {
  width: 100%;
  max-width: 1000px;
}

.rank-management-shell:has(#tabOrg.active #chartView:not(.hidden)) {
  max-width: none;
}

.rank-management-shell:has(#tabSettings.active) {
  max-width: none;
}

.rank-management-shell:has(#tabOrg.active #chartView:not(.hidden)) #chartView,
.rank-management-shell:has(#tabOrg.active #chartView:not(.hidden)) .org-chart-wrap {
  width: 100%;
  max-width: none;
}

/* ===== Page Header ===== */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.page-header h1 {
  /* 본문 15px와 3px 차이라 위계가 없었다 → 제목을 확실히 키운다 (2026-08-16) */
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -0.9px;
  color: var(--text-primary);
}

.page-header p {
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 2px;
}

.page-header .header-actions {
  display: flex;
  gap: 10px;
}

/* ===== Stat Cards ===== */
.stat-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-bottom: 20px;
}

.stat-card {
  background: var(--bg-primary);
  border-radius: 12px;
  padding: 16px 18px;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 0 0 1px rgba(16, 24, 40, 0.03);
  border: none;
}

.stat-card .stat-label {
  font-size: 11px;
  color: var(--text-secondary);
  font-weight: 500;
  margin-bottom: 4px;
}

.stat-card .stat-value {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.7px;
}

/* 그라데이션 글자 해제 — 숫자는 단색이어야 읽힌다 (대비 확보) */
.stat-card .stat-value.total { color: var(--text-primary); }
.stat-card .stat-value.active { color: var(--accent-hover); }
.stat-card .stat-value.leave { color: #b45309; }
.stat-card .stat-value.retired { color: var(--text-tertiary); }
.stat-card .stat-value.appointments { color: var(--accent-hover); }

/* ===== Toolbar (Search + Filters) ===== */
.toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.toolbar .btn {
  padding: 8px 14px;
  font-size: 13px;
}

.search-box {
  position: relative;
  flex: 0 0 220px;
  border-radius: var(--radius-sm);
  background: var(--bg-primary);
}

/* 모달 안 검색창은 모달 body 폭에 맞게 자동 확장 (toolbar는 220px 고정 표준 유지) */
.modal-overlay .modal-body .search-box,
.modal .modal-body .search-box {
  flex: 1 1 auto;
  width: 100%;
}
/* 단, 모달 안이라도 toolbar 안에 있으면 toolbar 표준(220px)을 따른다.
   안 그러면 검색창이 100% 폭을 먹어 필터·액션이 줄줄이 아래로 밀려난다. */
.modal-overlay .modal-body .toolbar .search-box,
.modal .modal-body .toolbar .search-box {
  flex: 0 0 220px;
  width: auto;
}

/* 검색 자동완성 드롭다운 (재사용 컴포넌트 — .search-box 안에 배치) */
.search-suggest {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 30;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  max-height: 320px;
  overflow-y: auto;
}
.search-suggest-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;
}
.search-suggest-item:hover,
.search-suggest-item.active {
  background: var(--bg-tertiary);
}
.search-suggest-item .ss-no {
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  min-width: 52px;
}
.search-suggest-item .ss-name {
  font-weight: 600;
  color: var(--text-primary);
}
.search-suggest-item .ss-org {
  margin-left: auto;
  color: var(--text-tertiary);
  font-size: 12px;
}

.search-box input,
.search-box input[type="search"] {
  width: 100%;
  padding: 8px 14px 8px 36px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: var(--font-stack);
  background: var(--bg-primary);
  transition: border-color var(--transition);
}

.search-box input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

/* 브라우저 기본 search input X 버튼 숨김 (우리 디자인 톤과 안 맞음).
   ⚠ 종전에는 `.search-box` 안에만 걸려 있었다. 그 밖에서 `type="search"` 를 쓰면
     브라우저 기본 X 가 그대로 떴다 — 일정 「+ 추가」 고르개의 찾기 칸이 그랬다
     (2026-09-10 봉길님: 「버튼 디자인은 왜 이러냐?」).
     화면마다 예외를 만들 이유가 없다. **모든 검색 칸**으로 넓힌다 */
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}
input[type="search"]::-ms-clear,
input[type="search"]::-ms-reveal {
  display: none;
  width: 0;
  height: 0;
}

.search-box .search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
  width: 16px;
  height: 16px;
  pointer-events: none;
}

.search-box .search-icon svg {
  width: 16px;
  height: 16px;
  display: block;
}

.filter-select {
  padding: 8px 32px 8px 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: var(--font-stack);
  background: var(--bg-primary);
  color: var(--text-primary);
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M3 4.5l3 3 3-3'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  transition: border-color var(--transition);
}

.filter-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

/* input.filter-select (날짜 등 텍스트 입력) — select 화살표 제거 */
input.filter-select {
  background-image: none;
  padding-right: 12px;
  cursor: text;
}

/* 날짜 입력 (YYYY-MM-DD 자동 변환) — 표기 폭만큼만.
   폼 안에서는 `.form-group input` 의 width:100% 에 지므로 그쪽에도 같은 폭을 다시 건다.
   두 자리가 같은 값을 보도록 폭은 --date-input-w 하나로 둔다 */
input[data-date-auto-format] {
  width: var(--date-input-w);
  flex-shrink: 0;
}

/* 요일 칩 색 변형 — 토요일(파랑)/일요일(빨강). 평일은 .badge-retired(회색) 재사용 */
.badge-weekday-sat {
  background: linear-gradient(135deg, #eff6ff, rgba(59, 130, 246, 0.15));
  color: #1d4ed8;
  border: 1px solid rgba(59, 130, 246, 0.22);
}
.badge-weekday-sun {
  background: linear-gradient(135deg, #fef2f2, rgba(239, 68, 68, 0.15));
  color: #b91c1c;
  border: 1px solid rgba(239, 68, 68, 0.22);
}

/* 월 입력 (type="month") — 날짜 input과 동일 폭/높이 (토글 전환 시 layout shift 방지) */
input[type="month"].filter-select {
  width: 120px;
  height: 35px;
  box-sizing: border-box;
  flex-shrink: 0;
}

/* ===== Tabs ===== */
.tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border-light);
  margin-bottom: 16px;
}

.tab-btn {
  padding: 10px 16px;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all var(--transition);
  font-family: var(--font-stack);
}

.tab-btn:hover:not(.active) {
  color: var(--text-primary);
  border-bottom-color: rgba(164, 143, 212, 0.3);
}

.tab-btn.active {
  border-bottom: 2px solid var(--accent);
  color: var(--accent);
  font-weight: 600;
  background: none;
}

/* ===== Table ===== */
.table-container {
  background: var(--bg-primary);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 0 0 1px rgba(16, 24, 40, 0.03);
  border: none;
  overflow-x: auto;
  overflow-y: hidden;
}

.table-scroll {
  flex: 1 1 auto;
  overflow: auto;
  min-height: 0;
}

table {
  width: 100%;
  border-collapse: collapse;
}

thead th {
  padding: 12px 16px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0;
  /* 열 제목은 읽는 자리지 칠하는 자리가 아니다. 배경도 지운다 (2026-08-16) */
  background: transparent;
  border-bottom: 1px solid var(--border-light);
  white-space: nowrap;
}

/* 스크롤되는 표의 열 제목에는 반드시 배경이 있어야 한다.
   ⚠ position:sticky 는 자리만 잡아주지 배경을 칠해주지 않는다. 위 `thead th` 가
     `background: transparent` 라(2026-08-16 「열 제목은 칠하는 자리가 아니다」) 헤더를
     고정하는 순간 본문 행이 그대로 통과해 글자가 겹쳐 보인다.
   2026-09-01 급여명세에서 발견했는데, 같은 증상이 4개 화면에 더 있었다
   (보험 보험료·노무 건강검진·법정교육·회사규정). 페이지마다 배경을 덧대면 다음 화면에서 또 난다.
   여기서 한 번에 준다 — 스크롤 컨테이너 배경과 같은 색이라 고정 안 한 표는 보이는 게 달라지지 않는다.
   페이지가 제 배경(그라데이션 등)을 지정하면 그쪽 명시도가 높아 그대로 이긴다. */
.table-scroll thead th {
  background: var(--bg-primary);
}

tbody td {
  padding: 17px 16px;
  font-size: 13.5px;
  border-bottom: 1px solid var(--border-light);
  vertical-align: middle;
  text-align: center;
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr {
  transition: background var(--transition);
}

tbody tr:hover {
  background: var(--bg-secondary);
}

.table-link {
  color: var(--accent);
  font-weight: 500;
  cursor: pointer;
}

.table-link:hover {
  text-decoration: underline;
}

tbody tr .btn {
  opacity: 0;
  transition: opacity var(--transition), all var(--transition);
}

tbody tr:hover .btn {
  opacity: 1;
}

/* ===== Badges ===== */
/* 2026-08-16 플렉스형 — 알약·그라데이션·테두리 제거. 면색만으로 구분한다 */
.badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 700;
  border: none;
  white-space: nowrap;
}

.badge-active {
  background: #e7f7ef;
  color: #00794a;
}

.badge-leave {
  background: #fff3e0;
  color: #9a5b00;
}

.badge-retired {
  background: var(--bg-tertiary);
  color: var(--text-tertiary);
}

.badge-emerald {
  background: var(--bg-tertiary);
  color: var(--text-secondary);
}

.badge-blue {
  background: #eef3fb;
  color: #1d4a80;
}

.badge-warning {
  background: #fff3e0;
  color: #9a5b00;
}

.badge-danger {
  background: #fdeeee;
  color: #a32020;
}

/* toolbar 내부 badge — 컨트롤(filter-select 등) 높이·모서리에 맞춰 사각형으로 통일 */
.toolbar .badge {
  display: inline-flex;
  align-items: center;
  height: 35px;
  padding: 0 12px;
  border-radius: 8px;
  font-weight: 600;
  cursor: default;
  box-sizing: border-box;
}

/* ===== Buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 18px;
  border: none;
  border-radius: 9px;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
  font-family: var(--font-stack);
}

.btn:focus-visible {
  outline: 2px solid rgba(43, 42, 51, 0.55);
  outline-offset: 2px;
}

/* 2026-08-16 정돈 — 초록 그림자·확대 애니메이션 제거. 누르는 자리는 움직이지 않는다 */
.btn-primary {
  background: var(--btn-ink-soft);
  border: 1px solid var(--btn-ink-soft);
  color: #fff;
  font-weight: 600;
  border-radius: 9px;
  padding: 11px 20px;
  box-shadow: none;
  transition: background var(--transition);
}

.btn-primary:hover {
  background: var(--btn-ink);
  border-color: var(--btn-ink);
  box-shadow: none;
}

.btn-primary:active {
  background: #1f1e26;
  border-color: #1f1e26;
  box-shadow: none;
}

.btn-secondary {
  background: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
}

.btn-secondary:hover {
  background: var(--bg-secondary);
}

.btn-danger {
  background: var(--danger);
  color: #fff;
}

.btn-danger:hover {
  background: #dc2626;
  transform: translateY(-1px);
}

.btn-danger-outline {
  background: var(--bg-primary);
  color: var(--danger);
  border: 1px solid var(--danger);
}

.btn-danger-outline:hover {
  background: var(--danger-bg);
  transform: translateY(-1px);
}

/* 메인메뉴 맨 위의 큰 실행 버튼 (2026-09-03 봉길님: 「메일작성 버튼을 네모박스로 크게」).

   ⚠⚠ **선택자를 두 번 겹쳐 쓴다.** clay.css 가 `html[data-skin="clay"] .sidebar-nav a` 로
     메뉴 글자를 잡는데(특이도 0-2-2), 그냥 `.sidebar-cta`(0-1-0)로는 진다.
     게다가 style.css 가 clay.css 보다 **먼저** 실려서 같은 값이어도 뒤가 이긴다.
     실측(2026-09-03): 배경만 내 것이 먹고 글자색은 회색 rgb(93,91,105), 굵기 400, 높이 36 —
     봉길님이 「밋밋하다」고 하신 게 이것이었다. 색을 고르는 문제가 아니라 규칙이 밀린 것이다.
     클래스를 두 번 적어 0-3-2 로 올려 확실히 이기게 한다.

   ⚠ 색은 제품 색(clay 데이브레이크)의 연보라다. 먹빛으로 했다가 되돌렸다 —
     모달 저장 버튼과 같은 색이라 화면에서 두 번째로 무거운 것이 되고,
     바로 아래 메뉴와 같은 계열이라 「켜진 메뉴」처럼 보였다(봉길님 지적).
   ⚠ 이 한 자리에만 쓴다. 여러 개를 두면 무엇이 중요한지 사라진다 */
.sidebar-nav a.sidebar-cta.sidebar-cta {
  display: block;
  /* ⚠ 메뉴 줄은 높이가 --panel-item-h(36px)로 못박혀 있다(격자를 맞추려고 넣은 것이다).
     그대로 두면 여백을 아무리 줘도 36px 에 눌려 「밋밋」해진다 — 실측으로 확인했다.
     이 버튼은 격자 밖의 것이므로 높이를 풀어 준다 */
  height: auto;
  min-height: 0;
  /* 위 여백 0 — 레일 첫 항목(16)·본문 카드(16)와 **같은 선**에 서야 한다.
     2px 을 주었더니 메인메뉴만 18 로 어긋났다(2026-09-03 실측, 봉길님: 「상단 여백 동일하게」) */
  margin: 0 8px 18px;
  padding: 15px 12px;
  border: 0;
  border-radius: 14px;
  /* 한 겹 더 깊은 보라를 아래에 깔아 **면이 아니라 덩어리로** 보이게 한다 */
  background: linear-gradient(160deg, #b3a1de 0%, #9a83cd 55%, #8d74c6 100%);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.2px;
  text-align: center;
  text-decoration: none;
  box-shadow:
    0 6px 16px rgba(141, 116, 198, 0.36),
    0 1px 0 rgba(255, 255, 255, 0.45) inset;
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}

/* ⚠ 호버에서 **배경을 다시 적어 준다.** clay.css 의 `.sidebar-nav a:hover` 가
   흰 배경을 깔아서, 그냥 두면 흰 바탕에 흰 글자가 된다(2026-09-03 봉길님 지적).
   메뉴 호버는 「흰 판이 떠오르는」 효과인데 이건 단추라 그 규칙이 맞지 않는다.
   대신 **살짝 떠오르고 그림자가 깊어지는** 효과를 준다 — 눌리는 것에 어울리는 움직임이다 */
.sidebar-nav a.sidebar-cta.sidebar-cta:hover {
  background: linear-gradient(160deg, #bcaee6 0%, #a48fd4 55%, #9578cd 100%);
  color: #fff;
  transform: translateY(-1px);
  box-shadow:
    0 10px 24px rgba(141, 116, 198, 0.46),
    0 1px 0 rgba(255, 255, 255, 0.55) inset;
}

/* 누르는 자리는 아래로 살짝 눌린다 — 링크가 아니라 단추임을 몸이 먼저 안다 */
.sidebar-nav a.sidebar-cta.sidebar-cta:active {
  transform: translateY(1px);
  box-shadow: 0 3px 8px rgba(141, 116, 198, 0.4);
}

/* 비밀번호 칸의 눈 단추 — 2026-09-03 봉길님: 「비밀번호 볼 수 있게」.
   ⚠ 종전에는 login.html 안에만 있던 규칙이다. 메일 계정 연결에서도 같은 것이 필요해
     공통으로 올린다 — 화면마다 베껴 두면 한쪽만 고쳐지는 날이 온다.
     (login.html 에 남은 같은 규칙은 값이 같아 부딪히지 않는다) */
.password-wrapper {
  position: relative;
}

.password-wrapper input {
  padding-right: 40px;
}

.btn-pw-toggle {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-secondary);
  line-height: 1;
}

.btn-pw-toggle:hover { color: var(--text-primary); }
.btn-pw-toggle svg { display: block; }

.btn-sm {
  padding: 6px 12px;
  font-size: 12px;
}

.btn .btn-svg-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  display: block;
}

.btn-icon {
  padding: 6px 8px;
  background: none;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text-secondary);
  transition: all var(--transition);
  font-family: var(--font-stack);
}

.btn-icon:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

input[type='checkbox'] {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1px solid var(--border-color);
  border-radius: 5px;
  background-color: #fff;
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
  vertical-align: middle;
}

input[type='checkbox']:checked {
  border-color: var(--accent);
  background-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 14 14' fill='none'%3E%3Cpath d='M11.5 3.75L5.75 9.5L2.5 6.25' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 11px 11px;
}

input[type='checkbox']:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(164, 143, 212, 0.16);
}

/* ===== Cards ===== */
/* 2026-08-16 플렉스형 — 테두리를 지우고 머리카락 그림자 한 겹으로만 띄운다.
   초록 광채·hover 애니메이션은 없음 */
.card {
  background: var(--bg-primary);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 0 0 1px rgba(16, 24, 40, 0.03);
  border: none;
  padding: 18px;
  margin-bottom: 16px;
}

.card-title {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border-light);
}

/* ===== Form ===== */
.employee-form-card {
  max-width: 900px;
}

.employee-detail-shell {
  max-width: 900px;
}

.form-section {
  margin-bottom: 28px;
}

.form-section-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.form-section-icon {
  width: 24px;
  height: 24px;
  color: var(--accent);
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.form-section-icon svg {
  stroke: currentColor;
  stroke-width: 1.5;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.form-section-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
  white-space: nowrap;
}

.form-section-divider {
  flex: 1;
  height: 1px;
  background: var(--border-color);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.form-grid + .form-grid {
  margin-top: 16px;
}

.form-grid.col-2 {
  grid-template-columns: repeat(2, 1fr);
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.form-group.full-width {
  grid-column: 1 / -1;
}

/* 모달 본문에서 연속된 폼 그룹(제목/본문 등) 사이 간격 */
.modal-body .form-group + .form-group {
  margin-top: 16px;
}

/* form-grid(여러 열) 안에서는 grid gap이 간격을 담당 — 세로용 margin-top을 제거해
   그리드 행 정렬이 16px씩 어긋나는 현상을 방지 */
.modal-body .form-grid .form-group + .form-group {
  margin-top: 0;
}

/* 모달 본문 안내 카드(.info-banner) 아래 여백 — 다음 섹션과 답답하지 않게 */
.modal-body .info-banner {
  margin-bottom: 24px;
}

.form-group.span-2 {
  grid-column: span 2;
}

.form-group label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

.field-required {
  color: #ef4444;
  font-weight: 700;
  font-size: 15px;
  line-height: 1;
  margin-left: 2px;
}

/* ⚠ 체크박스·라디오는 뺀다. 이 블록의 width:100%·padding·border 가 1069줄의 전역
   커스텀 체크박스(16x16 네모)를 덮어써서, 네모가 칸 전체로 늘어나고 옆 글자가
   한 글자 폭으로 눌려 세로로 쌓인다. 특이도가 같아 나중에 나오는 이쪽이 이긴다.
   값을 다시 적어 되돌리지 않고 선택자에서 빼는 이유 — 되돌리려면 16px·테두리·모서리를
   여기 한 번 더 적어야 하고, 그러면 디자인이 두 곳에 박힌다 (2026-09-02).
   ⚠ 제외는 `:not()` 이 아니라 `:where()` 로 감싼다. `:not([type="checkbox"])` 는 특이도를
     (0,1,1) → (0,3,1) 로 끌어올려, 뒤에 오는 날짜칸 규칙(0,2,1)까지 이겨버린다.
     `:where()` 는 특이도가 0이라 이 선택자의 무게가 원래대로 남는다. */
.form-group input:not(:where([type="checkbox"], [type="radio"])),
.form-group select,
.form-group textarea {
  padding: 10px 14px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: var(--font-stack);
  color: var(--text-primary);
  transition: border-color 0.15s, box-shadow 0.15s;
  width: 100%;
}

/* 날짜칸은 폼 안에서도 표기 폭을 지킨다 — 위 블록의 width:100% 가 특이도 동률로 이겨서
   「YYYY-MM-DD」 한 칸이 화면 너비 전체로 늘어나 있었다 (2026-09-02).
   폭 값은 :root 의 --date-input-w 하나뿐이다. 761줄과 여기가 같은 값을 본다 */
.form-group input[data-date-auto-format] {
  width: var(--date-input-w);
  flex-shrink: 0;
}

/* 체크박스 한 줄 — 이름표가 아니라 「누르는 줄」이라 굵게 쓰지 않는다.
   `.form-group label` 이 (0,1,1) 이라 클래스만으로는 굵기를 못 이긴다 */
.form-group label.check-line,
.check-line {
  font-weight: 400;
  gap: 8px;
  /* 아래에 입력칸이 따로 없으니 이름표 여백도 없앤다 */
  margin-bottom: 0;
  cursor: pointer;
}

.form-group select:not(.auto-filled) {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5l3.5 3.5 3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-color: var(--bg-primary);
  padding-right: 36px;
  cursor: pointer;
}

.form-group input[readonly],
.form-group input.auto-filled,
.form-group select.auto-filled {
  background: var(--bg-secondary);
  color: var(--text-secondary);
  cursor: default;
  border-color: transparent;
}

.form-group input[readonly]:focus,
.form-group input.auto-filled:focus,
.form-group select.auto-filled:focus {
  outline: none;
  border-color: transparent;
  box-shadow: none;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

.al-usage-grid {
  display: grid;
  gap: 18px 16px;
}

.al-usage-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.al-usage-field.full-width {
  grid-column: 1 / -1;
}

.al-usage-field label {
  margin: 0;
  color: #6b7280;
  font-size: 12px;
  font-weight: 600;
}

.al-usage-field input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]),
.al-usage-field select {
  width: 100%;
  min-height: 40px;
  padding: 10px 14px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  background: #ffffff;
  color: var(--text-primary);
  font-family: var(--font-stack);
  font-size: 13px;
  outline: none;
}

.al-usage-field input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):focus,
.al-usage-field select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

.al-usage-field input:disabled,
.al-usage-field select:disabled {
  background: #f8fafc;
  color: #94a3b8;
  cursor: default;
}

.al-leave-type-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.al-leave-type-row {
  display: grid;
  gap: 8px;
}

.al-leave-type-row.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.al-leave-type-row.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.al-leave-type-row.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.al-leave-type-option {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 10px 8px;
  border: 1.5px solid #e5e7eb;
  border-radius: 10px;
  background: #ffffff;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
  user-select: none;
}

.al-leave-type-option:hover {
  border-color: #a48fd4;
  background: #f6f2fd;
}

.al-leave-type-option input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 0;
  height: 0;
}

.al-leave-type-option .leave-type-label {
  font-size: 13px;
  font-weight: 600;
  color: #111827;
  line-height: 1.2;
  white-space: nowrap;
}

.al-leave-type-option:has(input:checked) {
  border-color: #a48fd4;
  background: #f4f0fc;
}

.al-leave-type-option:has(input:checked) .leave-type-label {
  color: #6b5a91;
}

@media (max-width: 720px) {
  .al-usage-grid,
  .al-leave-type-row.cols-2,
  .al-leave-type-row.cols-3,
  .al-leave-type-row.cols-4 {
    grid-template-columns: 1fr !important;
  }
}

.status-display {
  padding: 9px 14px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  min-height: 42px;
  display: flex;
  align-items: center;
}

.form-check-group {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 2px 4px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
}

.form-check-group input[type="radio"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

/* 자격면허 행 */
.license-row {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.8fr) minmax(0, 0.95fr) minmax(0, 1fr) minmax(0, 0.95fr) auto;
  gap: 8px;
  align-items: end;
  margin-bottom: 8px;
  width: 100%;
  min-width: 0;
}

.license-row input,
.license-row select {
  height: 42px;
  padding: 0 14px;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  background: var(--bg-primary);
  font-size: 14px;
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.license-row input:focus,
.license-row select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

.btn-remove-row {
  width: 34px;
  height: 34px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  border: 1px solid var(--border-color);
  background: var(--bg-primary);
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  flex-shrink: 0;
  transition: border-color 0.15s, color 0.15s;
}

.btn-remove-row:hover {
  border-color: #ef4444;
  color: #ef4444;
}

.form-check-group label,
.form-check-group span {
  color: inherit;
  cursor: pointer;
  margin-bottom: 0;
}

.form-check-group input:disabled + label,
.form-check-group input:disabled + span {
  color: var(--text-secondary);
}

.form-check-group input:disabled + label,
.form-check-group input:disabled + span,
.form-check-group input:disabled {
  cursor: default;
}

.form-group textarea {
  resize: vertical;
  min-height: 80px;
}

.conditional-field {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.3s ease, opacity 0.3s ease, margin-bottom 0.3s ease;
  margin-bottom: 0;
  pointer-events: none;
}

.conditional-field.show {
  max-height: 300px;
  opacity: 1;
  margin-bottom: 0;
  padding-top: 16px;
  pointer-events: auto;
}

/* form-group 단위 conditional은 grid 정렬 맞추기 위해 padding 제거 */
.form-group.conditional-field.show {
  padding-top: 0;
  max-height: none;
  overflow: visible;
}

.career-field {
  opacity: 0.4;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

.career-field.active {
  opacity: 1;
  pointer-events: auto;
}

.input-with-suffix {
  position: relative;
  display: flex;
  align-items: center;
}

.input-suffix-target {
  width: 100%;
  padding-right: 38px;
}

.input-suffix {
  position: absolute;
  right: 14px;
  font-size: 13px;
  color: var(--text-tertiary);
  pointer-events: none;
}

.tag-input-wrapper {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  min-height: 42px;
  background: var(--bg-primary);
  cursor: text;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.tag-input-wrapper:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: rgba(164, 143, 212, 0.08);
  border: 1px solid rgba(164, 143, 212, 0.3);
  border-radius: 16px;
  font-size: 13px;
  color: var(--accent);
  font-weight: 500;
  animation: chipSlideIn 0.2s ease;
}

@keyframes chipSlideIn {
  from {
    opacity: 0;
    transform: scale(0.8);
  }

  to {
    opacity: 1;
    transform: scale(1);
  }
}

.tag-remove {
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}

.tag-remove:hover {
  color: #8b74c4;
}

.tag-input {
  flex: 1;
  min-width: 120px;
  border: none;
  background: transparent;
  font-size: 13px;
  font-family: var(--font-stack);
  outline: none;
}

.form-group .tag-input {
  width: auto;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
}

.form-group .tag-input:focus {
  border-color: transparent;
  box-shadow: none;
}

.form-actions {
  display: flex;
  gap: 10px;
  justify-content: space-between;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--border-light);
}

.form-actions-right {
  display: flex;
  gap: 10px;
}

/* ===== Detail Page ===== */
.detail-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 24px;
}

.detail-profile {
  display: flex;
  align-items: center;
  gap: 20px;
}

.detail-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--accent-light);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 700;
  color: var(--accent);
}

.detail-info h2 {
  font-size: 20px;
  font-weight: 700;
  margin-bottom: 4px;
}

.detail-info .detail-meta {
  font-size: 13px;
  color: var(--text-secondary);
}

.info-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.info-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.info-item .info-label {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: 500;
  white-space: nowrap;
}

.info-item .info-value {
  font-size: 13.5px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.table-empty-message {
  padding: 24px;
  color: var(--text-tertiary);
}

/* ===== Org Tree ===== */
.org-tree {
  padding: 4px 0;
  --org-level-offset: 0px;
  --org-connector-y: 22px;
  --org-connector-color: #e5e7eb;
}

.org-node {
  position: relative;
  --org-action-width: 88px;
}

.org-node-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px 7px calc(10px + var(--org-level-offset, 0px));
  border-radius: 6px;
  cursor: pointer;
  transition: background var(--transition);
}

.org-node-header:hover {
  background: var(--bg-secondary);
}

.org-node-toggle {
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--text-tertiary);
  transition: transform var(--transition);
  flex-shrink: 0;
}

.org-node-toggle.expanded {
  transform: rotate(90deg);
}

/* 레벨 뱃지 */
.org-node-level-badge {
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 6px;
  white-space: nowrap;
  flex-shrink: 0;
}
.org-node-level-badge.lv-1 { background: #f4f0fc; color: #a48fd4; }
.org-node-level-badge.lv-2 { background: #f0fdfa; color: #0d9488; }
.org-node-level-badge.lv-3 { background: #ecfeff; color: #0891b2; }

.org-node-name {
  font-size: 13.5px;
  font-weight: 600;
  flex: 1;
  color: var(--text-primary);
}

.org-node-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-light);
  padding: 2px 8px;
  border-radius: 10px;
  white-space: nowrap;
  flex-shrink: 0;
}
.org-node-count.is-empty {
  color: var(--text-tertiary);
  background: var(--bg-tertiary);
}

.org-node-actions {
  display: flex;
  justify-content: flex-start;
  gap: 4px;
  width: var(--org-action-width);
  opacity: 0;
  transition: opacity var(--transition);
  flex-shrink: 0;
}
.org-node-header:hover .org-node-actions {
  opacity: 1;
}

/* ===== 조직 트리 순서 변경 (드래그) =====
   같은 상위 조직 안에서 형제끼리만 자리를 바꾼다.
   다른 상위 조직 위에 올리면 놓을 수 없다는 표시를 내고 드롭을 막는다. */
.org-node-handle {
  width: 16px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-tertiary);
  cursor: grab;
  opacity: 0;
  transition: opacity var(--transition), color var(--transition);
}
.org-node-header:hover .org-node-handle {
  opacity: 1;
}
.org-node-handle:hover {
  color: var(--accent);
}
.org-node-handle:active {
  cursor: grabbing;
}
/* 형제가 하나뿐이면 옮길 자리가 없다 */
.org-node-handle.is-disabled {
  visibility: hidden;
}

/* 끌고 있는 조직은 하위 조직까지 함께 옮겨진다 — 노드 전체를 흐리게 */
.org-node.is-dragging {
  opacity: 0.45;
}

/* 놓을 자리 — 헤더가 아니라 노드 전체(하위 조직 포함) 기준으로 표시한다.
   헤더에만 선을 그으면 하위 조직이 있는 조직에서 "그 조직의 자식 자리"로 읽힌다. */
.org-node.is-drop-before {
  box-shadow: inset 0 2px 0 0 var(--accent);
}
.org-node.is-drop-after {
  box-shadow: inset 0 -2px 0 0 var(--accent);
}
/* 상위 조직이 달라 놓을 수 없는 자리 */
.org-node.is-drop-deny > .org-node-header {
  background: #fef2f2;
  box-shadow: inset 0 0 0 1px #fca5a5;
}

.org-children {
  position: relative;
  margin-left: 16px;
  padding-left: 20px;
}

.org-children::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 1.5px;
  height: var(--org-connector-y);
  background: var(--org-connector-color);
}

.org-children > .org-node::before {
  content: '';
  position: absolute;
  left: -20px;
  top: var(--org-connector-y);
  width: 18px;
  height: 1.5px;
  background: var(--org-connector-color);
}

.org-children > .org-node:not(:last-child)::after {
  content: '';
  position: absolute;
  left: -20px;
  top: var(--org-connector-y);
  bottom: calc(var(--org-connector-y) * -1);
  width: 1.5px;
  background: var(--org-connector-color);
  pointer-events: none;
}

/* 레벨 컬럼 정렬: 중간 레벨을 건너뛴 노드도 해당 레벨 축까지 연결 */
.org-children > .org-node[data-level-offset="1"]::before { width: 54px; }
.org-children > .org-node[data-level-offset="2"]::before { width: 90px; }
.org-children > .org-node[data-level-offset="3"]::before { width: 126px; }

/* ===== Org Summary Bar ===== */
.org-summary {
  display: flex;
  gap: 16px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.org-summary-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-secondary);
}

.org-summary-item .summary-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.org-summary-item .summary-value {
  font-weight: 700;
  color: var(--text-primary);
}

/* ===== Org Chart (조직도) ===== */
.org-chart-wrap {
  overflow-x: auto;
  overflow-y: visible;
  min-height: clamp(560px, calc(100vh - 300px), 820px);
  padding: 24px 24px clamp(260px, 34vh, 420px);
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
}

.org-chart {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  min-width: fit-content;
  margin: 0;
  --chart-card-height: 64px;
  --chart-level-gap: 40px;
  --chart-card-width: 144px;
  --chart-line-color: #e5e7eb;
}

.chart-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}

.chart-card {
  background: linear-gradient(135deg, #fff, #f8fafb);
  border: 1.5px solid var(--border-color);
  border-radius: 8px;
  padding: 12px 14px;
  text-align: center;
  width: var(--chart-card-width);
  min-width: var(--chart-card-width);
  height: var(--chart-card-height);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition: all 0.25s ease;
  position: relative;
}

.chart-card:hover {
  border-color: var(--accent);
  box-shadow: 0 6px 20px rgba(164, 143, 212, 0.12);
  transform: translateY(-2px);
}

.chart-card .chart-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 4px;
  line-height: 1.25;
  letter-spacing: 0;
  white-space: nowrap;
  overflow: visible;
  max-width: 100%;
}

.chart-card .chart-leader {
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.chart-card .chart-count {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-light);
  padding: 2px 10px;
  border-radius: 20px;
}

.chart-card.level-company {
  border-color: var(--accent);
  background: linear-gradient(135deg, rgba(164, 143, 212, 0.06), #fff);
}

.chart-card.level-1 {
  border-color: rgba(164, 143, 212, 0.5);
}

.chart-card.level-2 {
  border-color: rgba(13, 148, 136, 0.35);
}

.chart-card.level-3 {
  border-color: rgba(20, 184, 166, 0.25);
}

.chart-card.level-4 {
  border-color: rgba(6, 182, 212, 0.2);
}

.chart-connector {
  width: 2px;
  height: 20px;
  background: var(--chart-line-color);
  margin: 0 auto;
}

.chart-h-line {
  height: 2px;
  background: var(--chart-line-color);
  position: absolute;
  top: 0;
}

.chart-level-spacer {
  height: calc(var(--chart-card-height) + var(--chart-level-gap));
  width: 2px;
  background: var(--chart-line-color);
  margin: 0 auto;
  flex-shrink: 0;
}

.chart-children {
  display: flex;
  gap: 12px;
  justify-content: center;
  align-items: flex-start;
  position: relative;
  padding-top: 20px;
}

.chart-children > .chart-node {
  position: relative;
}

.chart-children > .chart-node::before {
  content: '';
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  width: 2px;
  height: 20px;
  background: var(--chart-line-color);
}

/* ===== Rank / Position List ===== */
.item-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.item-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.item-row:hover {
  background: var(--bg-secondary);
}

.item-order {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg-tertiary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.item-name {
  flex: 1;
  font-size: 13.5px;
  font-weight: 500;
}

.item-actions {
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity var(--transition);
}

.item-row:hover .item-actions {
  opacity: 1;
}

/* ===== Modal ===== */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  opacity: 0;
  visibility: hidden;
  transition: all var(--transition);
}

.modal-overlay.show {
  opacity: 1;
  visibility: visible;
}

/* ⚠ **떠 있는 창은 불투명해야 한다.** 종전에는 `var(--bg-primary)` 를 썼는데,
   clay 스킨이 그 변수를 유리처럼 `rgba(255,255,255,0.55)` 로 바꾼다. 카드·패널에는 어울리지만
   모달에서는 **뒤 내용이 그대로 비쳐** 글자가 겹쳐 읽혔다 (2026-09-03 봉길님).
   그래서 모달만 자기 변수를 본다 — clay 는 이 변수를 모르므로 어느 화면에서든 흰색이다. */
.modal,
.modal-content {
  background: var(--modal-bg, #ffffff);
  border-radius: 18px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.12);
  width: 90%;
  max-width: 480px;
  padding: 24px;
  transform: translateY(10px);
  transition: transform var(--transition);
  /* ⚠ **창보다 길어지면 안쪽에서 굴린다.** 종전에는 높이 제한이 없어서, 칸이 몇 개만 늘어도
     모달이 화면 밖으로 삐져나가 **저장 버튼을 누를 수 없었다**
     (2026-09-03 실측: 「내 정보」에 자기소개·올해 목표를 넣자 모달 1106px vs 창 700px,
      저장 버튼이 창 아래로 나감). 시험이 먼저 잡았지만 사용자도 똑같이 겪는 문제였다.
     ⚠ 여기(.modal)가 아니라 본문(.modal-body)에 스크롤을 걸어야 머리·바닥이 제자리에 남는다. */
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
}

/* 모달 바닥 버튼줄 — 본문이 굴러도 **늘 보인다**. 본문 안에 두면 같이 밀려 올라가
   창이 낮을 때 저장을 못 누른다 (2026-09-03 「내 정보」에서 실제로 그랬다) */
.modal-foot {
  flex: none;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 24px 20px;
  border-top: 1px solid var(--border-light);
}

/* 본문만 굴린다 — 제목과 아래 버튼줄은 늘 보인다.

   ⚠ **좌우 여백을 건드리지 말 것.** 한때 「글자가 스크롤바에 닿지 않게」 하려고
     `padding-right: 2px` 를 줬다가, 본문만 **왼쪽 48 / 오른쪽 36** 으로 12px 어긋났다
     (2026-09-03 봉길님: 「좌우 여백이 동일하지 않다」, 실측으로 확인).
     제목줄·버튼줄은 24/24 로 맞는데 본문만 틀어져 더 눈에 띄었다.
   ⚠ 스크롤바는 좌우 여백(padding) **바깥쪽**에 그려진다. 그래서 padding 만 좌우 같게 두면
     글자 기준 여백은 저절로 대칭이다 — 여기서 더 손댈 필요가 없다.
     `scrollbar-gutter: both-edges` 도 시도했지만 양쪽에 10px 씩 자리를 예약하는 바람에
     본문만 24 → 34 로 더 들어가 제목줄과 어긋났다(실측). 쓰지 않는다. */
.modal > .modal-body,
.modal-content > .modal-body {
  min-height: 0;          /* flex 자식은 min-height:auto 라 안 눌리면 overflow 가 안 걸린다 */
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.modal-overlay.show .modal {
  transform: translateY(0);
}

.modal--wide {
  width: min(760px, calc(100vw - 32px));
  max-width: 760px;
  padding: 0;
  overflow: hidden;
  border-radius: 20px;
}

.modal--wide .modal-header {
  margin-bottom: 0;
  padding: 16px 20px;
  background: #ffffff;
}

.modal--wide .modal-body {
  padding: 24px;
  background: #f8fafc;
  max-height: calc(100vh - 200px);
  overflow-y: auto;
}

.modal--wide .modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 0;
  padding: 14px 20px 18px;
  background: #ffffff;
}

.modal--wide .btn {
  min-width: 78px;
}

@media (max-width: 640px) {
  .modal--wide .modal-header,
  .modal--wide .modal-body,
  .modal--wide .modal-footer {
    padding-left: 18px;
    padding-right: 18px;
  }
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color);
  flex: none;             /* 본문이 굴러도 제목줄은 줄어들지 않는다 */
}

.modal-body {
  padding: 24px;
}

.modal-header h3 {
  font-size: 16px;
  font-weight: 700;
}

.modal-close {
  background: none;
  border: none;
  font-size: 18px;
  cursor: pointer;
  color: var(--text-secondary);
  padding: 4px;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border-light);
}

/* 확인창처럼 문구 한 줄만 담는 작은 모달. 480px 를 그대로 쓰면 짧은 물음이
   가로로 늘어져 눈이 한 번에 못 읽는다 (2026-09-05) */
.modal.modal-sm { max-width: 400px; }
.modal.modal-sm .modal-header { padding: 4px 2px 14px; margin-bottom: 16px; }
.modal.modal-sm .modal-body { padding: 0 2px; }
.modal.modal-sm .modal-footer { margin-top: 18px; padding-top: 14px; }

/* ===== Empty State ===== */
.empty-state,
.empty {
  text-align: center;
  padding: 80px 40px;
  background: var(--bg-secondary);
  border-radius: var(--radius-lg);
  color: var(--text-tertiary);
}

.empty-state .empty-icon {
  font-size: 48px;
  margin-bottom: 12px;
}

.empty-state p {
  font-size: 14px;
}

/* ===== Toast ===== */
.toast-container {
  position: fixed;
  top: calc(var(--gnb-height) + 12px);
  right: 20px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.toast {
  background: var(--text-primary);
  color: #fff;
  padding: 12px 20px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  box-shadow: var(--shadow-md);
  animation: toastIn 0.3s ease, toastOut 0.3s ease 2.7s forwards;
}

@keyframes toastIn {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes toastOut {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* ===== Appointment ===== */
.employee-search-wrap {
  position: relative;
}

.employee-search-result {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  max-height: 200px;
  overflow-y: auto;
  z-index: 50;
  display: none;
}

.employee-search-result.show {
  display: block;
}

.employee-search-result[hidden] {
  display: none !important;
}

.employee-search-item {
  display: flex;
  align-items: center;
  gap: 4px 8px;
  flex-wrap: wrap;
  min-height: 44px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 13px;
  text-align: left;
  line-height: 1.4;
  transition: background var(--transition);
}

.employee-search-item:hover,
.employee-search-item.is-active {
  background: var(--bg-secondary);
}

.employee-search-item + .employee-search-item {
  border-top: 1px solid var(--border-color);
  border-radius: 0;
}

.employee-search-item.is-empty {
  color: var(--text-tertiary);
  cursor: default;
}

.employee-search-item.is-empty:hover {
  background: transparent;
}

.employee-search-item.is-resigned {
  color: #94a3b8;
}

.employee-search-mark {
  color: var(--text-secondary);
  font-size: 12px;
}

.transfer-info {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 16px;
  align-items: center;
  background: var(--bg-secondary);
  padding: 16px;
  border-radius: var(--radius-sm);
  margin-top: 12px;
}

.transfer-arrow {
  font-size: 20px;
  color: var(--text-tertiary);
}

.transfer-box {
  text-align: center;
}

.transfer-box .transfer-label {
  font-size: 11px;
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.transfer-box .transfer-value {
  font-size: 14px;
  font-weight: 600;
}

/* ===== Tab Content ===== */
.tab-content {
  display: none;
}

.tab-content.active {
  display: block;
}

/* toolbar가 tab-content로 토글되는 경우 display: flex 유지 (글로벌 .toolbar 룰 보존) */
.toolbar.tab-content.active {
  display: flex;
}

/* ===== Scrollbar ===== */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, #d1d5db, #9ca3af);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-tertiary);
}

/* ===== Utility ===== */
.text-center { text-align: center; }
.text-right { text-align: right; }
.mt-4 { margin-top: 16px; }
.mb-4 { margin-bottom: 16px; }
.hidden { display: none !important; }

/* ===== Statistics / Charts ===== */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

@media (max-width: 768px) { .kpi-row { grid-template-columns: repeat(3, 1fr); } }

.kpi-card {
  background: #fff;
  border: 1px solid #f0f0f0;
  border-radius: 16px;
  padding: 20px 22px 18px;
  text-align: left;
  box-shadow: 0 2px 12px rgba(0,0,0,0.05);
  transition: box-shadow 0.2s, transform 0.2s;
  position: relative;
  overflow: hidden;
  min-height: 120px;
}
.kpi-card::after {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--kpi-color, #c0aee6), var(--kpi-color2, #6ee7b7));
  border-radius: 16px 16px 0 0;
}
.kpi-card:hover { box-shadow: 0 8px 28px rgba(0,0,0,0.09); transform: translateY(-2px); }
.kpi-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 10px; }
.kpi-icon {
  width: 38px; height: 38px; border-radius: 10px;
  background: var(--kpi-bg, #f4f0fc);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.kpi-icon svg { width: 18px; height: 18px; }
.kpi-label { font-size: 11px; color: #9ca3af; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; margin-bottom: 2px; }
.kpi-value { font-size: 26px; font-weight: 800; letter-spacing: -0.5px; line-height: 1.1; margin-bottom: 6px; }
.kpi-value.emerald { background: linear-gradient(135deg, var(--kpi-color, #c0aee6), var(--kpi-color2, #8b74c4)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
.kpi-sub { font-size: 11px; color: #b0b8c1; line-height: 1.6; }
.contract-alert { margin-top: 20px; }
.contract-alert-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.contract-alert-table th { padding: 6px 12px; text-align: left; font-size: 11px; color: #9ca3af; font-weight: 600; letter-spacing: 0.04em; border-bottom: 1px solid #f0f0f0; }
.contract-alert-table td { padding: 8px 12px; border-bottom: 1px solid #f9fafb; color: #374151; }
.contract-alert-table tr:last-child td { border-bottom: none; }
.contract-alert-dday { display: inline-block; padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 700; }
.contract-alert-dday.urgent { background: #fef2f2; color: #ef4444; }
.contract-alert-dday.warning { background: #fff7ed; color: #f97316; }
.contract-alert-dday.normal { background: #eef6f1; color: #3f7a5c; }
.kpi-sub strong { color: #6b7280; font-weight: 600; }
.kpi-ratio-bar { display: flex; height: 5px; border-radius: 3px; overflow: hidden; margin-top: 8px; background: #f3f4f6; }
.kpi-ratio-fill { height: 100%; border-radius: 3px; background: linear-gradient(90deg, var(--kpi-color, #c0aee6), var(--kpi-color2, #6ee7b7)); transition: width 0.8s cubic-bezier(0.34,1.56,0.64,1); }

.stats-grid .card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #374151;
}
.stats-grid .card-title::before {
  content: '';
  display: inline-block;
  width: 3px; height: 15px;
  background: linear-gradient(180deg, #c0aee6, #a48fd4);
  border-radius: 2px;
  flex-shrink: 0;
}

.stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-bottom: 20px;
}

@media (max-width: 768px) { .stats-grid { grid-template-columns: 1fr; } }

.stats-grid > .card.full,
.stats-grid > .full { grid-column: 1 / -1; }

/* 가로 바 차트 */
.h-bar-list { display: flex; flex-direction: column; gap: 10px; }
.h-bar-row { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.h-bar-label { width: 90px; text-align: right; color: var(--text-secondary); font-weight: 500; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-bar-track { flex: 1; height: 22px; background: #f3f4f6; border-radius: 6px; overflow: hidden; }
.h-bar-fill { height: 100%; border-radius: 6px; transition: width 0.8s cubic-bezier(0.34, 1.56, 0.64, 1); min-width: 2px; display: flex; align-items: center; padding-left: 8px; font-size: 11px; font-weight: 600; color: #fff; }
.h-bar-value { width: 45px; text-align: right; font-weight: 700; color: var(--text-primary); flex-shrink: 0; }


/* 세로 바 차트 */
.v-bar-chart { display: flex; align-items: flex-end; gap: 8px; height: 160px; padding-top: 8px; }
.v-bar-group { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; }
.v-bar-bars { flex: 1; display: flex; align-items: flex-end; gap: 3px; width: 100%; }
.v-bar { flex: 1; border-radius: 4px 4px 0 0; min-height: 2px; transition: height 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); position: relative; }
.v-bar.hire { background: var(--accent); }
.v-bar.resign { background: #f97316; }
.v-bar-label { font-size: 11px; color: var(--text-tertiary); font-weight: 500; }
.v-bar-tip { position: absolute; top: -18px; left: 50%; transform: translateX(-50%); font-size: 10px; font-weight: 700; color: var(--text-primary); white-space: nowrap; }
.chart-legend { display: flex; gap: 20px; margin-top: 16px; font-size: 12px; color: var(--text-secondary); }
.chart-legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }

/* 도넛 차트 */
.donut-wrap { display: flex; align-items: center; gap: 28px; }
.donut-svg { width: 140px; height: 140px; flex-shrink: 0; }
.donut-legend { display: flex; flex-direction: column; gap: 8px; flex: 1; }
.donut-legend-item { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--text-secondary); }
.donut-legend-dot { width: 12px; height: 12px; border-radius: 4px; flex-shrink: 0; }
.donut-legend-value { margin-left: auto; font-weight: 700; color: var(--text-primary); }

/* ===== Toolbar Layout ===== */
.toolbar-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}

.toolbar-row .toolbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  flex-wrap: wrap;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  margin-left: auto;
}

/* ===== View Toggle (재직자/퇴직자, 일/월 등 — 글로벌 표준) ===== */
.view-toggle {
  display: inline-flex;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--bg-primary);
}
.view-toggle button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 35px;
  padding: 7px 14px;
  border: none;
  border-radius: 0;
  background: var(--bg-primary);
  font-size: 13px;
  font-family: var(--font-stack);
  cursor: pointer;
  color: var(--text-secondary);
  transition: all var(--transition);
  box-shadow: none;
}
.view-toggle button + button {
  border-left: 1px solid var(--border-color);
}
.view-toggle button:hover:not(.active) {
  background: var(--bg-secondary);
  color: var(--text-primary);
}
.view-toggle button.active {
  background: var(--btn-ink-soft);
  color: #ffffff;
  font-weight: 600;
}

/* ===== Toggle Button Group ===== */
/* 사용법: <div class="btn-toggle"><button class="active">목록</button><button>조직도</button></div> */
.btn-toggle {
  display: inline-flex;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  overflow: hidden;
  flex-shrink: 0;
}

.btn-toggle button {
  padding: 7px 14px;
  border: none;
  background: var(--bg-primary);
  font-size: 13px;
  font-family: var(--font-stack);
  cursor: pointer;
  color: var(--text-secondary);
  transition: all var(--transition);
}

.btn-toggle button + button {
  border-left: 1px solid var(--border-color);
}

.btn-toggle button:hover:not(.active) {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.btn-toggle button.active {
  background: var(--btn-ink-soft);
  color: #fff;
  font-weight: 600;
}

/* ===== Pill Tabs (서브탭용 — .tabs.tab-pill 또는 div.tab-pill) ===== */
.tab-pill {
  display: flex;
  gap: 6px;
  border-bottom: none;
  padding: 0;
  margin-bottom: 16px;
}

.tab-pill .tab-btn {
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-bottom: 1px solid var(--border-color);
  border-radius: 20px;
  padding: 5px 16px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: 0;
}

.tab-pill .tab-btn:hover:not(.active) {
  background: var(--btn-ink-tint);
  color: var(--btn-ink);
  border-color: transparent;
  border-radius: 20px;
  border-bottom-color: transparent;
}

.tab-pill .tab-btn.active {
  background: var(--btn-ink-soft);
  color: #fff;
  border-color: var(--btn-ink-soft);
  border-bottom-color: var(--btn-ink-soft);
  font-weight: 600;
  border-radius: 20px;
}

/* ===== CL Badge (페이밴드 등급 표시) ===== */
.cl-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 700;
}

/* ===== Card Header (제목 + 우측 버튼 행) ===== */
/* 사용법: <div class="card-header"><span class="card-title">제목</span><button>추가</button></div> */
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}

.card-header .card-title {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
}

/* ===== Layout Grids ===== */
.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  align-items: start;
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
  align-items: start;
}

.grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  align-items: start;
}

/* ===== Info Banner (선택된 항목 요약 박스) ===== */
.info-banner {
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  margin-bottom: 16px;
  font-size: 13px;
}

.info-banner.accent {
  background: var(--accent-light);
  border-color: rgba(164, 143, 212, 0.25);
}

/* ===== Table Compact ===== */
.table-compact thead th {
  padding: 9px 12px;
}

.table-compact tbody td {
  padding: 8px 12px;
}

/* ===== Table Empty Row ===== */
/* 사용법: <tr><td class="table-empty" colspan="N">메시지</td></tr> */
.table-empty {
  text-align: center;
  padding: 40px 20px;
  color: var(--text-tertiary);
  font-size: 13px;
}

/* ===== Status Badges (통합 — badge-active/leave/retired 별칭) ===== */
.status-badge {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.status-badge.active,
.status-badge.s-active,
.status-badge--active {
  background: linear-gradient(135deg, #eef6f1, rgba(143, 191, 166, 0.28));
  color: #3f7a5c;
  border: 1px solid rgba(143, 191, 166, 0.4);
}

.status-badge.leave,
.status-badge.s-leave,
.status-badge--leave {
  background: linear-gradient(135deg, #fffbeb, rgba(245, 158, 11, 0.15));
  color: #b45309;
  border: 1px solid rgba(245, 158, 11, 0.2);
}

.status-badge.retired,
.status-badge.s-retired,
.status-badge--retired {
  background: linear-gradient(135deg, #f3f4f6, rgba(156, 163, 175, 0.15));
  color: #6b7280;
  border: 1px solid rgba(156, 163, 175, 0.2);
}

.status-badge.contract,
.status-badge.s-contract {
  background: linear-gradient(135deg, #eff6ff, rgba(59, 130, 246, 0.1));
  color: #1d4ed8;
  border: 1px solid rgba(59, 130, 246, 0.2);
}

.status-badge.pending,
.status-badge.s-pending {
  background: var(--warning-bg);
  color: #b45309;
  border: 1px solid rgba(245, 158, 11, 0.2);
}

.status-badge.attention {
  background: rgba(245, 158, 11, 0.12);
  color: #b45309;
  border-color: rgba(245, 158, 11, 0.28);
}

/* ===== Page Section Title (카드 밖 섹션 구분선) ===== */
.section-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 20px 0 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}

.section-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-color);
}

/* ===== Table Column Group (컬럼 묶음 경계선) =====
   묶음이 시작되는 컬럼(th·td)에 .col-group-start 를 주면 세로 경계선이 그어진다. */
.col-group-start {
  border-left: 1px solid var(--border-light);
}

/* ===== Timeline (이력 표시 공용 — 근무일정·연봉·발령 등) =====
   구조: .timeline > .timeline-item(.is-current) > .timeline-title + .timeline-meta
   현재 시점에 해당하는 항목에 .is-current 를 주면 점이 채워지고 강조된다. */
.timeline {
  position: relative;
  padding-left: 22px;
}

.timeline::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 6px;
  bottom: 6px;
  width: 1px;
  background: var(--border-color);
}

.timeline-item {
  position: relative;
  padding-bottom: 18px;
}

.timeline-item:last-child {
  padding-bottom: 0;
}

.timeline-item::before {
  content: '';
  position: absolute;
  left: -22px;
  top: 4px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--bg-primary);
  border: 1.5px solid var(--border-color);
  box-shadow: 0 0 0 3px var(--bg-primary);
}

.timeline-item.is-current::before {
  background: var(--accent);
  border-color: var(--accent);
}

.timeline-title {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-secondary);
}

.timeline-item.is-current .timeline-title {
  font-weight: 600;
  color: var(--text-primary);
}

.timeline-meta {
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

.timeline-item.is-current .timeline-meta {
  color: var(--accent-hover);
}

.timeline-note {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.6;
}

/* ===== 인사통계 리디자인 2.0 ===== */
.stat-headline {
  display: flex; align-items: flex-end; justify-content: space-between;
  margin-bottom: 20px;
}
.stat-headline h1 { font-size: 20px; font-weight: 800; letter-spacing: -0.4px; color: var(--text-primary); }
.stat-asof { font-size: 12px; color: var(--text-tertiary); margin-left: 10px; }

/* KPI Strip */
.kpi-strip {
  display: flex; align-items: center;
  background: #fff; border: 1px solid var(--border-color);
  border-radius: 12px; padding: 18px 28px;
  margin-bottom: 16px; overflow-x: auto; gap: 0;
}
.kpi-s-item { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 110px; }
.kpi-s-value { font-size: 22px; font-weight: 800; letter-spacing: -0.5px; color: var(--kc, var(--text-primary)); }
.kpi-s-label { font-size: 11px; color: var(--text-tertiary); font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; }
.kpi-s-sub { font-size: 11px; color: var(--text-tertiary); }
.kpi-s-divider { width: 1px; height: 44px; background: var(--border-color); flex-shrink: 0; margin: 0 20px; }
.kpi-s-bar { display: flex; width: 80px; height: 4px; background: rgba(13,148,136,0.2); border-radius: 2px; margin-top: 4px; overflow: hidden; }
.kpi-s-bar-fill { height: 100%; background: var(--accent); border-radius: 2px; }

/* 알람 Ribbon */
.alert-ribbon {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 4px 0; margin-bottom: 8px;
}
.alert-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 14px; border-radius: 20px;
  font-size: 12.5px; font-weight: 500; cursor: pointer;
  transition: filter 0.15s; user-select: none; border: 1px solid transparent;
  font-family: var(--font-stack);
  background: none;
}
.alert-pill.danger  { background: #fef2f2; color: #b91c1c; border-color: rgba(239,68,68,0.25); }
.alert-pill.warning { background: #fffbeb; color: #b45309; border-color: rgba(245,158,11,0.25); }
.alert-pill.info    { background: #ecfeff; color: #0e7490; border-color: rgba(6,182,212,0.25); }
.alert-pill:hover   { filter: brightness(0.95); }
.alert-pill-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: apd 2s infinite; }
@keyframes apd { 0%,100%{opacity:1} 50%{opacity:0.35} }

/* 알람 Drawer */
.alert-drawer { max-height: 0; overflow: hidden; transition: max-height 0.35s cubic-bezier(0.4,0,0.2,1); }
.alert-drawer.open { max-height: 1200px; margin-bottom: 16px; }

/* Hero Section */
.hero-section { background: #f8fafb; border-radius: 12px; padding: 20px 24px; margin-bottom: 20px; }

/* Analysis Row */
.analysis-row { display: grid; gap: 28px; margin-bottom: 20px; align-items: start; }
.analysis-row.col-6-4 { grid-template-columns: 3fr 2fr; }
.analysis-row.col-4-6 { grid-template-columns: 2fr 3fr; }
.analysis-row.col-5-5 { grid-template-columns: 1fr 1fr; }
.analysis-row.col-4-3-3 { grid-template-columns: 2fr 1.5fr 1.5fr; }

/* Section Label */
.section-label {
  font-size: 11px; font-weight: 700; color: var(--text-secondary);
  text-transform: uppercase; letter-spacing: 0.06em;
  margin-bottom: 14px; display: flex; align-items: center; gap: 6px;
}
.section-label::before {
  content: ''; display: inline-block; width: 3px; height: 12px;
  background: var(--accent); border-radius: 2px; flex-shrink: 0;
}
.section-label.muted::before { background: var(--text-tertiary); }

/* stat-tabs pill override */
.stat-tabs.pill-tabs {
  display: inline-flex; gap: 4px;
  background: #f3f4f6; border-radius: 10px; padding: 4px;
  border-bottom: none; margin-bottom: 20px;
}
.stat-tabs.pill-tabs .stat-tab-btn {
  padding: 7px 18px; border-radius: 8px; font-size: 13px; font-weight: 600;
  color: var(--text-secondary); background: none; border: none; border-bottom: none;
  margin-bottom: 0; cursor: pointer; transition: all 0.15s;
  font-family: var(--font-stack);
}
.stat-tabs.pill-tabs .stat-tab-btn.active {
  background: #fff; color: var(--accent);
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
.stat-tabs.pill-tabs .stat-tab-btn:hover:not(.active) { color: var(--text-primary); }

/* ── 2026-04 디자인 경량화 ─────────────────────── */

/* KPI strip: 카드 테두리 제거 → 선 구분만 */
.kpi-strip {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border-color);
  border-radius: 0;
  padding: 14px 4px;
  margin-bottom: 14px;
}
.kpi-s-value { font-size: 20px; font-weight: 700; }
.kpi-s-divider { height: 32px; margin: 0 16px; }

/* 바 차트: 두께 줄이고 내부 텍스트 제거 */
.h-bar-track { height: 10px; border-radius: 4px; background: #f1f5f9; }
.h-bar-fill  { height: 100%; border-radius: 4px; padding: 0; font-size: 0; }
.h-bar-row   { gap: 8px; font-size: 12px; }
.h-bar-label { font-size: 12px; width: 80px; }
.h-bar-value { font-size: 12px; font-weight: 600; width: 38px; }
.h-bar-list  { gap: 7px; }

/* 탭: 좀 더 가볍게 */
.tabs { border-bottom: 1.5px solid var(--border-color); margin-bottom: 20px; display: flex; gap: 0; }
.tab-btn {
  padding: 8px 18px; font-size: 13px; font-weight: 600;
  color: var(--text-tertiary); background: none; border: none;
  border-bottom: 2px solid transparent; margin-bottom: -1.5px;
  cursor: pointer; transition: color 0.15s, border-color 0.15s;
  font-family: var(--font-stack);
}
.tab-btn:hover { color: var(--text-secondary); }
.tab-btn.active { color: var(--btn-ink); border-bottom-color: var(--btn-ink); }
.tab-content { display: none; }
.tab-content.active { display: block; }

/* section-label 경량화 */
.section-label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  margin-bottom: 12px; color: var(--text-secondary);
}
.section-label::before { width: 2px; height: 10px; }

/* 대시보드 요약 숫자 경량화 */
.dash-stat-value { font-size: 26px !important; font-weight: 700 !important; }
.dash-stat-label { font-size: 12px !important; }
.dash-stat-sub   { font-size: 11px !important; }

/* 바 트랙 최대 너비 제한 */
.h-bar-track { max-width: 280px; }

/* ── 종합 정제 pass-2 ───────────────────────── */
/* 바 트랙: flex 확장 대신 고정 폭 */
.h-bar-track { width: 150px; flex: 0 0 150px; max-width: none; }
/* 차트 그리드 간격 */
.chart-grid-2 { gap: 32px; }
.chart-grid-6-4 { gap: 32px; }

/* 인사통계 2열/3열 카드행: 카드 외곽만 동일 높이로 정렬 */
.stats-shell .chart-grid-2,
.stats-shell .chart-grid-3 { align-items: stretch; }
.stats-shell .chart-grid-2 > .stat-card,
.stats-shell .chart-grid-3 > .stat-card {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-self: stretch;
}
.stats-shell .chart-grid-2 > .stat-card > *,
.stats-shell .chart-grid-3 > .stat-card > * { flex: 0 0 auto; }

/* ===== 증명서 발급 ===== */
.certificate-shell { max-width: 1120px; }
.certificate-editor-grid { display:grid; grid-template-columns:minmax(320px, 380px) minmax(0, 1fr); gap:16px; align-items:start; }
.certificate-page [hidden] { display:none !important; }
.certificate-radio-group { display:flex; gap:12px; flex-wrap:wrap; position:relative; }
.certificate-type-options { grid-column:1 / -1; margin-bottom:2px; }
.certificate-radio-option { display:inline-flex; align-items:center; gap:8px; position:relative; font-size:13px; color:var(--text-primary); cursor:pointer; }
.certificate-radio-option input { position:absolute; width:1px; height:1px; margin:0; opacity:0; pointer-events:none; }
.certificate-radio-option span { display:inline-flex; align-items:center; gap:8px; position:relative; }
.certificate-radio-option span::before { content:""; width:16px; height:16px; flex:0 0 16px; border:1.5px solid #cbd5e1; border-radius:50%; box-sizing:border-box; transition:border-color var(--transition), box-shadow var(--transition); }
.certificate-radio-option span::after { content:""; position:absolute; left:4px; top:50%; width:8px; height:8px; border-radius:50%; background:#a48fd4; transform:translateY(-50%) scale(0); transition:transform var(--transition); }
.certificate-radio-option:hover span::before,
.certificate-radio-option input:focus-visible + span::before { border-color:#64748b; }
.certificate-radio-option input:focus-visible + span::before { box-shadow:0 0 0 3px rgba(164,143,212,0.16); }
.certificate-radio-option input:checked + span::before { border-color:#a48fd4; }
.certificate-radio-option input:checked + span::after { transform:translateY(-50%) scale(1); }
.selected-employee-card { margin-top:10px; padding:12px 14px; border:1px solid var(--border-color); border-radius:8px; background:#f8fafb; font-size:13px; color:var(--text-secondary); }
.selected-employee-card strong { color:var(--text-primary); margin-right:8px; }
.selected-employee-card span { color:var(--text-secondary); }
.selected-employee-card div { margin-top:4px; color:var(--text-secondary); }
.selected-employee-card.is-empty { color:var(--text-tertiary); }
.certificate-employee-search-results { min-height:220px; max-height:320px; overflow-y:auto; font-size:13px; }
.certificate-employee-search-message,
.certificate-employee-search-results .employee-search-item { display:flex; align-items:center; min-height:44px; padding:10px 14px; text-align:left; font-size:13px; line-height:1.4; }
.certificate-employee-search-message { margin:0; color:var(--text-tertiary); }
.certificate-employee-search-item { flex-wrap:wrap; gap:4px 8px; }
.certificate-employee-search-meta { color:var(--text-secondary); font-size:13px; }
.certificate-history-table { max-height:calc(100vh - 220px); min-height:280px; overflow:auto; }
.certificate-history-table table { min-width:900px; }
.certificate-document-wrap { width:100%; max-width:812px; margin:0 auto; background:#f8fafb; border:1px solid var(--border-color); border-radius:8px; padding:16px; overflow-x:hidden; overflow-y:auto; }
.certificate-output-panel { width:100%; max-width:812px; margin:0 auto; }
.certificate-output-actions { display:flex; justify-content:flex-end; gap:8px; margin:16px 0 12px; padding:0; }
.certificate-output-document { max-width:none; margin:0; background:#fff; }
.certificate-doc { width:100%; max-width:760px; min-width:0; margin:0 auto; }
.certificate-doc__top { display:flex; flex-direction:column; gap:4px; margin-bottom:24px; }
/* 좌우 칸은 반드시 같은 고정폭. minmax(140,200) 이면 로고 칸만 내용에 따라 넓어져
   (실측 157 vs 140) 제목이 왼쪽으로 밀린다. 로고 크기는 안쪽에서 맞춘다 */
.certificate-doc__title-row { display:grid; grid-template-columns:140px 1fr 140px; align-items:center; gap:16px; }
.certificate-doc__title-spacer { width:100%; height:1px; }
.certificate-doc__title { margin:0; text-align:center; white-space:nowrap; }
.certificate-doc__doc-no { text-align:left; font-size:12px; line-height:1.4; color:#000; }
.certificate-doc__doc-no span { display:inline; color:#555; margin-right:6px; }
.certificate-doc__doc-no strong { display:inline; font-size:13px; color:#000; font-weight:700; }
.certificate-doc__meta-table,
.certificate-doc__career-table { table-layout:fixed; width:100%; }
.certificate-doc__meta-table col { width:25%; }
.certificate-doc__meta-table td:first-child,
.certificate-doc__meta-table td:nth-child(3),
.certificate-doc__label-cell { background:#f5f5f5; font-weight:600; text-align:center; white-space:nowrap; }
.certificate-doc__meta-table td,
.certificate-doc__career-table th,
.certificate-doc__career-table td { word-break:keep-all; word-wrap:break-word; overflow-wrap:break-word; }
.certificate-doc__address-cell { text-align:left; padding-left:16px; }
.certificate-doc__body-text { margin:24px 0 28px; font-size:15px; line-height:1.8; text-align:center; }
.certificate-doc__career-table { margin:0 0 32px; }
.certificate-doc__bottom-meta { margin-top:32px; }
.certificate-page input.is-invalid { border-color:#ef4444 !important; box-shadow:0 0 0 4px rgba(239,68,68,0.1) !important; }
@media (max-width: 1100px) {
  .certificate-editor-grid { grid-template-columns:1fr; }
}

/* ===== 시용평가 ===== */
.probation-shell { width:100%; max-width: 1140px; }
.probation-page [hidden] { display:none !important; }
.probation-page .toolbar {
  flex-direction:column;
  align-items:stretch;
  gap:8px;
  margin-bottom:12px;
}
.probation-page .toolbar-row {
  display:flex;
  align-items:center;
  gap:8px;
  width:100%;
  flex-wrap:wrap;
}
.probation-page .toolbar-row .toolbar-right {
  margin-left:auto;
  display:flex;
  align-items:center;
  gap:8px;
  flex-shrink:0;
}
.probation-filter-summary {
  font-size:13px;
  font-weight:600;
  color:var(--text-secondary);
  white-space:nowrap;
}
.probation-eval-table-wrap {
  max-height:calc(100vh - 220px);
  overflow:auto;
  border:1px solid var(--border-color);
  border-radius:var(--card-radius, 12px);
  background:#fff;
  padding-bottom:8px;
}
.probation-eval-table {
  width:100%;
  border-collapse:separate;
  border-spacing:0;
  table-layout:fixed;
  background:#fff;
}
.probation-eval-table th {
  position:sticky;
  top:0;
  z-index:2;
  background:linear-gradient(90deg, #f8fafb, #f6f2fd);
  font-size:12.5px;
  font-weight:700;
  color:var(--text-secondary);
  padding:12px;
  text-align:center;
  border-bottom:1px solid var(--border-color);
  white-space:nowrap;
}
.probation-eval-table td {
  padding:12px;
  font-size:13px;
  color:var(--text-primary);
  border-bottom:1px solid #f1f5f9;
  text-align:center;
  vertical-align:middle;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.probation-eval-table td.col-name {
  font-weight:600;
  color:#0f172a;
}
.probation-eval-table td.col-org,
.probation-eval-table td.col-period { color:#64748b; }
.probation-eval-table th.col-period,
.probation-eval-table td.col-period { white-space:nowrap; }
.probation-eval-table td.is-fail { color:#ef4444; font-weight:700; }
.probation-eval-table tbody tr:hover { background:rgba(164,143,212,0.04); }
.probation-eval-table tbody tr:last-child td { border-bottom:none; }
.probation-eval-table th.col-average,
.probation-eval-table td.col-average {
  padding-left:18px;
  padding-right:28px;
}
.probation-eval-table th.col-phase,
.probation-eval-table td.col-phase {
  padding-left:18px;
  padding-right:18px;
}
.probation-eval-table td.col-phase {
  vertical-align:middle;
  padding-top:8px;
  padding-bottom:8px;
  overflow:visible;
}
.probation-eval-table td.col-mentor,
.probation-eval-table td.col-evaluator {
  overflow:visible;
  white-space:normal;
}
.person-search {
  position:relative;
  display:flex;
  align-items:center;
  width:100%;
  height:36px;
}
.person-search-icon {
  position:absolute;
  left:8px;
  top:50%;
  transform:translateY(-50%);
  color:#9ca3af;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  pointer-events:none;
}
.person-search.has-value .person-search-icon { visibility:hidden; }
.person-search-input {
  width:100%;
  height:36px;
  padding:0 28px 0 26px;
  border:1px solid #d1d5db;
  border-radius:6px;
  font-size:13px;
  line-height:1;
  background:#fff;
  box-sizing:border-box;
}
.person-search-input:focus {
  outline:none;
  border-color:var(--accent);
  box-shadow:0 0 0 2px rgba(164,143,212,0.15);
}
.person-search-clear {
  position:absolute;
  right:6px;
  top:50%;
  transform:translateY(-50%);
  width:18px;
  height:18px;
  padding:0;
  border:none;
  background:transparent;
  color:#9ca3af;
  font-size:14px;
  line-height:1;
  cursor:pointer;
  border-radius:50%;
}
.person-search-clear:hover { color:#374151; background:#f3f4f6; }
.person-search-list {
  position:absolute;
  top:calc(100% + 4px);
  left:0;
  right:0;
  max-height:240px;
  overflow-y:auto;
  background:#fff;
  border:1px solid #d1d5db;
  border-radius:6px;
  box-shadow:0 4px 12px rgba(0,0,0,0.08);
  z-index:50;
  padding:4px 0;
}
.person-search-list.is-flipped-up {
  top:auto;
  bottom:calc(100% + 4px);
}
.person-search-list[hidden] { display:none; }
.person-search-option {
  padding:6px 10px;
  font-size:13px;
  color:#111827;
  cursor:pointer;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.person-search-option:hover, .person-search-option.is-active { background:#f3f4f6; }
.person-search-empty { padding:6px 10px; font-size:12px; color:#9ca3af; }
.probation-score-cell {
  display:grid;
  grid-template-columns:56px 64px 26px;
  gap:10px;
  align-items:center;
  justify-content:center;
  min-height:52px;
  width:max-content;
  margin:0 auto;
}
.probation-score-input {
  width:100%;
  height:36px;
  padding:0 8px;
  border:1px solid var(--border-color);
  border-radius:6px;
  font-size:13px;
  font-weight:600;
  text-align:center;
  background:#fff;
  box-sizing:border-box;
}
.probation-score-input:focus {
  outline:none;
  border-color:#a48fd4;
  box-shadow:0 0 0 3px rgba(164,143,212,0.15);
}
.probation-score-input:disabled {
  background:#f8fafb;
  color:var(--text-tertiary);
  cursor:not-allowed;
}
.probation-score-input.is-fail, .probation-avg.is-fail { color:#ef4444; font-weight:700; }
.probation-score-input.is-overdue { border-color:#fca5a5; }
.probation-evidence-btn {
  width:100%;
  height:36px;
  padding:0 8px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:4px;
  border:1px solid var(--border-color);
  border-radius:6px;
  background:#fff;
  color:var(--text-secondary);
  cursor:pointer;
  font-size:12px;
  font-weight:600;
  line-height:1;
  white-space:nowrap;
  box-sizing:border-box;
  transition:border-color 0.15s, color 0.15s, background 0.15s;
}
.probation-evidence-btn:hover { border-color:var(--btn-ink); color:var(--btn-ink); }
.probation-evidence-btn:disabled { opacity:0.6; cursor:not-allowed; }
.probation-evidence-btn.is-uploaded {
  background:#f6f2fd;
  border-color:rgba(164,143,212,0.55);
  color:#6b5a91;
}
.probation-evidence-btn.is-uploading { cursor:wait; }
.probation-evidence-btn .paperclip-icon {
  width:12px;
  height:12px;
  color:inherit;
}
.probation-evidence-delete-btn {
  width:28px;
  height:36px;
  padding:0;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  border:1px solid transparent;
  border-radius:6px;
  background:transparent;
  color:#9ca3af;
  cursor:pointer;
  font-size:16px;
  line-height:1;
  box-sizing:border-box;
  transition:color 0.15s, background 0.15s, border-color 0.15s;
}
.probation-evidence-delete-btn:hover {
  color:#ef4444;
  border-color:rgba(239,68,68,0.4);
  background:#fef2f2;
}
.probation-evidence-delete-btn.is-hidden {
  visibility:hidden;
  pointer-events:none;
}
.probation-avg {
  display:inline-block;
  font-size:13px;
  font-weight:600;
}
.probation-overdue-dot { display:inline-block; width:5px; height:5px; border-radius:50%; background:#ef4444; margin-left:4px; vertical-align:middle; }
.paperclip-icon { display:inline-block; width:12px; height:12px; vertical-align:middle; flex:0 0 auto; }

/* 일정 설정 탭은 기존 유지 */
.probation-policy-card .form-grid { gap:12px; }
.probation-policy-note { margin:0 0 16px; font-size:12.5px; line-height:1.6; color:var(--text-secondary); }
.probation-policy-hint { margin:12px 0 0; font-size:12px; color:var(--text-tertiary); }
.probation-phase-toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; flex-wrap:wrap; }
.probation-phase-caption { font-size:12px; font-weight:600; color:var(--text-secondary); }
.probation-phase-list { display:flex; flex-direction:column; gap:12px; }
.probation-phase-row { display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:12px; align-items:end; padding:12px; border:1px solid var(--border-color); border-radius:10px; background:#f8fafb; }
.probation-phase-actions { display:flex; align-items:flex-end; }
.probation-empty-message { color:var(--text-tertiary); font-size:12.5px; }
.probation-na { color:var(--text-tertiary); font-size:12px; }

/* 인사통계 시용평가 미니 테이블 (기존 유지) */
.stats-probation-table-container { width:100%; }
.probation-eval-table.stats-probation-table { width:100%; min-width:100%; table-layout:auto; display:table; }
.stats-probation-table { min-width:0; }
.stats-probation-table th { padding:12px 16px; font-size:12.5px; line-height:1.5; }
.stats-probation-table td { padding:14px 16px; font-size:12.5px; line-height:1.5; }
.stats-probation-table th:last-child,
.stats-probation-table td:last-child { padding-right:32px; }
@media (max-width: 1100px) {
  .probation-phase-row { grid-template-columns:1fr; }
}

/* ===== appointment ===== */
.appointment-shell { max-width: 1120px; }
.appointment-editor-grid { display:grid; grid-template-columns:minmax(320px, 380px) minmax(0, 1fr); gap:16px; align-items:start; }
.appointment-page [hidden] { display:none !important; }
.appointment-employee-search-results { min-height:220px; max-height:320px; overflow-y:auto; font-size:13px; }
.appointment-employee-search-message,
.appointment-employee-search-results .employee-search-item { display:flex; align-items:center; min-height:44px; padding:10px 14px; text-align:left; font-size:13px; line-height:1.4; }
.appointment-employee-search-message { margin:0; color:var(--text-tertiary); }
.appointment-employee-search-item { flex-wrap:wrap; gap:4px 8px; }
.appointment-employee-search-meta { color:var(--text-secondary); font-size:13px; }
.appointment-history-table { max-height:calc(100vh - 220px); min-height:280px; overflow:auto; }
.appointment-history-table table { min-width:900px; }
.appointment-document-wrap { width:100%; max-width:812px; margin:0 auto; background:#f8fafb; border:1px solid var(--border-color); border-radius:8px; padding:16px; overflow-x:hidden; overflow-y:auto; }
.appointment-output-panel { width:100%; max-width:812px; margin:0 auto; }
.appointment-output-actions { display:flex; justify-content:flex-end; gap:8px; margin:16px 0 12px; padding:0; }
.appointment-output-document { max-width:none; margin:0; background:#fff; }
.appointment-doc__top { display:flex; flex-direction:column; gap:4px; margin-bottom:24px; }
/* 좌우 칸은 반드시 같은 고정폭. minmax(140,200) 이면 로고 칸만 내용에 따라 넓어져
   (실측 157 vs 140) 제목이 왼쪽으로 밀린다. 로고 크기는 안쪽에서 맞춘다 */
.appointment-doc__title-row { display:grid; grid-template-columns:140px 1fr 140px; align-items:center; gap:16px; }
.appointment-doc__title-spacer { width:100%; height:1px; }
.appointment-doc__title { margin:0; text-align:center; white-space:nowrap; }
.appointment-doc__doc-no { text-align:left; font-size:12px; line-height:1.4; color:#000; }
.appointment-doc__doc-no span { display:inline; color:#555; margin-right:6px; }
.appointment-doc__doc-no strong { display:inline; font-size:13px; color:#000; font-weight:700; }
.appointment-doc__meta-table .appointment-doc__value-cell { text-align:left; padding-left:16px; }
.appointment-doc__pretext { text-align:center; }
.appointment-preview-panel .appointment-doc__title { letter-spacing:6px; }
.appointment-page input.is-invalid { border-color:#ef4444 !important; box-shadow:0 0 0 4px rgba(239,68,68,0.1) !important; }
@media (max-width: 1100px) {
  .appointment-editor-grid { grid-template-columns:1fr; }
}

/* ===== contracts ===== */
.contracts-shell { width:100%; max-width:1400px; }
.contracts-page [hidden] { display:none !important; }
.contracts-page .toolbar-right {
  margin-left:auto;
  display:flex;
  align-items:center;
  gap:8px;
  flex-wrap:wrap;
}
.contracts-table-container {
  min-height:calc(100vh - 220px);
  overflow-x:auto;
  max-width:1400px;
  margin-left:0;
  margin-right:auto;
}
.contracts-table {
  width:100%;
  min-width:1150px;
  table-layout:fixed;
}
.contracts-table col.col-select { width:40px; }
.contracts-table col.col-name { width:90px; }
.contracts-table col.col-employee-no { width:70px; }
.contracts-table col.col-org { width:110px; }
.contracts-table col.col-title { width:110px; }
.contracts-table col.col-category { width:80px; }
.contracts-table col.col-status { width:90px; }
.contracts-table col.col-period { width:200px; }
.contracts-table col.col-updated-at { width:130px; }
.contracts-table col.col-action { width:220px; }
.contracts-table th,
.contracts-table td {
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  vertical-align:middle;
  line-height:1.35;
  padding:10px 12px;
}
.contracts-table th,
.contracts-table td.col-action-cell {
  text-align:center;
}
.contracts-table th.col-select-cell,
.contracts-table td.col-select-cell {
  text-align:center;
  padding:8px 4px;
}
.contracts-table th.col-select-cell input,
.contracts-table td.col-select-cell input {
  display:block;
  margin:0 auto;
}
.contracts-table tbody tr:last-child td {
  border-bottom:none;
}
.contracts-empty {
  padding:44px 24px;
  border:1px dashed rgba(164,143,212,0.25);
  border-radius:16px;
  background:linear-gradient(135deg, rgba(240,253,244,0.75), rgba(248,250,252,0.95));
  text-align:center;
}
.contracts-empty-cell {
  padding:16px !important;
}
.contracts-empty strong {
  display:block;
  margin-bottom:8px;
  font-size:15px;
  color:var(--text-primary);
}
.contracts-empty p {
  margin:0;
  font-size:13px;
  color:var(--text-secondary);
}
.contract-status-badge {
  display:inline-flex;
  align-items:center;
  padding:4px 10px;
  border-radius:999px;
  font-size:12px;
  font-weight:600;
  border:1px solid transparent;
  white-space:nowrap;
}
.contract-status-badge.is-draft {
  background:rgba(243,244,246,0.9);
  border-color:rgba(107,114,128,0.16);
  color:#6b7280;
}
.contract-status-badge.is-signed {
  background:rgba(143,191,166,0.2);
  border-color:rgba(143,191,166,0.36);
  color:#3f7a5c;
}
.contract-status-badge.is-sent {
  background:rgba(59,130,246,0.12);
  border-color:rgba(59,130,246,0.2);
  color:#2563eb;
}
.contract-status-badge.is-expiring {
  background:rgba(245,158,11,0.12);
  border-color:rgba(245,158,11,0.2);
  color:#d97706;
}
.contract-status-badge.is-ended {
  background:rgba(220,38,38,0.08);
  border-color:rgba(220,38,38,0.15);
  color:rgba(220,38,38,0.82);
}
.contract-status-badge.is-expired {
  background:rgba(220,38,38,0.14);
  border-color:rgba(220,38,38,0.3);
  color:#dc2626;
}
/* 계약서 PDF 내보내기(is-pdf-exporting) 공통 정리 — 관리자 미리보기·모바일 서명 PDF 동일.
   ① body를 계약서 페이지 폭(210mm)에 맞춰 대칭 정렬(화면 카드용 패딩/보더/그림자 제거)
      → A4 안에서 좌우 대칭으로 가운데 정렬(치우침 방지). */
.contract-print-body.is-pdf-exporting {
  width: 210mm;
  max-width: none;
  margin: 0 auto;
  padding: 0;
  border: 0;
  box-shadow: none;
  background: #fff;
}
/* ② 근로계약서→개인정보동의서 사이 빈 페이지 제거.
   근무계약 페이지 break-after + 동의서 break-before 이중 브레이크가 빈 페이지를 만들어,
   html2pdf의 단일 pagebreak(before:.privacy-consent-page)만 남기고 CSS 강제 브레이크를 해제한다.
   화면용 점선 구분선(::before)도 PDF에선 숨긴다. */
.contract-print-body.is-pdf-exporting .contract-print-page--work {
  break-after: auto;
  page-break-after: auto;
}
.contract-print-body.is-pdf-exporting .privacy-consent-page {
  break-before: auto;
  page-break-before: auto;
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.contract-print-body.is-pdf-exporting .contract-print-page--work + .privacy-consent-page::before {
  display: none;
}
.contract-type-picker {
  display:grid;
  grid-template-columns:repeat(2, minmax(0, 1fr));
  gap:12px;
}
.contract-type-option {
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:8px;
  width:100%;
  padding:18px;
  border:1px solid rgba(164,143,212,0.14);
  border-radius:14px;
  background:linear-gradient(135deg, rgba(240,253,244,0.55), #fff);
  color:var(--text-primary);
  text-align:left;
  cursor:pointer;
  transition:border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}
.contract-type-option:hover {
  border-color:rgba(164,143,212,0.35);
  box-shadow:0 12px 28px rgba(15,23,42,0.08);
  transform:translateY(-1px);
}
.contract-type-option strong {
  font-size:15px;
}
.contract-type-option span {
  font-size:12.5px;
  line-height:1.5;
  color:var(--text-secondary);
}
.contract-form-modal {
  width:min(960px, 94vw);
  max-width:960px;
  padding:0;
  overflow:hidden;
}
.contract-form-modal .modal-header {
  margin-bottom:0;
}
.contract-form-modal .modal-body {
  max-height:min(72vh, 760px);
  overflow:auto;
}
.contract-form-modal .modal-footer {
  margin-top:0;
  padding:16px 20px 20px;
}
.contract-form-modal .form-section:last-child {
  margin-bottom:0;
}
.contract-checkbox-grid {
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));
  gap:6px 12px;
  padding:2px 0 4px;
}
.contracts-employee-search-results {
  min-height:220px;
  max-height:320px;
  overflow-y:auto;
  font-size:13px;
}
.contracts-employee-search-message,
.contracts-employee-search-results .employee-search-item {
  display:flex;
  align-items:center;
  min-height:44px;
  padding:10px 14px;
  text-align:left;
  font-size:13px;
  line-height:1.4;
}
.contracts-employee-search-message {
  margin:0;
  color:var(--text-tertiary);
}
.contracts-employee-search-item {
  flex-wrap:wrap;
  gap:4px 8px;
}
.contracts-employee-search-meta {
  color:var(--text-secondary);
  font-size:13px;
}
.contracts-page input.is-invalid,
.contracts-page select.is-invalid,
.contracts-page textarea.is-invalid {
  border-color:#ef4444 !important;
  box-shadow:0 0 0 4px rgba(239,68,68,0.1) !important;
}
@media (max-width: 900px) {
  .contract-type-picker,
  .contract-form-modal .form-grid.col-2 {
    grid-template-columns:1fr;
  }
}

/* ===== 인쇄 문서 스타일 ===== */
.print-doc { background:#fff; padding:40px 60px; font-family:'Malgun Gothic','맑은 고딕',sans-serif; color:#000; }
.print-doc__title { font-size:28px; font-weight:700; letter-spacing:8px; }
.certificate-preview-panel .certificate-doc__title { letter-spacing:6px; }
/* 로고는 회사마다 가로세로비가 다르다(BU바움 1207x302 = 4:1). 이미지에 px 를 박으면
   비율이 다른 로고가 등록될 때 또 깨진다 — 박스 안에 맞추는 방식으로 둔다.
   hr4u 는 멀티테넌트라 이 자리는 반드시 비율에 견뎌야 한다 */
.print-doc__logo { width:100%; max-width:100%; min-height:60px; height:60px; border:1px dashed #999; display:flex; align-items:center; justify-content:flex-start; font-size:12px; color:#999; overflow:hidden; padding:0; margin:0; }
.print-doc__logo.has-image { border:none; padding:0; }
.print-doc__seal.has-image { border:none; border-radius:0; background:transparent; }
.print-doc__logo img,
.print-doc__seal img { display:block; width:auto; height:auto; max-width:100%; max-height:100%; object-fit:contain; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
.print-doc__meta-table { width:100%; table-layout:fixed; border-collapse:collapse; margin-bottom:32px; border:1px solid #000; }
.print-doc__meta-table td { border:1px solid #000; padding:8px 16px; }
.print-doc__meta-table td:first-child { background:#f5f5f5; font-weight:600; width:100px; text-align:center; }
.print-doc__meta-table.certificate-doc__meta-table td:first-child,
.print-doc__meta-table.certificate-doc__meta-table td:nth-child(3),
.print-doc__meta-table.certificate-doc__meta-table .certificate-doc__label-cell { width:25%; min-width:0; }
.print-doc__separator { text-align:center; margin:24px 0; font-size:14px; }
.print-doc__pretext { margin-bottom:16px; font-size:14px; }
.print-doc__table { width:100%; table-layout:fixed; border-collapse:collapse; margin-bottom:40px; font-size:13px; border:1px solid #000; }
.print-doc__table th, .print-doc__table td { border:1px solid #000; padding:8px; text-align:center; }
.print-doc__table th { background:#f5f5f5; font-weight:600; }
.print-doc__footer { text-align:center; margin-top:40px; }
.print-doc__date { margin-bottom:24px; font-size:14px; }
.print-doc__company-seal-wrap { display:inline-block; position:relative; text-align:center; }
.print-doc__company { font-size:16px; font-weight:700; line-height:1.6; text-align:center; }
.print-doc__seal { position:absolute; top:50%; right:-54px; transform:translateY(-50%); width:80px; height:80px; border:2px dashed #999; display:flex; align-items:center; justify-content:center; font-size:11px; color:#999; border-radius:50%; background:#fff; }
/* ===================================================================
   기안 미리보기 — 종이에 나갈 모습을 **모달**로 (2026-09-10 봉길님:
   「기안 다 적고 미리보기 기능 있으면 좋을듯」 → 「종이에 나갈 형태」 → 「모달로 띄우자」)

   ⚠ 종이 서식은 **새로 짓지 않았다.** 위 `.print-doc` 를 그대로 입는다 —
     인사발령서·증명서가 쓰는 그 종이다. 새로 지으면 같은 제품에서 종이가 두 얼굴이 된다.
     결재문서에만 있는 **도장 칸**만 `.ap-print__*` 로 얹는다
     (인사발령서가 `.appointment-doc__*` 로 얹는 것과 같은 방식).
   =================================================================== */
/* 종이가 놓이는 자리 — 결재 모달(.ap-modal-box) 안 본문. 여기만 굴러간다 */
.ap-modal-body.ap-paperwrap { padding: 20px; background: #e9e8ee; }
/* 종이 — A4 폭 그대로. 화면에서도 종이로 보여야 「나갈 모습」이 된다 */
.ap-paper {
  width: 210mm;
  min-height: 297mm;
  margin: 0 auto;
  box-sizing: border-box;
  /* 297mm 마다 옅은 선 — **여기서 종이가 넘어간다**를 보여준다.
     내용이 한 장을 넘으면 실제로 두 장이 나가는데, 미리보기가 한 장짜리로 보이면
     「나갈 모습」이 아니다. 인쇄할 때는 지운다(아래 @media print) */
  background: #fff repeating-linear-gradient(to bottom,
    transparent 0, transparent calc(297mm - 1px),
    #ddd9e6 calc(297mm - 1px), #ddd9e6 297mm);
  box-shadow: 0 4px 18px rgba(40, 30, 70, 0.16);
}

.ap-print__stamp { display: flex; justify-content: flex-end; margin-bottom: 24px; }
.ap-print__stampbox { display: flex; border: 1px solid #000; }
.ap-print__stamplab {
  width: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 1px solid #000;
  font-size: 12px;
  letter-spacing: 3px;
  writing-mode: vertical-rl;
}
.ap-print__cell { width: 90px; border-right: 1px solid #000; }
.ap-print__cell:last-child { border-right: 0; }
.ap-print__cell .who {
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid #000;
  font-size: 12px;
  background: #f5f5f5;            /* .print-doc__meta-table 머리와 같은 회색 */
}
.ap-print__cell .sign {
  height: 66px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 13px;
  color: #000;
}
.ap-print__cell .sign .nm { font-weight: 600; }
.ap-print__cell .sign .dt { font-size: 11px; color: #777; }

/* 제목은 가운데. 인사발령서(.appointment-doc__title)·증명서와 같은 방식으로 얹는다.
   ⚠ letter-spacing 8 을 되미는 padding 을 넣지 않는다 — 크롬이 마지막 글자 뒤 여백을
     이미 잘라 낸다. 넣었더니 오히려 8.0px 오른쪽으로 밀렸다(실측) */
.ap-print__title { margin: 0 0 32px; text-align: center; white-space: nowrap; }

/* ⚠ **화면 표 스타일이 종이로 샌다.** 전역 `tbody td` 가 값을 가운데로 세우고,
   결재 스킨(approval/css/clay.css 의 `html[data-skin="clay"] tbody td`)이 글자를 회색으로 칠한다.
   둘 다 종이보다 명시도가 높아 그냥 두면 종이가 화면처럼 보인다.
   인사발령서도 같은 것에 걸려 `.appointment-doc__value-cell { text-align:left }` 로 막고 있다 */
.ap-paper .print-doc__meta-table td { text-align: left; color: #000; }
.ap-paper .print-doc__meta-table td:first-child { text-align: center; }
.ap-paper .print-doc__meta-table td.money { text-align: right; }
/* 글상자(.ap-rich)도 화면 잉크색을 들고 온다 — 종이에서는 검정 */
.ap-paper .ap-rich { color: #000; }

.ap-print__sub { font-size: 14px; font-weight: 600; margin: 0 0 8px; }
.ap-print__files { margin: 0 0 24px; padding-left: 20px; font-size: 13px; }
.ap-print__files li { margin: 4px 0; }

/* 금액은 오른쪽에 서고 자릿수가 흔들리지 않는다 */
.print-doc__meta-table td.money { text-align: right; font-variant-numeric: tabular-nums; }
.print-doc__meta-table tr.total td { font-weight: 700; background: #fafafa; }

.no-print { }

@media print {
  @page { size: A4; margin: 0; }
  .no-print { display:none !important; }
  .gnb, .sidebar, .tabs, .toast-container, .toast { display:none !important; }
  html, body { width:210mm; min-height:0 !important; margin:0; background:#fff; }
  body { display:block !important; }
  .modal-overlay { position:static !important; background:none !important; overflow:visible !important; }
  /* 기안 미리보기 — 종이만 나간다. 창 머리줄·아래 단추줄과 회색 바탕은 종이가 아니다.
     ⚠ 미리보기가 떠 있을 때만 인쇄한다(body.ap-printing). 그러지 않으면 화면 뒤의
       기안 폼까지 같이 나간다 */
  body.ap-printing > *:not(.ap-modal) { display:none !important; }
  body.ap-printing .ap-modal { position:static !important; padding:0 !important; display:block !important; }
  body.ap-printing .ap-modal-back { display:none !important; }
  body.ap-printing .ap-modal-box {
    width:auto !important; max-height:none !important; border:0 !important;
    border-radius:0 !important; box-shadow:none !important; overflow:visible !important;
  }
  body.ap-printing .ap-modal-head, body.ap-printing .ap-modal-foot { display:none !important; }
  .ap-modal-body.ap-paperwrap { overflow:visible !important; padding:0 !important; background:#fff !important; }
  .ap-paper { width:auto !important; min-height:0 !important; box-shadow:none !important; background:#fff !important; }
  .modal { box-shadow:none !important; border-radius:0 !important; max-width:100% !important; max-height:none !important; overflow:visible !important; }
  .main-content { display:block !important; flex:none !important; min-height:0 !important; margin:0 !important; padding:0 !important; overflow:visible !important; }
  .appointment-shell { max-width:none !important; width:210mm !important; margin:0 !important; }
  .appointment-no-print, .appointment-form-panel, .appointment-history-list { display:none !important; }
  .appointment-output-panel { display:block !important; }
  .appointment-document-wrap { max-width:none !important; width:auto !important; border:0 !important; border-radius:0 !important; padding:0 !important; overflow:visible !important; background:#fff !important; }
  .appointment-page .print-doc {
    width: 210mm !important;
    height: 296mm !important;
    padding: 18mm !important;
    box-sizing: border-box !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    break-inside: avoid !important;
    page-break-inside: avoid !important;
    page-break-after: avoid !important;
  }
  .appointment-page.is-printing-issued-preview .appointment-history-panel,
  .appointment-page.is-printing-issued-preview .appointment-output-panel,
  .appointment-page.is-printing-issued-preview .appointment-editor-grid > .card:not(.appointment-preview-panel),
  .appointment-page.is-printing-issued-preview .appointment-preview-panel > .card-title { display:none !important; }
  .appointment-page.is-printing-issued-preview #tab-write,
  .appointment-page.is-printing-issued-preview .appointment-form-panel,
  .appointment-page.is-printing-issued-preview .appointment-editor-grid,
  .appointment-page.is-printing-issued-preview .appointment-preview-panel { display:block !important; }
  .appointment-page.is-printing-issued-preview .appointment-preview-panel { border:0 !important; box-shadow:none !important; padding:0 !important; background:#fff !important; }
  .certificate-shell { max-width:none !important; width:210mm !important; margin:0 !important; }
  .certificate-no-print, .certificate-form-panel, .certificate-history-list { display:none !important; }
  .certificate-output-panel { display:block !important; }
  .certificate-document-wrap { max-width:none !important; width:auto !important; border:0 !important; border-radius:0 !important; padding:0 !important; overflow:visible !important; background:#fff !important; }
  .certificate-doc { max-width:none !important; min-width:0 !important; margin:0 !important; }
  .certificate-page .print-doc {
    width: 210mm !important;
    height: 296mm !important;
    padding: 18mm !important;
    box-sizing: border-box !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    break-inside: avoid !important;
    page-break-inside: avoid !important;
    page-break-after: avoid !important;
  }
  .certificate-page.is-printing-issued-preview .certificate-history-panel,
  .certificate-page.is-printing-issued-preview .certificate-output-panel,
  .certificate-page.is-printing-issued-preview .certificate-editor-grid > .card:not(.certificate-preview-panel),
  .certificate-page.is-printing-issued-preview .certificate-preview-panel > .card-title { display:none !important; }
  .certificate-page.is-printing-issued-preview #tab-new,
  .certificate-page.is-printing-issued-preview .certificate-form-panel,
  .certificate-page.is-printing-issued-preview .certificate-editor-grid,
  .certificate-page.is-printing-issued-preview .certificate-preview-panel { display:block !important; }
  .certificate-page.is-printing-issued-preview .certificate-preview-panel { border:0 !important; box-shadow:none !important; padding:0 !important; background:#fff !important; }
}

/* ===== 조직구조 테이블 ===== */
.org-toggle-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 10px;
  color: var(--text-secondary);
  padding: 2px 4px;
  border-radius: 3px;
  transition: background 0.15s;
  margin-right: 4px;
  line-height: 1;
  flex-shrink: 0;
}

.org-toggle-btn:hover {
  background: rgba(164,143,212,0.1);
  color: #a48fd4;
}

.org-ctrl-btn {
  font-size: 11px;
  padding: 4px 10px;
  border-radius: 5px;
  border: 1px solid #e5e7eb;
  background: #fff;
  cursor: pointer;
  color: var(--text-secondary);
  transition: all 0.15s;
  font-weight: 500;
}

.org-ctrl-btn:hover {
  background: #f6f2fd;
  border-color: #a48fd4;
  color: #a48fd4;
}

.org-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.org-table { width: 100%; border-collapse: collapse; font-size: 12.5px; table-layout: fixed; }

.org-table thead th {
  padding: 12px 14px;
  text-align: center;
  vertical-align: middle;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  background: linear-gradient(90deg, #f8fafb, #f6f2fd);
  border-bottom: 2px solid #e5e7eb;
  white-space: nowrap;
  letter-spacing: -0.2px;
}

.org-table thead th:first-child { text-align: left; padding-left: 16px; }

.org-table tbody td {
  padding: 11px 14px;
  text-align: center;
  vertical-align: middle;
  border-bottom: 1px solid #f5f6f8;
  color: var(--text-primary);
  font-size: 12.5px;
}

.org-table tbody tr { transition: background 0.15s; }
.org-table tbody tr:hover { background: rgba(164,143,212,0.03); }
.org-table tbody tr:last-child td { border-bottom: none; }

.org-td-name { text-align: left !important; font-weight: 500; white-space: nowrap; }
.org-td-num { text-align: right !important; font-weight: 600; font-variant-numeric: tabular-nums; }
/* 인원 컬럼(2번째)만 가운데 정렬 */
.org-table th:nth-child(2),
.org-table td:nth-child(2) { text-align: center !important; }
.org-td { text-align: center; color: var(--text-secondary); }
.org-td-plus { color: #a48fd4 !important; font-weight: 600; }
.org-td-minus { color: #ef4444 !important; font-weight: 600; }

.org-table tbody tr.org-total-row td {
  border-top: 2px solid #e5e7eb;
  font-weight: 700;
  background: rgba(164,143,212,0.04);
  color: var(--text-primary);
  border-bottom: none;
}
.org-table tbody tr.org-total-row .org-td-num { color: #8b74c4; }

/* ===== wf-kpi ===== */
.wf-kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 20px; }
.wf-kpi-item {
  background: linear-gradient(135deg, #ffffff, #f8fafb);
  border-radius: 10px;
  padding: 14px 16px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.03);
  border: 1px solid rgba(225,229,235,0.5);
  transition: all 0.2s;
}
.wf-kpi-item:hover { transform: translateY(-2px); box-shadow: 0 4px 16px rgba(164,143,212,0.12); border-color: rgba(164,143,212,0.2); }
.wf-kpi-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; }
.wf-kpi-value { font-size: 22px; font-weight: 600; line-height: 1.2; margin-bottom: 6px; letter-spacing: -0.3px; }
.wf-kpi-sub { font-size: 12px; color: var(--text-secondary); line-height: 1.5; }

/* ===== records-chip (전역 표준 emerald 칩) ===== */
.records-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 0 10px;
  border: 1px solid rgba(164, 143, 212, 0.16);
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(236, 253, 245, 0.98), rgba(255, 255, 255, 0.98));
  color: #6b5a91;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.records-chip.is-muted {
  border-style: dashed;
  border-color: rgba(148, 163, 184, 0.42);
  background: rgba(248, 250, 252, 0.94);
  color: #94a3b8;
}

/* === Records Import 모달 (글로벌 — 근태기록·연차 사용내역 공통) === */
.records-import-stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 14px 20px 12px;
  background: #ffffff;
  border-bottom: 1px solid rgba(203, 213, 225, 0.4);
}
.records-import-step {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.12);
  color: #94a3b8;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.01em;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.records-import-step.is-active { background: rgba(164, 143, 212, 0.18); color: #6b5a91; }
.records-import-step.is-complete { background: rgba(143, 191, 166, 0.16); color: #a48fd4; }
.records-import-step-num {
  display: inline-flex;
  width: 18px;
  height: 18px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(148, 163, 184, 0.5);
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
}
.records-import-step.is-active .records-import-step-num,
.records-import-step.is-complete .records-import-step-num { background: #a48fd4; }
.records-import-step-divider { width: 18px; height: 1px; background: rgba(148, 163, 184, 0.4); }

.records-import-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
.records-import-kpis > div {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px;
  border: 1px solid rgba(203, 213, 225, 0.7);
  border-radius: 12px;
  background: #ffffff;
}
.records-import-kpis strong { color: #6b7280; font-size: 11px; font-weight: 700; letter-spacing: 0.02em; }
.records-import-kpis span { color: var(--text-primary); font-size: 18px; font-weight: 800; }

.records-import-result-summary {
  margin: 14px 0 0;
  padding: 10px 14px;
  border: 1px solid rgba(203, 213, 225, 0.6);
  border-radius: 10px;
  background: rgba(248, 250, 252, 0.7);
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.55;
}
.records-import-result-failure {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid rgba(239, 68, 68, 0.2);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(254, 242, 242, 0.7), rgba(254, 242, 242, 0.32));
}
.records-import-result-failure-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 8px;
  color: #b91c1c;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.records-import-result-failure-title::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ef4444;
}
.records-import-list,
.records-import-failure-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 240px;
  overflow-y: auto;
}
.records-import-list-item {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 12px;
  align-items: center;
  padding: 8px 12px;
  border: 1px solid rgba(226, 232, 240, 0.9);
  border-radius: 8px;
  background: #ffffff;
  font-size: 12px;
  line-height: 1.5;
}
.records-import-list-item strong { color: var(--text-primary); font-weight: 700; }
.records-import-list-item span { color: var(--text-secondary); }
.records-import-list-item span:last-child { color: #b91c1c; font-weight: 500; }

.records-import-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 8px 0 0;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgba(248, 250, 252, 0.92);
  color: var(--text-secondary);
  font-size: 12px;
}
.records-import-stats span strong { color: var(--text-primary); font-weight: 700; margin-right: 4px; }

.records-import-file-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  border: 1px dashed rgba(164, 143, 212, 0.32);
  border-radius: 14px;
  background: rgba(240, 253, 244, 0.6);
}
.records-import-file-row input[type="file"] { flex: 1; }

.records-modal {
  max-width: 700px;
  width: min(700px, calc(100vw - 32px));
  padding: 0;
  overflow: hidden;
  border-radius: 20px;
}
.records-modal .modal-header { margin-bottom: 0; padding: 16px 20px; background: #ffffff; }
.records-modal .modal-body { padding: 24px; background: #f8fafc; max-height: calc(100vh - 200px); overflow-y: auto; }
.records-modal .modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 0;
  padding: 14px 20px 18px;
  background: #ffffff;
}
.records-modal .btn { min-width: 78px; }

.records-form-card {
  padding: 22px;
  border: 1px solid rgba(203, 213, 225, 0.8);
  border-radius: 16px;
  background: #ffffff;
  box-shadow: 0 10px 26px rgba(15, 23, 42, 0.04);
}
.records-form-card + .records-form-card { margin-top: 16px; }
.records-form-card[hidden] { display: none; }

.records-helper { margin: 0; color: #94a3b8; font-size: 12px; line-height: 1.55; }

.app-loader-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 14px;
  background: rgba(255,255,255,0.88);
  backdrop-filter: blur(2px);
  z-index: 9000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease;
}

.app-loader-overlay.is-active {
  opacity: 1;
  pointer-events: auto;
}

.app-loader-spinner {
  width: 44px;
  height: 44px;
  border: 3px solid rgba(164,143,212,0.15);
  border-top-color: #a48fd4;
  border-radius: 50%;
  animation: appLoaderSpin 0.8s linear infinite;
}

@keyframes appLoaderSpin {
  to { transform: rotate(360deg); }
}

.app-loader-text {
  color: #6b5a91;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* ── 테이블 합계 tfoot sticky ── */
.payroll-table tfoot td {
  position: sticky;
  bottom: 0;
  z-index: 3;
  background: #f8faf9;
  font-weight: 700;
  border-top: 2px solid var(--border);
  padding: 10px 12px;
  white-space: nowrap;
}
.payroll-table tfoot td.col-freeze {
  z-index: 5;
}


/* ── 정보 툴팁 (info-tip) — 컬럼 헤더 등의 ⓘ 아이콘 + 말풍선. js/info-tip.js 와 한 쌍 ── */
.info-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-left: 4px;
  color: var(--text-tertiary);
  /* 클릭으로 여는 방식이라 「누를 수 있는 것」임이 드러나야 한다 */
  cursor: pointer;
  /* vertical-align:middle 은 baseline + x-height/2 기준이라 아이콘이 글자 중앙보다 약간 내려간다.
     em 단위로 보정해 글꼴 크기가 달라져도 항상 글자 중앙선에 맞도록 한다. */
  vertical-align: middle;
  position: relative;
  top: -0.15em;
  flex-shrink: 0;
}
.info-tip:hover,
.info-tip:focus-visible,
.info-tip.is-open {
  color: var(--accent);
  outline: none;
}
.info-tip svg {
  width: 14px;
  height: 14px;
}

.info-pop {
  position: fixed;
  z-index: 1200;
  max-width: 330px;
  padding: 12px 14px;
  border: 1px solid rgba(15, 23, 42, 0.1);
  border-radius: 10px;
  background: #ffffff;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.16);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: -0.01em;
  text-align: left;
  white-space: normal;
  /* 클릭으로 여는 방식이라 팝오버 안 텍스트를 선택·복사할 수 있어야 한다 */
  pointer-events: auto;
}
.info-pop[hidden] {
  display: none;
}
.info-pop-title {
  margin-bottom: 8px;
  color: var(--text-primary);
  font-size: 12.5px;
  font-weight: 700;
}
.info-pop-row {
  display: flex;
  gap: 10px;
}
.info-pop-row + .info-pop-row {
  margin-top: 4px;
}
.info-pop-key {
  flex: 0 0 34px;
  color: var(--text-tertiary);
  font-weight: 600;
}
.info-pop-val {
  flex: 1 1 auto;
  color: var(--text-primary);
}
.info-pop-note {
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid rgba(15, 23, 42, 0.07);
  color: var(--text-tertiary);
}


/* =========================================================
   글상자 — 여러 줄 본문 (전역 공용)
   ---------------------------------------------------------
   2026-09-02 approval/css/approval.css 에서 옮겨왔다. 결재 본문·게시판 본문이 같은 칸을
   쓴다. 클래스 이름은 결재 화면의 마크업이 그대로 돌게 두려고 ap- 접두어를 유지했다.
   --apFieldR / --apPadX / --apFieldFs 는 결재 화면이 제 값을 물려주고,
   그 밖의 화면에서는 아래 기본값이 쓰인다.
   ========================================================= */
/* =========================================================
   글상자 — 여러 줄 본문
   ========================================================= */

.ap-rich-box {
  border: 1px solid var(--field-edge, var(--border-color));
  border-radius: var(--apFieldR, 10px);
  background: var(--bg-primary);
  overflow: hidden;
}

.ap-rich-tools {
  display: flex;
  /* 창이 좁으면 단추가 잘리는 대신 줄을 바꾼다 — 표 묶음까지 켜지면 한 줄에 안 들어간다
     (실측 1426px 창에서 26px 남았다. 그보다 좁으면 넘친다) */
  flex-wrap: wrap;
  row-gap: 2px;
  align-items: center;
  gap: 2px;
  padding: 5px 6px;
  border-bottom: 1px solid var(--border-light);
}

.ap-rich-btn {
  width: 28px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.ap-rich-btn:hover { background: var(--bg-tertiary); color: var(--text-primary); }
/* 글상자에 덧붙는 글자 단추(글꼴·크기·글자색·표) — 아이콘 단추와 같은 높이, 폭은 글자만큼 (2026-09-05) */
.ap-rich-btn.rt-text { width: auto; padding: 0 8px; font-size: 12px; color: var(--text-secondary); white-space: nowrap; }

/* ===== 서식 편집기 부품 (js/rich-tools.js) — 메일·결재·게시판 공용 (2026-09-05) ===== */
.mail-tool-sep { width: 1px; height: 16px; background: var(--border-color); margin: 0 4px; flex: none; }
.mail-tool-swatch {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px;
  background: var(--mail-tool-color, #d94b4b); vertical-align: -1px;
}
/* 색 판 · 표 크기 판 — 글로벌 .menu-pop 위에 얹는다 */
.mail-pop-colors { display: grid; grid-template-columns: repeat(6, 22px); gap: 6px; padding: 6px; }
.mail-pop-colors button {
  width: 22px; height: 22px; border-radius: 6px; border: 1px solid rgba(0, 0, 0, 0.08);
  padding: 0; cursor: pointer; background: var(--c);
}
.mail-pop-colors button:hover { outline: 2px solid var(--accent); outline-offset: 1px; }
.mail-pop-grid { padding: 6px; }
.mail-pop-grid .mail-pop-cells { display: grid; grid-template-columns: repeat(8, 16px); gap: 3px; }
.mail-pop-grid .mail-pop-cells button {
  width: 16px; height: 16px; padding: 0; border: 1px solid var(--border-color); border-radius: 3px;
  background: #fff; cursor: pointer;
}
.mail-pop-grid .mail-pop-cells button.is-on { background: rgba(164, 143, 212, 0.35); border-color: var(--accent); }
.mail-pop-grid .mail-pop-label { padding: 6px 2px 0; font-size: 11.5px; color: var(--text-tertiary); text-align: center; }
/* 링크 입력칸 — 고른 글자 바로 아래 판 안에 */
.mail-link-input {
  height: 30px; width: 260px; border: 1px solid var(--border-color); border-radius: 7px; padding: 0 8px;
  font-family: inherit; font-size: 12.5px;
}
/* 링크 막대 — 커서가 링크 위에 있을 때 링크 아래 */
.mail-link-bar {
  position: fixed; z-index: 2100;
  display: flex; align-items: center; gap: 2px; padding: 4px 4px 4px 10px;
  background: #fff; border: 1px solid var(--border-color); border-radius: 10px;
  box-shadow: var(--shadow-md, 0 6px 18px rgba(40, 30, 70, 0.12));
  font-size: 12.5px;
}
.mail-link-bar .mail-link-url {
  max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--accent-blue, #3b5bd6); margin-right: 6px;
}
.mail-link-bar button,
.mail-table-tools button {
  height: 26px; padding: 0 8px; border: 0; border-radius: 6px; background: none; cursor: pointer;
  color: var(--text-secondary); font-family: inherit; font-size: 12px; line-height: 1; white-space: nowrap;
}
.mail-link-bar button:hover,
.mail-table-tools button:hover { background: var(--bg-tertiary); color: var(--text-primary); }
/* 도구줄 안 「표」 묶음 — 표 안에 있을 때만 */
.mail-table-tools { display: inline-flex; align-items: center; gap: 2px; }
/* 지금 쓸 수 없는 것(고른 칸이 하나뿐인데 합치기 등)은 흐리게 — 눌러도 아무 일 없는 단추를 두지 않는다 */
.mail-table-tools button:disabled { opacity: 0.35; cursor: default; }
.mail-table-tools button:disabled:hover { background: none; color: var(--text-secondary); }
.mail-table-tools[hidden] { display: none; }
/* 끌어서 고른 칸 — 배경색 위에 얹히는 덮개라 칠해 둔 색이 그대로 비친다. 화면용이며 문서에는 안 실린다 */
[contenteditable] td.ml-cell-sel,
[contenteditable] th.ml-cell-sel {
  outline: 2px solid var(--accent); outline-offset: -2px;
  background-image: linear-gradient(rgba(164, 143, 212, 0.22), rgba(164, 143, 212, 0.22));
}
/* 편집기와 읽는 자리(.ap-rich·.post-content)의 표는 자료 표가 아니다 — 편집기 밖으로는 못 나가게 한다.
   ⚠ 결재 화면은 approval.css 의 `.ap-page table { min-width: 880px }` 가 더 무거워 거기서도 따로 걷는다 */
[contenteditable] table,
.ap-rich table,
.post-content table { min-width: 0; max-width: 100%; border-collapse: collapse; }
[contenteditable] td { min-width: 40px; }
/* 읽는 자리(.ap-rich·.post-content)의 표·색은 인라인 스타일이 그린다 */

/* 본문에 넣은 그림 (2026-09-09). 칸보다 큰 그림이 들어와도 칸을 밀지 않는다 —
   ⚠ 넣을 때 인라인으로 max-width 를 달아 두지만, 다른 데서 온 그림(옮겨 붙인 글)은 그것이 없다 */
[contenteditable] img,
.ap-rich img,
.ap-rich-in img,
.post-content img { max-width: 100%; height: auto; }

/* 그림을 끌고 편집기 위에 들어왔을 때 — 「여기 놓으면 된다」를 테두리로만 말한다 */
[contenteditable].rt-dropping {
  outline: 2px dashed var(--accent);
  outline-offset: -2px;
}

/* 고른 그림의 테두리·손잡이 (2026-09-09 그림 크기 조절).
   ⚠ 본문 안에 넣지 않고 화면 위에 덧그린다 — 본문에 달면 그대로 편지·문서에 실려 나간다 */
.rt-img-frame {
  position: fixed; z-index: 2090; pointer-events: none;
  outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 2px;
}
.rt-img-frame[hidden] { display: none; }
.rt-img-grip {
  position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px;
  background: var(--accent); border: 2px solid #fff; border-radius: 3px;
  box-shadow: 0 1px 3px rgba(40, 30, 70, 0.25);
  cursor: nwse-resize; pointer-events: auto;
}
/* 크기 막대는 링크 막대와 같은 부품이다 — 숫자만 링크 주소 자리에 들어간다 */
.rt-img-bar .mail-link-url { color: var(--text-secondary); font-variant-numeric: tabular-nums; }

.ap-rich-btn svg { width: 15px; height: 15px; }

.ap-rich-in {
  min-height: 132px;
  /* 좌우는 다른 칸과 같은 값을 쓴다 — 글자 시작점이 어긋나면 글상자만 튄다 */
  padding: 12px var(--apPadX, 14px);
  font-size: var(--apFieldFs, 14px);
  line-height: 1.7;
  color: var(--text-primary);
  outline: none;
  overflow-y: auto;
  max-height: 420px;
}

.ap-rich-in:focus { background: var(--bg-primary); }

/* 양식관리 미리보기는 손대는 칸이 아니다 — 높이만 보여준다 */
.ap-rich-pv .ap-rich-in { min-height: 76px; }
.ap-rich-pv { opacity: 0.72; pointer-events: none; }

/* 쓰는 자리와 읽는 자리가 같은 모양이라야 「올린 대로 보인다」 */
.ap-rich-in ul,
.ap-rich-in ol,
.ap-rich ul,
.ap-rich ol { margin: 4px 0 4px 20px; padding: 0; }

.ap-rich-in li,
.ap-rich li { margin: 2px 0; }

.ap-rich-in p,
.ap-rich p { margin: 0 0 6px; }

.ap-rich-in a,
.ap-rich a { color: var(--accent); text-decoration: underline; }

/* 읽는 자리는 표 안일 수도 있다. 셀 정렬을 물려받으면 문단이 가운데로 몰려
   글머리표만 왼쪽에 덩그러니 남는다 — 본문은 언제나 왼쪽에서 시작한다 */
.ap-rich {
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--text-primary);
  white-space: normal;
  text-align: left;
}

.ap-rich > :last-child { margin-bottom: 0; }

/* =========================================================
   게시판 — 글 목록 · 글 보기 · 댓글 · 첨부 (전역 공용)
   ---------------------------------------------------------
   2026-09-02 그룹웨어 1단계. 페이지 전용 prefix 클래스를 만들지 않는 규칙에 따라
   여기(글로벌)에 둔다. 첨부·댓글·칩은 앞으로 다른 화면에서도 쓸 부품이다.
   ========================================================= */

/* 표에 아무것도 없을 때의 한 줄. 화면마다 인라인 style 로 가운데 정렬을
   다시 쓰던 것을 한곳으로 모았다 */
.empty-cell {
  text-align: center;
  color: var(--text-tertiary);
  padding: 28px 12px;
}

.text-muted { color: var(--text-secondary); }

/* ---------- 목록 ---------- */

/* ⚠ 칸(td)과 그 안의 줄(span)은 **다른 클래스**를 쓴다 (2026-09-05).
   전에는 둘 다 .post-title-cell 이라, 줄에 준 display:flex 가 td 에도 걸려
   **테이블 칸이 flex 컨테이너가 돼 있었다**(실측 td display:flex). 열 너비 계산이
   흔들릴 수 있다 — 칸은 칸이고 줄은 줄이다 */
.post-title { text-align: left; }

.post-link {
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 500;
}
.post-link:hover { color: var(--accent); text-decoration: underline; }

/* 댓글 수는 제목 뒤에 붙는다. 열을 따로 만들면 대부분 비어 있는 열이 하나 는다 */
.post-count {
  margin-left: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
}

.post-clip {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 5px;
  color: var(--text-tertiary);
}
.post-clip svg { width: 13px; height: 13px; }

/* 제목 칸 = [표시칸][제목][댓글수][첨부]를 한 줄에 세운다 (2026-09-05 봉길님 D안).
   제목만 줄어들게 두고 나머지는 안 줄인다 */
.post-title-cell {
  display: flex;
  align-items: center;
  min-width: 0;
}
.post-title-cell > .post-mark,
.post-title-cell > .badge,
.post-title-cell > .post-count,
.post-title-cell > .post-clip { flex: none; }
.post-title-cell > .post-link { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.post-title-cell > .badge { margin-right: 6px; }

/* 목록 왼쪽 **표시 칸** — 「고정」과 「NEW」가 여기 든다.
   ⚠ 왜 배지가 아니라 칸인가 (2026-09-05 봉길님: 시안 D 채택)
     ① 배지는 있고 없고에 따라 제목이 밀린다. 실측으로 제목 시작점이 **네 자리**로
        흩어져 있었다(233 / 188 / 232.5). 폭을 고정하니 **전부 한 자리**가 된다.
     ② 배지에 바탕색을 주면 줄마다 빨간 덩어리가 붙어 목록이 시끄럽다.
        표시는 목록에서 「어느 줄인지」만 알리면 되고, 내용은 제목이 말한다.
     ③ 글자 크기가 배지·제목과 셋으로 갈려 밑선과 중심을 동시에 못 맞추던 문제도
        같이 사라진다 — 칸 안에서 가운데로 모으면 그만이다.
   폭 42px: 압정 8.73 + 사이 5 + 「NEW」 26.94 = 40.67 에 여유를 뒀다.
   (2026-09-08 「고정」 두 글자를 압정 그림으로 바꾸며 56 → 42. 그만큼 제목이 넓어진다)
   ⚠ 여기 글자를 늘리려면 이 폭부터 다시 재야 한다. 넘치면 그 줄만 제목이 밀린다 */
.post-mark {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 42px;
  margin-right: 8px;
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
}
/* 고정 = 작은 압정 그림 (2026-09-08 봉길님). 옆의 NEW 는 글자다 — 그림과 글자로 성격을 갈라
   한 칸 안에서 서로 다른 것으로 읽히게 했다. 크기는 12 로 NEW 의 글자 높이와 나란하다 */
.post-mark-pin { display: inline-flex; align-items: center; color: var(--text-tertiary); }
/* 그림 비율 16:22 — 높이 12 에 맞추면 폭 8.73. 폭을 12 로 두면 세로로 눌린다 */
.post-mark-pin svg { width: 8.73px; height: 12px; display: block; }
.post-mark-new { font-weight: 800; letter-spacing: 0.3px; color: var(--danger); }

/* ---------- 글 보기 — 커뮤니티형 (2026-09-07 봉길님: 「커뮤니티 사이트들 레이아웃을 따라해줘」, C 뽐뿌·DC형 채택) ----------
   한 카드에 제목 → 정보 띠 → 본문 → 첨부 → 목록 → 댓글 → 쓰기 → 이전·다음 → 다른 글.
   ⚠ 읽는 폭 1080 — 결재 문서와 같은 값. 2560 창에서 카드가 2220 이라 한 줄이 한글 130자였다.
     남는 자리는 바탕이다(카드를 좁힌다. 안쪽만 좁히는 방식은 결재에서 두 번 틀렸다).
   ⚠ 좌우 여백 34 도 결재 문서(.ap-docbody)와 같은 값 — 같은 「문서 읽기」 화면이라 값을 맞춘다. */
.post-card { --post-pad: 34px; max-width: 1080px; margin: 0; padding: 0; overflow: hidden; }
/* 카드는 **창 바닥까지** (2026-09-07 봉길님: 「하단 여백!!」). 짧은 글이라고 카드 아래를 비우지 않는다 —
   굴러가는 판을 세로 flex 로 두고 카드가 남는 높이를 먹는다(내용이 더 길면 판이 굴러간다).
   조직도 카드(page-fill)와 같은 셈법이다 */
html[data-frame] .page-scroll:has(> .post-card) { display: flex; flex-direction: column; }
html[data-frame] .page-scroll > .post-card { flex: 1 0 auto; }

.post-head { position: relative; padding: 14px var(--post-pad) 0; }
.post-head .post-head-menu { position: absolute; top: 12px; right: 22px; }
.post-head-board { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; color: var(--accent); }
.post-head-board .badge { margin: 0; }
.post-head h2 {
  margin: 0;
  padding-bottom: 12px;
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.35;
  color: var(--text-primary);
}

/* 정보 띠 — 작성자 | 날짜 | (수정됨) | (게시기간) ······ 댓글 N. 구분자는 세로선, 오른쪽 묶음에는 없다 */
.post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  padding: 10px var(--post-pad);
  border-top: 1px solid var(--border-light);
  border-bottom: 1px solid var(--border-light);
  background: #f7f5f4;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.post-meta > #postAuthor { font-weight: 600; color: var(--text-primary); }
.post-meta > span:not(:first-child):not(.post-meta-right):not([hidden])::before { content: "|"; margin: 0 10px; color: #cfc9c5; }
.post-meta-right { margin-left: auto; display: flex; gap: 14px; color: var(--text-tertiary); }

.post-content { min-height: 120px; padding: 22px var(--post-pad) 30px; font-size: 14.5px; line-height: 1.85; }

.post-files { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 var(--post-pad) 22px; }
.post-files .file-list-title { flex-basis: 100%; margin: 0; }

/* 댓글 — 같은 카드 안. 줄은 촘촘하게(아바타 없음), 이름 · 시각 · 삭제 */
/* 본문과 가르는 선은 댓글이 갖는다 — 사이에 있던 「목록」 띠를 없앴다 (2026-09-08) */
.post-comments { padding: 18px var(--post-pad) 22px; border-top: 1px solid var(--border-light); }
.post-comments-title { margin: 0 0 4px; font-size: 14px; font-weight: 700; color: var(--text-primary); }
.post-comments-title b { color: var(--accent); }

/* 이전 글 · 다음 글 — 줄 44 (목록과 같은 --l-row-h) */
.post-nav { border-top: 1px solid var(--border-light); }
.post-nav a {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  height: 44px;
  padding: 0 var(--post-pad);
  font-size: 13.5px;
  color: var(--text-primary);
  text-decoration: none;
  border-top: 1px solid var(--border-light);
}
.post-nav a:first-child { border-top: 0; }
.post-nav a:hover { background: rgba(0, 0, 0, 0.02); }
.post-nav a > span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.post-nav .post-nav-k { font-size: 12px; font-weight: 600; color: var(--text-tertiary); }
.post-nav .post-nav-d { font-size: 12px; color: var(--text-tertiary); }

/* 이 게시판의 다른 글 — 전체보기 칸의 줄과 같은 격자 [표시 56][제목 1fr][작성자 92][날짜 76] · 44px */
.post-others { border-top: 8px solid #f6f3f2; }
.post-others-head {
  display: flex;
  align-items: center;
  height: 44px;
  padding: 0 var(--post-pad);
  font-size: 13.5px;
  font-weight: 700;
  border-bottom: 1px solid var(--border-light);
}
.post-others-head a { margin-left: auto; font-size: 12.5px; font-weight: 500; color: var(--text-secondary); text-decoration: none; }
.post-others-row {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) 92px 76px;
  gap: 10px;
  align-items: center;
  height: 44px;
  padding: 0 var(--post-pad);
  font-size: 13px;
  color: var(--text-primary);
  text-decoration: none;
  border-bottom: 1px solid var(--border-light);
}
.post-others-row:last-child { border-bottom: 0; }
.post-others-row > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.post-others-row > .post-mark { margin-right: 0; }
.post-others-row.is-now { background: rgba(164, 143, 212, 0.08); font-weight: 600; }
.post-others-row .post-others-w, .post-others-row .post-others-d { color: var(--text-secondary); font-size: 12.5px; }
.post-others-row .post-others-d { text-align: right; }

/* ---------- 첨부 ---------- */

.file-list-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 6px;
}

.file-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-primary);
  color: var(--text-primary);
  text-decoration: none;
  font-size: 13px;
}
.file-item + .file-item { margin-top: 6px; }
a.file-item:hover { border-color: var(--accent); color: var(--accent); }

.file-icon { display: inline-flex; color: var(--text-tertiary); }
.file-icon svg { width: 14px; height: 14px; }
.file-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-size { flex: none; font-size: 12px; color: var(--text-tertiary); }

.file-remove {
  flex: none;
  border: 0;
  background: transparent;
  color: var(--danger);
  font-size: 12px;
  cursor: pointer;
}

/* ---------- 칩 (필독 확인 현황) ---------- */

.chip {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  margin: 0 5px 5px 0;
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--danger-bg);
  color: var(--danger);
  font-size: 12px;
}

.chip-done { background: var(--success-bg); color: var(--success); }
.chip em { font-style: normal; font-size: 11px; opacity: 0.75; }

/* ---------- 댓글 ---------- */

.comment-list { list-style: none; margin: 0 0 14px; padding: 0; }

.comment-item {
  padding: 9px 0;
  border-top: 1px solid var(--border-light);
}
.comment-item:first-child { border-top: 0; }

.comment-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.comment-author { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.comment-time { font-size: 11.5px; color: var(--text-tertiary); }

/* ===== 목록 부품 (2026-09-05) =====
   봉길님: 「메일 모듈처럼 본문영역 스타일 맞춰 주길 바래. 그리고 정렬도」
   화면의 뼈대는 mail/index.html 이 기준이다(CLAUDE.md). 그런데 그 치수가 메일 화면
   안에만 있어 다른 모듈이 쓸 수 없었다 — 값을 **그대로** 옮겨 공용 부품으로 둔다.
   메일 쪽은 건드리지 않았다. 다음에 메일도 이 부품으로 옮기면 한 곳만 고치면 된다.

   쓰는 곳이 격자만 정하면 된다:
     .list-card { --lc-cols: 56px 1fr 170px 126px 70px; }
   머리줄(.list-cols)과 줄(.list-line)이 **같은 변수**를 본다 — 한쪽만 고치면 세로선이 어긋난다 */

.list-card {
  --lg: 10px;          /* 열 사이 간격 */
  --l-row-h: 44px;     /* 36 이면 빽빽. 40 이었으나 답답하다 하여 44 로 (2026-09-06 봉길님) */
  padding-top: 9px;    /* 칩·검색바의 중심을 왼쪽 두 줄과 맞추는 값 — 메일에서 실측으로 잡았다 */
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* 윗줄 = [칩들] ······ [검색]. 검색바는 제 줄을 갖는다 —
   컬럼 머리줄과 같은 줄에 두면 열을 밀어 제목이 잘린다 */
.list-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* ⚠ 오른쪽만 8px. 목록에 세로 스크롤바가 있어 그 바깥선이 오른쪽 경계로 보인다 */
  padding: 0 8px 10px 16px;
}

.list-chips { display: flex; gap: 6px; }

.list-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 11px;
  border: 1px solid var(--border-light);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.72);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}
.list-chip:hover { background: #fff; }
.list-chip.is-on { background: var(--btn-ink, #2b2a33); border-color: var(--btn-ink, #2b2a33); color: #fff; }
.list-chip-n:empty { display: none; }
.list-chip.is-on .list-chip-n { opacity: 0.8; }

/* 검색바는 옆의 칩과 **같은 알약**이다. 공통 .search-box 의 그림자·둥글기를 걷어내고
   칩 치수를 쓰되 높이만 한 단 두껍게(28 은 손이 들어가기에 얇다) */
.list-search {
  flex: 0 0 240px;
  height: 34px;
  border: 1px solid var(--border-light);
  border-radius: 17px;
  background: rgba(255, 255, 255, 0.72);
  box-shadow: none;
}
.list-search .search-icon svg { width: 15px; height: 15px; }
.list-search input {
  height: 32px;
  padding: 0 12px 0 34px;
  background: transparent;
  border: 0;
  box-shadow: none;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.list-search input:focus { outline: none; box-shadow: none; }

/* 머리줄 — 목록과 같은 격자, 살짝 눌린 바탕 */
.list-bulk {
  min-height: 36px;
  display: flex;
  align-items: center;
  padding: 0 16px;
  border-top: 1px solid var(--border-light);
  border-bottom: 1px solid var(--border-light);
  background: rgba(90, 80, 120, 0.03);
}

.list-cols,
.list-line {
  display: grid;
  grid-template-columns: var(--lc-cols);
  align-items: center;
  gap: var(--lg);
  width: 100%;
}

/* ⚠ 목록만 굴러가면 **스크롤바 폭만큼 줄이 머리줄보다 좁다.**
   머리줄에도 같은 자리를 예약해 세로선을 맞춘다 */
.list-body, .list-bulk { scrollbar-gutter: stable; }
.list-bulk { overflow-y: auto; }

.list-cols { color: var(--text-tertiary); font-size: 12px; min-height: 36px; }

/* 틀은 잠그고 목록만 굴린다 */
.list-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 16px; }

.list-line {
  min-height: var(--l-row-h);
  border-bottom: 1px solid var(--border-light);
  font-size: 13.5px;
}
.list-line:last-child { border-bottom: none; }
.list-line > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.list-empty { padding: 40px 0; color: var(--text-tertiary); font-size: 13px; text-align: center; }

/* 읽음 확인 — **줄 목록**이다 (2026-09-05 봉길님: 「칩형태로 하지말고」).
   이름과 시각을 양 끝에 세워 눈이 한 줄로 훑게 한다.
   안 읽은 사람이 위에 오고, 그 줄만 진하다 — 관리자가 찾는 것은 그쪽이다 */
/* ⚠ 360px 로 못박아 뒀더니 **한 번에 여덟 줄**만 보였다. 화면이 1234px 이어도 모달은
   573px 만 쓰고 나머지가 비었다(2026-09-05 실측, 구성원 120명). 화면에 맞춰 늘린다 —
   모달 머리·요약·검색칸이 먹는 만큼(약 260px)을 빼고 남는 높이를 목록이 쓴다 */
.reads-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: min(560px, calc(100vh - 260px));
  overflow-y: auto;
}
/* 안 읽음과 읽음 사이를 가른다 — 줄만 늘어놓으면 어디까지가 안 읽은 사람인지 안 보인다 */
.reads-head {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 8px 2px 6px;
  background: #fff;
  color: var(--text-tertiary);
  font-size: 11.5px;
  font-weight: 600;
}
.reads-head:first-child { padding-top: 0; }
.reads-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 2px;
  border-bottom: 1px solid var(--border-light);
  font-size: 13.5px;
}
.reads-row:last-child { border-bottom: none; }
.reads-name { color: var(--text-secondary); }
.reads-row.is-unread .reads-name { color: var(--text-primary); font-weight: 600; }
.reads-when { color: var(--text-tertiary); font-size: 12.5px; white-space: nowrap; }
.reads-row.is-unread .reads-when { color: var(--danger); }
.reads-empty { padding: 16px 2px; color: var(--text-tertiary); font-size: 13px; }

/* 수정 이력 (2026-09-05) — 읽음 확인과 같은 줄 목록. 줄을 누르면 그때의 내용이 펼쳐진다 */
.reads-row.is-open { border-bottom: none; }
.history-body {
  padding: 4px 2px 14px;
  border-bottom: 1px solid var(--border-light);
  font-size: 13px;
}
.history-body .history-title { font-weight: 600; margin: 0 0 8px; }
/* 글 본문(.post-content)의 최소 높이를 물려받으면 짧은 옛 내용 아래가 텅 빈다 */
.history-body .post-content { font-size: 13px; min-height: 0; }

/* 목록 줄 안의 「삭제」 — 임시저장 원고를 지우는 글자. 위험색·밑줄 없음 */
.list-line .line-del { color: var(--danger); font-size: 12.5px; text-decoration: none; }
.list-line .line-del:hover { text-decoration: underline; }

/* 글 머리의 ⋮ — 제목 줄 오른쪽 끝에 붙는다.
   ⚠ 같은 요소가 .menu-anchor 도 달고 있고 그쪽은 position:relative 다. 클래스 하나끼리는
     **나중에 선언된 것이 이기는데** .menu-anchor 가 이 아래(5935)에 있어, 그냥 쓰면
     relative 가 이겨 ⋮ 가 왼쪽 위에 붙는다(2026-09-05 실측). 부모를 앞에 붙여
     특이도를 올린다 — 파일 안 순서에 기대지 않는다 */

.comment-del {
  /* 오른쪽 끝으로 밀지 않는다 — 화면이 넓으면 어느 댓글의 버튼인지 안 읽힌다 */
  border: 0;
  background: transparent;
  /* ⚠ 종전에는 바로 옆 시각과 **똑같은 회색**(--text-tertiary)이었다. 눌리는 자리인 줄
     모르는데다 되돌릴 수 없는 동작이 화면에서 가장 조용했다 (2026-09-05).
     평소에는 한 칸 진하게, 얹으면 빨갛게 — 「누를 수 있다」와 「위험하다」를 나눠 말한다 */
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.comment-del:hover { color: var(--danger); }

.comment-body { font-size: 13.5px; line-height: 1.7; color: var(--text-primary); }

/* 대댓글 — 1단 답글 (2026-09-07). 원댓글 아래 40px 들여쓰고 왼쪽에 얇은 선으로 묶음을 보인다 */
.comment-item.is-reply { margin-left: 40px; padding-left: 12px; border-left: 2px solid var(--border-light); }
.comment-item.is-deleted .comment-body { color: var(--text-tertiary); }
.comment-reply {
  border: 0;
  background: transparent;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: inherit;
}
.comment-reply:hover { color: var(--accent); }
/* 답글 쓰기칸 — 댓글 쓰기칸과 같은 상자를 답글 자리(들여쓰기)에 */
.comment-list .comment-write.is-reply { list-style: none; margin: 6px 0 10px 40px; }
.comment-list .comment-write.is-reply textarea { min-height: 58px; }
.comment-write-bar .btn + .btn { margin-left: 6px; }

.comment-empty {
  padding: 18px 0;
  text-align: center;
  color: var(--text-tertiary);
  font-size: 13px;
}

/* 쓰기칸 — 테두리 한 상자 안에 글칸과 「등록」 (2026-09-07). 전에는 글칸 옆에 단추가 따로 서서
   넓은 창에서 단추가 칸 밖으로 튀어나왔다 */
.comment-write { margin-top: 12px; border: 1px solid var(--border-color); border-radius: 12px; background: var(--bg-primary); overflow: hidden; }
.comment-write-bar { display: flex; align-items: center; padding: 8px 10px; border-top: 1px solid var(--border-light); background: rgba(0, 0, 0, 0.015); }
.comment-write-hint { flex: 1; padding-left: 4px; font-size: 12px; color: var(--text-tertiary); }

.comment-write textarea {
  display: block;
  width: 100%;
  box-sizing: border-box;
  min-height: 74px;
  padding: 12px 14px;
  border: 0;
  outline: none;
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.6;
  resize: vertical;
}
.comment-write textarea:focus { outline: none; border-color: var(--accent); }

/* ---------- 홈의 최근 공지 ---------- */

.notice-feed { list-style: none; margin: 0; padding: 0; }

.notice-feed-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 0;
  border-top: 1px solid var(--border-light);
  font-size: 13.5px;
}
.notice-feed-item:first-child { border-top: 0; }

.notice-feed-item a {
  flex: 1 1 auto;
  color: var(--text-primary);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.notice-feed-item a:hover { color: var(--accent); text-decoration: underline; }

.notice-feed-date { flex: none; font-size: 12px; color: var(--text-tertiary); }

/* ===== 업무관리 좌측 메뉴 — 모듈 아래 하위 항목 (2026-09-02) =====
   메일플러그처럼 좌측에 모듈이 죽 늘어서고 지금 있는 모듈만 하위가 펼쳐진다. */

.sidebar-sub {
  margin: 2px 0 6px 0;
  padding-left: 46px;   /* 위 모듈 줄의 아이콘 폭 + 여백에 글자 시작점을 맞춘다 */
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sidebar-sub-item {
  display: block;
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 13px;
  color: var(--sidebar-text);
  text-decoration: none;
  transition: background var(--transition), color var(--transition);
}

.sidebar-sub-item:hover {
  background: rgba(255, 255, 255, 0.55);
  color: rgba(43, 42, 51, 1);
  text-decoration: none;
}

/* 하위 항목이 **지금 위치**다 — 상위와 같은 흰 알약을 준다.
   ⚠ `.sidebar-nav a.active`(0,2,1)가 `.sidebar-sub-item.active`(0,2,0)보다 세다.
     `.sidebar-nav` 를 앞에 붙여 특정성을 맞추지 않으면 여기 값이 통째로 무시된다
     (2026-09-03 실측으로 발견 — 0.7 을 줬는데 화면엔 0.8 이 나왔다) */
.sidebar-nav .sidebar-sub-item.active {
  background: rgba(255, 255, 255, 0.8);
  color: rgba(43, 42, 51, 1);
  font-weight: 500;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.85) inset,
              0 10px 22px -16px rgba(70, 60, 100, 0.5);
}

/* 아직 만들지 않은 기능 — 자리는 보여주되 누를 수 없다.
   눌렀다가 빈 화면을 보는 것보다 「준비 중」이 낫다 */
.sidebar-pending {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 8px;
  padding: 10px 14px;
  border-radius: 10px;
  color: var(--sidebar-text);
  opacity: 0.38;
  cursor: default;
  user-select: none;
}

.sidebar-external .nav-label::after {
  /* 새 탭으로 열린다는 표시 — 아이콘을 하나 더 두지 않고 글자 뒤에 붙인다 */
  content: "↗";
  margin-left: 4px;
  font-size: 11px;
  opacity: 0.6;
}

/* ---------- 법인설정: 로고 표시 크기 ---------- */

.logo-size-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

.logo-size-row + .logo-size-row { margin-top: 6px; }

.logo-size-row label {
  flex: none;
  /* 확대·좌우·상하 세 줄의 슬라이더 시작점을 맞춘다 */
  width: 34px;
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.logo-size-row input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
  /* 폼 안 입력칸 규격(테두리·여백)을 물려받으면 슬라이더가 상자 안에 갇힌다 */
  padding: 0;
  border: 0;
  background: transparent;
  accent-color: var(--accent);
}

.logo-size-row output {
  flex: none;
  min-width: 42px;
  text-align: right;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}

/* ===== 좌측 아이콘 레일 — C안 (2026-09-02 봉길님 확정) =====
   상단 가로 모듈 메뉴를 대체한다. 색은 전자결재 clay 스킨의 크림·라벤더.
   ⚠ 레일이 없는 화면(login 등)은 renderGNB 를 안 부르므로 body 패딩도 없어야 한다 —
     그래서 body 에 직접 주지 않고 :has() 로 레일이 있을 때만 민다 */
.gnb-rail {
  position: fixed;
  left: 0;
  /* 상단바가 화면 전체 한 줄을 쓰고, 레일은 그 아래부터 (2026-09-02 봉길님) */
  top: var(--gnb-height);
  bottom: 0;
  width: var(--rail-w);
  z-index: 150;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 위 여백·항목 간격 모두 패널과 같은 변수 — 첫 줄이 나란해진다 */
  padding: var(--nav-top) 0 14px;
  gap: var(--nav-item-gap);
  background: #f7f3ef;
  border-right: 1px solid #eae4dd;
  /* 창이 낮아 항목이 다 안 들어가면 레일 **안에서** 스크롤한다.
     종전에는 overflow 가 visible 이라 아래쪽 항목(설정 등)이 창 밖으로 잘려
     아예 누를 수 없었다 (2026-09-03 1280x560 실측: 마지막 항목 bottom 607 > 창 560).
     ⚠ overscroll-behavior: contain — 레일 끝에서 더 굴려도 본문이 따라 움직이지 않게 */
  overflow-y: auto;
  /* ⚠ 세로만 auto 로 두면 가로는 자동으로 auto 가 된다. 레일은 폭이 68px 뿐이라
     세로 스크롤바가 폭을 먹는 순간 항목이 1px 넘쳐 **가로 스크롤바까지 생겼다**
     (2026-09-03 실측: clientW 57 vs scrollW 58, 가로바 10px). 가로는 잘라낸다 */
  overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.gnb-rail::-webkit-scrollbar {
  width: 6px;
}

.gnb-rail::-webkit-scrollbar-thumb {
  background: rgba(120, 110, 130, 0.28);
  border-radius: 3px;
}

/* ⚠ **레일이 생기기 전에 자리를 잡아 둔다** (2026-09-04 봉길님: 「모듈 이동시 모든
   메인메뉴들이 늦게 뜸 — 리랜더링 하는 것 같음」).
   레일(.gnb-rail)은 JS 가 만든다. `body:has(.gnb-rail)` 만으로는 그 전까지 본문이
   왼쪽 0 에 있다가 레일이 생기는 순간 68px 밀린다 — 화면이 한 번 튄다.
   `.sidebar` 는 **HTML 에 정적으로 있으므로** 이것을 함께 보면 첫 페인트부터 자리가 맞는다. */
body:has(.gnb-rail),
body:has(.sidebar) {
  padding-left: var(--rail-w);
}

/* 상단바만은 레일 위 전체 한 줄 — body 패딩을 음수 마진으로 되물린다 */
body:has(.gnb-rail) .gnb,
body:has(.sidebar) .gnb {
  margin-left: calc(-1 * var(--rail-w));
  width: calc(100% + var(--rail-w));
}

/* ===== 레일·메인메뉴 자리를 **CSS 만으로** 미리 칠한다 =====
   (2026-09-04 봉길님: 「여전히 모듈 이동시마다 메인메뉴 배경이 늦게 채워지는데」)

   머리(<head>)의 동기 스크립트(firebase 3개 + config·init·auth)가 본문 파싱을 막아
   화면이 뜨기까지 실측 430~1100ms 가 걸린다. 그동안 `.sidebar` 는 **아직 없다** —
   HTML 에 적혀 있어도 파싱이 거기까지 가지 못했다. 그래서 왼쪽 240px 이 바탕색이다가
   본문이 뜨는 순간 한 번에 밝아졌다.

   ⚠ 그래서 **<html> 에 건다.** body 나 .sidebar 를 조건에 넣으면 그것이 파싱될 때까지
     기다리게 되어 아무 소용이 없다. `data-shell` 은 <html> 태그의 속성이라
     파싱 첫 줄에 읽힌다 — 스타일시트만 오면 바로 칠해진다.
   ⚠ 색은 **띠가 전담한다.** `.sidebar` 배경을 그대로 두면 같은 반투명이 두 번 얹혀
     완성 뒤에 한 번 더 밝아진다(아래 .sidebar 규칙 참조).
   ⚠ 한때 이것을 body::before 에 두었다가 **전 화면 색안개를 덮어 버렸다**
     (안개가 body::before 다. `body:has(.sidebar)::before` 가 특이도로 이긴다). */
html[data-shell]::before,
html[data-shell]::after {
  content: "";
  position: fixed;
  top: var(--gnb-height);
  bottom: 0;
  z-index: 0;
  pointer-events: none;
}

/* 모듈메뉴(아이콘 줄) 자리 — 레일 본체(z-index 150)가 뜨면 그 위를 덮는다 */
html[data-shell]::before {
  left: 0;
  width: var(--rail-w);
  background: var(--shell-rail-bg);
  border-right: 1px solid #eae4dd;
}

/* 메인메뉴(두 번째 열) 자리 */
html[data-shell]::after {
  left: var(--rail-w);
  width: var(--sidebar-width);
  background: var(--shell-panel-bg);
  border-right: 1px solid var(--border-light);
}

/* clay 화면은 구분선 색이 다르다 (아래 「좌측 메뉴 판」 규칙에서 쓰던 값과 같다) */
html[data-skin="clay"][data-shell]::after { border-right-color: rgba(90, 80, 120, 0.14); }
html[data-skin="clay"][data-shell]::before { border-right-color: rgba(90, 80, 120, 0.14); }

/* 색은 위 띠가 낸다 — 여기서 또 칠하면 같은 반투명이 두 번 얹혀 더 밝아진다.
   ⚠ 띠는 fixed 라 화면에 붙어 있고 .sidebar 는 sticky 다. 스크롤이 길어 메뉴가
     밀려 올라가도 자리 색은 그대로 남는다 — 종전보다 오히려 안정적이다 */
.sidebar {
  background: transparent;
  border-right: none;
}

.rail-item {
  position: relative;
  width: calc(var(--rail-w) - 10px);
  height: var(--nav-item-h);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  color: #8d8798;
  text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}

/* 레일 아이콘 위 NEW (2026-09-05 봉길님: 「숫자 표기를 하지 말자 … new 라고만」).
   목록의 NEW 표시(.post-mark-new)와 같은 글자 — 빨간 굵은 소문자 없이 NEW.
   아이콘(22px, 가운데)의 오른쪽 위에 선다: 실측 아이콘 top 428.75 / right 44.67 (레일 줄 top 420) */
.rail-count {
  position: absolute;
  /* 아이콘의 오른쪽 위 모서리에 **알약**으로 걸친다 (2026-09-05 봉길님: 「new 표시 좀 자연스럽게」).
     빨간 글자만 띄우니 아이콘 위에 글자가 얹힌 꼴이었다. 아이콘(22px)은 줄 안에서 x 18~40 · y 8.8~30.8 —
     알약 가운데를 그 모서리(40, 8.8)에 둔다: 높이 13 → top 2, 폭 ~26 → left 27 */
  top: 2px;
  left: 27px;
  height: 13px;
  padding: 0 4px;
  border-radius: 7px;
  display: inline-flex;
  align-items: center;
  /* 빨강은 레일의 연보라·회색 사이에서 혼자 소리쳤다 (2026-09-05 봉길님: 「너무 빨간색이라 튀는 느낌」).
     메뉴 옆 안 읽음 배지(.nav-count)와 같은 강조색을 쓴다 — 「알림」은 한 가지 색이면 된다 */
  background: var(--accent);
  color: #fff;
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.4px;
  line-height: 1;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.9);   /* 아이콘 선과 닿는 자리를 흰 테로 떼어 놓는다 */
}
.rail-count:empty { display: none; }

.rail-label {
  font-size: 10.5px;
  line-height: 1;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.rail-item:hover {
  background: rgba(255, 255, 255, 0.9);
  color: #2b2a33;
  text-decoration: none;
}

.rail-item.active {
  background: rgba(164, 143, 212, 0.2);
  color: #5f4d8c;
}


/* ===== 상단바 우측 프로필 =====
   이메일 글자 대신 아이콘 하나 (2026-09-02 봉길님). 눌러서 이름 변경·로그아웃.
   패널 하단에 있던 계정 영역은 여기로 이사했다 */
/* 프로필은 레일 맨 아래(설정 위)에 있다 — 다른 레일 항목과 같은 모양으로 세운다 */
.gnb-profile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 0;
}

.gnb-profile .rail-label {
  color: #8d8798;
}

.gnb-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  background: linear-gradient(135deg, #a48fd4, #8fbfa6);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gnb-avatar:hover {
  filter: brightness(1.06);
}

/* 메뉴는 레일 오른쪽으로 편다 — 레일이 좁아 아래로 펴면 화면 밖으로 나간다 */
/* ⚠ 이 팝업은 **body 직속**이다. 레일 안에 두면 레일의 overflow 에 잘려 안 보인다
   (2026-09-03). 자리는 js/data.js 의 bindProfileMenu > place() 가 잡아 준다 —
   여기에 left/bottom 을 다시 적지 말 것. z-index 는 상단바(200)·레일(150) 위여야 한다 */
.gnb-profile-menu {
  position: fixed;
  min-width: 208px;
  z-index: 1000;
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(43, 42, 51, 0.14);
  padding: 6px;
}

.gnb-profile-who {
  padding: 9px 10px 10px;
  border-bottom: 1px solid var(--border-light);
  margin-bottom: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.gnb-profile-who strong {
  font-size: 13.5px;
  color: var(--text-primary);
}

.gnb-profile-who span {
  font-size: 12px;
  color: var(--text-secondary);
  word-break: break-all;
}

.gnb-profile-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-primary);
}

.gnb-profile-item:hover {
  background: rgba(164, 143, 212, 0.12);
}

/* 인쇄에는 레일이 낄 자리가 없다 — 계약서·증명서가 60px 밀려 나오면 사고다 */
@media print {
  .gnb-rail {
    display: none;
  }

  body:has(.gnb-rail),
  body:has(.sidebar) {
    padding-left: 0;
  }

  html[data-shell]::before,
  html[data-shell]::after { display: none; }
}

/* ===== 그리기 전 바탕 — **백지를 없앤다** =====
   (2026-09-04 봉길님: 「모듈 이동시 모든 메인메뉴들이 늦게(배경색이 늦게) 뜸」)

   머리의 동기 스크립트(firebase 3개 + config·init·auth)가 본문 파싱을 막아
   화면이 뜨기까지 실측 430~1100ms 가 걸린다. 그동안 무엇이 보이느냐가 갈렸다:
     · clay 를 읽는 모듈(메일·게시판) — html 바탕이 #fcfaf9 라 **크림색**
     · 아닌 모듈(인사·급여)        — html 바탕이 **투명**이라 브라우저 기본 **흰색**
   그래서 흰 화면이 잠깐 보였다가 안개가 깔리며 크림으로 바뀌었다.
   바탕을 여기서 못박아 두면 첫 픽셀부터 제 색이다 — clay 의 --base 와 같은 값이다.
   ⚠ 색을 바꿀 일이 있으면 approval/css/clay.css 의 --base 와 **함께** 고칠 것. */
html {
  background: #fcfaf9;
}

/* ===== 전 화면 색안개 — 전자결재(clay)의 배경을 공통으로 =====
   (2026-09-02 봉길님: 「다른 메뉴들도 배경 스타일을 전자결재 메뉴에서 보이는
   배경과 디자인으로」) approval 화면은 clay.css 의 .clay-bg(움직이는 4겹 안개)가
   이미 있으므로 여기 것은 끈다 — 안개가 두 겹이면 색이 탁해진다.
   색은 clay.css 의 --hz1~4 와 같은 값이다 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(640px 520px at 8% -6%, rgba(255, 217, 201, 0.40), transparent 70%),
    radial-gradient(700px 560px at 96% -4%, rgba(217, 214, 247, 0.38), transparent 72%),
    radial-gradient(760px 540px at 38% 108%, rgba(207, 234, 223, 0.38), transparent 70%),
    radial-gradient(460px 380px at 82% 104%, rgba(255, 230, 184, 0.26), transparent 68%);
}

html[data-skin="clay"] body::before {
  content: none;
}

@media print {
  body::before {
    content: none;
  }
}

/* 레일도 유리 — 안개가 살짝 비치는 반투명 크림 */
.gnb-rail {
  background: rgba(247, 243, 239, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

/* 잠긴 레일 항목(메일·일정) — 흐리게, 눌리지 않는다 */
.rail-pending {
  opacity: 0.4;
  cursor: default;
}

.rail-pending:hover {
  background: none;
  color: #8d8798;
}

/* 하단 그룹(인사관리·설정) 앞의 빈 공간 — 남은 높이를 다 차지해 아래로 민다 */
.rail-gap {
  flex: 1;
}

/* ===== 내 정보(프로필 설정) — taskit 방식 참고 (2026-09-02 봉길님) =====
   아바타를 눌러 열고, 사진은 고른 즉시 미리 보이되 **저장을 눌러야 반영**된다.
   취소하면 원래 사진으로 돌아간다. 사진은 정사각 256px 로 줄여 문서에 담는다 —
   원본을 그대로 올리면 문서가 수 MB 가 되고, 파일이 계속 쌓인다 */
.gnb-avatar {
  overflow: hidden;
  padding: 0;
}

.gnb-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ===== 「내 정보」 머리 — 왼쪽 사진, 오른쪽 인사정보 (2026-09-03 봉길님:
   「사진 우측에 공간이 많으니 부서·직위·직책·업무·이메일 나오게」)
   ⚠ 라벨을 달지 않는다. 값만 봐도 무엇인지 알 수 있는 것들이라 라벨은 글자 수만 늘린다. */
.profile-head {
  display: flex;
  /* 사진을 오른쪽 정보 덩어리의 **한가운데**에 맞춘다 (2026-09-03 봉길님: 「사진이 우측 정보와
     비교하면 위로 올라가서 보인다」). 정보가 5줄(약 110px)이라 96px 사진을 위에 붙이면
     아래가 남아 한쪽으로 쏠려 보인다. */
  align-items: center;
  /* 사진과 오른쪽 정보 사이 (2026-09-03 봉길님: 「간격을 조금 더 벌려 달라」) */
  gap: 30px;
  /* 기본정보 마지막 줄(이메일)과 자기소개 사이에 **한 줄만큼** 더 띄운다
     (2026-09-03 봉길님: 「갭이 조금 있으면 덜 답답해 보일 것 같다 / 한 줄 정도면 충분」).
     ⚠ .modal-pad 의 자식 간격 16 과 **합쳐지지 않는다.** 위아래 margin 은 겹쳐서
       큰 쪽만 남으므로(실측: 20 을 줬더니 16+20 이 아니라 20 이 나왔다)
       원하는 최종 간격을 그대로 적는다. 16 + 한 줄(21) ≈ 36. */
  margin-bottom: 36px;
}

.profile-facts {
  min-width: 0;          /* 긴 이메일이 칸을 밀어내지 않게 */
  padding-top: 2px;
}

.profile-facts-name {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  margin-bottom: 6px;
  word-break: break-word;
}

.profile-facts-line {
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.65;
  word-break: break-word;
}

.profile-photo {
  position: relative;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: none;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  background: linear-gradient(135deg, #a48fd4, #8fbfa6);
}

.profile-photo-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: #fff;
  font-size: 34px;
  font-weight: 700;
}

.profile-photo-inner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* 편집·삭제는 사진 위에 겹쳐 두고 마우스를 올렸을 때만 드러낸다
   (2026-09-03 봉길님: 「사진 지우기 텍스트 버튼은 필요없고, 사진 위 호버 시 편집/삭제가」).
   ⚠ :focus-within 도 함께 건다 — 키보드로 탭해 온 사람에게는 호버가 없다. */
.profile-photo-actions {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  gap: 2px;
  padding: 4px 0;
  background: rgba(43, 42, 51, 0.62);
  opacity: 0;
  transition: opacity 0.12s ease;
}

.profile-photo:hover .profile-photo-actions,
.profile-photo:focus-within .profile-photo-actions {
  opacity: 1;
}

.profile-photo-act {
  background: none;
  border: none;
  padding: 1px 6px;
  border-radius: 5px;
  cursor: pointer;
  color: #fff;
  font-size: 11.5px;
  line-height: 1.5;
}

.profile-photo-act:hover {
  background: rgba(255, 255, 255, 0.22);
}

/* 둘 다 보일 때만 사이에 칸막이 — 삭제는 사진이 있을 때만 나온다 */
.profile-photo-act + .profile-photo-act {
  box-shadow: -1px 0 0 rgba(255, 255, 255, 0.3);
}

.profile-readonly {
  padding: 9px 12px;
  border-radius: 8px;
  background: rgba(90, 80, 120, 0.06);
  color: var(--text-secondary);
  font-size: 13.5px;
  word-break: break-all;
}

/* ===== 「내 정보」 줄 간격 — **한 규칙으로 준다** (2026-09-03 봉길님: 「간격 좀 잘 맞추고」)
   ⚠ 종전에는 `.form-group + .form-group`(16px)과 `.profile-hr-row`(16px)가 따로 있었다.
     그래서 **종류가 바뀌는 자리**에서 간격이 무너졌다 —
     두 칸 줄(직위·직책) 다음에 오는 한 칸 줄(자기소개)은 앞이 form-group 이 아니라서
     `+` 규칙이 안 걸려 **0px 로 붙었다.**
     자식 사이 간격을 하나로 묶으면 줄 종류가 섞여도 리듬이 유지된다. */
/* 스크롤은 바깥(.modal-body), 여백은 안쪽(.modal-pad).
   ⚠ 한 요소가 둘 다 맡으면 스크롤바가 여백 안쪽에 그려져 오른쪽만 그 폭만큼 좁아진다
     (2026-09-03 실측: 왼 48 / 오른 58). 나눠야 좌우가 같다. */
/* ⚠ 모달 자체에는 좌우 여백을 두지 않는다. 여백을 주면 스크롤 상자가 그만큼 안으로 들어가
   **스크롤바가 창 가장자리가 아니라 한가운데 떠 있는 것처럼 보인다**
   (2026-09-03 봉길님: 「스크롤바가 중간에 있으니 이상해. 우측 끝에 놓던지」).
   여백은 아래 세 영역(제목줄·본문 안쪽·버튼줄)이 각자 같은 값으로 준다. */
#gnbProfileModal .modal {
  padding: 0;
}

/* 세 영역의 좌우 여백을 한 값으로 — 34 = 예약된 스크롤바 자리 10 + 안쪽 24.
   이렇게 해야 제목·본문·버튼이 같은 세로선에 선다 */
#gnbProfileModal .modal-header,
#gnbProfileModal .modal-foot {
  padding-left: 30px;
  padding-right: 30px;
}

#gnbProfileModal .modal-body {
  padding: 0;
  /* ⚠ 스크롤바는 스크롤 상자 **안쪽** 오른쪽에 서고, 그만큼 자식 폭을 잠식한다.
     감싸는 요소를 아무리 더해도 오른쪽만 좁아지는 건 그대로다(실측으로 확인).
     `both-edges` 로 **양쪽에 같은 자리를 예약**해야 좌우가 같아진다. */
  scrollbar-gutter: stable both-edges;
}

/* 모달에 여백이 없으므로 여기서 온전히 20 을 준다(스크롤바 자리 10 과 합쳐 30) */
#gnbProfileModal .modal-pad {
  padding: 20px;
}

#gnbProfileModal .modal-pad > * + * {
  margin-top: 16px;
}

/* ===== 「내 정보」 버튼줄 — 새 제품 색(데이브레이크/clay)으로 못박는다
   (2026-09-03 봉길님: 「취소·저장 버튼 색상이 기존 HR4U 시스템 색상이라 별로다」)

   ⚠ 왜 여기서 다시 적나: 이 모달은 **모든 화면에서 뜨는데** 버튼 색의 출처는 화면마다 다르다.
     clay.css 를 싣는 화면(결재·게시판·근태·구성원)은 저장이 먹빛,
     안 싣는 화면(인사관리·급여·설정)은 옛 에메랄드(--accent #a48fd4)로 나왔다.
     셸 글꼴을 못박았던 것(20-9 ⑤)과 같은 이유로, 값을 여기 적어 **어디서나 같게** 만든다.
   ⚠ clay 토큰(--ink 등)은 clay.css 안에서만 살아 있으므로 **값을 그대로 적는다.** */
#gnbProfileModal .modal-foot .btn {
  border-radius: 15px;
  font-weight: 500;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

#gnbProfileModal .modal-foot .btn-primary {
  background: rgba(43, 42, 51, 0.92);
  border: 1px solid rgba(43, 42, 51, 0.92);
  color: #fff;
  box-shadow: none;
}

#gnbProfileModal .modal-foot .btn-primary:hover,
#gnbProfileModal .modal-foot .btn-primary:active {
  background: #2b2a33;
  border-color: #2b2a33;
  box-shadow: none;
}

#gnbProfileModal .modal-foot .btn-secondary {
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(90, 80, 120, 0.16);
  color: #5d5b69;
}

#gnbProfileModal .modal-foot .btn-secondary:hover {
  background: #fff;
  color: #2b2a33;
}

/* 눌린 자리 표시도 초록이 아니라 먹빛으로 */
#gnbProfileModal .modal-foot .btn:focus-visible {
  outline: 2px solid rgba(43, 42, 51, 0.55);
  outline-offset: 2px;
}

/* ===== 자기소개·올해 목표의 **글자 규칙 한 곳** (2026-09-03 봉길님:
   「내 정보에 입력한 텍스트 정렬 및 표기가 구성원 메뉴 조회 시와 동일하게」)

   ⚠ 두 화면은 스타일 출처가 다르다. 구성원·게시판·결재는 clay.css 를 싣고,
     인사관리 등은 싣지 않는다. **clay 가 `--font-stack` 을 다시 정의하고 자간까지 준다** —
     실측: 「내 정보」는 -apple-system / 자간 normal, 구성원은 Pretendard / 자간 -0.005em.
     같은 글이 화면마다 다른 폭으로 흘러 **줄바꿈 위치가 달라졌다.**
   ⚠ 그래서 이 글에 한해 글꼴·자간을 **여기서 못박는다.** 페이지가 clay 든 아니든 같게 나온다.
   ⚠ 줄바꿈 규칙도 맞춘다: 입력한 개행은 그대로(pre-wrap), 긴 낱말만 접는다(overflow-wrap).
   ⚠⚠ 특정성을 **일부러 올려 둔다**(`.note-text.note-text`). 입력칸에는 폼 공통 규칙
     `.form-group textarea`(0,2,1) 가 이미 걸려 있어서, 클래스 하나(0,1,0)로는 글자 크기를
     못 이긴다 — 실측에서 구성원은 13.5px, 입력칸은 13px 로 갈렸다. 클래스를 두 번 적어
     (0,2,0) 로 올리면 뒤에 오는 이 규칙이 이긴다. 요소 선택자를 늘리는 것보다 옮기기 쉽다. */
.note-text.note-text {
  font-family: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', system-ui, -apple-system, sans-serif;
  letter-spacing: -0.005em;
  font-size: 13.5px;
  line-height: 1.6;
  text-align: left;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  word-break: normal;
}

/* 「내 정보」의 자기소개·올해 목표 — 본인이 고치는 자리 (2026-09-03 봉길님).
   구성원 모듈은 읽기만 하므로 입력칸은 여기에만 있다 */
/* ⚠ 글꼴·자간·크기·줄바꿈은 **.note-text 가 정한다.** 여기서 다시 적지 않는다 —
   특히 `font-family: inherit` 를 두면 ID 규칙이라 .note-text 를 이겨서,
   페이지가 clay 냐 아니냐에 따라 글꼴이 갈리고 줄바꿈이 달라진다 (2026-09-03 실측).
   여기는 **입력칸의 모양**(테두리·여백·배경)만 맡는다. */
#gnbProfileIntro,
#gnbProfileGoal {
  width: 100%;
  /* 글이 흐르는 폭을 구성원 화면과 같게 — 안쪽여백 12×2 와 테두리 2 를 더한 값이 상자 폭이다 */
  max-width: calc(var(--note-line-width) + 26px);
  padding: 9px 12px;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  background: var(--modal-bg, #fff);
  color: var(--text-primary);
  resize: vertical;
  outline: none;
}

#gnbProfileIntro:focus,
#gnbProfileGoal:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(164, 143, 212, 0.1);
}

.profile-note-count {
  margin-top: 4px;
  text-align: right;
  color: var(--text-tertiary);
  font-size: 11.5px;
}

.profile-note-year {
  color: var(--text-tertiary);
  font-weight: 400;
}

.profile-hr-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  /* ⚠ form-grid 클래스를 함께 단다 — .modal-body .form-group + .form-group 의
     margin-top:16px 이 두 번째 칸만 밀어 내려 라벨 줄이 어긋난다 (실측 582 vs 598).
     그 해제 규칙이 .form-grid 에 이미 있으므로 전용 규칙을 또 만들지 않는다 */
  align-items: start;
  /* 다만 위 칸(이메일)과의 간격은 직접 준다 — 위 규칙은 form-group 끼리만 걸려서
     form-grid 인 이 줄에는 안 붙는다. 실측 0px 로 이메일 칸에 붙어 있었다 (2026-09-02) */
  margin-top: 16px;
}

/* 사진 확대·위치 — 회사 로고와 같은 조작이다 (2026-09-02 봉길님).
   미리보기는 저장과 같은 캔버스로 그리므로, 보이는 그대로가 저장된다 */
.profile-zoom-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  max-width: 260px;
}

.profile-zoom-row label {
  font-size: 12px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.profile-zoom-row input[type="range"] {
  flex: 1;
  accent-color: #a48fd4;
}

.profile-zoom-value {
  font-size: 12px;
  color: var(--text-secondary);
  width: 38px;
  text-align: right;
  flex-shrink: 0;
}

.profile-photo-hint {
  margin: 0;
  font-size: 11.5px;
  color: var(--text-secondary);
}

/* 끌어서 옮기는 중에 사진이 선택되지 않게 */
.profile-photo {
  touch-action: none;
  user-select: none;
}

/* ===== 레일 ↔ 패널 같은 격자 (B안, 2026-09-02 봉길님) =====
   지금까지는 레일 첫 항목과 패널 첫 메뉴가 14px 어긋났고, 아래로 갈수록 더 벌어졌다.
   항목 높이(--nav-item-h)와 간격(--nav-item-gap)을 한 값으로 묶어 두 열이 같은 줄에 선다.
   ⚠ 위 여백은 **레일에서만** 준다(--nav-top). 양쪽에서 각자 주면 한쪽을 고칠 때 또 어긋난다 */
.sidebar-nav > span.sidebar-pending {
  height: var(--panel-item-h);   /* 눌리는 항목과 같은 높이여야 줄이 안 어긋난다 */
  box-sizing: border-box;
  margin: 0 8px var(--nav-item-gap);
}

/* 하위 메뉴는 격자 밖이다 — 접혀 있다 펼쳐지는 것이라 같은 리듬을 강요하지 않는다 */
.sidebar-sub {
  margin-bottom: var(--nav-item-gap);
}

/* 기본 로고(회사 로고 미등록)의 아이콘을 레일 아이콘과 같은 세로선에 둔다.
   회사 로고를 올린 경우는 로고칸(208px)을 꽉 채우므로 건드리지 않는다 (2026-09-02 봉길님) */
.gnb-logo:has(.gnb-logo-icon) {
  padding-left: calc((var(--rail-w) - 36px) / 2);
}

/* 좌측 메뉴 판 — 결재처럼 clay 를 쓰는 화면에서 본문과 구분한다
   (2026-09-02 봉길님: 「메뉴부분도 그냥 구분선 넣고 배경색을 다르게」).
   ⚠ clay.css 는 비유바움 운영 화면이 함께 쓰므로 건드리지 않고, 여기서 덧입힌다 */
/* ⚠ clay.css 가 style.css **뒤에** 실린다. 같은 특정성으로 쓰면
   `html[data-skin="clay"] .sidebar { background: transparent; border-right: none }` 에
   덮여 아무 일도 안 일어난다(실측: 배경 rgba(0,0,0,0) · 구분선 0px).
   그래서 부모(.body-wrap)를 한 단계 더 붙여 특정성을 올린다 */
/* ⚠ 2026-09-04: 색·구분선은 **<html> 의 띠**(html[data-shell]::after)가 맡는다.
   여기서 또 칠하면 같은 반투명이 두 번 얹혀 clay 화면만 더 밝아진다(실측).
   띠는 본문 파싱 전에 그려지므로 「메인메뉴 배경이 늦게 채워진다」도 함께 없앤다 */
html[data-skin="clay"] .body-wrap > .sidebar {
  background: transparent;
  border-right: none;
}

html[data-skin="clay"] body > .gnb-rail {
  border-right: 1px solid rgba(90, 80, 120, 0.14);
}

/* ===== 주민등록번호 검증 메시지 (2026-09-04) =====
   입력칸 바로 아래. 오류는 붉게, 「확인 필요」는 주황으로 — 둘을 같은 색으로 두면
   2020-10 이후 발급분(검증번호가 원래 안 맞는다)이 오류처럼 보인다. */
.rid-msg {
  display: none;
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
}
.rid-msg.is-error { display: block; color: var(--danger); }
.rid-msg.is-warn { display: block; color: var(--warning); }

/* ---------- 눌러서 여는 작은 목록 ----------
   「이동 ▾」처럼 **고르는 순간 실행되는** 자리에 쓴다.
   ⚠ 고르는 칸(select)과 실행 단추를 나누면 기본값이 남아 잘못 눌리기 쉽다 —
     안 고르고 눌러도 맨 앞 폴더로 가버렸다 (2026-09-04 봉길님: 「실수하기 딱인데」). */
.menu-anchor { position: relative; display: inline-flex; }

/* ⚠ **화면 기준(fixed)** 으로 띄운다. 도구줄이 overflow:auto 라 그 안에 절대배치하면
   36px 짜리 띠에 잘려 목록이 아예 안 보였다 (2026-09-04 실측). 좌표는 JS 가 단추에서 잰다 */
.menu-pop {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2100;
  min-width: 168px;
  max-height: 292px;
  overflow-y: auto;
  padding: 4px;
  /* ⚠ 흰색을 **못박는다**. clay 가 --bg-primary 를 반투명으로 바꿔 놓아
     변수를 쓰면 목록 글자가 메뉴를 뚫고 비친다 (2026-09-04 실측 rgba(255,255,255,.55)).
     로그인 화면 모달에서 같은 일을 겪고 같은 방법으로 막았다 */
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
}

.menu-pop-head {
  padding: 6px 10px 4px;
  color: var(--text-tertiary);
  font-size: 11.5px;
}

.menu-pop-item {
  display: block;
  width: 100%;
  height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 12.5px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.menu-pop-item:hover { background: var(--btn-ink-tint); }
/* 지금 쓸 수 없는 항목은 흐리게 — 「눌러도 아무 일이 없다」를 만들지 않는다 (2026-09-11) */
.menu-pop-item:disabled { opacity: 0.35; cursor: default; }
.menu-pop-item:disabled:hover { background: none; }
.menu-pop-sep { height: 1px; margin: 4px 6px; background: var(--border-light); }
/* 항목이 많은 판은 **두 칸**으로. 한 칸으로 늘어놓으면 max-height(292)에 걸려 아래가 잘린다
   — 2026-09-11 표 편집 판(11항목 ≈ 370px)에서 「테두리색·칸 배경」이 안 보였다.
   한 줄을 통째로 쓰고 싶은 항목에는 .is-wide */
.menu-pop-2col { display: grid; grid-template-columns: repeat(2, minmax(92px, 1fr)); column-gap: 2px; }
.menu-pop-2col .menu-pop-item.is-wide { grid-column: 1 / -1; }

/* 지우는 항목은 글자만 붉게. 바탕까지 칠하면 메뉴 안에서 그것만 단추처럼 튄다 */
.menu-pop-item.is-danger { color: var(--danger); }
.menu-pop-item.is-danger:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }

/* 색 고르개 — .menu-pop 안에 얹는 색 알 여섯.
   ⚠ **mail/index.html 안에 갇혀 있던 것을 글로벌로 올렸다** (2026-09-10).
     메일 폴더 이름표 색이 이 클래스를 쓰는데 규칙이 그 페이지에만 있어,
     같은 클래스를 쓴 일정 화면에서는 색 알이 통째로 안 보였다.
     한 부품을 두 모듈이 쓰면 규칙은 글로벌에 있어야 한다 */
.menu-pop-colors { display: flex; gap: 7px; padding: 4px 10px 8px; }
.menu-pop-color {
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1px solid rgba(90, 80, 120, 0.14);
  border-radius: 50%;
  cursor: pointer;
}
/* 고른 색은 테두리 한 겹을 띄워 표시한다 — 안쪽 색을 가리지 않는다 */
.menu-pop-color.is-on { box-shadow: 0 0 0 2px var(--bg-primary), 0 0 0 3.5px var(--text-tertiary); }

/* ⋮ 단추 — 「이 줄/이 글에 할 수 있는 일」을 여는 자리. 메일 폴더 줄과 게시판 글 머리가
   같은 모양을 쓴다 (2026-09-05). 세로 점 셋은 가로 자리를 덜 먹는다 */
.menu-dots {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-tertiary);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.menu-dots:hover { background: var(--sidebar-hover); color: var(--text-primary); }
.menu-dots[aria-expanded="true"] { background: var(--sidebar-hover); color: var(--text-primary); }

/* 되돌릴 수 있는 토스트 — 되돌리기 단추가 붙으면 스스로 사라지지 않고 JS 가 시간을 잰다 */
.toast--action { animation: toastIn 0.3s ease; }

.toast-action {
  margin-left: 14px;
  height: 24px;
  padding: 0 10px;
  border: 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.22);
  color: inherit;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.toast-action:hover { background: rgba(255, 255, 255, 0.34); }

/* =========================================================
   날짜 고르개 — 우리 톤의 작은 달력 (js/date-picker.js)
   2026-09-04 봉길님: 「캘린더 피커 스타일도 기본형이 아닌 우리 제품 스타일에 맞는 형태면」
   ⚠ 「캘린더 피커 금지」는 브라우저 기본 input[type=date] 를 말한다. 이것은 우리가 그린다.
   ⚠ data-date-picker 가 붙은 칸에만 단추가 생긴다 — 필터·목록의 날짜 칸은 그대로다
   ========================================================= */
.dp-wrap {
  position: relative;
  display: block;
}
/* 단추가 글자를 가리지 않게 오른쪽을 비워 둔다 */
.dp-wrap > input { padding-right: 36px; }

/* ⚠ 오른쪽을 비워 두기만 하고 칸을 넓히지 않아 **「YYYY-MM-DD」가 잘렸다**
   (2026-09-06 실측). 글로벌 폭이 120px 인데 그건 단추가 없던 시절의 값이다 —
   padding 12 + 36 을 빼면 글자 자리가 72px 밖에 안 남는다(단추 없을 때는 96px).
   글자 자리를 원래대로 96px 로 돌려놓는다: 96 + 12 + 36 = 144.
   ⚠ 페이지에서 고치지 않는다 — 단추를 붙인 칸이면 어디서나 같은 문제다
     (게시판 글쓰기·결재 기안·부재 설정이 이미 이 부품을 쓴다) */
.dp-wrap > input[data-date-auto-format] { width: 144px; }

/* ⚠ **폼 안에서는 날짜 칸도 다른 칸처럼 격자를 채운다.**
   위 144px 은 (0,2,1) 이라 `.ap-field input { width:100% }`(0,1,1) 를 이긴다. 그래서 결재 기안
   폼에서 지출일만 짧아졌고, 감싸개(.dp-wrap)는 block 이라 칸 전체 폭을 차지하니
   달력 단추가 그 오른쪽 끝 — **칸에서 뚝 떨어져** 섰다
   (2026-09-08 봉길님: 「칩이 짧고 날짜 선택 버튼은 왜 저렇게 칩 밖에 있지」).
   ⚠ 필터·기간 칸(결재위임의 「자리를 비우는 기간」 등)은 flex 안이라 감싸개가 칸 폭을 따르므로
     지금도 단추가 칸 안에 있다 — 그쪽은 짧은 것이 맞다. 폼 격자만 바로잡는다. */
.ap-field .dp-wrap > input[data-date-auto-format] { width: 100%; }

.dp-open {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.dp-open:hover { background: rgba(15, 23, 42, 0.06); color: var(--text-secondary); }
.dp-open svg { width: 15px; height: 15px; pointer-events: none; }

.dp-pop {
  position: fixed;
  /* ⚠ **어떤 창 안에서 열리든 맨 위**여야 한다 (2026-09-10 봉길님: 「시간 선택할 때
     화면 뒤로 빠지는 부분」). 400 은 모달(1000)·토스트(2000)·팝오버(2100)·일정 등록 창(2200)
     보다 **낮아서**, 그 위에서 고르개를 열면 통째로 뒤로 깔렸다 — 일정 화면만의 문제가 아니라
     모달 안 날짜 칸도 같았다. 고르개보다 위에 있어야 하는 것은 없다 */
  z-index: 2300;
  width: 258px;
  padding: 10px;
  background: var(--modal-bg);
  border: 1px solid var(--border-color);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.16);
  font-family: var(--font-stack);
}

.dp-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 2px 8px;
}
.dp-head .dp-title {
  flex: 1;
  text-align: center;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}
.dp-nav {
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
}
.dp-nav:hover { background: var(--bg-tertiary); color: var(--text-primary); }

.dp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.dp-dow {
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--text-tertiary);
}
.dp-dow.dp-sun { color: #e06a6a; }
.dp-dow.dp-sat { color: #6a86e0; }

.dp-day {
  height: 30px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--text-primary);
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
}
.dp-day:hover { background: var(--bg-tertiary); }
/* 이번 달이 아닌 날 — 지우지 않고 흐리게 둔다. 달을 넘길 때 자리가 흔들리지 않는다 */
.dp-day.dp-out { color: var(--text-tertiary); opacity: 0.55; }
/* 오늘은 테두리로만 — 고른 날과 헷갈리지 않게 */
.dp-day.dp-today { box-shadow: inset 0 0 0 1px var(--accent); }
/* 쉬는 날 — 공휴일과 일요일은 **글자를 빨갛게** (2026-09-04 봉길님).
   점 같은 표시를 덧붙이지 않는다. 이름은 title 로만 단다(칸이 30px 이라 적을 자리가 없다) */
.dp-day.dp-off { color: #e06a6a; }
.dp-day.dp-off.dp-out { color: #e06a6a; opacity: 0.4; }
.dp-day.dp-on {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  box-shadow: none;
}


.dp-foot {
  display: flex;
  gap: 6px;
  padding-top: 8px;
  margin-top: 6px;
  border-top: 1px solid var(--border-light);
}
.dp-quiet {
  flex: 1;
  height: 30px;
  border: 1px solid var(--border-color);
  border-radius: 9px;
  background: var(--bg-primary);
  color: var(--text-secondary);
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
}
.dp-quiet:hover { border-color: var(--accent); color: var(--accent); }

/* =========================================================
   시각 고르개 (js/time-picker.js) — 날짜 고르개와 같은 결
   2026-09-05 봉길님: 「시간 피커도 만드는게 어떨까?」
   ⚠ data-time-picker 가 붙은 칸에만 단추가 생긴다(opt-in)
   ========================================================= */
.tp-wrap { position: relative; display: block; }
.tp-wrap > input { padding-right: 36px; }

.tp-open {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tp-open:hover { background: rgba(15, 23, 42, 0.06); color: var(--text-secondary); }
.tp-open svg { width: 15px; height: 15px; pointer-events: none; }

.tp-pop {
  position: fixed;
  /* ⚠ **어떤 창 안에서 열리든 맨 위**여야 한다 (2026-09-10 봉길님: 「시간 선택할 때
     화면 뒤로 빠지는 부분」). 400 은 모달(1000)·토스트(2000)·팝오버(2100)·일정 등록 창(2200)
     보다 **낮아서**, 그 위에서 고르개를 열면 통째로 뒤로 깔렸다 — 일정 화면만의 문제가 아니라
     모달 안 날짜 칸도 같았다. 고르개보다 위에 있어야 하는 것은 없다 */
  z-index: 2300;
  /* 열 안 스크롤바가 10px 을 먹는다(실측) — 그만큼 넓게 잡아야 숫자가 가운데 선다 */
  width: 176px;
  padding: 8px;
  background: var(--modal-bg);
  border: 1px solid var(--border-color);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.16);
  font-family: var(--font-stack);
}

/* 시 / 분 두 열. 가운데 선으로 나눈다 */
.tp-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.tp-col {
  height: 196px;
  overflow-y: auto;
  scrollbar-width: thin;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tp-col:first-child { border-right: 1px solid var(--border-light); padding-right: 6px; }
.tp-col::-webkit-scrollbar { width: 5px; }
.tp-col::-webkit-scrollbar-thumb { background: rgba(120, 110, 130, 0.28); border-radius: 3px; }

.tp-item {
  flex: none;
  height: 30px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-primary);
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
}
.tp-item:hover { background: var(--bg-tertiary); }
.tp-item.tp-on { background: var(--accent); color: #fff; font-weight: 600; }

.tp-foot { padding-top: 8px; margin-top: 6px; border-top: 1px solid var(--border-light); }
.tp-quiet {
  width: 100%;
  height: 30px;
  border: 1px solid var(--border-color);
  border-radius: 9px;
  background: var(--bg-primary);
  color: var(--text-secondary);
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
}
.tp-quiet:hover { border-color: var(--accent); color: var(--accent); }

/* ===== 표준 화면 틀 — 「틀은 잠그고 안쪽만 굴린다」 (2026-09-06) =====
   메일에서 확립한 뼈대(여백 16×4 · 틀 잠금 · 목록만 스크롤)를 **글로벌 부품**으로 뽑았다.
   전에는 페이지마다 같은 <style> 블록을 베껴 넣었다 — 한 곳을 고치면 나머지가 뒤처졌고,
   실제로 게시판·메일만 표준이고 결재 일부·근태·구성원은 예전 여백(24/24/48)에 머물러 있었다.

   쓰는 법
     <html lang="ko" data-shell data-frame>            ← 이 한 글자로 틀이 잠긴다
     <main class="main-content"> … </main>             ← 여백 16×4 · 세로 flex
     굴러갈 자리에  class="page-scroll"                 (flex:1 · min-height:0 · overflow-y:auto)
     남는 자리를 채울 카드에 class="page-fill"          (그 안에서 머리·목록·꼬리를 다시 나눈다)

   ⚠ 굴러갈 자리를 안 정하면 내용이 길 때 **잘린다.** 틀을 잠그는 일과 한 쌍이다.
   ⚠ 결재의 분할 화면(.ap-split)은 제 CSS 가 이미 같은 값을 갖고 있어 건드리지 않는다.
   ⚠ 특정성 — clay.css 가 `html[data-skin="clay"] .main-content:not(.ap-split)`(0,3,1)로
     아래 여백 48 을 못박는다. 그래서 .main-content 를 두 번 적어 (0,4,1) 로 올린다.
   ⚠ max-width 는 건드리지 않는다. 읽는 폭을 1000px 로 좁혀 둔 화면(결재 문서·양식)이 있다 */
html[data-frame], html[data-frame] body { height: 100%; overflow: hidden; }

html[data-frame] .body-wrap { height: calc(100vh - var(--gnb-height)); min-height: 0; }

html[data-frame] .main-content.main-content:not(.ap-split) {
  height: calc(100vh - var(--gnb-height));
  /* 네 방향 모두 16 — 레일 첫 항목·메인메뉴 첫 항목의 위 여백과 같은 선 */
  padding: 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* 감춘 것은 감춘 채로 — 아래 규칙들이 display 를 주므로 [hidden] 이 밀리지 않게 못박는다 */
html[data-frame] [hidden] { display: none !important; }

/* 남는 자리를 차지하되 **안에서 다시 위아래로 나누는** 칸 (도구줄 + 목록 등) */
html[data-frame] .page-col {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* 머리줄·도구줄은 눌리지 않는다 — 세로 flex 안에서 기본값(flex-shrink:1)이면
   내용이 길 때 이것들부터 찌그러진다 */
html[data-frame] .main-content > .page-header,
html[data-frame] .main-content > .toolbar,
html[data-frame] .page-col > .toolbar { flex: none; }

html[data-frame] .page-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* 굴러가는 표의 머리줄은 붙어 있는다 — 배경은 위 `.table-scroll thead th` 가 이미 칠한다.
   ⚠ `.table-scroll` 로 한정한다. 글 본문·결재 문서 안에 사람이 넣은 표까지 머리줄이
     달라붙으면 읽는 데 방해가 된다 */
html[data-frame] .table-scroll.page-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 4;
}

/* 카드 **안**에서 굴러가는 자리의 스크롤바 — 카드 오른쪽 가장자리에 딱 붙인다.
   ⚠ 기본 thumb 은 `border: 2px solid transparent` + `background-clip: content-box` 라
     좌우 2px 이 비고 그 자리로 카드 배경이 비친다. 카드 밖에서는 안 보이지만
     **카드 가장자리에서는 색 배경과 맞닿아 흰 띠로 도드라진다**
     (2026-09-08 봉길님: 「스크롤바 우측에 흰색 여백은 왜 있지?」 — 실측 2px).
     폭을 6 으로 줄이고 thumb 이 그 6 을 꽉 채우게 한다. 고친 뒤 실측: 흰 띠 0px */
html[data-frame] .page-fill .page-scroll::-webkit-scrollbar { width: 6px; }
html[data-frame] .page-fill .page-scroll::-webkit-scrollbar-thumb {
  border: 0;
  background-clip: border-box;
  border-radius: 6px;
}

/* 남는 자리를 전부 차지하는 카드. `.card` 의 아래 margin 16 을 지운다 —
   남겨 두면 위 16 · 아래 32 로 벌어진다 */
html[data-frame] .page-fill {
  flex: 1;
  min-height: 0;
  margin-bottom: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ===================================================================
   일정(달력) — 월 격자 (2026-09-10 봉길님 A안 확정)

   목록 카드(.list-card)와 **같은 부품**을 쓰고, 굴러가는 목록이 들어갈 자리에
   달력 격자가 앉는다. 「한 화면 = 한 장」 — 한 달이 스크롤 없이 통째로 보인다.

   ⚠ 첫 가로 구분선은 결재·메일·게시판과 **같은 y(133.67)** 에 서야 한다
     (카드위 80 + .list-card 패딩 9 + 도구줄 34 + 아래 10 + 테두리 0.67).
     그래서 도구줄에 .view-toggle(35)·.btn(35) 을 두지 않는다 — 그것들을 쓰면
     도구줄이 46.33 이 되어 구분선이 136 으로 내려간다(2026-09-10 실측).
     보기 전환·「오늘」은 메일과 같은 **칩(.list-chip, 28)** 이다.

   ⚠ 좌우 안쪽 여백 16 은 요일 머리줄(.list-bulk)과 달력 몸통(.cal-body)이 **같이** 써야 한다.
     한쪽만 고치면 요일 이름이 날짜 열 중심에서 벗어난다(고치기 전 실측 5.44px).
   =================================================================== */

/* 달력은 안이 굴러가지 않는다 — 목록은 굴러가므로 머리줄에도 스크롤바 자리를 비워
   세로선을 맞추지만(scrollbar-gutter: stable), 달력에서 그 자리를 비워 두면
   **요일 머리줄만 그만큼 좁아진다.** 그래서 달력 카드에서만 되돌린다 */
.cal-card .list-bulk { scrollbar-gutter: auto; overflow: visible; }

/* 목록 보기 — [날짜 190][내용 1fr][이름 170]. 머리줄(.list-cols)과 줄(.list-line)이
   이 한 줄을 같이 본다. 한쪽만 고치면 그날로 세로선이 어긋난다 */
.cal-card { --lc-cols: 190px 1fr 170px; }
.cal-card .list-line > :nth-child(1) { color: var(--text-secondary); font-size: 12.5px; }
.cal-card .list-line > :nth-child(3) { color: var(--text-secondary); font-size: 12.5px; }

/* 도구줄 왼쪽 — [월|주|목록] · ‹ 2026년 9월 › · 오늘 */
.cal-nav { display: flex; align-items: center; gap: 8px; }
.cal-nav .cal-mon {
  display: flex;
  align-items: center;
  gap: 2px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-primary);
}
/* 「‹ 제목 ›」 — 제목이 화살표 사이 가운데 (2026-09-10 봉길님이 시안 C 를 고르심).
   ⚠ 폭을 **가장 긴 문구**에 못박는다. 안 그러면 주를 넘길 때마다 화살표가 움직인다.
     실측(같은 글꼴·굵기로 재 봄):
       월 「2026년 12월」 78 · 일 「2026년 12월 31일 (수)」 139.2 ·
       주(같은 달) 141.2 · 주(달 걸침) 167.1 · **주(두 자리 달) 「2026년 11월 30일 – 12월 6일」 182.6**
     ⚠ **좌우 padding(6+6)까지 더해야 한다.** 182.6 만 보고 190 으로 잡았더니 그 주에서만
       오른쪽 화살표가 4.6px 밀렸다(실측) → 182.6 + 12 = 194.6 → **196**.
       시안에서 168 → 190 → 196 으로 두 번 재서 잡았다 */
.cal-nav .cal-mon { gap: 6px; }
.cal-nav .cal-mon > b {
  font-weight: 700;
  white-space: nowrap;
  min-width: 196px;
  padding: 0 6px;
  text-align: center;
}

/* 포커스 표시 — 브라우저 기본 outline 은 우리 톤이 아니다 (2026-09-10 봉길님:
   「이 부분 표시 방법 좀 어떻게 안될까 이상하다」 — 누른 화살표에 동그라미가 남았다).
   ⚠ 없애지 않는다. 키보드로 옮겨 다니는 사람에게는 **지금 어디 있는지** 알려주는 유일한 표시다 */
.cal-arrow:focus { outline: none; }
.cal-arrow:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-primary), 0 0 0 4px var(--accent);
}
.cal-nav .cal-arrow {
  width: 26px;
  height: 26px;
  flex: none;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
}
.cal-nav .cal-arrow:hover { background: var(--bg-tertiary); color: var(--text-primary); }

/* 요일 머리줄 — .list-bulk 안에 7열로 앉는다 */
.cal-dows { display: grid; grid-template-columns: repeat(7, 1fr); width: 100%; }
.cal-dows > span { font-size: 12px; color: var(--text-tertiary); text-align: center; }
.cal-dows > span.is-sun { color: #e06a6a; }
.cal-dows > span.is-sat { color: #6a86e0; }

/* 달력 몸통 — 주가 남는 자리를 고르게 나눠 갖는다.
   ⚠ 높이는 CSS 가 책임진다. JS 는 「한 칸에 몇 개를 그릴지」만 센다 */
.cal-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 0 16px;   /* .list-bulk · .list-body 와 같은 값 — 위 ⚠ 참고 */
}

.cal-week {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* 아래 가르는 선을 **border 로 주지 않는다.** 그 1px 이 레이아웃에 들어가
     마지막 주만 0.66px 낮아졌다(실측). box-shadow 는 자리를 차지하지 않는다 */
  box-shadow: inset 0 -1px 0 var(--border-light);
  /* 날짜 칸을 가르는 세로선 — 칸마다 border 를 주면 숫자줄에만 생기고 일정 자리에서 끊긴다.
     배경으로 그어 두 줄을 관통하게 한다. 왼쪽 첫 선은 카드 안쪽 여백과 겹치므로 1px 밀어 감춘다 */
  background-image: linear-gradient(to right, var(--border-light) 1px, transparent 1px);
  background-size: calc(100% / 7) 100%;
  background-position: -1px 0;
}
.cal-week:last-child { box-shadow: none; }

/* 날짜 숫자 줄 */
.cal-nums { display: grid; grid-template-columns: repeat(7, 1fr); flex: none; }
.cal-num {
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: var(--text-secondary);
}
.cal-num.is-sun, .cal-num.is-off { color: #e06a6a; }
.cal-num.is-sat { color: #6a86e0; }
/* 이번 달이 아닌 날 — 지우지 않고 흐리게 둔다. 달을 넘길 때 자리가 흔들리지 않는다 */
.cal-num.is-out { opacity: 0.4; }
/* 오늘은 **채운다.** 날짜 피커(.dp-today)는 「고른 날」과 헷갈리지 않게 테두리만 두르지만
   달력에는 고르는 개념이 없어 다툴 상대가 없다 */
.cal-num.is-today > i {
  font-style: normal;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}

/* 일정 자리 — 7열 격자. 여러 날 일정은 grid-column span 으로 이어 붙인다 */
.cal-evs {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-auto-rows: var(--cal-ev-h, 21px);
  row-gap: 2px;
  padding: 0 0 4px;
  overflow: hidden;
}

/* 일정 한 줄 — 셀 안 배지는 한 줄 강제 (두 줄로 넘기지 않는다) */
.cal-ev {
  display: block;
  min-width: 0;
  margin: 0 4px;
  padding: 0 7px;
  height: 19px;
  line-height: 19px;
  border-radius: 5px;
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-decoration: none;
  cursor: pointer;
}
/* 여러 날에 걸친 일정은 **한 덩어리가 여러 칸을 가로지른다**(grid-column: span N).
   날마다 조각을 만들어 이어 붙이지 않는다 — 조각 사이에 이음매가 보이고 글자도 조각마다 잘린다.
   주 경계에서만 끊기므로, 그 끊긴 쪽 모서리를 펴서 「이어진다」고 알린다 */
/* ⚠ 이어지는 쪽의 **여백은 그대로 두고 모서리만** 편다 (2026-09-10 봉길님: 「줄이 왜 안맞냐?」).
   margin 을 0 으로 지웠더니 지난주에서 이어진 칩만 4px 왼쪽으로 나가,
   같은 날 시작하는 칩과 **글자 시작점이 어긋났다.** 한 화면에서 줄이 안 맞아 보이는 원인이었다.
   모서리를 각지게 두는 것만으로 「여기서 끊긴 게 아니라 이어진다」는 뜻은 충분히 전해진다 */
.cal-ev.is-cut-l { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.cal-ev.is-cut-r { border-top-right-radius: 0; border-bottom-right-radius: 0; }

/* 색은 근태기록의 배지에서 **그대로** 가져왔다 — 같은 것이 화면마다 다른 색이면 두 얼굴이 된다.
   연차·휴가 = .badge-leave · 출장·외근 = .badge-blue · 공휴일 = .badge-danger ·
   교육·검진 = .badge-emerald · 사람이 적은 일정 = 강조색 옅은 면 */
.cal-ev.is-leave   { background: #fff3e0; color: #9a5b00; }
.cal-ev.is-trip    { background: #eef3fb; color: #1d4a80; }
.cal-ev.is-holiday { background: #fdeeee; color: #a32020; }
.cal-ev.is-edu     { background: var(--bg-tertiary); color: var(--text-secondary); }
.cal-ev.is-event   { background: var(--accent-light); color: #5b4a8a; }
.cal-ev.is-birthday { background: #e7f7ef; color: #00794a; }   /* 생일 = .badge-active */

/* 칸에 못 담은 개수 — 「+2개 더」. 칸을 넘기지 않는다 */
.cal-more {
  margin: 0 4px;
  padding: 0 6px;
  height: 19px;
  line-height: 19px;
  font-size: 11.5px;
  color: var(--text-tertiary);
  background: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}
.cal-more:hover { color: var(--accent); }

/* ===================================================================
   주 보기 — 좌측 시간축 (2026-09-10 봉길님: 「주 단위로 보일 때는 시간축도 좌측에」)

   ⚠ 요일 머리줄(.list-bulk) · 종일 띠(.cal-allday) · 시간 격자(.cal-hgrid) 셋이
     **같은 열 자리**를 써야 한다. 열 폭은 여기 한 곳(--cal-time-w)에서만 정한다.
   ⚠ 주 보기는 시간 격자가 굴러간다. 그 스크롤바 폭만큼 7열이 좁아지는데 위 두 줄에는
     그 자리가 없어 오른쪽으로 갈수록 벌어졌다(실측 0.43 → 5.58px). 셋 모두 같은 자리를
     예약해 맞춘다. **월 보기는 정반대**다 — 아무것도 안 굴러가므로 그 자리를 비우지 않는다.
   =================================================================== */
/* --cal-cols : 시간축 오른쪽 열 수. 주 보기 7 · 일 보기 1.
   요일 머리줄·종일 띠·시간 격자가 **이 하나**를 같이 본다 — 한 곳에서만 정한다 */
.cal-card { --cal-time-w: 58px; --cal-hour-h: 44px; --cal-cols: 7; }
.cal-card[data-view="day"] { --cal-cols: 1; }

.cal-card[data-view="week"] .cal-dows,
.cal-card[data-view="day"] .cal-dows { grid-template-columns: var(--cal-time-w) repeat(var(--cal-cols), 1fr); }
.cal-card[data-view="week"] .list-bulk,
.cal-card[data-view="day"] .list-bulk { scrollbar-gutter: stable; overflow-y: auto; }

/* 종일 띠 — 날짜 숫자 + 종일 일정(연차·출장·공휴일).
   월 보기의 한 주와 **같은 부품**(.cal-nums / .cal-evs / .cal-ev)을 그대로 쓴다 */
.cal-allday {
  display: grid;
  grid-template-columns: var(--cal-time-w) repeat(var(--cal-cols), 1fr);
  flex: none;
  padding: 0 16px;
  /* 종일 일정이 많아도 시간 격자를 밀어내지 않는다 — 세 줄까지 보이고 넘치면 안에서 굴린다 */
  max-height: 118px;
  overflow-y: auto;
  scrollbar-gutter: stable;
  box-shadow: inset 0 -1px 0 var(--border-light);
}
.cal-allday > .cal-allday-label {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 8px;
  color: var(--text-tertiary);
  font-size: 11px;
}
.cal-allday > .cal-allday-body { grid-column: 2 / -1; min-width: 0; }
.cal-allday .cal-nums,
.cal-allday .cal-evs { grid-template-columns: repeat(var(--cal-cols), 1fr); }
/* 빈 자리를 누르면 그 날짜로 종일 일정을 적는다 — 누를 수 있다는 것이 보여야 한다.
   ⚠ 월 보기의 .cal-evs 는 해당 없다(거기는 칸 자체가 누르는 자리다) */
.cal-allday .cal-evs { min-height: 46px; padding-bottom: 6px; cursor: pointer; }

/* 시간 격자 — 카드 안에서 여기만 굴러간다 */
.cal-hours {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-gutter: stable;
  padding: 0 16px;
  position: relative;
}
.cal-hgrid {
  display: grid;
  grid-template-columns: var(--cal-time-w) repeat(var(--cal-cols), 1fr);
  position: relative;
}
/* 시간 이름표 — 글자 중심이 그 시각의 **가로선 위**에 온다(구글과 같다).
   첫 줄은 격자 맨 위 선이라 이름표를 감춘다 — 위로 잘려 반쪽만 보인다 */
.cal-hour-label {
  grid-column: 1;
  height: var(--cal-hour-h);
  display: flex;
  justify-content: flex-end;
  padding-right: 8px;
  color: var(--text-tertiary);
  font-size: 11px;
  transform: translateY(-6px);
}
.cal-hour-label:first-child { visibility: hidden; }

/* 한 시간 칸 — 30분 자리에 옅은 눈금을 넣어 「반」이 보이게 한다 */
/* ⚠ 30분 눈금은 **두지 않는다** (2026-09-10 봉길님: 「30분 단위 격자도 빼자」).
   한 시간마다 한 줄이면 충분하고, 반 칸 선이 있으면 격자가 촘촘해 시끄럽다 */
.cal-hour-cell {
  height: var(--cal-hour-h);
  box-shadow: inset 0 -1px 0 var(--border-light), inset -1px 0 0 var(--border-light);
  cursor: pointer;
}
/* 오늘 열은 아주 옅게 깔아 둔다 */
.cal-hour-cell.is-today { background-color: rgba(164, 143, 212, 0.045); }
/* ⚠ 호버는 **오늘 칸까지 눌러 이겨야** 한다 (2026-09-10 봉길님: 「오늘은 색이 겹쳐서 보이지가 않는군」).
   `.cal-hour-cell:hover` 와 `.cal-hour-cell.is-today` 는 특정성이 같아(0,2,0) 나중에 선언된
   쪽이 이긴다 — 오늘 열에서는 호버가 통째로 묻혔다. 겹친 선택자를 같이 적고 **더 진하게** 한다 */
.cal-hour-cell:hover,
.cal-hour-cell.is-today:hover { background-color: rgba(164, 143, 212, 0.16); }

/* 시각이 있는 일정 — 격자 위에 얹는다. 자리는 JS 가 잰 좌표로 정한다 */
.cal-slot {
  position: absolute;
  z-index: 2;
  padding: 2px 7px;
  border-radius: 6px;
  background: var(--accent-light);
  color: #5b4a8a;
  /* ⚠ 왼쪽 색 띠를 **두지 않는다** (2026-09-10 봉길님: 「생성된 일정 앞에 띠지 좀 그렇네」).
     종일 칩(.cal-ev)은 배경만으로 칠하는데 시각 블록에만 띠가 붙어 두 얼굴이 됐다.
     색은 배경이 이미 말한다 */
  font-size: 11.5px;
  line-height: 1.35;
  overflow: hidden;
  cursor: pointer;
}
/* ⚠ 제목은 **한 줄로 자른다.** 두 줄이 되면 한 시간짜리 블록(44px) 안에서
   아래 시각이 밀려 잘린다(2026-09-10 실측 — 「14:00~15:00」이 반쯤 잘렸다).
   구글도 짧은 블록에서는 제목을 한 줄로 줄인다 */
.cal-slot b {
  display: block;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-slot span { display: block; color: var(--text-secondary); font-size: 11px; }

/* 지금 시각 — 오늘 열에만 선다 */
.cal-now { position: absolute; z-index: 3; height: 0; border-top: 1.5px solid #e0524a; }
.cal-now::before {
  content: "";
  position: absolute;
  left: -4px;
  top: -4.5px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #e0524a;
}

/* ===================================================================
   빠른 등록 — 구글캘린더 방식 (2026-09-10 봉길님: 「구글캘린더 일정등록 방식이 좋은듯」)
   칸을 누르면 **그 자리에** 작은 창이 뜬다. 제목만 적어도 저장된다.
   =================================================================== */
.cal-quick {
  position: absolute;
  z-index: 2200;
  /* 폭은 **한 줄에 들어가야 하는 것**이 정한다 (실측):
     아이콘 20 + 날짜칸 144 + 시각칸 86 + 물결 9 + 시각칸 86 + 간격 8×4 = 377
     + 좌우 패딩 32 = 409 → 412. 372 로 뒀더니 종료 시각 칸이 259px 잘렸다 */
  width: 412px;
  padding: 14px 16px 12px;
  /* ⚠ 흰색을 못박는다 — clay 가 --bg-primary 를 반투명으로 바꿔 놓아 뒤가 비친다 */
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: 14px;
  box-shadow: var(--shadow-md);
}
.cal-quick-title {
  width: 100%;
  height: 36px;
  margin: 0 0 10px;
  padding: 0 2px;
  border: 0;
  border-bottom: 2px solid var(--border-color);
  background: none;
  font-family: inherit;
  font-size: 16px;
  color: var(--text-primary);
}
.cal-quick-title::placeholder { color: var(--text-tertiary); }
.cal-quick-title:focus { outline: none; border-bottom-color: var(--accent); }

.cal-quick-row { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; }
/* ⚠ 줄 앞 아이콘은 **두지 않는다** (2026-09-10 봉길님: 「앞에 이모티콘 빼고」).
   달력·사람 그림이 없어도 칸이 무엇인지 값과 자리가 이미 말한다 */
.cal-quick-row input[type="text"] { height: 32px; }
/* 날짜·시각 고르개 — 감싸개만 좁히면 **안의 칸은 그대로**라 밖으로 삐져나온다
   (실측 줄넘침 108px). 감싸개에 폭을 주고 칸이 그 폭을 채우게 한다 */
.cal-quick-row .dp-wrap { width: 144px; flex: none; }   /* 글자 96 + 패딩 12 + 단추 36 */
.cal-quick-row .tp-wrap { width: 86px; flex: none; }    /* 「HH:mm」 다섯 글자 + 단추 */
.cal-quick-row .dp-wrap > input,
.cal-quick-row .tp-wrap > input { width: 100%; }
.cal-quick-row .cal-quick-tilde { color: var(--text-tertiary); font-size: 12.5px; }
.cal-quick-row label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--text-secondary);
  cursor: pointer;
}

/* 참석자 — 명부에서 골라 담는다 (2026-09-10 봉길님: 「구성원 정보로 참석자 검색해서 추가」).
   담긴 사람은 칩, 그 뒤에 이어서 타이핑한다. 후보 목록은 글로벌 .menu-pop 을 쓴다.
   ⚠ **타이핑을 시작해야** 후보가 뜬다 — 칸을 누른 것만으로 목록을 펼치지 않는다 */
.cal-att-box {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
  min-height: 32px;
  padding: 3px 8px;
  border: 1px solid var(--border-color);
  border-radius: 10px;
  background: var(--bg-primary);
  cursor: text;
}
.cal-att-box:focus-within { border-color: var(--accent); }
/* 칸은 남는 자리를 먹되 칩이 늘면 줄어든다 */
.cal-att-box > input {
  flex: 1;
  min-width: 90px;
  height: 24px;
  border: 0;
  padding: 0 2px;
  background: none;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--text-primary);
}
.cal-att-box > input:focus { outline: none; }
.cal-att {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 4px 0 9px;
  border-radius: 12px;
  background: var(--btn-ink-tint);
  color: var(--text-primary);
  font-size: 12px;
  white-space: nowrap;
}
.cal-att > button {
  width: 16px;
  height: 16px;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--text-tertiary);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
}
.cal-att > button:hover { background: rgba(15, 23, 42, 0.08); color: var(--text-primary); }
/* 후보 줄 — 이름 옆에 부서를 흐리게. 동명이인을 가르는 유일한 단서다 */
/* ⚠⚠ **일정 등록 창 위에서 열리는 것은 전부 여기 적는다.**
   창(.cal-quick)이 z-index 2200 이라, 그 위에서 여는 팝오버가 2100(.menu-pop 기본)이면
   **창 뒤로 깔려 반쯤 가려진다.** 2026-09-10 하루에 **세 번** 겪었다 —
   시각 고르개(.tp-pop) · 참석자 후보(.cal-att-pop) · 반복 목록(.cal-repeat-pop).
   새 팝오버를 만들면 **여기 이름을 더한다.** 한 줄이 빠지면 그날로 같은 증상이 난다.
   (날짜·시각 고르개는 모달 안에서도 쓰이므로 제 자리에서 이미 2300 이다) */
.cal-att-pop,
.cal-repeat-pop { z-index: 2300; }

/* 「다른 사람 일정 +」 고르개 (2026-09-10 봉길님: 「디자인이 안 이쁘다」).
   글로벌 .menu-pop 위에 얹는다 — 새 창을 짓지 않는다.
   구글캘린더의 「사용자 검색」 자리와 같은 구조: 맨 위 찾기 칸, 그 아래 팀·구성원.
   ⚠ 담기면 달력에서 **무슨 색으로 보일지** 점으로 미리 알린다. 이름만 늘어놓으면
     담고 나서야 색을 알게 되고, 그때는 이미 여럿이 섞여 있다 */
.cal-watch-pop { z-index: 2300; width: 268px; padding: 0; max-height: 360px; overflow: hidden; display: flex; flex-direction: column; }
.cal-watch-find {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 12px;
  border-bottom: 1px solid var(--border-light);
  color: var(--text-tertiary);
}
.cal-watch-find svg { width: 15px; height: 15px; flex: none; }
.cal-watch-find input {
  flex: 1;
  min-width: 0;
  height: 24px;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--text-primary);
}
.cal-watch-find input:focus { outline: none; }
.cal-watch-list { flex: 1; min-height: 0; overflow-y: auto; padding: 4px; }

/* 줄 — [색 점][이름 ······ 곁말] */
.cal-watch-pop .menu-pop-item {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 34px;
}
.cal-watch-pop .menu-pop-item .dot { width: 8px; height: 8px; border-radius: 3px; flex: none; }
.cal-watch-pop .menu-pop-item .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* 곁말 — 팀이면 인원수, 사람이면 부서. 동명이인·같은 이름 팀을 가르는 단서다 */
.cal-watch-pop .menu-pop-item .sub { flex: none; color: var(--text-tertiary); font-size: 11.5px; }
/* 묶음 머리는 첫 줄 위에서 여백을 덜 먹는다 */
.cal-watch-pop .menu-pop-head { padding: 8px 10px 3px; }
.cal-watch-pop .menu-pop-head:first-child { padding-top: 4px; }
.cal-watch-none { padding: 22px 12px; color: var(--text-tertiary); font-size: 12.5px; text-align: center; }
.menu-pop-item .cal-att-dept { color: var(--text-tertiary); font-size: 11.5px; margin-left: 6px; }

/* 고르개 단추 — 칸처럼 보이되 누르면 우리 팝오버가 열린다.
   .filter-select 를 그대로 입어 다른 칸과 높이·테두리가 같다 */
.cal-quick-pick {
  width: 100%;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5l3.5 3.5 3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

.cal-quick-foot { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.cal-quick-foot .cal-quick-more {
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  color: var(--text-secondary);
  font-size: 12.5px;
}
.cal-quick-foot .cal-quick-more:hover { color: var(--accent); }
.cal-quick-foot .cal-quick-save { margin-left: auto; }

/* ===================================================================
   보기 고르개 — 메인메뉴 안 (2026-09-10 봉길님: 「체크박스 활성화로 볼 수 있게」)
   구글캘린더의 「내 캘린더 / 다른 캘린더」 자리다.
   ⚠ 「전체 일정 / 내 일정」 메뉴 두 줄은 없앴다 — 이 체크 목록이 같은 말을 더 잘 한다.
   =================================================================== */
.cal-side-group {
  display: flex;
  align-items: center;
  gap: 6px;
  /* 줄이 좁아졌으니(50 → 36) 묶음 위 여백도 함께 줄인다 — 안 그러면 묶음만 멀어 보인다 */
  margin: 12px 0 2px;
  padding: 0 16px 0 22px;
  color: var(--text-tertiary);
  font-size: 11.5px;
}
/* ⚠ 「+」 는 **묶음 머리에 두지 않는다** (2026-09-10 봉길님: 「저거 수직 정렬 또 안맞췄네」).
   묶음 머리의 + 는 오른쪽 16, 줄의 ⋮ 는 오른쪽 22 에 서서 중심이 5px 어긋났다(실측).
   자리를 다투게 만든 것이 잘못이라 **목록 맨 아래 한 줄**로 내렸다 —
   담는 곳이 하나뿐이라 「생일을 뺐는데 어디서 다시 담나」도 함께 풀린다.
   구글캘린더도 「다른 캘린더 +」 가 목록 아래에 있다 */
.cal-side-addrow {
  width: calc(100% - 16px);
  border: 0;
  background: none;
  font-family: inherit;
  color: var(--text-tertiary);
  text-align: left;
}
.cal-side-addrow:hover { background: var(--btn-ink-tint); color: var(--text-primary); }
/* + 기호가 색 알과 **같은 16px 자리**에 선다 — 그래야 글자가 다른 줄과 같은 x(122) 에 온다 */
.cal-side-addrow .cal-side-plus {
  width: 16px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  line-height: 1;
}

/* ⚠ 상자를 **메뉴 항목(.sidebar-nav a)과 똑같이** 잡는다 — margin 0 8px · padding 0 14px.
   그래야 체크가 메뉴 글자와 **같은 세로선(98)** 에 선다. 처음에는 margin 12 · padding 10 이라
   줄이 12px 안쪽에서 시작하고 글자가 141 에 섰다(실측). 구글도 체크가 이름보다 왼쪽에 있다 */
/* 줄 = [체크·이름][⋮]. 메일 폴더 줄(.mail-subbox-row)을 그대로 답습했다 —
   색 고르기·목록에서 빼기를 ⋮ 안으로 접는다.
   ⚠ 항목 사이 여백을 **줄이 갖는다.** 안쪽 label 이 갖고 있으면 줄이 그만큼 길어져
     줄 한가운데가 글자 한가운데보다 아래가 되고 ⋮ 가 이름보다 내려가 보인다
     (메일에서 실측으로 겪은 것: 줄 50px / 링크 36px) */
/* ⚠ 줄 사이를 **4** 로 좁혔다. 메뉴 항목 간격(--nav-item-gap 14)을 그대로 쓰니
   줄 하나가 50px 이 되어 일곱 줄에 350px 을 썼고 목록이 통째로 허전했다(실측) */
.cal-side-row { position: relative; display: flex; align-items: center; margin: 0 0 4px; }

.cal-side-item {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  box-sizing: border-box;
  height: 32px;
  margin: 0 8px;
  padding: 0 14px;
  border-radius: 12px;
  cursor: pointer;
  color: rgba(93, 91, 105, 1);
  font-size: 13.5px;
}
.cal-side-item:hover { background: var(--btn-ink-tint); }

/* ⋮ — 평소에는 숨어 있다가 손이 닿으면 나온다.
   ⚠ 세로 자리를 못박는다. top 없이 절대배치하면 줄 상자 끝에 서서 이름보다 내려간다 */
.cal-side-more {
  position: absolute;
  right: 22px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-tertiary);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.cal-side-row:hover .cal-side-more,
.cal-side-more:focus-visible,
.cal-side-more[aria-expanded="true"] { opacity: 1; }
.cal-side-more:hover { background: var(--sidebar-hover); color: var(--text-primary); }
/* 색 점 — 이 일정이 달력에서 무슨 색으로 보이는지 미리 알린다 */
.cal-side-item > span:not(.cal-side-dot) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ⚠ **켜고 끄는 체크가 없다** (2026-09-10 봉길님: 「버튼을 켜는 방식으로 하지말고,
   등록 제거 방식으로 하는게 더 괜찮은 방법같은데」).
   목록에 있으면 보이고, 안 보려면 뺀다 — 한 가지 방식이다.
   종전에는 「체크로 끄기」와 「목록에서 빼기」가 같은 일을 두 방식으로 하고 있었다.
   ⚠ 색 알 12px 을 좌우 여백 2 로 감싸 **체크가 서던 16px 자리를 그대로** 쓴다.
     그래야 이름이 서는 x(122)가 안 움직인다 */
.cal-side-dot {
  width: 9px;
  height: 9px;
  margin: 0 3.5px;
  border-radius: 50%;
  flex: none;
}

/* ===================================================================
   조직도 — 법인 → 본부 → 팀, 위에서 아래로 뻗는 나무 (2026-09-07 봉길님)

   비유바움 R&R 조직도 엑셀(`비유바움(주) R&R 조직도.xlsx`)의 형태를 따랐다.
   박스마다 사람이 [직책][직위][이름][하는 일] 네 칸으로 들어간다.

   ⚠ **`.orgmap` 안으로 한정한다.** `.chart-card` · `.chart-node` 같은 이름을
     인사관리 조직도(hr/org-management.html · hr/rank-management.html)가 이미
     자기 <style> 안에서 쓰고 있다. 스코프를 안 씌우면 그 화면이 같이 바뀐다.
   =================================================================== */

/* 조직 사이 간격 — 한 곳에서 정한다 (2026-09-07 봉길님: 상하 두 배 · 가로 1.5배).
   ⚠ 상하(--org-gap-v)는 **세 군데가 같은 값이어야** 선이 안 끊긴다:
     세로 연결선 높이 · 자식 그룹 위 여백 · 자식마다 위로 뻗는 선.
     하나만 고치면 선이 허공에서 끝나거나 카드를 파고든다. */
.orgmap {
  --org-gap-v: 44px;   /* 상위 ↔ 하위 (전 22) */
  --org-gap-h: 15px;   /* 동급끼리 (전 10) */
  /* 선 굵기도 한 곳에서 — 다섯 군데(세로선·가로선·자식 위 선·본줄기·가지 팔)에 흩어져 있어
     하나만 고치면 굵기가 섞인다. 2px 는 두껍다는 지적을 받았다 (2026-09-07 봉길님). */
  --org-line: 1px;
}

/* 판 — 나무는 가로로 길다. **판만 굴리고** 바깥 화면은 밀리지 않는다.
   ⚠ 본문(.page-scroll)이 대신 굴러가면 안 된다. 요약표 높이까지 더해져 몇 px 넘치는
     순간 세로 스크롤바가 생기고, 상단바·메뉴가 밀린다 (실측 627 vs 622 = 5px 초과).
     그래서 조직도가 든 본문은 세로로 세워 두고 **남는 높이를 판이 먹는다.** */
/* 위 여백 48 — 법인 카드가 요약 줄 바로 밑에 붙어 「너무 상단에서 시작한다」(2026-09-07 봉길님).
   ⚠ 맞춤 배율(mbFitScale)이 이 여백을 computed style 로 읽어 뺀다 — 숫자를 JS 에 또 적지 않는다 */
/* 세로 가운데 (2026-09-08 봉길님: 「아니면 세로 정렬도 중앙으로 맞추든지」).
   조직이 옆으로 길면 가로에 맞춰 줄이느라 세로에 여백이 크게 남는다(실측 위 56 · 아래 339).
   ⚠ **safe** center 다 — 나무가 판보다 커지면 가운데가 아니라 **위에서 시작**한다.
     그냥 center 로 두면 넘칠 때 위쪽이 잘려 법인 카드를 영영 못 본다.
     실측으로 확인: 넘치는 상태에서 위 여백 48 유지, 잘림 없음. */
.orgmap { overflow: auto; padding: 48px 4px 8px; display: grid; align-content: safe center; }

#membersBody[data-view="chart"] {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#membersBody[data-view="chart"] .orgmap { flex: 1; min-height: 0; }
/* 요약 줄은 줄어들지 않는다 — 판이 남는 높이를 가져간다 */
#membersBody[data-view="chart"] .org-summary { flex: none; }

/* ⚠ 배율은 transform:scale 이 아니라 **zoom** 이다. scale 은 그림만 줄이고 자리는
     원래 크기로 남아 오른쪽에 빈 공간과 쓸데없는 가로 스크롤이 생긴다 */
.orgmap-inner { display: inline-block; min-width: 100%; }

/* 조직 요약 — **인사관리 조직도(hr/org-management.html)가 쓰는 부품 그대로**다.
   ⚠ 새로 짓지 않는다 (CLAUDE.md 1번). 전에는 테두리 친 2열 표를 따로 만들었는데,
     같은 제품 안에 그런 부품이 없어 혼자 딴 화면으로 보였다 (2026-09-07 봉길님 지적).
   ⚠ 판(.orgmap) **밖**에 둔다. 안에 두면 나무를 옆으로 굴릴 때 같이 밀려나가 사라진다 */
.org-summary {
  display: flex;
  gap: 20px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.org-summary-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-secondary);
}
.org-summary-item .summary-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.org-summary-item .summary-value { font-weight: 700; color: var(--text-primary); }
.org-summary-sep {
  margin-left: 8px;
  padding-left: 16px;
  border-left: 1px solid var(--border-color);
}
/* 확대·축소는 요약 줄 **오른쪽 끝**. 좌측이 값, 우측이 조작 — 도구줄 표준과 같은 결이다 */
.org-summary .chart-zoom { margin-left: auto; }

/* 나무 뼈대 — 인사관리 조직도와 같은 구조(.chart-node/.chart-children/.chart-connector) */
.orgmap .chart-node { display: flex; flex-direction: column; align-items: center; position: relative; }
.orgmap .chart-children {
  display: flex;
  gap: var(--org-gap-h);
  justify-content: center;
  position: relative;
  padding-top: var(--org-gap-v);
}
.orgmap .chart-connector { width: var(--org-line); height: var(--org-gap-v); background: var(--border-color); }
.orgmap .chart-h-line { position: absolute; top: 0; height: var(--org-line); background: var(--border-color); }
.orgmap .chart-children > .chart-node::before {
  content: '';
  position: absolute;
  top: calc(var(--org-gap-v) * -1);
  /* ⚠ translateX(-50%) 를 쓰지 않는다. 1px 선을 정확히 가운데 두려면 반드시 x.5 에 놓이고,
     그 순간 두 픽셀에 번져 흐릿하거나 굵어 보인다(실측 x.83, 배율 1.5 화면).
     가운데에서 0.5px 오른쪽에 두는 편이 눈에 띄지 않고 선명하다. */
  left: 50%;
  width: var(--org-line);
  height: var(--org-gap-v);
  background: var(--border-color);
}
/* 자식 박스는 **위쪽을 맞춰** 세운다 — 사람 수가 달라도 머리줄이 한 선에 선다 */
.orgmap .chart-children > .chart-node { align-self: flex-start; }
.orgmap-tree { display: flex; justify-content: center; }

/* ---- 본줄기와 좌우 가지 ----
   단계가 얕은 조직(기술총괄·연구소처럼 팀 위에 있는 것)은 **본줄기 좌우로 가지**를 뻗고,
   가장 깊은 단계만 아래에 나란히 선다. 봉길님이 주신 조직도 이미지의 모양이다.
   ⚠ 이렇게 하지 않으면 CTO·연구소·팀이 **한 줄에 서서** 위아래가 안 보인다
     (2026-09-07 봉길님: 「기술총괄이 기술연구소보다 상위인 게 느껴지지 않는다」). */
.orgmap .chart-spine {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  row-gap: 16px;
  padding: calc(var(--org-gap-v) / 2) 0;
  width: 100%;
}
/* 가운데를 지나는 세로 본줄기 */
.orgmap .chart-spine::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: var(--org-line);
  /* 반픽셀 보정을 하지 않는다 — 위 세로선과 같은 이유 */
  background: var(--border-color);
}
/* 팔은 카드 세로 한가운데가 아니라 **머리줄 중앙**에 붙인다. 한가운데로 두면 카드 높이에
   따라 팔 자리가 달라지고(실측 43.2 vs 39.2), 하필 머리줄 경계선(44.7) 바로 위에 걸쳐
   어긋나 보인다 (2026-09-07 봉길님). 머리줄은 늘 44 라 22 면 정확히 그 가운데다. */
.orgmap .chart-aside { display: flex; align-items: flex-start; position: relative; }
.orgmap .chart-aside .chart-arm { margin-top: 22px; }
.orgmap .chart-aside[data-side="left"] { grid-column: 1; justify-self: end; }
.orgmap .chart-aside[data-side="right"] { grid-column: 2; justify-self: start; }
/* 카드에서 본줄기까지 뻗는 가로 팔 */
.orgmap .chart-arm { width: 40px; height: var(--org-line); background: var(--border-color); flex: none; }

/* 박스 — 폭은 글자가 잘리지 않는 최소로 잡는다.
   296 은 넓어 조직 사이가 벌어져 보였다 (2026-09-07 봉길님: 「카드 너비와 여백이 너무 크다」).
   셈: 좌우 여백 28 + 직책 52 + 직위 30 + 사이 24 + 이름 63 + 담당업무 48 ≒ 245 */
/* ⚠⚠ **글로벌에 이미 `.chart-card` 가 있다** (이 파일 위쪽, 인사통계 조직도용):
     display:flex · align-items:center · justify-content:center · width/min-width/height 고정 ·
     padding 12px 14px · text-align:center.
   이름이 같아 **그 위에 얹히는 바람에** 카드 안쪽 상자가 내용 폭으로 쪼그라들었다
   (실측: 카드 252 인데 안쪽 .chart-people 은 219.3). 이름이 잘린 진짜 원인이 이것이다
   (2026-09-07 봉길님 「이름 짤리는 것」). 물려받는 값을 하나씩 **명시적으로 되돌린다.**
   ⚠ 나중에 이 절을 손볼 때 아래 네 줄을 지우지 말 것 — 지우면 다시 쪼그라든다. */
.orgmap .chart-card {
  /* 폭 = 좌우 여백 28 + 직책 52 + 직위 52 + 이름 44 + 사이 24 = 200 이 바닥.
     여기에 **팀 설명**(이름 아래 한 줄)이 가장 긴 것에 맞춰 넓힌다 — JS 가 정한다(24자 상한).
     카드마다 폭이 다르면 격자가 흔들리므로 **모든 카드가 같은 폭**이다 (2026-09-07 규칙). */
  width: var(--org-card-w, 200px);
  display: block;      /* 글로벌 flex + align-items:center 를 끊는다 — 자식이 폭을 꽉 채운다 */
  min-width: 0;        /* 글로벌 min-width: var(--chart-card-width) = 144px */
  height: auto;        /* 글로벌 height: var(--chart-card-height) = 64px */
  padding: 0;          /* 글로벌 padding: 12px 14px */
  box-sizing: border-box;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.86);
  overflow: hidden;
  text-align: left;
}
/* 단은 **색을 늘리지 않고 진하기로만** 가른다 — 엑셀은 본부마다 주황·파랑·초록·노랑이지만
   우리 화면은 clay 라벤더 한 계열이다. 색을 늘리면 다른 모듈과 따로 논다 */
/* ⚠ 기준은 트리 깊이(depth)가 아니라 **조직 단계(level)** 다. 지금 데이터는 상위 조직이
     전부 법인 직속이라 깊이로는 CTO·연구소·팀이 전부 같은 값이 되어 구분이 사라진다
     (2026-09-07 봉길님 지적). */
.orgmap .chart-card[data-lv="0"] { border-color: rgba(var(--accent-rgb), 0.5); }
.orgmap .chart-card[data-lv="0"] .chart-card-head { background: rgba(var(--accent-rgb), 0.16); }
.orgmap .chart-card[data-lv="1"] { border-color: rgba(var(--accent-rgb), 0.34); }
.orgmap .chart-card[data-lv="1"] .chart-card-head { background: rgba(var(--accent-rgb), 0.10); }
.orgmap .chart-card[data-lv="2"] .chart-card-head { background: rgba(13, 148, 136, 0.09); }
.orgmap .chart-card[data-lv="3"] .chart-card-head { background: rgba(20, 184, 166, 0.07); }
.orgmap .chart-card[data-empty="1"] { opacity: 0.66; }
/* 사람이 없는 카드는 머리줄만 남는다 — 아래 구분선이 있으면 빈 줄이 하나 더 있는 것처럼 보인다 */
.orgmap .chart-card[data-empty="1"] .chart-card-head { border-bottom: 0; }


/* 팀 이름은 **왼쪽**. 2026-09-08 에 가운데로 옮겼다가 봉길님이 「이상하긴 하네, 원래대로 하자」
   하셔서 되돌렸다. 사람 줄이 왼쪽인데 머리만 가운데면 세로선이 둘로 갈린다.
   ⚠ ⋮ 는 흐름에서 빼내 오른쪽에 세운다(absolute) — 흐름에 두면 그 폭만큼 이름이 밀려
     ⋮ 가 뜬 상자와 아닌 상자의 이름 자리가 달라진다 */
/* 머리줄 = [팀 이름 (인원수)] + 그 아래 [역할·목적]. 두 줄이 한 덩어리다.
   ⚠ 역할이 없으면 12 + 제목 20 + 12 = 44 로 종전 높이 그대로다(min-height 와 같은 값) */
.orgmap .chart-card-head {
  position: relative;
  min-height: 44px;
  padding: 12px 30px 12px 14px;   /* 오른쪽 30 — ⋮ 가 인원수를 덮지 않을 만큼 */
  border-bottom: 1px solid var(--border-light);
}
.orgmap .chart-card-title { display: flex; align-items: center; gap: 7px; }
.orgmap .chart-card-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 인원수는 이름 **바로 옆** (2026-09-03 봉길님). 엑셀도 「경영지원팀 (5)」로 붙여 썼다 */
.orgmap .chart-card-count { font-size: 12.5px; color: var(--text-tertiary); flex: none; }

/* 조직 작업 ⋮ — 직제관리에서만 그린다(js/orgchart.js 의 editable).
   ⚠ **자리는 늘 차지하고 보이기만 감춘다.** display:none 으로 하면 마우스를 올릴 때
     이름 칸 폭이 바뀌어 상자가 흔들린다 (2026-09-08) */
.orgmap .chart-card-menu {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  flex: none;
  visibility: hidden;
}
.orgmap .chart-card:hover > .chart-card-head .chart-card-menu,
.orgmap .chart-card-menu.is-open { visibility: visible; }
.orgmap .chart-card-menu .menu-dots { font-size: 15px; line-height: 1; padding: 2px 2px; }

/* ⚠ 조직도는 zoom 배율(35% 까지 내려간다)이 걸려 있다. 팝오버를 그 안에 두면 **글자까지 같이
   줄어들어** 읽을 수 없다. 그래서 화면(body)에 fixed 로 띄우고 ⋮ 의 실제 좌표에 맞춘다 */
.menu-pop--fixed { position: fixed; top: auto; left: auto; right: auto; bottom: auto; }
.menu-pop-item[disabled] { color: var(--text-tertiary); cursor: default; }
.menu-pop-item[disabled]:hover { background: none; }

/* 사람 줄 — 엑셀의 네 칸.
   ⚠ 칸 폭을 grid 로 **못박는다.** 직책·직위 길이가 달라도 이름이 서는 x 가 같아야
     세로로 읽힌다. 직책이 없으면 칸을 비우되 **없애지 않는다** */
.orgmap .chart-people { padding: 2px 0 6px; }
.orgmap .chart-person {
  display: grid;
  /* ⚠ 담당업무를 `auto` 로 두면 그쪽이 먼저 먹고 이름이 눌린다(실측 40.5px = 한글 3자 딱).
     업무 칸을 **고정**으로 잡고 남는 폭은 전부 이름에게 준다 — 사람 이름이 잘리면 누구인지
     알 수 없고, 업무는 잘려도 덜 치명적이다. */
  /* 이름 칸은 **내용 폭(auto)**, 담당업무가 바로 뒤(gap 8)에 붙는다.
     ⚠ 이름을 1fr 이나 고정 70 으로 두면 3글자 이름 뒤가 30px 비어 「박봉길 …… 경영관리」가 된다
       (2026-09-07 봉길님: 「이름하고 담당업무 사이 간격이 넓다」 — 70 고정으로 고쳤다가
        실측 37.5 로 그대로라 다시 고쳤다). 이름 길이가 다르면 담당업무 자리가 조금 다르지만
       이 회사 이름은 거의 3글자고, 「(F)」 붙은 이름들은 담당업무가 비어 있다. */
  /* 이름 칸은 **3자 기준 44px 고정**, 담당업무는 그 뒤에 넉넉히(18px) 띄운다.
     이름을 내용 폭(auto)으로 두면 줄마다 담당업무 자리가 달라져 세로로 안 맞는다
     (2026-09-07 봉길님: 「3자 이름을 기준으로 잡고 수직 정렬되게 전체적으로 간격을 띄어라」).
     긴 이름(「(F)김소선」 실측 63px)은 44 를 넘어 **간격으로 흘러나온다** — 44+8+18=70 안이라
     담당업무를 건드리지 않는다. 70 을 넘는 이름(한글 5자 이상)이 생기면 이 값을 다시 본다. */
  /* 직위 칸 52 — 직책 칸과 같다. 「부사장」 잉크가 실측 47px 라 40 으로도 이름과 0.5px 였다 (2026-09-07) */
  /* [직책 52][직위 52][이름]. 담당업무 칸은 없앴다 (2026-09-08 봉길님) — 이름이 남는 폭을 갖는다 */
  grid-template-columns: 52px 52px minmax(44px, 1fr);
  align-items: center;
  gap: 8px;
  /* ⚠⚠ 한 줄 안의 글자는 **한 크기·한 줄높이** 다. 직책 칩·직위·이름·담당업무 전부.
     크기가 다르면 밑선과 중심을 동시에 못 맞춘다 — 상자(align-items)는 맞아도 **잉크**가 어긋난다.
     2026-09-06 결재 알림에서 겪고 기록해 두고도 2026-09-07 여기서 또 어겼다
     (봉길님: 「수평정렬도 맞추면 좋겠다… 몇 번을 말하는 건지」). 이 두 줄을 자식에서 덮지 말 것.
     검증은 Range 로 잉크 세로 중심을 재서 한 줄 안 차이 0 — agents/DESIGN-RULES.md §6. */
  font-size: 12.5px;
  line-height: 20px;
  width: 100%;
  /* 줄 높이 34 — 글자는 목록 화면과 같은 13.5px 로 두되 줄만 촘촘하게 한다.
     27 은 「조직도만 작아 보인다」였고 44 는 「여백이 너무 크다」였다 (둘 다 2026-09-07 봉길님).
     조직도는 한 상자에 여러 줄이 겹겹이 들어가므로 목록 화면의 44 를 그대로 쓰면 세로가 길어진다. */
  min-height: 34px;
  padding: 0 14px;
  border: 0;
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
/* ⚠ 마우스를 올려도 **바탕을 칠하지 않는다** (2026-09-07 봉길님).
   조직도는 줄을 고르는 목록이 아니라 한눈에 보는 그림이다 — 지나가는 자리마다 색이 켜지면
   눈이 그리로 끌려가 정작 조직의 모양이 안 읽힌다. 누를 수 있다는 것은 손 모양(cursor)이 말한다. */

.orgmap .chart-role {
  display: block;
  padding: 0;            /* 세로 padding 을 두지 않는다 — 줄높이 20 그대로여야 옆 글자와 중심이 같다 */
  border-radius: 10px;
  background: var(--accent-light);
  color: #6b57a5;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
}
.orgmap .chart-role:empty { background: none; }
/* ⚠ 직책자가 없는 카드라고 직책 칸을 접지 **않는다.** 한때 접었더니 카드마다 글자가 서는
   자리가 달라졌다 (2026-09-07 봉길님: 「팀장이 없어도 동일하게」). 칸은 늘 네 개다. */
.orgmap .chart-rank { color: var(--text-secondary); white-space: nowrap; }
.orgmap .chart-pname {
  color: var(--text-primary);
  font-weight: 500;      /* 강조는 굵기로만 — 크기를 키우면 줄이 어긋난다 */
  white-space: nowrap;
  overflow: visible;     /* 3자 칸을 넘는 이름은 자르지 않고 옆 간격으로 내보낸다 */
}
/* 팀 이름 아래 한 줄 — 그 조직이 하는 일 (2026-09-08 봉길님). 사람마다 적던 담당업무를
   조직마다 한 번 적는 자리다. **한 줄로 자른다** — 두 줄이 되면 상자 높이가 제각각이 된다.
   머리줄 **안**에 있으므로 좌우 여백은 머리줄이 이미 준다 */
.orgmap .chart-card-purpose {
  margin-top: 3px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 겸직은 칩이 아니라 이름 앞 「(겸)」 으로 적는다 — 칩을 두면 직책 칩과 크기가 달라 줄이 어긋났다 (2026-09-07 봉길님) */

/* 사람이 없는 자리 — 엑셀의 「공석」.
   ⚠ 사람 줄과 **같은 44** 다. 다르면 옆 박스와 줄이 어긋난다 */
.orgmap .chart-vacant {
  display: flex;
  align-items: center;
  min-height: 34px;
  padding: 0 14px;
  color: var(--text-tertiary);
  font-size: 12.5px;
}

/* 도구줄 오른쪽 확대·축소 — 높이는 다른 컨트롤과 같은 35 */
.chart-zoom { display: inline-flex; align-items: center; gap: 6px; }
.chart-zoom button,
.chart-zoom .chart-zoom-value {
  height: 35px;
  min-width: 35px;
  padding: 0 8px;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  background: var(--bg-primary);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}
/* ⚠ 상자만 35px 로 맞추면 **글자는 위에 붙는다** — line-height 19.5px 가 35px 안에서
   위로 쏠려 단추 글자보다 7.8px 높이 떴다(실측, 2026-09-07 봉길님 지적).
   상자가 아니라 **글자**를 가운데 세운다. */
.chart-zoom .chart-zoom-value {
  min-width: 68px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.chart-zoom button:hover:not(:disabled),
.chart-zoom .chart-zoom-value:hover {
  border-color: rgba(var(--accent-rgb), 0.35);
  color: var(--accent);
  background: var(--accent-light);
}
.chart-zoom button:disabled { opacity: 0.4; cursor: not-allowed; }
