/* ==========================================================================
   스마트 웰페어 — 목록 테이블 + 좌측 사이드바 고정  v2.0  (2026-09-10)
   위치: public/css/table.css   →   URL: /css/table.css
   선행: /css/tokens.css

   [v1 에서 바뀐 점]
   토큰 이름을 v2 기준으로 전부 치환했습니다. --accent → --ui-accent,
   --st-done-* → --status-success-* 등. 리터럴 hex 0개, 미정의 참조 0개 확인.
   dialog.css 에서 겪은 두 가지도 미리 반영했습니다.
     · box-sizing: 이 앱은 전역 리셋이 없으므로 이 컴포넌트 안으로만 한정
     · word-break: keep-all — 한글 어절 단위 줄바꿈

   [근거] 닥스웨이브(docswave.com) 문서 목록 실측값
     9열 / 총 2056px · th 배경 --ui-header-fill / 600 / --ink-muted / padding 12
     tr 1줄 49px · 2줄 67px · 상태·일시 center, 나머지 left
     페이지네이션 10/100 선택 + |< < 1 2 3 … > >|
   ========================================================================== */

/* ==========================================================================
   0. 박스모델 — 전역 리셋 금지. 이 컴포넌트 안으로만 한정합니다.
   index.html 에 box-sizing 이 39곳 개별 선언돼 있고 body·일반 div 는
   content-box 입니다. 전역으로 바꾸면 기존 63KB 인라인 CSS 가 흔들립니다.
   ========================================================================== */
.sw-table-wrap, .sw-table-wrap *,
.sw-sidebar, .sw-sidebar *,
nav.admin-sidebar, nav.admin-sidebar *,
.sw-form-table, .sw-form-table *{
  box-sizing: border-box;
}

/* ==========================================================================
   1. 좌측 서브 메뉴 고정 (sticky)
   본문이 길어져도 좌측 메뉴가 화면에 남습니다.

   [실측 확인 2026-09-10, 배포본]
     #adminShell        display flex · align-items flex-start · overflow visible
     nav.admin-sidebar  position static (이게 원인) · width 200px
     sticky 를 깨는 조상 overflow  없음
   → position:sticky 만 바꿔주면 됩니다. 마크업 수정 불필요.

   폭은 건드리지 않습니다. 기존 200px 을 유지해야 레이아웃이 안 흔들립니다.
   (v1 은 220px 을 강제해서 기존 화면 폭을 바꿨습니다 — 제거했습니다)
   ========================================================================== */
.sw-sidebar,
nav.admin-sidebar{
  position: sticky;
  /* header#appHeader 가 sticky·top:0 이고 높이가 고정이 아니다(실측 기본 116px /
     큰글씨 121px). sw-table.js 의 syncStickyTop() 이 실측값을 --sticky-top 에
     넣는다. JS 가 없으면 0px 폴백 - 레이아웃은 안 깨지고 헤더에 가려질 뿐이다. */
  top: calc(var(--sticky-top, 0px) + var(--space) * 4);
  align-self: flex-start;
  flex: 0 0 auto;
  max-height: calc(100vh - var(--sticky-top, 0px) - var(--space) * 8);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--ui-border) transparent;
}

/* 새로 만드는 사이드바에만 폭을 줍니다. 기존 nav.admin-sidebar 는 그대로. */
.sw-sidebar{ width: 220px; }
.sw-sidebar::-webkit-scrollbar,
nav.admin-sidebar::-webkit-scrollbar{ width: 8px; }
.sw-sidebar::-webkit-scrollbar-thumb,
nav.admin-sidebar::-webkit-scrollbar-thumb{ background: var(--ui-border); border-radius: var(--r-chip); }

/* (구버전 .sw-has-sticky-header 분기는 제거했습니다 - 헤더 높이를 --h-btn 으로
   추정하면 실측 116px 과 40px 어긋나고, 큰글씨 모드에서 또 달라집니다.
   위 --sticky-top 실측 방식이 두 경우를 모두 덮습니다.) */

/* 모바일에서는 고정 해제 */
@media (max-width: 768px){
  .sw-sidebar,
  nav.admin-sidebar{
    position: static;
    width: 100%;
    max-height: none;
    overflow-y: visible;
  }
}

/* 사이드바 내부 항목 */
.sw-sidebar__group{ margin-bottom: calc(var(--space) * 4); }
.sw-sidebar__group-title{
  padding: 0 calc(var(--space) * 3) var(--space);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-muted);
  letter-spacing: .02em;
}
.sw-sidebar__item{
  display: flex; align-items: center; gap: calc(var(--space) * 2);
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  border-radius: var(--r-field);
  font-size: var(--fs-base); color: var(--ink-muted);
  text-decoration: none;
  transition: background var(--t-fast) ease, color var(--t-fast) ease;
}
.sw-sidebar__item:hover{ background: var(--surface-alt); color: var(--ink); text-decoration: none; }
.sw-sidebar__item.is-active{ background: var(--ui-accent-tint); color: var(--ui-accent); font-weight: 600; }
.sw-sidebar__count{ margin-left: auto; font-size: var(--fs-xs); color: var(--ink-muted); }
.sw-sidebar__item.is-active .sw-sidebar__count{ color: var(--ui-accent); }

/* ==========================================================================
   2. 테이블
   ========================================================================== */
.sw-table-wrap{
  background: var(--surface);
  border: 1px solid var(--ui-border);
  border-radius: var(--r-card);
  overflow: hidden;
}

/* 좌우 스크롤은 이 컨테이너에만 허용 — 페이지 본문은 절대 가로 스크롤되지 않는다 */
.sw-table-scroll{
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--ui-border) transparent;
}

.sw-table{
  width: 100%;
  min-width: 1200px;              /* 열이 뭉개지지 않는 최소 폭 */
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-base);
}

/* --- 머리행 --- */
.sw-table thead th{
  position: sticky; top: 0; z-index: 2;
  height: var(--row-h);
  padding: var(--pad-cell);
  background: var(--ui-header-fill);
  border-bottom: 1px solid var(--ui-border);
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--ink-muted);
  text-align: left;
  white-space: nowrap;
}
.sw-table thead th.is-center{ text-align: center; }
.sw-table thead th.is-right { text-align: right; }

/* 정렬 가능한 머리행 */
.sw-table th[aria-sort]{ cursor: pointer; user-select: none; }
.sw-table th[aria-sort]:hover{ color: var(--ink); }
.sw-table th[aria-sort="ascending"]::after { content: ' \2191'; color: var(--ui-accent); }
.sw-table th[aria-sort="descending"]::after{ content: ' \2193'; color: var(--ui-accent); }

/* --- 본문행 --- */
.sw-table tbody td{
  height: var(--row-h);
  padding: var(--pad-cell);
  border-bottom: 1px solid var(--ui-border-soft);
  color: var(--ink);
  vertical-align: middle;
}
.sw-table tbody tr:last-child td{ border-bottom: 0; }
.sw-table tbody tr:hover{ background: var(--surface-alt); }
.sw-table tbody tr.is-selected{ background: var(--ui-accent-tint); }
.sw-table tbody tr.is-unread .sw-cell-title{ font-weight: 700; }   /* 회람·수신 미확인 */

.sw-table td.is-center{ text-align: center; }
.sw-table td.is-right { text-align: right; font-variant-numeric: tabular-nums; }
.sw-table td.is-num   { text-align: right; font-variant-numeric: tabular-nums; }

/* 2줄 행 (문서명 + 부제) */
.sw-table tbody tr.is-2line td{ height: var(--row-h-2l); }
.sw-cell-title{ display: block; color: var(--ink); }
.sw-cell-title:hover{ color: var(--ui-accent); }
.sw-cell-sub{
  display: block; margin-top: 2px;
  font-size: var(--fs-xs); color: var(--ink-muted);
}

/* 한글은 어절 단위로 끊어야 읽힙니다 (dialog.css 와 같은 규칙) */
.sw-table td, .sw-table th,
.sw-form-table td, .sw-form-table th,
.sw-empty__title, .sw-empty__desc{
  word-break: keep-all;
}

/* 긴 문서명 줄임 */
.sw-cell-ellipsis{
  display: block;
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- 열 폭 (닥스웨이브 실측 규격) --- */
.sw-col-check   { width: 56px;  min-width: 56px;  }
.sw-col-status  { width: 140px; min-width: 140px; }
.sw-col-title   { width: 500px; min-width: 280px; }
.sw-col-person  { width: 200px; min-width: 120px; }
.sw-col-datetime{ width: 180px; min-width: 150px; }
.sw-col-docno   { width: 300px; min-width: 180px; }
.sw-col-label   { width: 300px; min-width: 160px; }
.sw-col-action  { width: 120px; min-width: 120px; }

/* --- 선택 체크박스 --- */
.sw-table input[type="checkbox"]{
  width: 16px; height: 16px;
  accent-color: var(--ui-accent);
  cursor: pointer;
}

/* --- 툴바 (검색 · 필터 · 일괄결재) --- */
.sw-table-toolbar{
  display: flex; align-items: center; flex-wrap: wrap;
  gap: calc(var(--space) * 2);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border-bottom: 1px solid var(--ui-border-soft);
  background: var(--surface);
}
.sw-table-toolbar__spacer{ flex: 1 1 auto; }
.sw-table-toolbar .sw-input,
.sw-table-toolbar .sw-select{ width: auto; min-width: 140px; }
.sw-table-toolbar__count{ font-size: var(--fs-sm); color: var(--ink-muted); }
.sw-table-toolbar__count strong{ color: var(--ui-accent); }

/* 선택 시 뜨는 일괄 동작 바 */
.sw-bulkbar{
  display: flex; align-items: center; gap: calc(var(--space) * 2);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  background: var(--ui-accent-tint);
  border-bottom: 1px solid var(--ui-border);
  font-size: var(--fs-sm); color: var(--ui-accent);
}
.sw-bulkbar[hidden]{ display: none !important; }
.sw-bulkbar__spacer{ flex: 1 1 auto; }

/* ==========================================================================
   3. 페이지네이션 — 닥스웨이브 형식 (10/100 + |< < 1 2 3 … > >|)
   ========================================================================== */
.sw-pager{
  display: flex; align-items: center; justify-content: center;
  gap: calc(var(--space) * 2);
  padding: calc(var(--space) * 4);
  border-top: 1px solid var(--ui-border-soft);
  background: var(--surface);
}
.sw-pager__size{ margin-right: auto; }
.sw-pager__size .sw-select{ width: auto; height: calc(var(--h-field) - 6px); font-size: var(--fs-sm); }
.sw-pager__info{ margin-left: auto; font-size: var(--fs-sm); color: var(--ink-muted); }

.sw-pager__list{ display: flex; align-items: center; gap: var(--space); }
.sw-pager__btn{
  display: inline-flex; align-items: center; justify-content: center;
  min-width: calc(var(--h-btn) - 6px);
  height: calc(var(--h-btn) - 6px);
  padding: 0 calc(var(--space) * 2);
  background: var(--surface);
  border: 1px solid var(--ui-border);
  border-radius: var(--r-field);
  font-size: var(--fs-sm); color: var(--ink-muted);
  cursor: pointer;
}
.sw-pager__btn:hover:not(:disabled){ background: var(--surface-alt); color: var(--ink); }
.sw-pager__btn:disabled{ opacity: .4; cursor: not-allowed; }
.sw-pager__btn.is-current{
  background: var(--ui-accent-tint); border-color: var(--ui-accent);
  color: var(--ui-accent); font-weight: 600;
}
.sw-pager__gap{ padding: 0 var(--space); color: var(--ink-muted); }

@media (max-width: 768px){
  .sw-pager{ flex-wrap: wrap; }
  .sw-pager__size, .sw-pager__info{ margin: 0; width: 100%; text-align: center; }
}

/* ==========================================================================
   4. 정의형 표 (서식 그대로의 기안 화면 — 휴가/출장/교육 신청서)
   종이 서식의 표 구조를 그대로 재현한다
   ========================================================================== */
.sw-form-table{
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
  background: var(--surface);
}
.sw-form-table th,
.sw-form-table td{
  border: 1px solid var(--ui-border);
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  vertical-align: middle;
}
.sw-form-table th{
  width: 120px;
  background: var(--ui-header-fill);
  font-weight: 600; color: var(--ink-muted);
  text-align: center;
  white-space: nowrap;
}
.sw-form-table td .sw-input,
.sw-form-table td .sw-select,
.sw-form-table td .sw-textarea{
  border: 0; background: transparent; height: auto; padding: 0;
  box-shadow: none;
}
.sw-form-table td .sw-input:focus,
.sw-form-table td .sw-select:focus,
.sw-form-table td .sw-textarea:focus{
  box-shadow: inset 0 -2px 0 var(--ui-accent);
}
.sw-form-table caption{
  padding-bottom: calc(var(--space) * 3);
  font-size: var(--fs-h2); font-weight: 600; color: var(--ink);
  letter-spacing: .3em;
}
/* 결재란 */
.sw-approval-box{ border-collapse: collapse; float: right; }
.sw-approval-box th,
.sw-approval-box td{ border: 1px solid var(--ui-border); text-align: center; font-size: var(--fs-xs); }
.sw-approval-box th{ width: 56px; background: var(--ui-header-fill); }
.sw-approval-box td{ width: 72px; height: 56px; }

@media print{
  .sw-form-table th, .sw-form-table td,
  .sw-approval-box th, .sw-approval-box td{ border-color: var(--ink); }
  .sw-form-table th, .sw-approval-box th{ background: transparent; }
}

/* ==========================================================================
   5. 목록에 필요한 보조 컴포넌트
   sw-table.js 가 내보내는 클래스들입니다. components.css 없이 단독으로
   동작하도록 여기 함께 담았습니다(단계적 적용을 위해).
   .sw-btn 3종은 dialog.css 에 이미 있으므로 중복 정의하지 않습니다.
   ========================================================================== */

/* --- 상태 배지 — 앱의 기존 --status-* 토큰을 그대로 씁니다 --- */
.sw-badge{
  display: inline-flex; align-items: center; gap: var(--space);
  height: calc(var(--h-btn) - 12px);
  padding: 0 calc(var(--space) * 3);
  border-radius: var(--r-chip);
  font-size: var(--fs-xs); font-weight: 600;
  white-space: nowrap;
}
.sw-badge--pending{ background: var(--status-pending-bg); color: var(--status-pending-text); }
.sw-badge--success{ background: var(--status-success-bg); color: var(--status-success-text); }
.sw-badge--danger { background: var(--status-danger-bg);  color: var(--status-danger-text); }
.sw-badge--neutral{ background: var(--status-neutral-bg); color: var(--status-neutral-text); }

/* --- 작은 버튼 (일괄 동작 바에서 씀. dialog.css 의 .sw-btn 을 축소) --- */
.sw-btn--sm{
  height: calc(var(--h-btn) - 8px);
  padding: 0 calc(var(--space) * 3);
  font-size: var(--fs-sm);
}

/* --- 문서 라벨 칩 --- */
.sw-chip{
  display: inline-flex; align-items: center;
  padding: 2px calc(var(--space) * 2);
  border: 1px solid var(--ui-border);
  border-radius: var(--r-field);
  background: var(--surface);
  font-size: var(--fs-xs); color: var(--ink-muted);
  white-space: nowrap;
}

/* --- 재실 상태 점 (🟢🟡🔴 대체) --- */
.sw-dot{ width: 8px; height: 8px; border-radius: var(--r-chip); display: inline-block; }
.sw-dot--in { background: var(--status-success-text); }
.sw-dot--out{ background: var(--status-pending-text); }
.sw-dot--off{ background: var(--status-neutral-text); }

/* --- 아이콘 --- */
.sw-icon{
  width: var(--icon); height: var(--icon);
  flex: 0 0 auto;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;   /* 기존 svgIcon() 계열이 2라 한 화면에 섞여도 굵기가 같아야 한다 */
  /* 이모지를 치환하면 flex 가 아닌 버튼·문단 안에 글자와 나란히 놓이는 자리가 많다.
     inline SVG 는 기본이 baseline 정렬이라 그대로 두면 글자보다 살짝 떠 보인다. */
  vertical-align: -0.15em;
}
.sw-icon--sm{ width: calc(var(--icon) - 4px); height: calc(var(--icon) - 4px); }
.sw-icon--muted{ color: var(--ink-muted); }

/* 기존 빈 상태(.empty-state-icon)는 2.4em 글리프 자리였다. 이모지를 SVG 로 바꾸면서
   그 크기(≈34px)에 맞추되, 큰글씨 모드에서 함께 커지도록 --icon 배수로 둔다.
   색은 .empty-state 의 --text-subtle 을 currentColor 로 물려받는다. */
.empty-state-icon .sw-icon{ width: calc(var(--icon) * 2); height: calc(var(--icon) * 2); vertical-align: baseline; }

/* --- 빈 상태 — 문구는 sw-strings.js 가 공급 --- */
.sw-empty{
  display: flex; flex-direction: column; align-items: center;
  gap: calc(var(--space) * 3);
  padding: calc(var(--space) * 14) calc(var(--space) * 5);
  text-align: center;
  color: var(--ink-muted);
}
.sw-empty__icon{
  width: 44px; height: 44px;
  color: var(--ui-border); stroke-width: 1.4;
}
.sw-empty__title{ font-size: var(--fs-lg); font-weight: 600; color: var(--ink); }
.sw-empty__desc{ font-size: var(--fs-sm); }
.sw-empty__action{ margin-top: calc(var(--space) * 2); }

/* --- 로딩 스켈레톤 --- */
.sw-skeleton{
  height: var(--row-h);
  border-radius: var(--r-field);
  background: linear-gradient(90deg,
    var(--surface-alt) 25%, var(--ui-border-soft) 37%, var(--surface-alt) 63%);
  background-size: 400% 100%;
  animation: swShimmer 1.3s ease infinite;
}
@keyframes swShimmer{ from{ background-position:100% 0 } to{ background-position:0 0 } }

/* --- 셀 링크 --- */
.sw-cell-link{ text-decoration: none; color: inherit; display: block; }
.sw-cell-link:hover .sw-cell-title{ color: var(--ui-accent); text-decoration: underline; }

/* --- 접근성 전용 텍스트 --- */
.sw-sr-only{
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   6. 기존 표 머리행 정합 (2026-09-10 추가)

   [왜 .resp-table 이 아니라 .data-table-header 인가]
   .resp-table 규칙 9개는 전부 @media (max-width:768px) 안의 "카드 모드"이고
   데스크톱 규칙이 하나도 없다. 데스크톱 머리행 모양은 index.html:199 의
   .data-table-header th 한 규칙에서 나온다 (실제 사용 48곳, 그중 42곳이
   .resp-table 표). 그래서 정합 대상은 이 클래스다.

   [특이도]
   table.css 는 인라인 <style> 보다 먼저 로드되므로 같은 특이도면 밀린다.
   .data-table-header th (0,1,1) 를 이기려고 tr.data-table-header th (0,1,2)
   로 한 단계만 올린다. !important 는 쓰지 않는다 - 카드 모드 규칙을 나중에
   못 덮게 된다.

   [바꾸는 것]
   th 글자 0.85em(11.9px)·#222222 → var(--fs-base)(14px)·var(--ink-muted)
     머리행이 본문보다 작아 위계가 뒤집혀 있었다. 같은 크기 + 흐린 색으로 세운다.
   th 배경 #F5F6F8 → var(--ui-header-fill)   파랑/보라 테마를 따라간다
   sortable hover #ECEEF1 → var(--ui-accent-tint)
   대비비: ink-muted on header-fill 파랑 5.56 / 보라 5.48 — 전부 AA
   ========================================================================== */
tr.data-table-header th{
  background: var(--ui-header-fill);
  color: var(--ink-muted);                /* #222222 → 흐리게 (위계) */
  font-size: var(--fs-base);              /* 0.85em(11.9px) → 14px */
  font-weight: 600;
  text-align: left;
  padding: var(--pad-cell) calc(var(--space) * 4);
  border-bottom: 1px solid var(--ui-border);
  white-space: nowrap;
  word-break: keep-all;
}

/* 큰글씨 모드에서도 --fs-base·--pad-cell 이 함께 커지므로 별도 규칙이 필요 없다 */

tr.data-table-header th.sortable:hover{
  background: var(--ui-accent-tint);
  color: var(--ui-accent);
  cursor: pointer;
}

/* 본문 셀 — 반드시 min-width:769px 로 감싼다.
   감싸지 않으면 table.resp-table tbody td (0,1,2) 가 카드 모드의
   .resp-table td (0,1,1) 를 이겨서 좁은 폭의 카드 레이아웃이 깨진다. */
@media (min-width: 769px){
  table.resp-table tbody td{
    padding: var(--pad-cell) calc(var(--space) * 4);
    border-bottom: 1px solid var(--ui-border-soft);
    vertical-align: middle;
    word-break: keep-all;
  }
  table.resp-table tbody tr:last-child td{ border-bottom: 0; }
  table.resp-table tbody tr:hover{ background: var(--surface-alt); }
  /* 숫자 열: 해당 th/td 에 class="num" 을 주면 오른쪽 정렬 + 자릿수 맞춤 */
  table.resp-table tbody td.num,
  tr.data-table-header th.num{ text-align: right; font-variant-numeric: tabular-nums; }
}

/* 실별예약 일별비교 표(index.html:1222~) 는 주석에 적힌 대로 .data-table-header 의
   배경/굵기 톤을 따라간다. 배경만 토큰으로 맞춰야 톤이 갈라지지 않는다.
   패딩·정렬은 좁은 열(min-width 60px) 때문에 일부러 덮어쓴 것이라 건드리지 않는다. */
table.rs-daily-table th{ background: var(--ui-header-fill); }
