@charset "UTF-8";
/* ⚠️ 분기 눈금이 가장 먼저다 — 아래 모든 파일이 이 변수와 mixin 을 쓴다 */
/* =====================================================
 * 분기 — 이 제품의 반응형 눈금 (2026-09-10 확정)
 *
 * ⚠️ **숫자를 여기서만 정한다.** 예전에 _shorts.scss 가 1360 · 900 · 640 을,
 *    _toast.scss 가 768 을 제각기 적고 있었다. 한 곳을 고쳐도 나머지가
 *    옛 눈금에 남아, 같은 폭에서 화면마다 다르게 접힌다.
 *
 * ─ 눈금을 이렇게 고른 근거 (전 화면을 재서 나온 값이다)
 *
 *   본문이 버티는 바닥        900px 안팎 (표 여덟 · 검수 · 계정 관리)
 *   LNB 가 늘 떼어 가는 폭    250 + 좌우 여백 40 = 290px
 *
 *   그래서 1200px 이 갈림길이다 —
 *     1200px  LNB 켜짐 → 본문 910   바닥에 딱 닿는다
 *     1199px  LNB 서랍 → 본문 1159  접는 순간 249px 를 되찾는다
 *   1200 아래에서 LNB 를 켜 두면 본문이 바닥을 뚫는다. 그 자리에서 서랍으로
 *   바꾸면 오히려 넓어진다. **여기가 햄버거가 서는 자리다.**
 *
 *   ⚠️ 노트북(1512 · 1440 · 1366 · 1280)에서는 LNB 가 그대로 보인다.
 *      흔한 폭에서 메뉴를 감추지 않는 것이 이 선의 요점이다.
 *
 * ─ 넷으로 나눈 까닭
 *   XL(1690 이상)을 따로 두면 **지금 모습이 조금도 안 바뀐다.**
 *   반응형을 넣다가 멀쩡한 것을 건드리는 사고를 막는 자리다.
 * ===================================================== */
/*
  ⚠️ **1400 이 아니라 1690 이다.** 처음에 1400 으로 적었다가 재서 잡았다 —
     `.section` 이 1400px 을 담으려면 뷰포트가 그만큼이면 안 되고 **LNB 250 +
     여백 40 을 더한 1690px** 이어야 한다. 1400px 로 두었더니 1400px 창에서
     290px 이 넘쳤다. 고치려던 것을 그 폭에서 그대로 남긴 셈이었다.
*/
/* 이상 — 본문이 1400 을 담는다. 지금 모습 그대로 */
/* 미만 — LNB 가 덮개 서랍이 된다 (햄버거) */
/* 미만 — 본문에서 **두 칸이 뜻을 잃는다.** 나란히 두었을 때
   좁은 쪽이 제 일을 못 하는 폭이다 — 대시보드의 「차트 · 최근
   발행 게시물」 줄이 여기서 위아래로 쌓인다.
   ⚠️ 재서 나온 값이다: 2fr : 1fr 이라 목록 칸은 (헤더폭-20)/3 이고,
      834px 에서 259px · 768px 에서 237px 이 됐다. 그 칸에는
      로고 · 날짜 · 제목 · 노출 · 좋아요 다섯이 들어간다. */
/* 미만 — 한 단. 헤더의 「내 것」 묶음이 서랍으로 내려간다 */
/* ---------- 표 전용 눈금 둘 ----------
   ⚠️ **표만 이 아래가 더 필요하다.** 위의 넷은 「칸이 몇 줄로 서나」를 정하는
      눈금인데, 표는 그 아래에서도 **열을 하나씩 접어야** 한다.
      $bp-m(900) 부터 시작해 네 칸으로 접는다 — 900 · 768 · 600 · 480.

   ⚠️ 왜 768 부터인가. `min-width` 를 실측값으로 바로잡으면 가장 큰 표가
      725px(관리자 접속 이력)이다. 768px 뷰포트에서 본문은 728px 이라
      **거기까지는 아무것도 안 접어도 들어간다.** 그 아래부터가 진짜다.

   ⚠️ 예전 견본에는 1024 · 900 · 768 · 600 넷이 적혀 있었다. `min-width: 1300px`
      시절에 잡은 값이라 **1024 칸은 허깨비였다** — 멀쩡히 들어가는 열을 그
      폭에서 감추고 있었다. 그 하나만 지운다.
   ⚠️ **처음에 900 칸까지 지웠다가 되돌렸다.** 「768 부터 시작하면 된다」고
      적었는데, 계정 관리(9열)를 재 보니 **834px 에서 5px · 768px 에서 13px**
      넘쳤다. 열이 아홉이고 값이 한 줄로 서면 900 아래에서 이미 자리가 없다.
      재기 전에 칸을 지운 것이 틀렸다.
   ---------------------------------------- */
/* 미만 — 표에서 두 번째 곁열이 사라진다 (tc-p2) */
/* ⚠️ 900 칸은 $bp-m 을 그대로 쓴다 (tc-p4) — 본문이 두 칸을
      잃는 폭과 표가 곁열을 잃는 폭이 같은 자리다 */
/* 미만 — 표가 「언제 · 무엇 · 상태」 셋만 남는다 (tc-p1) */
/* ---------- 헤더 전용 눈금 둘 ----------
   ⚠️ **헤더는 뷰포트가 아니라 「제 폭」이 문제다.** LNB 가 켜져 있으면 290px 을
      먼저 떼이므로, 같은 뷰포트에서도 헤더에 남는 자리가 다르다.
        LNB 켜짐(≥1200)   헤더 = 뷰포트 - 290
        LNB 서랍(<1200)   헤더 = 뷰포트 -  40
      그래서 위의 셋과 눈금이 겹치지 않는다. 재서 나온 값은 이렇다.

        햄버거                       36
        빵부스러기                  236 ~ 273  (화면 이름에 따라)
        제목                         73 ~ 128
        기관 탭                     276
        「내 것」 다섯               496
        사이(20 × 2)                 40

        넷 다 서려면              1179   ← 기관 탭까지
        탭을 빼면                  983
        빵부스러기까지 빼면         645

   ⚠️ **이 숫자는 재서 나온 것이다.** 처음에는 눈대중으로 1030 이라고 적고
      눈금을 1400 으로 잡았는데, **1440px 에서 여전히 깨졌다** — 제목이
      「작업 …」으로 잘리고 빵부스러기가 「시스템 / 관리」로 두 줄이 됐다.
      실제로는 1179px 이 필요했다.

   ⚠️ 눈금을 이 둘로 고른 셈. 처음에 **탭도 768 에서 내렸다가** 1024px 에서
      헤더가 깨져 잡았다 — 제목이 「작…」으로 잘리고 빵부스러기가
      「시스템 / 관리」로, 단추가 「메뉴 / 구조도」로 두 줄이 됐다.
   ---------------------------------------- */
/* 기관 탭이 헤더에 설 수 있는 최소 뷰포트.
   여기는 LNB 가 켜진 구간이라 헤더 = 뷰포트 - 290 이고, 탭까지 서려면 1179 다.
     1179 + 290 = 1469  ← 계산상 바닥
   1500 으로 둔 것은 그 여유 31px 이 **화면 이름 한 글자**도 못 되기 때문이다. */
/* 빵부스러기를 접는 폭. 여기는 LNB 가 이미 서랍이라 헤더 = 뷰포트 - 40.
   ⚠️ **여기 위에서는 하드 눈금으로 지키지 않는다.** 빵부스러기는 줄바꿈 없이
      말줄임으로 줄어들게 해 두었다(_header.scss) — 「홈 › 시스템 관리 › …」가
      한 마디씩 두 줄로 꺾이는 것을 막는 것이 먼저다. 900 은 **줄어들어도
      읽을 것이 남지 않는 지점**이다(헤더 860, 빵을 뺀 나머지가 645).
   ⚠️ **LNB 가 켜져 있을 때 접지 않는다.** 그때는 왼쪽 메뉴의 강조가 같은 말을
      하지만, 서랍이 되면 **어디에 있는지 말하는 것이 이것뿐**이다. */
/*
  쓰는 법 — `@include under($bp-l) { ... }`
  ⚠️ **max-width 는 1px 을 뺀다.** 빼지 않으면 1200px 에서 두 규칙이 함께
     걸려, 그 폭에서만 LNB 가 켜진 채로 본문이 전폭이 되는 어긋난 그림이 뜬다.
  ⚠️ 0.02px 이 아니라 1px 이다. 이 제품은 정수 폭만 다룬다.
*/
/* 사이 — [$a, $b) */
/* ⚠️ 층(그림자·라운드) 눈금 — 아래 모든 파일이 이 변수를 쓴다 */
/* =====================================================
 * 층 — 그림자와 라운드의 단 (2026-09-10 확정)
 *
 * 「AI 가 만든 티가 난다」의 한 원인이 **같은 역할에 값이 여러 가지**인 것이다.
 * 재 보니 이랬다.
 *
 *   면(카드)에 쓰인 그림자    3가지    16화면 · 6화면 · 3화면
 *   라운드                   8가지    8px 44곳 · 12px 30곳 · 10px 24곳 · 6 · 5 · 4 · 3 · 2
 *   간격                    13가지
 *
 * ⚠️ **종류가 많은 것이 문제가 아니라, 뜻 없이 많은 것이 문제다.** 세 가지
 *    그림자가 「무엇이 더 중요한가」를 말하지 않고 그냥 파일마다 달랐다.
 *
 * ⚠️ **`10px 10px 10px` 가 세 화면에 남아 있었다.** 오른쪽·아래로 밀린 그림자다.
 *    `_dashboard.scss` 는 이미 2026-09 초에 「관리자 화면의 카드는 종이 한 장이지
 *    떠 있는 물건이 아니다 — 아래로만 살짝 지고 흐리게 퍼지게 한다」고 정하고
 *    `0 2px 8px` 로 바꿨는데, **그 결정이 나머지 화면에 퍼지지 않았다.**
 *    여기서 그 결정을 제품 전체로 옮긴다 — 새로 정하는 것이 아니다.
 * ===================================================== */
:root {
  /* ---------- 그림자 — 세 단 ----------
     ⚠️ 단은 **높이**를 뜻한다. 장식이 아니다.
        elev-1  바탕에 놓여 있다        카드 · 검색 상자 · 안내
        elev-2  본문 위에 떠 있다       모달 · 드롭다운 · 서랍 · 토스트 · 달력
        edge-up 화면에 붙어 있다        아래에 고정된 줄의 위쪽 그늘
     ⚠️ **한 화면에서 elev-2 는 하나뿐이다.** 둘이 겹치면 어느 것이 위인지
        가늠으로만 알게 된다. 모달이 떠 있는 동안 뒤는 막이 덮는다. */
  --elev-0: none;
  --elev-1: 0 2px 8px rgba(0, 0, 0, 0.06);
  --elev-2: 0 12px 28px rgba(0, 0, 0, 0.14);
  --edge-up: 0 -4px 12px rgba(0, 0, 0, 0.06);
  /*
    ⚠️ **`elev-0` 이 없으면 층을 만들 수 없다.** 사다리에 오르는 칸만 있고
       내리는 칸이 없으면, 주인공을 세우려고 그것만 올리게 된다 — 그러면
       전부 조금씩 떠서 결국 다시 평평해진다. **나머지를 내리는 쪽이 맞다.**
    ⚠️ `elev-0` 은 면이 없는 것이 아니라 **뜨지 않은 면**이다. 테두리로 경계를
       말한다 — 그 테두리 색이 아래 `--surface-line` 이다.
  */
  --surface-line: var(--gray-400);
  /* ---------- 세로 리듬 — 두 단 ----------
     ⚠️ **한 값(16px)으로 다 두었더니 묶음이 안 보였다.** 재 보니 이랬다.
          안내 → 고지   16px      둘 다 「참고」다
          고지 → 검색   16px      여기서 성격이 바뀐다
          검색 → 표     24px      이게 화면의 주인공(높이의 82%)이다
        성격이 바뀌는 자리와 안 바뀌는 자리가 **같은 간격**이라, 넷이 그냥
        줄줄이 쌓인 것으로 보인다.
     ⚠️ 두 단이면 충분하다. 셋을 두면 어느 것을 쓸지 매번 고민하게 된다.
          rhythm-tight  같은 묶음 안
          rhythm-loose  묶음이 바뀔 때 */
  --rhythm-tight: 12px;
  --rhythm-loose: 32px;
  /* ---------- 라운드 — 세 단 + 동그라미 ----------
     ⚠️ 크기 차이가 **역할 차이**여야 한다.
        radius-sm   부품    단추 · 입력칸 · 배지 · 타일
        radius-md   면      카드 · 상자 · 모달
        radius-pill 알약    상태 칩 · 탭
     ⚠️ 10px 24곳이 8 과 12 사이에 끼어 있었다. **면은 12, 부품은 8** 로 가른다 —
        10px 은 어느 쪽도 아니어서 옆에 놓이면 어긋나 보인다. */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-pill: 999px;
  --radius-circle: 50%;
}

/*
  ⚠️ **다크에서 그림자를 짙게 한다.** 어두운 바탕에서 rgba(0,0,0,.06) 은
     보이지 않아 카드 경계가 사라진다. 라이트와 같은 값을 쓰면 다크에서만
     층이 없어진다 — 한 번 겪으면 「다크에서 카드가 안 보인다」로 온다.
*/
[data-theme=dark] {
  --surface-line: var(--gray-600);
  --elev-1: 0 2px 8px rgba(0, 0, 0, 0.4);
  --elev-2: 0 12px 28px rgba(0, 0, 0, 0.55);
  --edge-up: 0 -4px 12px rgba(0, 0, 0, 0.35);
}

/* reset.scss */
*,
*:before,
*:after {
  box-sizing: border-box;
  flex-shrink: 1;
}

html {
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
  overflow-wrap: break-word;
  box-sizing: border-box;
  word-break: keep-all;
}

:lang(ko) {
  word-break: keep-all;
  word-wrap: break-word;
}

body,
h1,
h2,
h3,
h4,
h5,
h6,
div,
p,
address,
ul,
ol,
li,
dl,
dt,
dd,
table,
th,
td,
form,
fieldset,
legend,
hr {
  margin: 0;
  padding: 0;
}

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
  display: block;
}

::-moz-focus-inner {
  border: 0;
  padding: 0;
}

html ::-webkit-scrollbar {
  /* 스크롤 바(배경)의 너비 */
  width: 8px;
  height: 8px;
  /* 스크롤 바의 배경색 */
  background-color: #f6f6f6;
}
html {
  /* 스크롤 바의 색상 지정 */
}
html ::-webkit-scrollbar-thumb {
  /* 스크롤 바의 색상 */
  background-color: #5A5A5A;
  border-radius: var(--radius-sm);
}
html {
  /* 스크롤 바 호버 시 색상 지정 */
}
html ::-webkit-scrollbar-thumb:hover {
  /* 스크롤 바의 색상 */
}

body {
  color: var(--color-darken);
  font-family: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;
  box-sizing: border-box;
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: none;
     -moz-text-size-adjust: none;
          text-size-adjust: none;
}

caption,
legend {
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
}

table {
  border-spacing: 0;
  table-layout: fixed;
}

picture {
  display: inline-block;
}

picture > img {
  display: block;
}

img,
picture,
video,
canvas {
  max-width: 100%;
  border: none;
}

img {
  vertical-align: top;
}

hr.type-dashed {
  border-top-style: dashed;
}
hr.type-hide {
  display: none;
}

ol,
ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
}

dl,
dt,
dd {
  margin: 0;
  padding: 0;
}

a {
  display: inline-block;
  text-decoration: none;
  text-underline-position: under;
  color: var(--color-darken);
}

button {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background: transparent;
  border: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
  overflow: visible;
  color: inherit;
  cursor: pointer;
  font-size: inherit;
  font-family: inherit;
}
button:disabled {
  cursor: default;
}

input,
select,
textarea {
  box-sizing: border-box;
  outline: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

select::-ms-expand {
  display: none;
}

input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active {
  -webkit-text-fill-color: #000 !important;
  box-shadow: 0 0 0px 1000px #fff inset !important;
}

input:autofill,
input:autofill:hover,
input:autofill:focus,
input:autofill:active {
  -webkit-text-fill-color: #000 !important;
  box-shadow: 0 0 0px 1000px #fff inset !important;
}

svg {
  fill: transparent;
}

/*
  hidden 속성은 언제나 숨긴다
  ------------------------------------------------------------------
  브라우저 기본값은 `[hidden] { display: none }` 인데, 우리가 클래스에
  display 를 주는 순간(예: .btn { display: inline-flex }) 그 기본값이 진다.
  둘 다 요소 선택자보다 강해서 나중에 온 쪽이 이기기 때문이다.

  실제로 게시글 팝업에서 [삭제] 버튼을 hidden 으로 감춰 뒀는데, 「게시글 등록」
  으로 열어도 그대로 보였다(page/board/mng-board.jsp · assets/js/board.js).
  화면마다 `.btn[hidden] { display:none }` 같은 땜질을 하는 대신 여기 한 줄로 못박는다.

  !important 를 쓴 이유 — hidden 은 '지금 이 요소는 없는 것으로 쳐라'는 뜻이라
  어떤 display 규칙도 이겨야 한다. 예외를 두면 이 버그가 다시 돌아온다.
*/
[hidden] {
  display: none !important;
}

:root {
  /* gray */
  --gray-100: #fcfcfd;
  --gray-100-rgb: 252, 252, 253;
  --gray-200: #f9f9fb;
  --gray-200-rgb: 249, 249, 251;
  --gray-300: #eff0f3;
  --gray-300-rgb: 239, 240, 243;
  --gray-400: #e7e8ec;
  --gray-400-rgb: 231, 232, 236;
  --gray-500: #e0e1e6;
  --gray-500-rgb: 224, 225, 230;
  --gray-600: #d8d9e0;
  --gray-600-rgb: 216, 217, 224;
  --gray-700: #cdced7;
  --gray-700-rgb: 205, 206, 215;
  --gray-800: #b9bbc6;
  --gray-800-rgb: 185, 187, 198;
  --gray-900: #8b8d98;
  --gray-900-rgb: 139, 141, 152;
  /* semantic color */
  /*
    브랜드 색.
    ⚠️ 「화면 세팅 > 메뉴 색상」의 **강조색**이 이 값을 통째로 갈아 끼운다
       (assets/js/appearance.js). 인라인 스타일로 :root 에 박히므로 라이트·다크를
       가리지 않고 이긴다. 즉 이 파일의 값은 **고르지 않았을 때의 기본값**이다.
    ⚠️ 아래 셋은 여기서 파생된다. 강조색을 바꾸면 함께 따라온다 —
       --color-primary-deep · --bg-primary-soft · --on-primary.
       앞의 둘은 쓰이는데 정의가 없어 규칙이 통째로 죽어 있었다(2026-09-07 발견).
  */
  /* ⚠️ 버건디(#9F1836)였다 → 파랑으로 되돌린다(2026-09-23 대표님).
        기본 LNB 배경이 파스텔 분홍→하늘 그라데이션인데 강조색만 버건디라
        「기본」을 고르면 배경과 강조가 서로 다른 시절의 색이었다. */
  --color-primary: #289DD2;
  --color-primary-rgb: 40, 157, 210;
  /* 옅은 면 — 배지·칩의 바탕. rgb 를 참조하므로 강조색을 따라온다 */
  --bg-primary-soft: rgba(var(--color-primary-rgb), 0.12);
  /* 그 옅은 면 위에 얹는 글자 — 기본색보다 어둡게. JS 가 강조색에 맞춰 다시 계산한다 */
  --color-primary-deep: #1B6D93;
  /*
    브랜드 색 **면 위**에 얹는 글자색.
    ⚠️ 예전에는 이런 곳마다 #fff 를 박아 뒀다. 강조색이 고정이던 때는 맞았지만,
       이제 관리자가 노랑·연회색을 고를 수 있다 — 흰 글자가 사라진다.
       JS 가 고른 색의 밝기를 재서 흰색/검은색 중 읽히는 쪽을 넣는다.
  */
  --on-primary: #fff;
  /*
    브랜드 색 면 위의 **아이콘**(svg 를 <img> 로 넣는다) 을 --on-primary 와 같은
    색으로 만드는 필터. 흰색용과 검은색용 두 벌뿐이라 값으로 둔다.
    ⚠️ --on-primary 를 바꾸면 이것도 함께 바꿔야 한다. appearance.js 가 짝으로 맞춘다.
  */
  --on-primary-filter: brightness(0) saturate(100%) invert(100%);
  --color-secondary: #C09C63;
  --color-secondary-rgb: 192, 156, 99;
  --color-darken: #000;
  --color-darken-rgb: 0, 0, 0;
  --color-white: #fff;
  --color-white-rgb: 255, 255, 255;
  /*
    보조 텍스트 — 본문보다 한 단 낮지만 **읽히는** 회색.
    ⚠️ 이 프로젝트의 --gray-100~900 은 전부 밝다. 면과 테두리를 위한 눈금이지
       글자를 위한 눈금이 아니다. 가장 어두운 --gray-900(#8b8d98)조차 흰 바탕에서
       3.30:1 이라 본문 기준(WCAG AA 4.5:1)에 못 미친다.
       실제로 브레드크럼을 --gray-600 으로 칠했더니 1.41:1 — 거의 안 보였다.
    ⚠️ 그래서 글자용 눈금을 따로 둔다. 색상·채도는 --gray-900 과 같은 계열(231°/6%)로
       두고 명도만 44% 로 낮춘 값이다. 흰 바탕 5.22:1 로 통과한다.
  */
  --text-muted: #6a6c77;
  --text-muted-rgb: 106, 108, 119;
  --color-point: #107C41;
  --color-point-rgb: 16, 124, 65;
  --color-disabled: var(--gray-200);
  --color-disabled-rgb: var(--gray-200-rgb);
  --color-red: #DE4841;
  --color-red-rgb: 222, 72, 65;
  /*
    ---- 경고(주황) ----
    ⚠️ 「고쳐야 함(빨강)」과 「있으나 쓸모없음(주황)」은 다른 말이라 색도 달라야 한다.
       그런데 이 팔레트에는 그 중간이 없었다 — point 는 청록(#5D9DAA)이라
       '끝났다'로 읽히고, secondary 는 보라라 뜻이 없다.
       그래서 주황을 하나 들인다. 쓰는 곳 : 웹접근성 점검(page/accessibility/).
    ⚠️ 흰 바탕 대비 5.3:1 이다. 작은 글자(4.5:1 기준)에도 쓸 수 있는 어두운 주황을
       골랐다 — 밝은 주황(#F0A020 류)은 3:1 도 안 나와 배지 글자가 안 읽힌다.
  */
  --color-warn: #B26A00;
  --color-warn-rgb: 178, 106, 0;
  --color-blue: #4568F2;
  --color-blue-rgb: 69, 104, 242;
  /* border */
  /*
    ---- LNB 외형 (화면 설정에서 덮어쓴다) ----
    page/setting/lnb-color.jsp · logo.jsp 에서 고른 값이 assets/js/appearance.js 를 통해
    :root 인라인 스타일로 이 토큰들을 덮는다. 저장값이 없으면 아래 기본값이 그대로 쓰인다.

    ⚠️ 값을 바꾸려면 여기만 고친다. components/_aside.scss 에 색을 직접 박으면
       화면 설정이 그 자리를 못 덮어 '골랐는데 안 바뀌는' 칸이 생긴다.
  */
  /*
    ⚠️ 5단 그라데이션이다. 2단으로 줄이면 가운데가 탁해진다 —
       분홍에서 하늘로 넘어가는 구간(28~78%)에 중간색을 두어야 매끈하다.
  */
  --aside-bg: linear-gradient(
    180deg,
    #f5e6e8 0%,
    #f2eef1 28%,
    #e6edf5 55%,
    #cfe3f7 78%,
    #9fc7ec 100%
  );
  --aside-accent: var(--color-primary);
  --aside-accent-soft: rgba(var(--color-primary-rgb), 0.5);
  --aside-text: var(--color-darken);
  --aside-logo: url("../images/logo-cms-revehit.png");
  --border-primary: var(--color-primary);
  --border-primary-rgb: var(--color-primary-rgb);
  --border-secondary: var(--color-secondary);
  --border-secondary-rgb: var(--color-secondary-rgb);
  --border-darken: var(--color-darken);
  --border-darken-rgb: var(--color-darken-rgb);
  --border-white: var(--color-white);
  --border-white-rgb: var(--color-white-rgb);
  --border-point: var(--color-point);
  --border-point-rgb: var(--color-point-rgb);
  --border-disabled: var(--color-disabled);
  --border-disabled-rgb: var(--color-disabled-rgb);
  --border-red: var(--color-red);
  --border-red-rgb: var(--color-red-rgb);
  --border-blue: var(--color-blue);
  --border-blue-rgb: var(--color-blue-rgb);
  /* background */
  --bg-primary: var(--color-primary);
  --bg-primary-rgb: var(--color-primary-rgb);
  --bg-secondary: var(--color-secondary);
  --bg-secondary-rgb: var(--color-secondary-rgb);
  --bg-darken: var(--color-darken);
  --bg-darken-rgb: var(--color-darken-rgb);
  --bg-white: var(--color-white);
  --bg-white-rgb: var(--color-white-rgb);
  --bg-point: var(--color-point);
  --bg-point-rgb: var(--color-point-rgb);
  --bg-disabled: var(--color-disabled);
  --bg-disabled-rgb: var(--color-disabled-rgb);
  --bg-red: var(--color-red);
  --bg-red-rgb: var(--color-red-rgb);
  --bg-blue: var(--color-blue);
  --bg-blue-rgb: var(--color-blue-rgb);
}

/* ================================
   Dark Theme (Charcoal baseline)
   ================================ */
[data-theme=dark] {
  /* gray scale (라이트 → 다크 톤 매핑) */
  --gray-100: #1a1a1a;
  --gray-100-rgb: 26, 26, 26;
  --gray-200: #1e1e1e;
  --gray-200-rgb: 30, 30, 30; /* 카드/패널 기본 배경 */
  --gray-300: #232323;
  --gray-300-rgb: 35, 35, 35;
  --gray-400: #2c2c2c;
  --gray-400-rgb: 44, 44, 44;
  --gray-500: #383838;
  --gray-500-rgb: 56, 56, 56;
  --gray-600: #444444;
  --gray-600-rgb: 68, 68, 68; /* 비활성 텍스트/아이콘 */
  --gray-700: #555555;
  --gray-700-rgb: 85, 85, 85;
  --gray-800: #666666;
  --gray-800-rgb: 102, 102, 102;
  --gray-900: #777777;
  --gray-900-rgb: 119, 119, 119; /* 보조 텍스트 */
  /* semantic color (명도/채도 조정으로 대비 확보) */
  --color-white: #121212;
  --color-white-rgb: 18, 18, 18; /* 전체 배경(페이지) */
  --color-darken: #f5f5f5;
  --color-darken-rgb: 245, 245, 245; /* 기본 본문 텍스트 */
  --text-muted: #989aa4;
  --text-muted-rgb: 152, 154, 164; /* 보조 텍스트 — #121212 위 6.68:1 */
  --color-primary: #289DD2;
  --color-primary-rgb: 40, 157, 210;
  --bg-primary-soft: rgba(var(--color-primary-rgb), 0.22);
  --color-primary-deep: #8FD0EE; /* 어두운 바탕에서는 옅은 쪽이 읽힌다 */
  --on-primary: #fff;
  --on-primary-filter: brightness(0) saturate(100%) invert(100%);
  --color-secondary: #C09C63;
  --color-secondary-rgb: 192, 156, 99;
  --color-point: #66BD50;
  --color-point-rgb: 102, 189, 80;
  --color-red: #DE4841;
  --color-red-rgb: 222, 72, 65;
  --color-warn: #E0A63A;
  --color-warn-rgb: 224, 166, 58; /* 어두운 바탕에서는 밝혀 준다 */
  --color-blue: #418be2;
  --color-blue-rgb: 69, 104, 242;
  --color-disabled: var(--gray-600);
  --color-disabled-rgb: var(--gray-600-rgb);
  /* border (rgba(var(--*-rgb), alpha)로 반투명 활용 추천) */
  --border-primary: var(--color-primary);
  --border-primary-rgb: var(--color-primary-rgb);
  --border-secondary: var(--color-secondary);
  --border-secondary-rgb: var(--color-secondary-rgb);
  --border-darken: var(--color-darken);
  --border-darken-rgb: var(--color-darken-rgb);
  --border-white: var(--color-white);
  --border-white-rgb: var(--color-white-rgb);
  --border-point: var(--color-point);
  --border-point-rgb: var(--color-point-rgb);
  --border-disabled: var(--color-disabled);
  --border-disabled-rgb: var(--color-disabled-rgb);
  --border-red: var(--color-red);
  --border-red-rgb: var(--color-red-rgb);
  --border-blue: var(--color-blue);
  --border-blue-rgb: var(--color-blue-rgb);
  /* background (컴포넌트/상태별 용도 매핑) */
  --bg-white: var(--color-white);
  --bg-white-rgb: var(--color-white-rgb); /* 페이지 루트 배경 */
  --bg-darken: var(--color-darken);
  --bg-darken-rgb: var(--color-darken-rgb); /* 반전(라이트) 배경용 */
  --bg-primary: var(--color-primary);
  --bg-primary-rgb: var(--color-primary-rgb);
  --bg-secondary: var(--color-secondary);
  --bg-secondary-rgb: var(--color-secondary-rgb);
  --bg-point: var(--color-point);
  --bg-point-rgb: var(--color-point-rgb);
  --bg-disabled: #2a2a2a;
  --bg-disabled-rgb: 42, 42, 42;
  --bg-point: var(--color-point);
  --bg-point-rgb: var(--color-point-rgb);
  /* 보너스: 자주 쓰는 overlay/헤어라인 */
  --overlay-01: rgba(0, 0, 0, .3);
  --overlay-02: rgba(0, 0, 0, .6);
  --hairline: rgba(var(--border-white-rgb), .08); /* 어두운 배경 위 1px 경계 */
}

/* ================================
   revehitSNS 확장 토큰 — **개발본 전용**
   (React tokens.css에서 역이식)

   ⚠️ 퍼블(pub 1b2de75)에는 없는 블록이다. 퍼블 자산을 다시 반영할 때
      이 블록은 **지우지 말 것** — 게시글 화면 셋(platform · postWrite ·
      reviewQueue)의 인라인 스타일이 --text-secondary 를 쓴다.
   ⚠️ --radius-* 는 여기 두지 않는다. 퍼블이 _elevation.scss 에서
      세 단(sm 8 · md 12 · pill · circle)으로 정의한다 — 여기에 또 두면
      나중에 온 쪽이 이겨서 퍼블 마크업의 라운드가 조용히 어긋난다.
   ================================ */
:root {
  /* surface */
  --surface-page: var(--color-white);
  --surface-card: var(--color-white);
  --surface-aside: var(--color-white);
  --surface-header: var(--color-white);
  /* text */
  --text-primary: var(--color-darken);
  --text-secondary: var(--gray-900);
  --text-disabled: var(--gray-800);
  --text-on-primary: #fff;
  /* border / shadow */
  --border-default: var(--gray-500);
  --border-focus: var(--color-primary);
  --shadow-card: 0 0 12px rgba(0, 0, 0, .08);
  --shadow-aside: 2px 0 8px rgba(0, 0, 0, .06);
  /* layout */
  --aside-width: 250px;
  --header-height: 75px;
  /* spacing */
  --space-4: 4px;
  --space-8: 8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-20: 20px;
  --space-24: 24px;
  --space-32: 32px;
  --space-48: 48px;
  /* SNS brand */
  --sns-linkedin-bg: #e8f0fe;
  --sns-linkedin-text: #0a66c2;
  --sns-instagram-bg: #fce4ec;
  --sns-instagram-text: #c2185b;
  --sns-facebook-bg: #e3f2fd;
  --sns-facebook-text: #1565c0;
  --sns-x-bg: #f0f0f0;
  --sns-x-text: #000;
  /* chart (dashboard/index.jsp의 COLORS 상수를 변수화) */
  --chart-main: #891a26;
  --chart-point: #d4af37;
  --chart-sub: #6c7a89;
  --chart-rust: #b85c38;
  --chart-sage: #5c8a6a;
  --chart-mauve: #9b5e82;
  --transition-base: .2s ease;
}

[data-theme=dark] {
  --surface-page: #121212;
  --surface-card: #1e1e1e;
  --surface-aside: #1a1a1a;
  --surface-header: #1a1a1a;
  --text-primary: #f5f5f5;
  --text-secondary: #aaa;
  --text-disabled: #666;
  --border-default: #383838;
  --shadow-card: 0 0 12px rgba(0, 0, 0, .4);
  --shadow-aside: 2px 0 8px rgba(0, 0, 0, .4);
  --sns-x-bg: #2a2a2a;
  --sns-x-text: #f5f5f5;
}

/* Pretendard */
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-Black.woff") format("woff"), url("fonts/Pretendard-Black.woff2") format("woff2");
  font-weight: 900;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-ExtraBold.woff") format("woff"), url("fonts/Pretendard-ExtraBold.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-Bold.woff") format("woff"), url("fonts/Pretendard-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-SemiBold.woff") format("woff"), url("fonts/Pretendard-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-Medium.woff") format("woff"), url("fonts/Pretendard-Medium.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-Regular.woff") format("woff"), url("fonts/Pretendard-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-Light.woff") format("woff"), url("fonts/Pretendard-Light.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-ExtraLight.woff") format("woff"), url("fonts/Pretendard-ExtraLight.woff2") format("woff2");
  font-weight: 200;
  font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  font-style: normal;
  src: url("fonts/Pretendard-Thin.woff") format("woff"), url("fonts/Pretendard-Thin.woff2") format("woff2");
  font-weight: 100;
  font-display: swap;
}
.container {
  width: 100%;
  max-width: 100%;
  margin: 0 auto;
}

/* ================================================= */
/* 1. 폰트 가중치 Map 및 기본 변수 정의 (핵심 유틸리티) */
/* ================================================= */
/* ============================================== */
/* 2. 타이포그래피 스타일 Map 정의 (디자인 시스템) */
/* ============================================== */
/* ================================================= */
/* 2-1. 반응형 size Map (PC 대비 size만 오버라이드) */
/* ================================================= */
/* ============================================= */
/* 3. 공용 유틸: 레벨별 size 조회 (브레이크포인트) */
/* ============================================= */
/* ============================================= */
/* 4. 범용 믹스인: @include body-1-1 형태로 사용 */
/* - 핵심: selector 컨텍스트(&)로 미디어를 함께 출력 */
/* ============================================= */
/* ============================================= */
/* 5. 레벨별 믹스인: 최종 사용 형태 유지 */
/* ============================================= */
/* ========================================== */
/* 6. 클래스 자동 생성(선택): 기존 형태 유지 */
/* ========================================== */
.display-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 72px;
}

.title-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 48px;
}

.title-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 40px;
}

.title-3 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 32px;
}

.title-4 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 24px;
}

.body-1-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 24px;
}

.body-1-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 24px;
}

.body-2-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
}

.body-2-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 20px;
}

.body-3-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}

.body-3-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
}

.body-4-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
}

.body-4-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}

.body-5-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 14px;
}

.body-5-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
}

:root {
  /* ========================================= */
  /* 🚨 전역 필터 변수 (GLOBAL FILTER VARIABLES) 🚨 */
  /* ========================================= */
  --filter-default: brightness(0) saturate(100%) invert(97%) sepia(1%) saturate(153%) hue-rotate(355deg) brightness(79%) contrast(88%);
  --filter-primary: brightness(0) saturate(100%) invert(51%) sepia(36%) saturate(973%) hue-rotate(153deg) brightness(97%) contrast(87%);
  --filter-secondary: brightness(0) saturate(100%) invert(88%) sepia(96%) saturate(2725%) hue-rotate(246deg) brightness(76%) contrast(85%);
  --filter-white: brightness(0) saturate(100%) invert(99%) sepia(35%) saturate(41%) hue-rotate(186deg) brightness(109%) contrast(98%);
  --filter-dark: brightness(0) saturate(100%) invert(0%) sepia(10%) saturate(7498%) hue-rotate(85deg) brightness(94%) contrast(97%);
}

.filter-primary {
  filter: var(--filter-primary) !important;
}

.filter-secondary {
  filter: var(--filter-secondary) !important;
}

.filter-white {
  filter: var(--filter-white) !important;
}

.filter-dark {
  filter: var(--filter-dark) !important;
}

/* =========================================
   Button
   - Filled: hover/focus/active → rgba(var(--*-rgb), α)
   - Line  : gray 배경 + 텍스트/보더만 강조
========================================= */
/*
  단추 규격
  ==================================================================
  높이는 **네 개뿐**이다. 자리가 크기를 정한다 — 눈대중으로 고르지 않는다.

    36px  기본        화면 바닥의 저장·취소, 모달 바닥, 검색 카드,
                      표 위 도구 줄, 아이콘만 있는 단추(정사각 36×36).
                      이 제품 단추의 대부분이다.
    40px  .size-md    **입력칸·드롭다운과 나란히 서는** 단추.
                      .text-field 와 .dropdown_button 이 40px 이다.
                      36px 을 옆에 세우면 4px 이 뜬다 — 한 줄로 안 읽힌다.
    30px  .size-sm    **글·표 칸·상자 머리줄에 붙는** 단추.
                      옆에 선 것이 글이라 36px 은 그 줄을 밀어낸다.
                      글자는 12px 밑으로 내리지 않는다 — 눈과 손가락이 못 따라간다.
    50px  .size-lg    **로그인 화면의 단독 단추.** 관리자 화면 안에서는 쓰지 않는다.
                      한 화면에 할 일이 하나뿐일 때만 이만큼 커진다.

  ⚠️ 높이를 padding 으로 만들지 않는다. 글자 크기가 조금만 달라져도 같은
     자리의 단추들이 1~2px 씩 어긋난다. 실제로 그렇게 어긋나 있었다 —
     헤더의 로그아웃(34px)이 옆의 아이콘 단추(36px)와, 권한 세팅의
     「전체 읽기」(25px)가 같은 줄의 것들과 맞지 않았다.
     그래서 아래 네 값을 토큰으로 두고, .btn 이 아닌 전용 단추도 이것을 쓴다.

  ⚠️ **규격 밖에 두는 것** — 단추 모양이지만 크기를 스스로 갖는 부품들이다.
       .modal-close(32)   창 모서리의 닫기. 제목 줄 높이를 따른다.
       .dropdown_button(40) 단추가 아니라 **입력 컨트롤**이다.
       .dp-btn(20)        입력칸 **안에** 들어가는 달력 아이콘.
       달력의 .nav(32)    달력 팝업 안의 월 이동 화살표. 팝업의 부품이다.
       .tag-del(18)       칩 안의 지우기.
       .se-grip(22×24)    장면 줄의 차례 바꾸기 손잡이. 줄 안의 부품이다.
       .pager-item(36)    쪽 번호. 기본과 같은 36 이라 따로 맞출 것이 없다.
       .tab · .preset-card · .page-guide-toggle · .theme-opt
                          각자의 부품 규칙을 따른다.
*/
:root {
  --btn-h: 36px;
  --btn-h-sm: 30px;
  --btn-h-md: 40px;
  --btn-h-lg: 50px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px; /* 텍스트+아이콘 간격 */
  min-width: 80px;
  /*
    ⚠️ **단추 글자는 꺾이지 않는다.** 칸이 좁아지면 글자가 두 줄이 되는데
       (375px 모달 발의 「지금 발행」이 「지금 / 발행」으로 꺾였다), 단추는
       **한 덩이로 읽혀야** 누를 것인지 판단이 된다.
       줄이 좁으면 단추가 다음 줄로 접히는 쪽이 맞다 — 배지와 같은 규칙이다.
  */
  white-space: nowrap;
  height: var(--btn-h);
  padding: 0 16px;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--bg-white);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}
.btn span {
  flex-shrink: 0;
}
.btn:hover, .btn:focus {
  outline: none;
  /* 필요 시 inset 효과 사용
  box-shadow: inset 0 0 0 3px rgba(0,0,0,.08);
  */
}
.btn:disabled, .btn.is-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  box-shadow: none;
}
.btn {
  /* =======================
  0) size
  ======================= */
  /* 글·표 칸·상자 머리줄에 붙는 단추 — 위 「단추 규격」 참고 */
}
.btn.size-sm {
  min-width: auto;
  height: var(--btn-h-sm);
  padding: 0 10px;
  gap: 4px;
  font-size: 13px;
}
.btn {
  /* 입력칸·드롭다운과 나란히 서는 단추 — 저쪽이 40px 이다 */
}
.btn.size-md {
  height: var(--btn-h-md);
  gap: 8px;
}
.btn {
  /* 로그인 화면의 단독 단추 — 관리자 화면 안에서는 쓰지 않는다 */
}
.btn.size-lg {
  height: var(--btn-h-lg);
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
  gap: 12px;
}
.btn {
  /* =======================
  1) Filled 타입
  ======================= */
}
.btn.btn-primary {
  background: var(--color-primary);
  border-color: var(--color-primary);
  /* ⚠️ #fff 였다. 강조색을 관리자가 고르게 되면서 밝은 색이면 글자가 사라진다 */
  color: var(--on-primary);
}
.btn.btn-primary:hover:not(:disabled), .btn.btn-primary:focus:not(:disabled) {
  background: rgba(var(--color-primary-rgb), 0.85);
  border-color: rgba(var(--color-primary-rgb), 0.85);
}
.btn.btn-primary:active:not(:disabled) {
  background: rgba(var(--color-primary-rgb), 0.7);
  border-color: rgba(var(--color-primary-rgb), 0.7);
}
.btn.btn-secondary {
  background: var(--color-secondary);
  border-color: var(--color-secondary);
  color: #fff;
}
.btn.btn-secondary:hover:not(:disabled), .btn.btn-secondary:focus:not(:disabled) {
  background: rgba(var(--color-secondary-rgb), 0.85);
  border-color: rgba(var(--color-secondary-rgb), 0.85);
}
.btn.btn-secondary:active:not(:disabled) {
  background: rgba(var(--color-secondary-rgb), 0.7);
  border-color: rgba(var(--color-secondary-rgb), 0.7);
}
.btn.btn-point {
  background: var(--color-point);
  border-color: var(--color-point);
  color: #fff;
}
.btn.btn-point:hover:not(:disabled), .btn.btn-point:focus:not(:disabled) {
  background: rgba(var(--color-point-rgb), 0.85);
  border-color: rgba(var(--color-point-rgb), 0.85);
}
.btn.btn-point:active:not(:disabled) {
  background: rgba(var(--color-point-rgb), 0.7);
  border-color: rgba(var(--color-point-rgb), 0.7);
}
.btn.btn-red {
  background: var(--color-red);
  border-color: var(--color-red);
  color: #fff;
}
.btn.btn-red:hover:not(:disabled), .btn.btn-red:focus:not(:disabled) {
  background: rgba(var(--color-red-rgb), 0.85);
  border-color: rgba(var(--color-red-rgb), 0.85);
}
.btn.btn-red:active:not(:disabled) {
  background: rgba(var(--color-red-rgb), 0.7);
  border-color: rgba(var(--color-red-rgb), 0.7);
}
.btn.btn-blue {
  background: var(--color-blue);
  border-color: var(--color-blue);
  color: #fff;
}
.btn.btn-blue:hover:not(:disabled), .btn.btn-blue:focus:not(:disabled) {
  background: rgba(var(--color-blue-rgb), 0.85);
  border-color: rgba(var(--color-blue-rgb), 0.85);
}
.btn.btn-blue:active:not(:disabled) {
  background: rgba(var(--color-blue-rgb), 0.7);
  border-color: rgba(var(--color-blue-rgb), 0.7);
}
.btn.btn-dark {
  background: var(--bg-darken);
  border-color: var(--border-darken);
  color: var(--color-white);
}
.btn.btn-dark:hover:not(:disabled), .btn.btn-dark:focus:not(:disabled) {
  background: rgba(var(--color-darken-rgb), 0.85);
  border-color: rgba(var(--color-darken-rgb), 0.85);
}
.btn.btn-dark:active:not(:disabled) {
  background: rgba(var(--color-darken-rgb), 0.7);
  border-color: rgba(var(--color-darken-rgb), 0.7);
}
.btn {
  /* =======================
  2) Outlined 타입
  ======================= */
}
.btn.btn-red-line {
  background: var(--bg-white);
  border-color: var(--color-red);
  color: var(--color-red);
}
.btn.btn-red-line:hover:not(:disabled) {
  background: rgb(var(--gray-200-rgb));
  border-color: rgba(var(--color-red-rgb), 0.85);
  color: rgba(var(--color-red-rgb), 0.85);
}
.btn.btn-red-line:active:not(:disabled) {
  background: rgb(var(--gray-300-rgb));
  border-color: rgba(var(--color-red-rgb), 0.7);
  color: rgba(var(--color-red-rgb), 0.7);
}
.btn.btn-blue-line {
  background: var(--bg-white);
  border-color: var(--color-blue);
  color: var(--color-blue);
}
.btn.btn-blue-line:hover:not(:disabled) {
  background: rgb(var(--gray-200-rgb));
  border-color: rgba(var(--color-blue-rgb), 0.85);
  color: rgba(var(--color-blue-rgb), 0.85);
}
.btn.btn-blue-line:active:not(:disabled) {
  background: rgb(var(--gray-300-rgb));
  border-color: rgba(var(--color-blue-rgb), 0.7);
  color: rgba(var(--color-blue-rgb), 0.7);
}
.btn.btn-dark-line {
  background: var(--bg-white);
  border-color: var(--border-darken);
  color: var(--color-darken);
}
.btn.btn-dark-line.btn-icon-left svg, .btn.btn-dark-line.btn-icon-left i, .btn.btn-dark-line.btn-icon-right svg, .btn.btn-dark-line.btn-icon-right i {
  width: 16px;
  height: 16px;
  /* Filled 버튼 대비 아이콘 가독성 확보 */
  filter: brightness(0) saturate(100%);
}
.btn.btn-dark-line:hover:not(:disabled) {
  background: rgb(var(--gray-200-rgb));
  border-color: rgba(var(--color-darken-rgb), 0.85);
  color: rgba(var(--color-darken-rgb), 0.85);
}
.btn.btn-dark-line:active:not(:disabled) {
  background: rgb(var(--gray-300-rgb));
  border-color: rgba(var(--color-darken-rgb), 0.7);
  color: rgba(var(--color-darken-rgb), 0.7);
}
.btn {
  /* =======================
  3) 아이콘 조합
  ======================= */
}
.btn.btn-icon-left svg, .btn.btn-icon-left i, .btn.btn-icon-right svg, .btn.btn-icon-right i {
  width: 16px;
  height: 16px;
  /* Filled 버튼 대비 아이콘 가독성 확보 */
  filter: var(--filter-white);
}
.btn {
  /*
    파일 형식 아이콘은 색을 뒤집지 않는다.

    ⚠️ 위 filter 는 **단색 선 아이콘**(icon-plus · icon-search · icon-recycle …)을
       단추 글자색에 맞추려고 건 것이다. 그런데 icon-xls 같은 파일 형식 아이콘은
       **색이 곧 뜻이다** — 초록 시트에 흰 XLS 글자로 「엑셀」을 말한다.
       거기에 filter 를 걸면 전부 한 색으로 뭉개져서 **까만 덩어리**가 된다.
       (dark-line 단추에서는 검정, filled 단추에서는 흰 덩어리)
       실제로 그렇게 보여서 「아이콘이 깨졌다」는 지적을 받은 자리다 —
       page/translate/glossary.jsp, page/nonPayment/nonPayment.jsp,
       page/platform/postList.jsp 셋에서 같은 증상이었다.
    ⚠️ 그래서 filter 를 **푼다.** 아이콘 색이 단추 글자색과 안 맞는 것이
       뜻을 잃는 것보다 낫다. 파일 형식 아이콘은 원래 브랜드색으로 읽는 물건이다.
    ⚠️ 지금 단추 안에 들어가는 건 icon-xls 뿐이지만, 나머지 형식도 같이 적어 둔다.
       나중에 하나를 단추에 넣고 또 까만 덩어리를 보게 되는 일을 막는다.
  */
}
.btn.btn-icon-left .icon-xls,
.btn.btn-icon-left .icon-doc,
.btn.btn-icon-left .icon-pdf,
.btn.btn-icon-left .icon-hwp,
.btn.btn-icon-left .icon-jpg,
.btn.btn-icon-left .icon-png, .btn.btn-icon-right .icon-xls,
.btn.btn-icon-right .icon-doc,
.btn.btn-icon-right .icon-pdf,
.btn.btn-icon-right .icon-hwp,
.btn.btn-icon-right .icon-jpg,
.btn.btn-icon-right .icon-png {
  /*
    ⚠️ !important 다. filter 를 거는 자리가 넷이나 되고
       (.btn-icon-*, .btn-dark-line 안, 다크모드 블록 둘)
       그중 셋이 이 규칙보다 무겁다. 여기서 무게 싸움을 하면
       나중에 블록이 하나 더 생길 때 또 까맣게 된다.
       「파일 형식 아이콘은 어떤 경우에도 색을 뒤집지 않는다」는
       예외가 없는 규칙이라 아예 못 덮게 둔다.
  */
  filter: none !important;
}
.btn {
  /* 방향 유틸 필요 시 해제
  &.btn-icon-left { flex-direction: row; }
  &.btn-icon-right { flex-direction: row-reverse; }
  */
  /* =======================
  4) 아이콘만 버튼
  ======================= */
}
.btn.btn-icon-only {
  min-width: auto;
  width: var(--btn-h);
  height: var(--btn-h);
  padding: 0;
  border-radius: var(--radius-sm);
}
.btn.btn-icon-only svg, .btn.btn-icon-only i {
  width: 18px;
  height: 18px;
  pointer-events: none;
  filter: var(--filter-dark);
}
.btn.btn-icon-only:hover:not(:disabled), .btn.btn-icon-only:focus:not(:disabled) {
  background-color: rgb(var(--gray-200-rgb));
}
.btn.btn-icon-only:hover:not(:disabled) svg, .btn.btn-icon-only:hover:not(:disabled) i, .btn.btn-icon-only:focus:not(:disabled) svg, .btn.btn-icon-only:focus:not(:disabled) i {
  filter: brightness(0) saturate(100%) invert(0%) sepia(22%) saturate(4270%) hue-rotate(73deg) brightness(91%) contrast(87%);
}
.btn.btn-icon-only:hover:not(:disabled).btn-primary, .btn.btn-icon-only:focus:not(:disabled).btn-primary {
  background-color: rgba(var(--bg-primary-rgb), 0.85);
}
.btn.btn-icon-only:hover:not(:disabled).btn-secondary, .btn.btn-icon-only:focus:not(:disabled).btn-secondary {
  background-color: rgba(var(--bg-secondary-rgb), 0.85);
}
.btn.btn-icon-only:hover:not(:disabled).btn-point, .btn.btn-icon-only:focus:not(:disabled).btn-point {
  background-color: rgba(var(--bg-point-rgb), 0.85);
}
.btn.btn-icon-only:hover:not(:disabled).btn-red, .btn.btn-icon-only:focus:not(:disabled).btn-red {
  background-color: rgba(var(--bg-red-rgb), 0.85);
}
.btn.btn-icon-only:hover:not(:disabled).btn-blue, .btn.btn-icon-only:focus:not(:disabled).btn-blue {
  background-color: rgba(var(--bg-blue-rgb), 0.85);
}
.btn.btn-icon-only:active:not(:disabled) {
  background: rgb(var(--gray-300-rgb));
}
.btn.btn-icon-only:active:not(:disabled) svg, .btn.btn-icon-only:active:not(:disabled) i {
  filter: brightness(0) saturate(100%) invert(0%) sepia(22%) saturate(4270%) hue-rotate(73deg) brightness(91%) contrast(87%);
}

/* darkmode */
[data-theme=dark] .btn.btn-dark-line.btn-icon-left svg, [data-theme=dark] .btn.btn-dark-line.btn-icon-left i {
  filter: brightness(0) saturate(100%) invert(99%) sepia(35%) saturate(41%) hue-rotate(186deg) brightness(109%) contrast(98%);
}
[data-theme=dark] .btn.btn-dark-line.btn-icon-right svg, [data-theme=dark] .btn.btn-dark-line.btn-icon-right i {
  filter: brightness(0) saturate(100%) invert(99%) sepia(35%) saturate(41%) hue-rotate(186deg) brightness(109%) contrast(98%);
}
[data-theme=dark] .btn.btn-icon-only svg, [data-theme=dark] .btn.btn-icon-only i {
  filter: brightness(0) saturate(100%) invert(99%) sepia(35%) saturate(41%) hue-rotate(186deg) brightness(109%) contrast(98%);
}
[data-theme=dark] .btn.btn-icon-only:hover svg, [data-theme=dark] .btn.btn-icon-only:hover i {
  filter: brightness(0) saturate(100%) invert(99%) sepia(35%) saturate(41%) hue-rotate(186deg) brightness(109%) contrast(98%);
}

/*
  ⚠️ 입력칸 글자는 본문보다 한 눈금 작다(16 → 14). 드롭다운·textarea 와
     같은 크기다 — 검색 필터 한 줄에 이 셋이 나란히 서는데, 크기가
     제각각이면 같은 줄인데도 눈높이가 어긋나 보였다.
  ⚠️ placeholder 는 따로 적지 않는다. 글꼴 크기를 물려받으므로 함께 줄어든다.
     여기서 다시 적으면 다음에 눈금을 옮길 때 고칠 자리가 둘이 된다.
*/
input {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  border: none;
  width: 100%;
  height: 100%;
  background-color: transparent;
}

.text-field {
  width: 100%;
  height: 40px;
  border-radius: var(--radius-sm);
  padding: 0 10px;
  display: flex;
  align-items: center;
  border: 1px solid var(--gray-800);
  background-color: var(--color-white);
  color: var(--color-darken);
  overflow: hidden;
}
.text-field:focus, .text-field:hover {
  border: 1px solid var(--color-primary);
}
.text-field.error {
  border: 1px solid var(--color-red);
  position: relative;
}
.text-field.error::after {
  content: "";
  position: absolute;
  right: 15px;
  color: var(--color-red);
  background-image: url("../images/icon/icon-error.svg");
  background-size: contain;
  background-repeat: no-repeat;
}
.text-field {
  /*
    ⚠️ 잠긴 글자색으로 --color-disabled 를 쓰지 않는다. 그 값은 --gray-200
       (#f9f9fb) 이라 잠긴 배경(--bg-disabled)과 같은 색이다 — 글자가
       배경에 묻혀 사라진다. 잠긴 칸도 무엇이 적혀 있었는지는 읽혀야 한다.
  */
}
.text-field:disabled {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  cursor: not-allowed;
  color: var(--text-muted);
}
.text-field:disabled:hover {
  border: 1px solid var(--border-disabled);
}
.text-field {
  /*
    ⚠️ .text-field 는 input 자체일 때도 있고(검색칸), 달력처럼 input 을 감싸는
       상자일 때도 있다. 상자일 때는 :disabled 가 걸리지 않는다 — div 는
       잠기지 않으니까. 그래서 클래스로도 받는다(.dropdown.disabled 와 같은 짝).
  */
}
.text-field.disabled {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  cursor: not-allowed;
}
.text-field.disabled:hover {
  border: 1px solid var(--gray-600);
}
.text-field.disabled input {
  color: var(--text-muted);
  cursor: not-allowed;
}
.text-field.disabled .dp-btn {
  cursor: not-allowed;
  opacity: 0.4;
}

/*
  읽기 전용 입력칸.
  ⚠️ .text-field 안에 &:read-only 로 두면 안 된다. :read-only 는
     「고칠 수 없는 것 전부」를 가리켜 div 도 걸린다 — 달력처럼 input 을
     감싸는 .text-field 상자가 언제나 잠긴 색으로 칠해진다. 실제로 그랬다.
     그래서 input 일 때로 좁혀 바깥에 따로 적는다.
*/
input.text-field:-moz-read-only {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  cursor: not-allowed;
}
input.text-field:read-only {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  cursor: not-allowed;
}

/*
  비밀번호 칸 — 안에 「보기」 단추를 품는다.

  ⚠️ **login.scss 에 있었다.** 그러면 로그인 화면에만 붙는다 — 비밀번호 변경
     화면은 index.css + page.css 를 부르므로 같은 마크업이 스타일 없이 나왔다.
     두 화면이 같은 부품을 쓰므로 공용(index.css)으로 옮긴다.
  ⚠️ .text-field 는 입력칸 자체일 때도 있고 **입력칸을 감싸는 상자**일 때도
     있다(달력이 같은 규약이다). 여기는 상자 쪽이라 안의 input 이 테두리를
     갖지 않는다 — 위의 `input { border: none }` 이 그 일을 한다.
*/
.pw-field {
  gap: 8px;
}
.pw-field input {
  min-width: 0;
}

/*
  비밀번호 보기 — 눈 그림.

  ⚠️ **그림에는 늘 「지금 보이는 중인가, 누르면 보이는가」의 모호함이 있다.**
     그래서 두 가지로 막는다 —
       ① `aria-pressed` 로 상태를 말한다(낭독기)
       ② `title` 로 다음에 일어날 일을 말한다(마우스)
     그림만 두면 어느 쪽도 답하지 못한다.
  ⚠️ 그림은 **감을 때 사선(icon-eye-off)** 이다. 사선이 「막는다」를 뜻하므로
     눌러서 감긴 상태를 사선으로 그린다 — 지금 상태를 그린다.
  ⚠️ 줄어들지 않는다. 비밀번호가 길어져도 자리를 지킨다.
  ⚠️ 24px 짜리 그림이지만 누르는 자리는 32px 이다. 손가락과 마우스가
     맞히기에 24px 은 작다.
*/
.pw-toggle {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.pw-toggle::before {
  content: "";
  width: 22px;
  height: 22px;
  background: url("../images/icon/icon-eye.svg") no-repeat center/contain;
  opacity: 0.65;
  transition: opacity 0.15s ease;
}
.pw-toggle {
  /* 눌린 상태 = 지금 보이는 중 — 감긴 그림(사선)으로 바꾼다 */
}
.pw-toggle[aria-pressed=true]::before {
  background-image: url("../images/icon/icon-eye-off.svg");
  opacity: 1;
}
.pw-toggle:hover::before {
  opacity: 1;
}
.pw-toggle:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
}

.dropzone {
  border: 2px dashed var(--gray-600);
  border-radius: var(--radius-md);
  /*
    ⚠️ min-height 가 없으면 파일을 붙이는 순간 상자가 커지면서(안내 한 줄 →
       썸네일 40px 줄) 아래 항목들이 밀린다. 업로드 칸이 여러 개인 화면
       (메인배너는 4개)에서는 이 흔들림이 눈에 띈다.
       빈 상태를 파일 한 줄이 들어간 높이로 미리 잡아 둔다.
       76px = 썸네일 40 + 상하 padding 32 + 테두리 4 (box-sizing: border-box)
  */
  min-height: 76px;
  max-height: 260px;
  padding: 16px;
  background: var(--gray-200);
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: auto;
  margin-bottom: 8px;
}

.dropzone.is-dragover {
  background: #f1f3ff;
  border-color: #6c7cff;
}

.dz-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.btn {
  padding: 6px 12px;
  border: 1px solid #ccc;
  border-radius: var(--radius-sm);
  background: var(--color-white);
  cursor: pointer;
}

.dz-guide {
  color: #6b6e7a;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}

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

.file-list li {
  font-family: system-ui;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
}

.file-list li:nth-child(odd) {
  background: var(--color-white);
}

.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;
}

.search-box {
  display: flex;
  align-items: center;
  gap: 8px;
}
.search-box .btn {
  flex-shrink: 0;
}

/* =====================================================
 * 첨부 올리기 상자 — **개발본 전용**
 *
 * ⚠️ 퍼블(pub 1b2de75)에는 없다. 개발본의 게시글 작성 · 숏폼 작성이
 *    실제 업로드 UI(목록 · 지우기 단추 · 안내글)를 쓰기 때문에 여기 둔다.
 *    퍼블 자산을 다시 반영할 때 이 블록은 지우지 말 것.
 * ⚠️ 위쪽 `.dropzone` · `.file-list` 는 퍼블 것이다. 이 상자는 그 바깥에서
 *    쓰는 다른 묶음이라 이름이 겹치지 않는다.
 * ===================================================== */
.file-upload-box .top {
  display: flex;
  align-items: center;
  gap: 8px;
}
.file-upload-box .bot {
  margin-top: 8px;
}
.file-upload-box .bot .flex {
  flex-wrap: wrap;
}
.file-upload-box .bot .flex span {
  width: calc(50% - 8px);
}
.file-upload-box .bot .flex span.shrink-0 {
  width: 100%;
}
.file-upload-box .file-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.file-upload-box .file-item {
  display: flex;
  align-items: center;
  gap: 8px;
}
.file-upload-box .file-item a {
  color: var(--color-blue);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.file-upload-box .file-item .btn {
  margin-left: auto;
  flex-shrink: 0;
}
.file-upload-box .file-item .btn-wrap {
  margin-left: auto;
  flex-shrink: 0;
}
.file-upload-box .file-item .btn-wrap .btn {
  margin-left: 0;
}
.file-upload-box .guide-text {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
}

/* dropdown */
.dropdown {
  position: relative;
  width: 100%;
  /*
    ⚠️ 뿌리에 적는다 — 단추(.dropdown_button)에만 적으면 펼친 목록
       (.dropdown_list 는 뿌리의 자식이다)이 따라 줄지 않아,
       고르는 글자와 고른 글자의 크기가 달라진다.
    ⚠️ input·textarea 와 같은 눈금(14)이다. 검색 필터 한 줄에 셋이 나란히 선다.
  */
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
}
.dropdown.size-sm .dropdown_button {
  height: 36px;
}
.dropdown_button {
  width: 100%;
  height: 40px;
  padding: 0 40px 0 12px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid var(--gray-800);
  background: var(--color-white); /* light: #fff, dark: #121212 */
  color: var(--color-darken); /* light: #3a3a3a, dark: #f5f5f5 */
  cursor: pointer;
  position: relative;
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.dropdown_button::after {
  content: "";
  position: absolute;
  right: 12px;
  top: 50%;
  width: 24px;
  height: 24px;
  background: url("../images/icon/icon-arrow-down.svg") no-repeat center/24px 24px;
  transform: translateY(-50%) rotate(0deg);
  transition: transform 0.2s ease;
  pointer-events: none;
  opacity: 0.9;
}
.dropdown_button:hover, .dropdown_button:focus {
  border-color: var(--color-primary);
}
.dropdown_value {
  color: var(--color-darken);
  line-height: 1;
  transition: color 0.2s ease;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dropdown_list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 4px); /* 기본은 아래로 */
  background: var(--color-white); /* 다크에서는 차콜 */
  border: 1px solid var(--gray-800);
  border-radius: var(--radius-sm);
  box-shadow: var(--elev-2);
  max-height: 220px; /* JS에서 동적으로 갱신 */
  overflow: auto;
  padding: 6px 0;
  display: none;
  z-index: 9999;
}
.dropdown {
  /* 공간 부족 시 위로 펼치기 */
}
.dropdown.is-above .dropdown_list {
  top: auto;
  bottom: calc(100% + 4px);
  box-shadow: var(--edge-up);
}
.dropdown {
  /* 열림 상태 */
}
.dropdown[aria-open=true] .dropdown_button::after {
  transform: translateY(-50%) rotate(180deg);
}
.dropdown[aria-open=true] .dropdown_list {
  display: block;
}
.dropdown_option {
  padding: 10px 12px;
  cursor: pointer;
  line-height: 1.4;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  color: var(--color-darken);
  transition: background-color 0.15s ease, color 0.15s ease;
  /* hover & active */
}
.dropdown_option:hover {
  background: var(--gray-300);
}
.dropdown_option.is-active {
  background: var(--gray-400);
}
.dropdown_option {
  /* 선택 상태: 배경과 글자 강조 */
}
.dropdown_option[aria-selected=true] {
  background-color: var(--bg-primary);
  color: var(--color-white);
  font-weight: 600;
}
.dropdown {
  /* 에러 상태 */
}
.dropdown.error .dropdown_button {
  border-color: var(--color-red);
}
.dropdown.error .dropdown_button:hover, .dropdown.error .dropdown_button:focus {
  border-color: var(--color-red);
}
.dropdown.error .dropdown_button::after {
  opacity: 1;
}
.dropdown.error .dropdown_button { /* 필요 시 아이콘 교체 */ }
.dropdown {
  /* 비활성 */
}
.dropdown.disabled .dropdown_button {
  background-color: var(--bg-disabled);
  border-color: var(--grey-600);
  color: var(--border-disabled);
  cursor: not-allowed;
}
.dropdown.disabled .dropdown_button:hover, .dropdown.disabled .dropdown_button:focus {
  border-color: var(--border-disabled);
}
.dropdown.disabled .dropdown_button::after {
  opacity: 0.5;
}
.dropdown.disabled .dropdown_value {
  color: var(--border-disabled);
}
.dropdown {
  /* 플레이스홀더 상태 */
}
.dropdown.is-placeholder .dropdown_value {
  color: var(--gray-900);
}
.dropdown.is-placeholder { /* 다크에서 중간톤 보조 텍스트 */ }
.dropdown {
  /* 선택 반영: data-selected=true 일 때 value 색상 포인트 */
}
.dropdown[data-selected=true] .dropdown_value {
  color: var(--color-primary);
}

/*
  드롭다운이 열려 있는 동안, **스크롤은 안 하면서 자르기만 하던 조상**의
  잘림을 잠깐 푼다(assets/js/dropdown.js 의 releaseClip).

  ⚠️ .modal-body 는 overflow:auto 다. 내용이 짧아 스크롤이 필요 없을 때도 그 값은
     절대 배치된 목록을 자른다. 엑셀 다운로드 모달에서 다섯 줄짜리 목록이 200px 로
     눌려 마지막 항목이 안 보였다.
  ⚠️ 진짜로 스크롤하는 조상에는 붙이지 않는다(JS 가 걸러 낸다) — 거기서 풀면
     모달이 제 높이를 넘어 늘어난다.
*/
.is-clip-off {
  overflow: visible !important;
}

/* -------------------------------
공통 control (체크/라디오 공용 가능)
---------------------------------*/
.control {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 30px;
  position: relative;
}
.control input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}
.control label {
  position: relative;
  padding-left: 25px;
  line-height: 24px;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}
.control.disabled label {
  cursor: not-allowed;
  opacity: 0.6;
}

/* -------------------------------
체크박스 단일
---------------------------------*/
.checkbox label::before,
.checkbox label::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}
.checkbox label::before {
  width: 20px;
  height: 20px;
  border: 1px solid var(--gray-800);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  transition: border-color 0.2s, background-color 0.2s;
}
.checkbox label::after {
  width: 20px;
  height: 20px;
  background: url("../images/icon/icon-check.svg") no-repeat center/14px 14px;
  opacity: 0;
  transition: opacity 0.15s;
}
.checkbox input:focus + label::before,
.checkbox label:hover::before {
  border-color: var(--color-primary);
}
.checkbox input:checked + label::before {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.checkbox input:checked + label::after {
  opacity: 1;
  filter: invert(1) brightness(10);
}
.checkbox.disabled label::before {
  background: var(--gray-800);
  border-color: var(--gray-600);
}
.checkbox.disabled input:checked + label::before {
  background: var(--gray-800);
  border-color: var(--gray-600);
}
.checkbox {
  /*
    ⚠️ 위의 `.disabled` 는 **감싼 상자에 붙이는 클래스**다. 그런데 스크립트로 칸을
       잠글 때는 보통 `input.disabled = true` 만 한다(그게 실제로 못 누르게 하는
       유일한 방법이므로). 그러면 진짜로는 잠겼는데 **모양은 멀쩡해서**,
       담당자는 눌러 보고 아무 일도 안 일어나면 고장으로 읽는다.
       (서브페이지 번역 목록에서 「미번역」이 아닌 줄이 그랬다)

    → 칸 자신의 상태를 보고 그리게 한다. 클래스를 같이 붙이는 걸 잊어도 어긋나지 않는다.
  */
}
.checkbox input:disabled + label {
  cursor: not-allowed;
  opacity: 0.5;
}

/* -------------------------------
체크박스 그룹
---------------------------------*/
.checkbox-group {
  border: 0;
  padding: 0;
  display: flex;
}
.checkbox-group .field-title {
  margin-bottom: 12px;
}
.checkbox-group.vertical {
  flex-direction: column;
  gap: 12px;
}
.checkbox-group.horizontal {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 10px 20px;
}
/* 라디오 (단일) — 공통 .control은 기존 것 사용 */
.radio {
  /* 시각 요소: 바깥 원(보더) + 안쪽 점 */
}
.radio label::before,
.radio label::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}
.radio {
  /* 바깥 원 */
}
.radio label::before {
  width: 20px;
  height: 20px;
  border: 1px solid var(--gray-800);
  border-radius: var(--radius-circle);
  background: var(--color-white);
  transition: border-color 0.2s, background-color 0.2s;
}
.radio {
  /* 안쪽 점(선택 표시) */
}
.radio label::after {
  left: 4px; /* 바깥 원 기준 안쪽 여백 */
  width: 12px;
  height: 12px;
  border-radius: var(--radius-circle);
  background: var(--color-primary);
  opacity: 0;
  transition: opacity 0.15s;
}
.radio {
  /* hover/focus 시 보더 강조 */
}
.radio input:focus + label::before,
.radio label:hover::before {
  border-color: var(--color-primary);
}
.radio {
  /* checked 상태 */
}
.radio input:checked + label::before {
  border-color: var(--color-primary);
}
.radio input:checked + label::after {
  opacity: 1;
}
.radio {
  /* disabled 상태 */
}
.radio.disabled label {
  cursor: not-allowed;
  opacity: 0.6;
}
.radio.disabled label::before {
  background: var(--bg-disabled);
  border-color: var(--gray-600);
}
.radio.disabled label:hover::before {
  border-color: var(--gray-600);
}
.radio.disabled input:checked + label::before {
  border-color: var(--gray-600);
}
.radio.disabled input:checked + label::after {
  background: var(--gray-800);
}

/* 라디오 그룹 */
.radio-group {
  border: 0;
  padding: 0;
}
.radio-group .field-title {
  margin-bottom: 12px;
}
.radio-group {
  display: flex;
}
.radio-group.vertical {
  flex-direction: column;
  gap: 12px;
}
.radio-group.horizontal {
  flex-direction: row;
  flex-wrap: wrap; /* 좁을 때 줄바꿈 */
  gap: 20px;
}
.radio-group.justify-center {
  justify-content: center;
}

/* 라디오 선택 시 none,block */
.radio1-content,
.radio2-content {
  display: none;
}

.radio-content.is-active {
  display: block;
}

.switch label {
  position: relative;
  padding-left: 64px;
  line-height: 28px;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}
.switch {
  /* 트랙 (기본: Off) */
}
.switch label::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 28px;
  /* ⚠️ 단(`--radius-*`)을 쓰지 않는다. 스위치 트랙은 높이의 절반이어야
        알약이 된다 — 높이가 28px 이라 14px 이다. */
  border-radius: 14px;
  background: #e0e0e0; /* Off 상태 트랙 */
  transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
.switch {
  /* 썸 */
}
.switch label::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 2px;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
  border-radius: var(--radius-circle);
  background: var(--color-white); /* Off 상태 썸 */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: left 0.2s ease;
}
.switch {
  /* Hover/Focus */
}
.switch input:focus + label::before {
  box-shadow: 0 0 0 4px rgba(46, 124, 246, 0.35); /* primary shadow */
}
.switch label:hover::before {
  box-shadow: 0 0 0 4px rgba(46, 124, 246, 0.35);
}
.switch {
  /* ON 상태 */
}
.switch input:checked + label::before {
  background: var(--color-primary, #2e7cf6);
}
.switch input:checked + label::after {
  left: 26px;
}
.switch {
  /* Disabled 상태 */
}
.switch.disabled,
.switch input:disabled + label {
  cursor: not-allowed;
}
.switch.disabled label::before,
.switch input:disabled + label::before {
  background: #f4f4f4; /* Disabled 트랙 */
  box-shadow: none;
}
.switch.disabled label::after,
.switch input:disabled + label::after {
  background: #d6d6d6; /* Disabled 썸 */
  box-shadow: none;
}
.switch.disabled label:hover::before {
  box-shadow: none;
}

.icon {
  display: flex;
  align-items: center;
  justify-content: center;
}
.icon:before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
}
.icon {
  /*
    화면 모드 (components/header.jsp — .theme-switch)
    ⚠️ SVG 에 stroke 색이 박혀 있다. 색은 _global.scss 에서 filter 로 뒤집는다
       (켜진 칸 = 흰색, 꺼진 칸 = 검정 55%).
  */
}
.icon.icon-mode-light:before {
  background-image: url(../images/icon/icon-mode-light.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-mode-dark:before {
  background-image: url(../images/icon/icon-mode-dark.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon {
  /*
    LNB 접기 / 펼치기 (components/header.jsp)
    ------------------------------------------------------------------
    막대(패널 자리) + 방향 화살표. 접히면 화살표만 오른쪽으로 뒤집힌다.
    ⚠️ 한 파일을 rotate 로 돌리지 않고 두 파일로 나눈 이유 —
       180도 돌리면 막대까지 오른쪽으로 가서 '오른쪽 패널'로 읽힌다.
       막대는 왼쪽에 두고 화살표만 바꿔야 뜻이 맞는다.
  */
}
.icon.icon-panel-collapse:before {
  background-image: url(../images/icon/icon-panel-collapse.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-panel-expand:before {
  background-image: url(../images/icon/icon-panel-expand.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon {
  /*
    햄버거 — **1200px 아래에서만** 쓴다(components/_header.scss).
    ⚠️ 위의 접기 화살표와 뜻이 다르다. 화살표는 「이미 보이는 것을 접는다」,
       햄버거는 「감춰진 것을 연다」다. 폭에 따라 하는 일이 실제로 달라지므로
       그림도 갈라야 한다 — 같은 그림이면 눌러 보고 나서야 알게 된다.
  */
}
.icon.icon-menu:before {
  background-image: url(../images/icon/icon-menu.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-recycle:before {
  background-image: url(../images/icon/icon-recycle.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-search:before {
  background-image: url(../images/icon/icon-search.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-save:before {
  background-image: url(../images/icon/icon-save.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-close:before {
  background-image: url(../images/icon/icon-close.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-arrow-left-rec:before {
  background-image: url(../images/icon/icon-arrow-left-rec.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-arrow-left-end-rec:before {
  background-image: url(../images/icon/icon-arrow-left-end-rec.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-arrow-right-rec:before {
  background-image: url(../images/icon/icon-arrow-right-rec.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-arrow-right-end-rec:before {
  background-image: url(../images/icon/icon-arrow-right-end-rec.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-plus:before {
  background-image: url(../images/icon/icon-plus.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-check:before {
  background-image: url(../images/icon/icon-check.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-x:before {
  background-image: url(../images/icon/icon-x.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-dotdot:before {
  background-image: url(../images/icon/icon-dotdot.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon {
  /*
    ---- 위·아래 화살표 ----
    ⚠️ svg 는 하나뿐이다(icon-arrow-down.svg). 위쪽은 그것을 180° 돌려서 쓴다 —
       같은 모양의 파일을 하나 더 두면 한쪽만 고쳐져 짝이 어긋난다.
    쓰는 곳 : 본문 구성 항목 순서 바꾸기 (page/contents/mng-contents.jsp)
  */
}
.icon.icon-arrow-down:before {
  background-image: url(../images/icon/icon-arrow-down.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-arrow-up:before {
  background-image: url(../images/icon/icon-arrow-down.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
  transform: rotate(180deg);
}
.icon.icon-setting:before {
  background-image: url(../images/icon/icon-setting.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-delete:before {
  background-image: url(../images/icon/icon-delete.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-exchange:before {
  background-image: url(../images/icon/icon-exchange.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-pdf:before {
  background-image: url(../images/icon/icon-pdf.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-doc:before {
  background-image: url(../images/icon/icon-doc.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-xls:before {
  background-image: url(../images/icon/icon-xls.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-hwp:before {
  background-image: url(../images/icon/icon-hwp.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-jpg:before {
  background-image: url(../images/icon/icon-jpg.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-png:before {
  background-image: url(../images/icon/icon-png.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-zip:before {
  background-image: url(../images/icon/icon-zip.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon {
  /*
    ---- 아래 둘은 **개발본 전용**이다 ----
    ⚠️ 퍼블(pub 1b2de75)의 _icon.scss 에는 없다. 개발본에만 있는 화면이 쓴다 —
       첨부(게시글 작성 · 숏폼 작성의 파일 목록) · 빼기(권한 격자에서 한 줄 지우기).
       그림 파일도 개발본에만 있다(images/icon/icon-attachment.svg · icon-minus.svg).
    ⚠️ 퍼블 자산을 다시 반영할 때 이 둘은 지우지 말 것.
  */
}
.icon.icon-attachment:before {
  background-image: url(../images/icon/icon-attachment.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.icon.icon-minus:before {
  background-image: url(../images/icon/icon-minus.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}

/* darkmode */
[data-theme=dark] .icon {
  filter: brightness(0) saturate(100%) invert(99%) sepia(35%) saturate(41%) hue-rotate(186deg) brightness(109%) contrast(98%);
}

.chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
  padding: 8px;
  border-radius: var(--radius-sm);
  font-style: normal;
  flex-shrink: 0;
  /* color */
}
.chip.primary {
  background-color: var(--bg-darken);
  color: var(--color-white);
}
.chip.secondary {
  background-color: var(--bg-secondary);
  color: var(--color-white);
}
.chip.point {
  background-color: var(--bg-point);
  color: var(--color-white);
}
.chip.gray {
  background-color: var(--gray-800);
  color: var(--color-white);
}
.chip {
  /* size */
}
/* =====================================================
 * 배지 — 상태와 종류를 한 조각으로 알린다 (2026-09-11 하나로 모음)
 *
 * ─ 모으기 전에 무엇이 있었나 (전수 조사 · 견본 화면 제외)
 *
 *     이름           곳    높이      글자    라운드        꼴
 *     .badge         78   24px      12px   sm(8px)     면을 채운다
 *     .log-kind      22   2px 여백   13px   pill        옅은 바탕
 *     .sns-badge      6   2px 여백   11px   md(12px)    옅은 바탕(채널색)
 *     .bdg            5   2px 여백   12px   pill        흰 바탕
 *     ─ 합계        111
 *
 *     .badgebox       0   ← 마크업에서 쓰지 않는다 (죽은 CSS · 지웠다)
 *     .state-badge    0   ← 마크업에서 쓰지 않는다 (죽은 CSS · 약 100줄 지웠다)
 *
 *   같은 일을 하는 것이 **네 이름 · 네 크기 · 세 라운드**로 갈려 있었다.
 *   375px 에서 글자가 11 · 12 · 13 세 가지로 섞여 나왔다.
 *
 * ─ 하나로 모은 규칙
 *
 *   ① 이름은 `.badge` 하나
 *   ② 크기는 하나 — 높이 24px · 글자 12px · `--radius-sm`
 *   ③ **기본은 옅은 꼴**(옅은 바탕 + 진한 글자)
 *   ④ 채우는 것은 `.is-solid` 를 붙인 것만
 *
 * ⚠️ **왜 옅은 꼴을 기본으로 했나.** 이 제품에서 정한 「주인공은 하나만 띄운다」를
 *    따른다. 목록에서 주인공은 그 줄의 문장이나 이름이고, 상태는 그것을 돕는
 *    표시다. 진한 배지가 줄마다 아홉 개 서면 눈이 먼저 그것들로 간다.
 *    ⚠️ **되돌리는 것은 한 줄이다** — 아래 `.is-solid` 의 색 정의를 기본 쪽과
 *       맞바꾸면 예전 모습으로 돌아간다. 보고 정하면 된다.
 *
 * ⚠️ **글자 크기는 줄지 않는다.** 12px 가 이 제품의 가장 작은 눈금이다.
 * ⚠️ **줄바꿈을 막는다.** 표의 열이 좁아도 배지는 줄지 않고 열이 밀리는 쪽이
 *    낫다 — 상태를 못 읽으면 배지를 둘 이유가 없다.
 * ⚠️ **폭은 `min-width` 다.** 예전에 `width: 24px` 로 박아 두어 「발행 완료」가
 *    두 줄로 뭉개진 적이 있다.
 * ===================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 24px;
  padding: 0 8px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  /* ⚠️ flex 항목 안에서 찌그러지지 않게 — 표 셀도 flex 인 곳이 있다 */
  flex-shrink: 0;
  /* 색을 안 적으면 회색 — 「종류」로 읽힌다 */
  background-color: var(--gray-200);
  color: var(--text-muted);
  /* =====================================================
   * 색 일곱 — 뜻으로 고른다
   *
   *   gray     종류 · 분류        조회 · 다운로드 · 기타 · 알 수 없음
   *   primary  사람이 한 일       등록 · 수정 · 승인
   *   point    되었음             로그인 · 성공 · 연동됨
   *   blue     예정 · 켜짐        예약 · 변경 · 사용
   *   warn     걸렸음(사고 아님)  실패
   *   red      막혔음 · 되돌림    잠김 · 반려 · 삭제
   *   darken   끝났음 · 기다림    발행 완료 · 완료 · 대기
   *
   * ⚠️ **「실패」와 「잠김」을 같은 빨강으로 두지 않는다**(관리자 접속 이력).
   *    비밀번호를 한 번 틀린 것은 아직 사고가 아니다. 셋이 단계로 읽혀야
   *    위쪽 세 줄만 보고도 무슨 일이 있었는지 알 수 있다 —
   *      성공(point) → 실패(warn) → 잠김(red)
   * ⚠️ **색만으로 말하지 않는다.** 글자가 성공 · 실패 · 잠김으로 다르다.
   *    색을 못 가리는 이용자에게 이 셋은 같은 밝기로 보인다.
   * ===================================================== */
}
.badge.gray {
  background-color: var(--gray-200);
  color: var(--text-muted);
}
.badge.primary {
  background-color: var(--bg-primary-soft);
  color: var(--color-primary-deep);
}
.badge.point {
  background-color: rgba(var(--color-point-rgb), 0.16);
  color: var(--color-point);
}
.badge.blue {
  background-color: rgba(var(--color-blue-rgb), 0.12);
  color: var(--color-blue);
}
.badge.warn {
  background-color: rgba(var(--color-warn-rgb), 0.14);
  color: var(--color-warn);
}
.badge.red {
  background-color: rgba(var(--color-red-rgb), 0.14);
  color: var(--color-red);
}
.badge.darken {
  background-color: var(--gray-300);
  color: var(--color-darken);
}
.badge {
  /* =====================================================
   * 채운 꼴 — **손이 가야 하는 하나에만** 붙인다
   *
   * ⚠️ 한 줄에 둘 이상 붙이면 둘 다 안 보인다. 그 줄에서 가장 급한 것 하나다.
   * ⚠️ `--color-darken` 은 다크에서 밝은 색으로 뒤집힌다. 글자는
   *    `--color-white` 를 써야 함께 뒤집혀 대비가 유지된다.
   * ===================================================== */
}
.badge.is-solid.gray {
  background-color: var(--gray-900);
  color: #fff;
}
.badge.is-solid.primary {
  background-color: var(--color-primary);
  color: var(--on-primary);
}
.badge.is-solid.point {
  background-color: var(--color-point);
  color: #fff;
}
.badge.is-solid.blue {
  background-color: var(--color-blue);
  color: #fff;
}
.badge.is-solid.warn {
  background-color: var(--color-warn);
  color: #fff;
}
.badge.is-solid.red {
  background-color: var(--color-red);
  color: #fff;
}
.badge.is-solid.darken {
  background-color: var(--color-darken);
  color: var(--color-white);
}
.badge {
  /* =====================================================
   * ⚠️ **채널 색(`ch-*`)을 지웠다 (2026-09-11).**
   *
   * 예전 `.sns-badge` 를 옮겨 온 것인데, 쓰는 곳이 **게시물 작성 한 화면
   * 여섯 곳**뿐이었다. 그리고 그것이 혼동을 만들고 있었다 —
   * 375px 에서 「검수 요청」(상태)과 「Instagram」(채널)이 나란히 서서
   * 같은 것으로 읽혔다. 발행 내역 · 발행 검수는 같은 값을 처음부터
   * 「A · B」 글자로 보여주고 있었다.
   *
   * ⚠️ 그래서 규칙을 세웠다 — **배지는 상태만.**
   *    상태 · 결과 · 구분처럼 **시간에 따라 바뀌는 것**에만 쓴다.
   *    채널 이름처럼 바뀌지 않는 이름표는 글자로 둔다.
   *
   * 채널을 눈에 띄게 해야 할 일이 생기면 **배지가 아니라 로고**를 쓴다 —
   * 채널 관리(platform.jsp)가 그렇게 하고 있다. 그림은 상태 낱말과
   * 절대 섞이지 않는다.
   * ===================================================== */
}

/* =====================================================
 * ⚠️ 지운 것 — 되살릴 일이 생기면 git 이력에 있다
 *
 *   .badgebox      마크업 0곳. 「정의가 없어 글자만 나왔다」며 만든 것인데
 *                  그 22곳이 지금은 없다
 *   .state-badge   마크업 0곳 · 약 100줄. 번역 흐름(미번역 → AI 번역중 →
 *                  검수 대기 → 검수완료)을 위한 것이었는데 이 제품에 그
 *                  흐름이 없다. is-none · is-busy · is-wait · is-done ·
 *                  is-stale · is-live · is-fail · is-warn 여덟 단계가
 *                  아무 화면에서도 쓰이지 않았다
 *   .badge.secondary · .point(채운 것) · .line · .dark
 *                  마크업 0곳. `dark` 는 주석에 「39회」라 적혀 있었는데
 *                  실제로는 한 곳도 없었다 — 주석이 코드보다 오래 남았다
 *
 *   `git log -- assets/scss/_badge.scss`
 * ===================================================== */
.table-wrap {
  width: 100%;
  overflow: auto;
  border: 1px solid var(--gray-500);
  background: var(--color-white);
}

/* 테이블 본체 */
.table {
  width: 100%;
  min-width: 1300px;
  border-collapse: separate;
  border-spacing: 0;
  /*
    ⚠️ 표 글자는 본문보다 한 눈금 작다(16 → 14). 표는 한 화면에 수십 줄이
       들어오는 유일한 곳이라, 본문과 같은 크기면 한 번에 보이는 줄이 줄고
       열이 가로로 밀린다.
    ⚠️ 배지(12px)·.cell-none(13px)은 제 크기를 직접 적고 있어 따라 줄지 않는다.
       거기가 이미 최소 크기다.
  */
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  color: var(--color-darken);
}
.table thead th {
  padding: 15px;
  background: var(--gray-300);
  font-weight: 700;
  border-bottom: 1px solid var(--border-darken);
  white-space: nowrap;
  text-align: center;
}
.table tbody th {
  padding: 15px;
  background: var(--gray-300);
  border-bottom: 1px solid var(--gray-500);
  font-weight: 700;
  white-space: nowrap;
  text-align: center;
}
.table tbody td {
  text-align: center;
  padding: 15px;
  border-bottom: 1px solid var(--gray-500);
  color: var(--color-darken);
  vertical-align: middle;
  /*
    ⚠️ 문장이 든 칸의 정렬을 여기에도 적는다. 최상위 .cell-text 는 (0,1,0)
       이라 이 규칙(0,2,1)에 밀려 **한 번도 먹지 않았다.** 발췌·문장이
       가운데 정렬로 남아 줄마다 시작점이 달랐다.
  */
}
.table tbody td.cell-text {
  text-align: left;
  word-break: keep-all;
}
.table tbody td.is-border {
  border-right: 1px solid var(--gray-500);
}
.table tbody td a.color-blue {
  display: inline-block;
  vertical-align: middle;
}
.table tbody td .icon {
  display: inline-block;
  width: 24px;
  height: 24px;
}
.table tbody td .thumb-img-wrap {
  display: flex;
  gap: 8px;
  justify-content: center;
  align-self: center;
}
.table tbody td .thumb-img-wrap .thumb-img {
  width: auto;
  height: auto;
}
.table tbody td .thumb-img {
  width: 112.8px;
  height: 164.5px;
  overflow: hidden;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-sm);
  margin: 0 auto;
}
.table tbody td .thumb-img img {
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
}
.table {
  /*
    모달을 여는 제목 칸 — 한 줄로 자른다.

    ⚠️ **max-width: 0 이 핵심이다.** 자동 배치 표(table-layout: auto)에서
       「이 칸은 내용만큼 넓어지려 하지 마라」를 말하는 방법은 이것뿐이다.
       그러면 남는 가로가 이 칸으로 몰리고, 안쪽 덩어리가 그 폭에 맞춰
       잘린다. 안 주면 제목이 긴 줄 하나가 열을 통째로 벌려 놓는다.
    ⚠️ 말줄임은 안쪽 a 가 한다 — td 에 걸어도 먹지 않는다(칸의 내용이
       블록이라서). -webkit-line-clamp 는 쓰지 않는다. 한 줄이면
       text-overflow 로 충분하고, 그쪽은 세로 가운데 정렬이 어긋난다.
    ⚠️ 이 규칙은 위의 `a.color-blue { display: inline-block }` 보다
       **뒤에 있어야** 한다. 특정도가 같아서 순서로 갈린다.
  */
}
.table tbody td.cell-title {
  max-width: 0;
  text-align: left;
}
.table tbody td.cell-title > a,
.table tbody td.cell-title > b,
.table tbody td.cell-title > span {
  display: block;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.table tbody tr:last-child td {
  border-bottom: 0;
}
.table {
  /* 첫/마지막 셀 라운드 느낌 */
  /* 행 hover */
}
.table tbody tr {
  transition: background-color 0.15s ease;
}
.table tbody tr:hover {
  background: var(--gray-200);
}
.table tbody tr.is-selected {
  background-color: rgba(var(--bg-primary-rgb), 0.2);
}
.table tbody tr.notice td {
  font-weight: 700;
}
.table tbody tr.notice td:first-child {
  color: var(--color-primary);
}
.table .no-data td {
  padding: 20px;
  text-align: center;
  color: #666;
  background: #fafafa;
}
.table {
  /*
    모달 안의 가로형 표.
    ⚠️ 바깥 .table 은 min-width: 1300px 이다. 목록 화면에서는 맞지만
       모달은 그 폭을 낼 수 없어 표가 잘리고 가로 스크롤이 생긴다.
  */
}
.table.table-in-modal {
  min-width: 0;
}
.table.table-in-modal thead th,
.table.table-in-modal tbody td {
  padding: 12px;
}
.table {
  /*
    값을 읽기만 하는 세로 표 — 상세 모달에서 쓴다.
    ⚠️ 바깥 .table 의 min-width: 1300px 을 반드시 풀어야 한다.
       모달 안에서는 그 폭을 쓸 수 없어 가로 스크롤이 생긴다.
    ⚠️ hover 로 줄 색을 바꾸지 않는다. 누를 수 있는 줄처럼 보이는데
       실제로는 읽기만 하는 값이라, 눌러 보고 나서야 알게 된다.
  */
}
.table.table-vertical {
  width: 100%;
  min-width: 0;
  border-collapse: collapse;
}
.table.table-vertical th,
.table.table-vertical td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--gray-500);
  vertical-align: middle;
}
.table.table-vertical th {
  background: var(--gray-300);
  font-weight: 700;
  white-space: nowrap;
  text-align: left;
  /* 이름 옆에 붙는 값표 — 「사유 [기타]」처럼 이름과 한 덩어리로 읽힌다 */
}
.table.table-vertical th .badge {
  margin-left: 8px;
  vertical-align: middle;
}
.table.table-vertical td {
  background: var(--color-white);
  text-align: left;
  word-break: break-all;
  /* 문장이 들어오는 칸은 어절로 끊어야 읽힌다 */
  /*
    ⚠️ 정렬을 여기에도 적는다. 아래 최상위 .cell-text 는 (0,1,0) 이라
       .table tbody td (0,2,1) 에 밀려 **한 번도 먹지 않았다.** 문장 칸이
       가운데 정렬로 남아 줄마다 시작점이 달랐다.
  */
}
.table.table-vertical td.cell-text {
  text-align: left;
  word-break: keep-all;
}
.table.table-vertical tr:last-child th,
.table.table-vertical tr:last-child td {
  border-bottom: 0;
}

.js-week-table-body tr {
  display: none;
}

.js-week-table-body tr.is-show {
  display: table-row;
}

/* =====================================================
 * 표 안의 칸 도우미
 *
 * ⚠️ 처음에는 웹접근성 점검 화면 전용(.a11y-table .cell-text)으로 뒀는데,
 *    서브페이지 번역 목록에서도 똑같이 필요했다. 표 공통이라 여기로 옮긴다.
 * ===================================================== */
/*
  문장이 들어가는 칸.
  ⚠️ 이 표의 기본 정렬은 가운데다. 「무엇이 문제인가」 같은 문장을 가운데
     정렬하면 줄마다 시작점이 달라져 훑어 읽을 수가 없다. 그 칸만 왼쪽으로 붙인다.
  ⚠️ 한글은 어절 단위로 끊어야 읽힌다.
*/
.cell-text {
  text-align: left;
  word-break: keep-all;
  line-height: 1.5;
}

/* ⚠️ 표 안에서 쓸 때의 정렬은 .table tbody td.cell-text 가 맡는다 —
      여기 (0,1,0) 만으로는 표의 가운데 정렬을 이기지 못한다. */
/*
  아직 갈 자리가 없는 칸 — 「번역 중」처럼 지금은 누를 것이 없는 상태.
  ⚠️ 단추처럼 보이면 눌러 보게 된다. 글자로만 둔다.
*/
.cell-none {
  color: var(--gray-900);
  font-size: 13px;
}

/* =====================================================
 * 좁은 화면 — 표는 제 안에서 굴린다 (2026-09-10 반응형)
 *
 * ⚠️ **2026-09-11 에 바뀌었다.** 여기 「표를 카드로 바꾸지 않는다」고 적혀
 *    있었는데, **600px 미만에서는 줄을 세로로 쌓는다**(components/_tableList.scss).
 *    까닭은 이랬다 — 375px 에서 「일시」 하나가 줄의 절반을 먹는데도 감춘
 *    열이 셋이었고, 이 제품의 열은 곁다리가 아니라 전부 쓰이는 값이다.
 *    세로로 쌓으면 가로 한계가 없어져 **하나도 감출 필요가 없다.**
 *    「여러 줄을 훑어 견준다」는 600px 이상에서 지킨다.
 * ⚠️ 아래 그늘(굴러간다는 표시)은 **600~1199px 구간**에서 값을 한다.
 *    `.table-wrap` 이 `overflow: auto` 인 것은 그대로다.
 *
 * ⚠️ **다만 굴러간다는 것이 보여야 한다.** 오른쪽 끝을 흐리게 덮어 「더
 *    있다」를 말한다. 끝까지 굴리면 그 그늘이 사라진다 —
 *    `background-attachment: local` 이 그 일을 한다(스크립트가 필요 없다).
 * ===================================================== */
@media (max-width: 1199px) {
  .table-wrap {
    background-image: linear-gradient(to right, var(--color-white) 30%, rgba(255, 255, 255, 0)), linear-gradient(to left, var(--color-white) 30%, rgba(255, 255, 255, 0)), linear-gradient(to right, rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0)), linear-gradient(to left, rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0));
    background-position: 0 0, 100% 0, 0 0, 100% 0;
    background-repeat: no-repeat;
    background-size: 32px 100%, 32px 100%, 12px 100%, 12px 100%;
    background-attachment: local, local, scroll, scroll;
  }
}
/*
  ⚠️ 다크에서 흰 덮개를 그대로 쓰면 **표 양끝에 흰 띠**가 남는다.
     덮개는 「바탕과 같은 색」이어야 그늘만 보인다.
*/
[data-theme=dark] .table-wrap {
  background-image: linear-gradient(to right, var(--color-white) 30%, rgba(18, 18, 18, 0)), linear-gradient(to left, var(--color-white) 30%, rgba(18, 18, 18, 0)), linear-gradient(to right, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0)), linear-gradient(to left, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0));
}

/* =====================================================
 * 상세 세로형 표 — 600px 미만에서 **한 칸씩 세로로 편다** (2026-09-11)
 *
 * ⚠️ 이 표는 한 줄에 **「이름 · 값 · 이름 · 값」 네 칸**이 든다. 「이름」 칸이
 *    `<colgroup>` 에 120px 로 박혀 있어, 값 칸은 남는 것을 반씩 나눠 갖는다.
 *    재서 나온 값 —
 *
 *      폭     모달 폭   이름칸   값칸    줄
 *      600     568      120     142    1줄   ← 여기까지 버틴다
 *      500     468      120      92    2줄
 *      414     382      120      49    ≈7줄
 *      375     343      120      30    ≈10줄  ← 글자가 한 자씩 떨어진다
 *
 * ⚠️ **`<table>` 의 `display` 를 `block` 으로 바꾼다.** 그래야 표 배치가 끝나고
 *    `<colgroup>` 의 120px 도 함께 힘을 잃는다. `col` 의 폭만 풀어서는 안 된다 —
 *    고정 배치(`_reset.scss` 의 `table-layout: fixed`)에서는 칸을 숨기거나
 *    폭을 풀어도 `<col>` 이 제 자리를 잡는다(목록 표에서 겪었다).
 *
 * ⚠️ 이름을 **값 위에** 둔다. 왼쪽에 두면 그 폭을 또 정해야 하고, 이름 길이가
 *    화면마다 달라 값의 시작점이 줄마다 어긋난다.
 *
 * ⚠️ 목록 표와 **같은 눈금(600px)** 을 쓴다. 목록에서 줄을 쌓기 시작하는 폭과
 *    상세에서 칸을 펴는 폭이 다르면, 같은 화면 안에서 두 번 접히는 셈이 된다.
 *
 * ⚠️ 이 규칙 하나가 **상세 표 24개 전부**에 닿는다 — 접속 이력 13 · 다운로드
 *    이력 5 · 작업 이력 2 · 권한 변경 · 발행 검수 · 숏폼 검수 · 숏폼 내려받기.
 * ===================================================== */
@media (max-width: 599px) {
  .table.table-vertical {
    display: block;
  }
  .table.table-vertical colgroup {
    display: none;
  }
  .table.table-vertical tbody,
  .table.table-vertical tr {
    display: block;
  }
  .table.table-vertical tr {
    border-bottom: 1px solid var(--gray-500);
  }
  .table.table-vertical tr:last-child {
    border-bottom: 0;
  }
  .table.table-vertical th,
  .table.table-vertical td {
    display: block;
    width: auto;
    padding: 0;
    border: 0;
    text-align: left;
    white-space: normal;
    vertical-align: baseline;
  }
  .table.table-vertical {
    /* 이름 — 값 위에 한 눈금 작고 흐리게 */
  }
  .table.table-vertical th {
    background: transparent;
    padding: 10px 14px 0;
    font-size: 12px;
    font-weight: 400;
    color: var(--text-muted);
  }
  .table.table-vertical td {
    background: transparent;
    padding: 2px 14px 10px;
  }
  .table.table-vertical {
    /* 마지막 줄의 테두리 없애기는 위에서 tr 로 처리했다 — 칸 쪽 규칙을 되돌린다 */
  }
  .table.table-vertical tr:last-child th,
  .table.table-vertical tr:last-child td {
    border-bottom: 0;
  }
}
/* =====================================================
 * 모달 안 비교 표 — 600px 미만에서 **한 줄에 「전 → 후」** (2026-09-11)
 *
 * 「항목 · 변경 전 · 변경 후」 세 칸인데, 375px 모달(299px)에서 나눠 가지면
 * 「주 3회 (월·수·금)」이 네 줄로 꺾인다.
 *
 *   발행 예정
 *   매일  →  주 3회 (월 · 수 · 금)
 *
 * ⚠️ 「변경 전」임을 취소선이, 「변경 후」임을 화살표가 말한다 — 머리줄을
 *    보지 않아도 읽힌다. 머리줄은 **지우지 않고 감춘다**(아래 참고).
 * ===================================================== */
@media (max-width: 599px) {
  .table.table-in-modal {
    display: block;
  }
  .table.table-in-modal colgroup {
    display: none;
  }
  .table.table-in-modal tbody,
  .table.table-in-modal tr {
    display: block;
  }
  .table.table-in-modal tr {
    padding: 10px 14px;
    border-bottom: 1px solid var(--gray-500);
  }
  .table.table-in-modal tr:last-child {
    border-bottom: 0;
  }
  .table.table-in-modal td {
    display: inline-block;
    width: auto;
    padding: 0;
    border: 0;
    text-align: left;
    vertical-align: baseline;
  }
  .table.table-in-modal {
    /* 항목 이름 — 값 위에 한 눈금 작고 흐리게 */
  }
  .table.table-in-modal td:first-child {
    display: block;
    margin-bottom: 2px;
    font-size: 12px;
    color: var(--text-muted);
  }
  .table.table-in-modal {
    /* 화살표가 「이 다음이 바뀐 값」이라고 말한다 */
  }
  .table.table-in-modal td.log-after::before {
    content: "→";
    margin: 0 8px;
    color: var(--text-muted);
  }
}
/* =====================================================
 * ⚠️ 머리줄은 **지우지 말고 감춘다** (2026-09-11)
 *
 * `thead { display: none }` 으로 감추면 **화면 낭독기에서 열 이름이 사라진다** —
 * 「2025-04-22」만 읽히고 그것이 등록일인지 마지막 접속인지 알 길이 없다.
 * `.sr-only` 와 같은 방식(1×1 로 잘라내기)으로 두면 눈에는 안 보이고
 * 낭독기에는 남는다.
 *
 * ⚠️ **이것만으로 다 되는 것은 아니다.** `display` 를 `table` 에서 `block` 으로
 *    바꾸면 브라우저가 그 요소들을 **표로 보지 않는다** — 칸과 머리줄의 짝도
 *    함께 끊긴다. 그 짝은 `assets/js/tableResponsive.js` 가 `role` 을 다시
 *    붙여 살린다. 둘을 함께 해야 값을 한다.
 * ===================================================== */
@media (max-width: 599px) {
  .table.is-list.is-event thead,
  .table.is-list.is-grid thead,
  .table.table-in-modal thead {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  /*
    ⚠️ **감춘 열의 `<th>` 도 되살린다.** 이 폭에서는 아무 열도 감추지 않는데,
       `display: none` 이 `<th>` 에는 그대로 걸려 있었다 — 낭독 트리에서
       「기관」 하나가 빠져 columnheader 가 6개가 아니라 5개였다(재서 확인).
       머리줄 전체가 이미 1×1 로 잘려 있으므로 눈에는 아무 영향이 없다.
    ⚠️ 특정도를 맞춘다: 감추는 규칙 `.table.is-collapsible .tc-p3` 이 (0,3,0) 이라
       `.table.is-list.is-event thead th` (0,3,2) 로 이겨야 한다.
  */
  .table.is-list.is-event thead th,
  .table.is-list.is-grid thead th {
    display: block;
  }
}
.textarea-box {
  width: 100%;
}
.textarea-box textarea {
  border: 1px solid var(--gray-600);
  background-color: var(--color-white);
  border-radius: var(--radius-sm);
  /* ⚠️ 18px 이었다 — 옆에 선 input(16) 보다 큰 유일한 입력칸이었다.
        입력칸끼리 눈금을 맞춘다(14). placeholder 도 함께 줄어든다. */
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  /* ⚠️ **줄 높이를 못 박는다.** 글꼴 믹스인은 크기·굵기·글꼴만 주고
        `line-height` 를 주지 않아서(믹스인 전체에 0건), 안 적으면 `normal`
        이 된다. `normal` 은 글꼴이 정하는 **소수**값이라 칸 높이가 글꼴에
        따라 달라진다. 14 × 1.5 = 21px 로 고정한다 — 프로젝트에서 가장 많이
        쓰는 값이 1.5 다.

        ⚠️ **이것으로 「마지막 줄이 반만 보이는 것」은 안 고쳐진다.**
           처음에 그렇게 믿고 넣었는데 재 보니 틀렸다 —
             내용 상자    84px ÷ 21 = 정확히 4.000줄
             실제 잘리는 곳 94px ÷ 21 =      4.476줄   ← 아래 테두리까지
           글자는 내용 상자가 아니라 **테두리에서** 잘린다. `padding-bottom`
           구간으로 다음 줄이 비쳐 나오므로, 여백이 있는 한 반 줄은 보인다.
           그리고 그것은 **스크롤 되는 칸의 정상 표시**다(「더 있다」).

        ⚠️ 이 줄 하나가 **화면 열 곳의 textarea 18개**에 닿는다. 칸이 20px
           높아졌다(86 → 106px). 숏폼 다듬기 5칸 · AI 설정 4칸이 가장 많다. */
  line-height: 1.5;
  width: 100%;
  height: 100%;
  padding: 10px;
  resize: none;
  overflow-y: auto;
}
.textarea-box textarea:-moz-read-only {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  color: var(--color-darken);
}
.textarea-box textarea:read-only {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  color: var(--color-darken);
}
.textarea-box textarea:-moz-read-only:hover {
  cursor: not-allowed;
  border: 1px solid var(--gray-600);
}
.textarea-box textarea:read-only:hover {
  cursor: not-allowed;
  border: 1px solid var(--gray-600);
}
.textarea-box:focus textarea, .textarea-box:hover textarea {
  border: 1px solid var(--color-primary);
}
.textarea-box.error textarea {
  border: 1px solid var(--color-red);
  position: relative;
}
.textarea-box.error textarea::after {
  content: "";
  position: absolute;
  right: 15px;
  color: var(--color-red);
  background-image: url("../images/icon/icon-error.svg");
  background-size: contain;
  background-repeat: no-repeat;
}
.textarea-box:disabled textarea {
  background-color: var(--bg-disabled);
  border: 1px solid var(--gray-600);
  cursor: not-allowed;
  color: var(--color-disabled);
}
.textarea-box:disabled textarea:hover {
  border: 1px solid var(--gray-600);
}

html {
  font-size: 16px;
}

body {
  -ms-overflow-style: none;
  overflow: hidden;
}
body.modal-open {
  overflow: hidden;
}

/*
  머리 높이 — **한 곳에서만 정한다.**

  이 값을 보는 곳이 넷이다.
    · #wrapper 의 그리드 첫 행           (헤더가 놓이는 줄)
    · #header .gnb                       (그 안의 내용 높이)
    · #aside h1                          (LNB 로고 칸 — 헤더와 눈높이가 맞아야 한다)
    · #contents .container 의 calc       (남는 높이를 다 쓰게)

  ⚠️ 예전에는 넷이 각자 75px 를 적고 있었다. 로고 칸만 56px 로 줄였더니
     헤더(75px)와 눈높이가 어긋났고, 그걸 맞추려 헤더를 줄이면 이번에는
     container 의 calc(100vh - 75px) 이 남아 본문이 화면 밖으로 밀린다.
     숫자를 하나로 모은다.

  ⚠️ 56px 인 근거 — 이 줄에서 가장 높은 것은 기관 탭(.tabs.is-compact, 38px)이다.
     위아래 9px 씩 남는다. 더 줄이면 탭이 헤더를 밀어낸다.
*/
:root {
  --header-h: 56px;
}

#wrapper {
  width: 100%;
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr);
  grid-template-rows: var(--header-h) minmax(0, 1fr);
  grid-template-areas: "aside header" "aside contents";
  min-height: 100vh;
  background-color: var(--bg-white);
  transition: all 0.4s;
}
#wrapper.aside_hide {
  grid-template-columns: 0 minmax(0, 1fr);
}
#wrapper.aside_hide aside {
  width: 0;
  overflow: hidden;
}
#wrapper {
  /*
    ⚠️ **1200px 아래에서는 LNB 가 격자에서 빠진다.** 칸을 0 으로 두고 LNB 는
       화면 위에 뜨는 서랍이 된다(components/_aside.scss).
    ⚠️ `aside_hide` 가 걸려 있든 말든 같다 — 큰 화면에서 접어 두고 창을 줄이면
       그 기억이 남아 서랍이 열리지 않는 상태가 될 수 있다. 여기서 못 박는다.
    ⚠️ `transition: all 0.4s` 이 위에 걸려 있다. 폭이 바뀌는 순간 격자가
       0.4초 동안 미끄러지는데, 창을 줄이는 동안 매 프레임 다시 시작해
       **끌리는 것처럼 보인다.** 분기 안에서는 격자 전환을 끈다.
  */
}
@media (max-width: 1199px) {
  #wrapper {
    grid-template-columns: 0 minmax(0, 1fr);
    transition: none;
  }
  #wrapper.aside_hide {
    grid-template-columns: 0 minmax(0, 1fr);
  }
}

/*
  서랍 뒤에 까는 어두운 막.
  ⚠️ **막이 없으면 본문이 눌린다.** 서랍이 떠 있는 동안 뒤를 누르면 그 밑의
     단추가 눌려, 메뉴를 닫으려던 손짓이 엉뚱한 일을 시킨다.
  ⚠️ `visibility` 를 함께 쓴다. `opacity: 0` 만으로는 막이 여전히 거기 있어
     닫힌 뒤에도 본문을 가로챈다.
*/
.aside-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.24s ease, visibility 0.24s;
}

body.aside-drawer-open {
  /*
    ⚠️ **이 제품에서 body 는 이미 늘 잠겨 있다** — 굴러가는 것은 `.container`
       다(위 참고). 그래서 이 줄은 지금 하는 일이 없다. 그래도 남겨 둔다:
       레이아웃이 바뀌어 body 가 굴러가게 되는 날 서랍 뒤가 함께 굴러가는 것을
       여기서 막는다. **없는 것이 아니라 아직 할 일이 없는 것이다.**
  */
  overflow: hidden;
}
body.aside-drawer-open .aside-backdrop {
  opacity: 1;
  visibility: visible;
}

/* 1200 이상에서는 서랍 자체가 없다 — 막도 뜨지 않는다 */
@media (min-width: 1200px) {
  .aside-backdrop {
    display: none;
  }
}
/* 말줄임 */
.line-1 {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.line-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* theme button */
/*
  화면 모드 — 두 칸 세그먼트 (라이트 / 다크)
  ------------------------------------------------------------------
  예전에는 체크박스 하나였다(.theme-switch-wrapper > .slider). 그러면
  '지금 무엇이 켜져 있는지'를 손잡이 위치로만 말해서, 해 그림이 보일 때
  '지금이 라이트'인지 '누르면 라이트가 되는지'가 헷갈렸다.

  두 칸을 두고 켜진 칸을 채워진 칩으로 덮으면 그 모호함이 없어진다.
  칩 색은 브랜드 파랑 — 이 CMS 는 이미 '선택 상태 = 브랜드 파랑'을 쓴다
  (활성 탭 알약 · LNB 활성 메뉴). 그래서 색이 새로 늘지 않는다.

  칩은 절대 배치라 좌우로 미끄러진다. 활성 탭 알약과 같은 움직임이다.
  ⚠️ 칸 폭이 고정이라 위치를 CSS 로 정한다. 탭처럼 JS 로 잴 필요가 없다.

  role="group" + aria-pressed 로 상태를 알린다.
  radiogroup 을 안 쓴 이유 — 라디오는 화살표키로 이동해야 하는데,
  칸이 둘뿐이라 Tab 으로 각각 닿는 편이 관리자에게 빠르다.
*/
.theme-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border-radius: var(--radius-sm);
  background-color: var(--gray-300);
  /* 켜진 칸을 덮는 칩. 절대 배치라 좌우로 미끄러진다 */
}
.theme-switch .theme-chip {
  position: absolute;
  z-index: 0;
  top: 4px;
  left: 4px;
  width: 32px;
  height: 30px;
  border-radius: var(--radius-sm);
  background-color: var(--color-primary);
  transition: left 0.28s cubic-bezier(0.22, 0.9, 0.3, 1);
}
.theme-switch {
  /* 다크를 고른 상태 — 칸 폭 32 + 간격 2 만큼 옮긴다 */
}
.theme-switch.is-dark .theme-chip {
  left: 38px;
}
.theme-switch .theme-opt {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 30px;
  min-width: auto;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  cursor: pointer;
}
.theme-switch .theme-opt .icon {
  width: 17px;
  height: 17px;
  transition: filter 0.2s ease, opacity 0.2s ease;
}
.theme-switch .theme-opt {
  /*
    꺼진 칸.
    SVG 에 stroke 색이 박혀 있어 다크에서는 그대로 두면 안 보인다.
    토큰마다 filter 를 새로 풀 수는 없으므로(필터는 CSS 변수를 못 읽는다)
    이미 있는 흑/백 필터에 opacity 를 얹어 중간톤을 만든다.
  */
}
.theme-switch .theme-opt:not(.is-active) .icon {
  filter: var(--filter-dark);
  opacity: 0.55;
}
.theme-switch .theme-opt {
  /* 켜진 칸은 파란 칩 위에 얹히므로 흰색 (칩 대비 3.13:1 — 비텍스트 기준 3:1 통과) */
}
.theme-switch .theme-opt.is-active .icon {
  filter: var(--filter-white);
  opacity: 1;
}
.theme-switch {
  /* 키보드로 왔을 때 어디에 있는지 보여야 한다 */
}
.theme-switch .theme-opt:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* 다크에서는 꺼진 칸을 흰색 계열로 뒤집는다. :not() 으로 켜진 칸은 건드리지 않는다 */
[data-theme=dark] .theme-switch .theme-opt:not(.is-active) .icon {
  filter: var(--filter-white);
}

@media (prefers-reduced-motion: reduce) {
  .theme-switch .theme-chip {
    transition: none;
  }
}
/* common style */
#contents {
  grid-area: contents;
  background: var(--gray-200);
  /*
    ⚠️ **이 상자가 스크롤 주체다.** body 가 아니라 여기가 굴러간다(body 는 overflow: hidden).

    ⚠️ 그래서 안쪽 여백(30px)이 `position: sticky` 가 멈추는 자리를 정한다.
       sticky 는 스크롤 영역의 **안쪽 여백 위**에서 멈추므로, `bottom: 0` 으로 붙여 둔
       하단 바는 바닥에서 30px 뜬 채로 서고 그 틈으로 본문이 지나가 보인다.
       `top: 0` 인 표 머리글도 30px 아래에 서서 그 위로 줄이 비친다.

       값을 쓰는 쪽 세 군데(교육 등록 · 권한 관리 · 번역 검수)에 따로 박으면
       여기 30px 을 고칠 때 셋이 어긋난다. 그래서 변수로 내려 준다 —
         bottom: calc(var(--container-pad) * -1);
    ⚠️ 이 변수를 지우거나 이름을 바꾸면 그 셋이 다시 뜬다.
  */
  --container-pad: 30px;
}
#contents .container {
  height: calc(100vh - var(--header-h));
  padding: var(--container-pad) 20px;
  margin: 0 auto;
  box-sizing: border-box;
  overflow-y: auto;
  /*
    ⚠️ 좁은 화면에서 30px 은 본문에서 떼어 가는 몫이 너무 크다 —
       390px 에서 좌우 40px 이면 본문이 350px 뿐이다.
  */
}
@media (max-width: 767px) {
  #contents .container {
    --container-pad: 16px;
    padding: var(--container-pad) 14px;
  }
}

.section {
  /*
    ⚠️ **`min-width: 1400px` 한 줄이 스물두 화면 전부의 가로 스크롤이었다.**
       LNB 250 + 좌우 여백 40 을 떼고 나면 1690px 아래 모든 폭에서 본문이
       칸을 넘겼다. 1366 노트북에서 324px, 1280 에서 410px 이 밀렸다.
       ⚠️ 넘친 것은 문서가 아니라 `.container` 였다 — `overflow-y: auto` 가
          가로도 `auto` 로 만들어, **LNB 와 헤더는 제자리인 채 안쪽만** 밀렸다.
          그래서 스크롤바가 눈에 안 띄고 「오른쪽이 잘렸다」로 보였다.

    ⚠️ **1400px 이상에서는 그대로 둔다.** 쓰는 사람 대부분이 이 폭이고,
       여기서 폭을 유동으로 바꾸면 멀쩡한 화면 스물둘이 한꺼번에 달라진다.
  */
  min-width: 0;
  overflow: visible;
}
@media (min-width: 1690px) {
  .section {
    min-width: 1400px;
  }
}

.relative {
  position: relative;
}

.blind {
  position: absolute;
  left: -99999px;
  display: block;
  width: 1px;
  height: 1px;
  overflow: hidden;
  text-indent: -99999px;
  clip: rect(0, 0, 0, 0);
}

.spacer {
  display: block;
  width: 100%;
  height: 1px;
  margin: 30px 0;
}

.flex {
  display: flex;
}
.flex .shrink-0 {
  flex-shrink: 0;
}
.flex {
  /* 방향 */
}
.flex.dir-row {
  flex-direction: row;
}
.flex.dir-col {
  flex-direction: column;
}
.flex {
  /* 정렬 */
}
.flex.align-center {
  align-items: center;
}
.flex.align-start {
  align-items: flex-start;
}
.flex.align-end {
  align-items: flex-end;
}
.flex.justify-center {
  justify-content: center;
}
.flex.justify-start {
  justify-content: flex-start;
}
.flex.justify-end {
  justify-content: flex-end;
}
.flex.justify-space-between {
  justify-content: space-between;
}
.flex {
  /*
    ⚠️ 정의가 없었는데 화면에서는 이미 쓰고 있었다(소셜 미디어 채널 연동 등).
       좁아지면 줄을 바꿔야 할 단추 묶음이 한 줄에 눌려 밀려 나가고 있었다.
  */
}
.flex.flex-wrap {
  flex-wrap: wrap;
}
.flex.with-btn {
  align-items: center;
  gap: 8px;
}
.flex.with-btn button {
  flex-shrink: 0;
}
.flex[class*=col-] {
  gap: 10px;
}
.flex.gap4 {
  gap: 4px;
}
.flex.gap8 {
  gap: 8px;
}
.flex.gap12 {
  gap: 12px;
}
.flex {
  /*
    ⚠️ gap16 만 없었다. gap4·gap8·gap12 는 있는데 16 만 빠져 있어서,
       `class="flex align-center gap16"` 이라고 적어 둔 자리가 그냥 붙어 있었다
       (교육 등록 화면의 「게시 / 임시저장」 라디오 둘).
       눈금이 4·8·12 로 이어지다 16 에서 끊기면, 쓰는 사람은 있는 줄 알고 적는다.
  */
}
.flex.gap16 {
  gap: 16px;
}

/* text */
.text-bold {
  font-weight: bold;
}

.text-center {
  text-align: center !important;
}

.text-right {
  text-align: right !important;
}

.text-left {
  text-align: left !important;
}

/* color */
.color-primary {
  color: var(--color-primary);
}

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

.color-point {
  color: var(--color-point);
}

.color-error {
  color: var(--color-red);
}

.color-darken {
  color: var(--color-darken);
}

.color-white {
  color: var(--color-white);
}

.color-red {
  color: var(--color-red);
}

.color-blue {
  color: var(--color-blue);
}

.error-text {
  color: var(--color-red);
  margin-top: 8px;
}

.guide-text-wrap p {
  font-size: 14px;
}

/* 필수 입력 표시 — <p class="field-title">배너명 <span class="req">*</span></p> */
.req {
  margin-left: 2px;
  color: var(--color-red);
}

/* 입력칸 아래 도움말 한 줄 */
/*
  글 안에 곁들이는 보조 설명 — <label> 안의 「— 새로 들어올 이름 41명」 같은 것.
  ⚠️ .field-help 는 블록이라 줄이 바뀐다. 같은 줄에 이어 붙일 자리가 없었다.
  ⚠️ 12px 밑으로 내리지 않는다. 본문 최소 크기다.
*/
.txt-sub {
  margin-left: 4px;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
  color: var(--gray-900);
  font-weight: 400;
}

/*
  곁들이는 보조 글자 — 「약 17시간 뒤」·「(A0010)」·「화면의 검색 결과」 같은 것.

  ⚠️ 전역 정의가 **없었다.** 대시보드 안에만 있어서 나머지 여덟 화면에서는 크기도
     색도 부모를 그대로 물려받았다. 엑셀 다운로드 모달에서는 부모가
     .field-title(18px/600) 이라 **곁들이는 안내가 라벨과 똑같이 크고 굵게** 나왔다.
  ⚠️ 색은 --gray-900 이 아니라 --text-muted 다. 앞의 것은 흰 바탕 3.30:1 로 본문
     기준(4.5:1) 미달이고, 글자를 작게 할수록 대비는 더 중요해진다.
*/
.txt-muted {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text-muted);
}

/*
  라벨(.field-title) 안에 괄호로 곁들이는 안내.
  ⚠️ 라벨의 크기·굵기를 물려받으면 안내가 라벨만큼 소리친다. 한 단 내린다.
  ⚠️ .color-red 도 마찬가지다 — 그 클래스는 색만 정하고 크기는 안 정한다.
     빨강은 이미 충분히 눈에 걸리므로 크기까지 키울 이유가 없다.
*/
.field-title .txt-muted,
.field-title .color-red,
.field-title .color-gray {
  font-size: 13px;
  font-weight: 400;
}
.field-title {
  /*
    ⚠️ 빨강을 여기서 한 번 더 세운다. 안내 span 은 .txt-muted 와 .color-red 를
       함께 갖는데, 둘 다 명시도가 같아서(0,1,0) 나중에 선언된 .txt-muted 의
       회색이 이겼다 — 「반드시 적어야 합니다」가 회색으로 나왔다.
  */
}
.field-title .color-red {
  color: var(--color-red);
}

.field-help {
  margin-top: 6px;
  /* ⚠️ 16px 였다. 입력칸 아래 곁들이는 한 줄이라 본문과 같은 크기일 이유가 없다 */
  font-size: 14px;
  line-height: 1.5;
  /* ⚠️ --gray-900 은 흰 바탕 3.30:1 로 AA 미달이다. 글자용 눈금을 쓴다(5.22:1) */
  color: var(--text-muted);
}
.field-help code {
  padding: 1px 5px;
  border-radius: var(--radius-sm);
  background-color: var(--gray-300);
}

/* list type */
.list-type.dot li {
  font-size: 18px;
  line-height: 1.5;
  position: relative;
  padding-left: 15px;
}
.list-type.dot li::before {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-circle);
  background-color: var(--bg-darken);
  position: absolute;
  top: 10px;
  left: 0;
}
.list-type.dot li.no-dot {
  padding-left: 0;
}
.list-type.dot li.no-dot::before {
  display: none;
}

/* space */
.mt0 {
  margin-top: 0px !important;
}

.mt4 {
  margin-top: 4px !important;
}

.mt8 {
  margin-top: 8px !important;
}

.mt12 {
  margin-top: 12px !important;
}

.mt16 {
  margin-top: 16px !important;
}

.mt24 {
  margin-top: 24px !important;
}

.mt36 {
  margin-top: 36px !important;
}

.mt48 {
  margin-top: 48px !important;
}

.mt56 {
  margin-top: 56px !important;
}

.mb0 {
  margin-bottom: 0px !important;
}

.mb8 {
  margin-bottom: 8px !important;
}

.mb12 {
  margin-bottom: 12px !important;
}

.mb24 {
  margin-bottom: 24px !important;
}

.mb36 {
  margin-bottom: 36px !important;
}

.mb48 {
  margin-bottom: 48px !important;
}

.mb56 {
  margin-bottom: 56px !important;
}

/*
  잠긴 칸 묶음 — 「예약 공개」를 안 골랐을 때의 공개 일시처럼,
  아직 쓸 수 없지만 **있다는 건 보여야 하는** 칸에 붙인다 (assets/js/board.js 의 lock()).

  ⚠️ 감추지 않고 흐리게만 한다. 감추면 '그런 걸 넣는 화면이 아니구나' 로 잘못 읽는다.
  ⚠️ disabled 만으로는 브라우저마다 표시가 달라 잠긴 줄 모르고 계속 눌러 본다.
     그래서 눈으로도 알리는 표시를 따로 둔다.
*/
.is-off {
  opacity: 0.45;
  pointer-events: none;
}

/* =====================================================
 * LNB 접힘을 html 속성으로도 잡는다 — **개발본 전용**
 *
 * ⚠️ 퍼블은 클래스만 본다. 개발본은 commonHead.jsp 의 인라인 스크립트가
 *    `#wrapper` 가 만들어지기 **전에** html 에 data-aside 를 넣는다.
 *    클래스만 보면 펼쳐진 채로 한 번 그려졌다가 접히는 장면이 보인다.
 * ⚠️ 퍼블 자산을 다시 반영할 때 이 블록은 지우지 말 것.
 * ===================================================== */
[data-aside=hidden] #wrapper {
  grid-template-columns: 0 minmax(0, 1fr);
}
[data-aside=hidden] #wrapper aside {
  width: 0;
  overflow: hidden;
}

/* LNB 가 접히면 화살표만 반대로 — 막대는 왼쪽에 그대로 둔다 */
[data-aside=hidden] #asideToggleBtn .icon::before {
  background-image: url(../images/icon/icon-panel-expand.svg);
}

#aside {
  width: 250px;
  background: var(--aside-bg);
  color: var(--color-white);
  grid-area: aside;
  border-right: 1px solid var(--gray-600);
  /*
    로고 칸 — 오른쪽 헤더와 눈높이를 맞춘다.
    ⚠️ 높이를 여기서 정하지 않는다. --header-h(_global.scss)가 헤더·그리드·본문
       높이를 한꺼번에 정하고, 이 칸도 그것을 본다. 예전에는 로고 칸만 따로
       56px 을 갖고 있어서 헤더(75px)와 어긋났다.
    ⚠️ 패딩으로 높이를 만들지 않는다(12+32+12=56 식). 로고 크기를 바꾸면 그
       계산을 다시 해야 한다. 칸 높이를 못 박고 안에서 가운데 정렬한다.
  */
}
#aside h1 {
  height: var(--header-h);
  display: flex;
  align-items: center;
  padding: 0 20px;
  border-bottom: 1px solid var(--gray-600);
}
#aside h1 a {
  display: block;
  width: 100%;
  height: 32px;
  margin: 0 auto;
  text-align: center;
}
#aside h1 a::after {
  content: "";
  width: 100%;
  height: 100%;
  display: block;
  background-image: var(--aside-logo);
  background-size: contain;
  background-repeat: no-repeat;
}

/*
  지금 보고 있는 한 줄.
  ⚠️ 채우지 않는다. 줄이 촘촘해지면 채운 알약이 목록을 뚝뚝 끊는다 —
     열여섯 줄 가운데 한 줄만 두껍게 부풀어 보인다. 글자를 강조색으로
     바꾸고 아주 옅게만 깐다. 촘촘한 목록에서는 이쪽이 더 잘 보인다.
  ⚠️ 그룹 머리(li.active)는 채우지도 않는다. 강조가 둘이면 「지금 어디」가
     흐려진다. 구역은 글자 진하기로만 말한다.
*/
/*
  LNB 본문
  ==================================================================
  ⚠️ 색을 여기에 박지 않는다. 「메뉴 색상」(page/setting/lnb-color.jsp)이
     --aside-* 토큰만 덮으므로, 여기서 #000 같은 값을 쓰면 **골라도 안 바뀌는
     자리**가 생긴다.

  ⚠️ 예전에는 2·3뎁스가 --bg-darken(검정) 판이었다. 한 그룹만 펴지는
     아코디언일 때는 「눌러서 내려온 판」으로 읽혔다. 그런데 전부 펴 두는
     지금은 그 검정이 LNB 의 대부분을 덮는다 — 고른 배경색은 위아래 띠로만
     남고 가운데는 검은 슬래브가 된다. 「메뉴 색상」이 하는 말과 어긋난다.
     판을 없앤다. LNB 는 **한 장의 면**이고, 층은 들여쓰기와 글자 크기로
     말한다. 채워서 강조하는 곳은 **지금 보고 있는 한 줄뿐**이다.

  ⚠️ 줄 사이 실선(rgba(255,255,255,.1))도 뺐다. 흰색 반투명이라 밝은 배경을
     고르면 아예 안 보인다. 어두운 배경에서만 맞는 선은 없는 편이 낫다.
*/
.aside-nav {
  /* 헤더가 아니라 위 로고 칸을 뺀다 — 숫자는 #aside 가 갖고 있다 */
  height: calc(100vh - var(--header-h));
  overflow-y: auto;
  padding: 4px 8px 20px;
  color: var(--aside-text);
  font-size: 13.5px;
  /*
    넘칠 때만 나오는 가느다란 막대.
    ⚠️ 전부 펴 두므로 노트북(768)에서는 실제로 넘친다. 배경색을 무엇으로
       고르든 튀지 않게 중립 회색으로 둔다.
  */
  scrollbar-width: thin;
  scrollbar-color: rgba(128, 128, 128, 0.4) transparent;
}
.aside-nav::-webkit-scrollbar {
  width: 10px;
}
.aside-nav::-webkit-scrollbar-track {
  background: transparent;
}
.aside-nav::-webkit-scrollbar-thumb {
  background: rgba(128, 128, 128, 0.4);
  border-radius: var(--radius-sm);
  border: 3px solid transparent;
  background-clip: content-box;
}
.aside-nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  border-radius: var(--radius-sm);
  color: var(--aside-text);
  transition: background-color 0.15s ease, color 0.15s ease;
  /*
    hover 덧칠.
    ⚠️ 색을 정하지 않고 currentColor 를 깐다 — 밝은 배경에서는 글자색이
       검으니 검게, 어두운 배경에서는 희게 깔린다. 토큰을 새로 만들지
       않고도 양쪽에서 맞는다.
  */
}
.aside-nav a::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  transition: opacity 0.15s ease;
  pointer-events: none;
}
.aside-nav a:hover::before {
  opacity: 0.08;
}
.aside-nav {
  /* 1뎁스 — 자식이 없으면 그냥 한 줄이다(대시보드) */
}
.aside-nav .depth1 {
  padding: 7px 10px;
  font-weight: 500;
}
.aside-nav .depth1 img {
  width: 16px;
  height: 16px;
  filter: brightness(0) saturate(100%) invert(50%) sepia(0%) saturate(1059%) hue-rotate(174deg) brightness(87%) contrast(81%);
}
.aside-nav .depth1.is-active {
  color: var(--aside-accent);
  font-weight: 700;
  opacity: 1;
  /* 강조색 위로 아주 옅게. currentColor 라 강조색이 무엇이든 따라간다 */
}
.aside-nav .depth1.is-active::before {
  opacity: 0.12;
}
.aside-nav .depth1.is-active:hover::before {
  opacity: 0.18;
}
.aside-nav {
  /*
    구역 머리 — 누르는 물건이 아니라 **구역 이름**이다.
    ⚠️ 예전에는 18px 짜리 줄이라 아래 항목들과 무게가 같았다. 전부 펴 두면
       같은 크기의 줄이 열여섯 개 이어져, 어디서 묶음이 시작되는지 눈이
       끊지 못한다. 작고 조용하게 두고, **이름 오른쪽으로 실선을 흘려**
       구역의 시작을 못박는다. 여백만으로 끊으면 줄이 촘촘할수록 안 끊긴다.
    ⚠️ 클래스는 JSP 가 붙인다(components/aside.jsp). aria-expanded 로 가르면
       스크립트가 돌기 전 한 번 다른 모습으로 그려진다.
  */
}
.aside-nav .depth1.is-group {
  padding: 14px 10px 4px;
  gap: 8px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  opacity: 0.45;
}
.aside-nav .depth1.is-group img {
  width: 12px;
  height: 12px;
}
.aside-nav .depth1.is-group {
  /* 이름과 캐럿 사이를 채우는 실선. 자리를 차지하는 빈 span 이라
     aria-hidden 이다(components/aside.jsp) */
}
.aside-nav .depth1.is-group .grp-rule {
  flex: 1 1 auto;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
}
.aside-nav .depth1.is-group {
  /* 접힘 표시 — 펴져 있으면 아래, 접으면 왼쪽을 가리킨다 */
}
.aside-nav .depth1.is-group::after {
  content: "";
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.2s ease;
}
.aside-nav .depth1.is-group[aria-expanded=false]::after {
  transform: rotate(-45deg) translate(-1px, 1px);
}
.aside-nav .depth1.is-group:hover::before {
  opacity: 0.06;
}
.aside-nav {
  /* 지금 들어와 있는 구역은 조금 또렷하게 — 채우지는 않는다 */
}
.aside-nav li.active > .depth1.is-group {
  opacity: 0.85;
}
.aside-nav {
  /* 2뎁스 */
}
.aside-nav .depth2 {
  /* ⚠️ slideUp/Down 이 높이를 재려면 있어야 한다 */
  overflow: hidden;
  /* -----------------------------------------------------
   * LNB 표시 — 빨간 숫자 하나뿐
   *
   * ⚠️ **모양은 하나다.** 한때 경고를 점(.lnb-dot)으로 갈랐다가 되돌렸다 —
   *    점은 「무엇인가 있다」까지만 말하고 뜻은 title 에 숨었는데,
   *    **title 은 터치에서도 키보드 포커스에서도 뜨지 않는다.**
   *    낭독기를 쓰지 않는 사람에게는 뜻이 닿지 않았다.
   *    숫자는 아무 설명 없이도 「n 개가 밀려 있다」로 읽힌다.
   * ⚠️ 줄 오른쪽 끝에 붙인다(margin-left:auto). 글자 바로 뒤에 두면
   *    메뉴 이름 길이에 따라 자리가 들쭉날쭉해 훑어 읽을 수 없다.
   * ⚠️ 색은 **고정값**이다. LNB 배경은 사람이 바꾸지만(화면 색상 변경)
   *    이건 「지금 봐야 한다」는 신호라 배경을 따라가면 안 된다.
   *    대신 글자를 흰색으로 박아 어느 배경에서도 읽히게 한다.
   * ----------------------------------------------------- */
}
.aside-nav .depth2 .lnb-count {
  flex: 0 0 auto;
  margin-left: auto;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--radius-sm);
  background: var(--color-red);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
  /* ⚠️ 숫자가 커져도 줄이 흔들리지 않게 — 20px 안에서만 자란다 */
  white-space: nowrap;
}
.aside-nav .depth2 {
  /* ⚠️ LNB 를 접으면 표시도 함께 사라져야 한다 — 이름이 없는데 숫자만
       떠 있으면 무엇의 숫자인지 알 수 없다 */
}
.aside_hide .aside-nav .depth2 .lnb-count {
  display: none;
}
.aside-nav .depth2 {
  /*
    묶음 안을 다시 가르는 줄 — 관리자 · 설정처럼 열 줄이 넘는 곳에 쓴다.
    ⚠️ **빈 <li> 를 넣지 않는다.** 눈에는 선 하나지만 키보드와 낭독기에는
       아무 뜻도 없는 줄이 하나 늘어난다. 클래스 하나로 위쪽에 선을 그린다.
    ⚠️ 선은 **글자 자리에 맞춰 들여쓴다**(30px). 왼쪽 끝까지 그으면
       묶음(depth1)을 가르는 선처럼 보여 단이 하나 더 있는 줄 안다.
    ⚠️ opacity 로만 옅게 한다. LNB 는 배경색을 사람이 바꾼다(화면 색상 변경) —
       고정된 회색을 쓰면 어두운 배경에서 사라진다.
  */
}
.aside-nav .depth2 > .depth2-item.is-groupstart {
  position: relative;
  margin-top: 8px;
  padding-top: 8px;
}
.aside-nav .depth2 > .depth2-item.is-groupstart::before {
  content: "";
  position: absolute;
  left: 30px;
  right: 10px;
  top: 0;
  height: 1px;
  background: currentColor;
  opacity: 0.18;
}
.aside-nav .depth2 {
  /* ⚠️ 들여쓰기는 **그룹 이름의 글자 자리**에 맞춘다(패딩 12 + 아이콘 14 +
     사이 10 = 36). 아이콘 밑으로 파고들면 묶음의 왼쪽 선이 두 개가 된다 */
}
.aside-nav .depth2 > .depth2-item > a {
  padding: 6px 10px 6px 30px;
  /* 아래에 3뎁스를 단 줄(화면 세팅)도 여닫는 물건이다 — 같은 표시를 준다 */
}
.aside-nav .depth2 > .depth2-item > a[aria-expanded]::after {
  content: "";
  flex: 0 0 auto;
  margin-left: auto;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  opacity: 0.5;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.2s ease;
}
.aside-nav .depth2 > .depth2-item > a[aria-expanded=false]::after {
  transform: rotate(-45deg) translate(-1px, 1px);
}
.aside-nav .depth2 > .depth2-item > a.is-active {
  color: var(--aside-accent);
  font-weight: 700;
  opacity: 1;
  /* 강조색 위로 아주 옅게. currentColor 라 강조색이 무엇이든 따라간다 */
}
.aside-nav .depth2 > .depth2-item > a.is-active::before {
  opacity: 0.12;
}
.aside-nav .depth2 > .depth2-item > a.is-active:hover::before {
  opacity: 0.18;
}
.aside-nav {
  /* 3뎁스 */
}
.aside-nav .depth3 {
  overflow: hidden;
}
.aside-nav .depth3:empty {
  display: none !important;
}
.aside-nav .depth3 > li > a {
  padding: 5px 10px 5px 46px;
  font-size: 12.5px;
  opacity: 0.82;
}
.aside-nav .depth3 > li > a.is-active {
  color: var(--aside-accent);
  font-weight: 700;
  opacity: 1;
  /* 강조색 위로 아주 옅게. currentColor 라 강조색이 무엇이든 따라간다 */
}
.aside-nav .depth3 > li > a.is-active::before {
  opacity: 0.12;
}
.aside-nav .depth3 > li > a.is-active:hover::before {
  opacity: 0.18;
}

/* ================================
   Dark Mode — Aside
   ------------------------------------------------------------------
   ⚠️ 예전에는 여기서 2·3뎁스 배경(#0D1117 · #080D13)과 글자색을 통째로 다시
      칠했다. 이제 위쪽이 전부 --aside-text · --aside-accent 만 쓰므로
      다시 칠할 것이 없다 — 어두운 테마는 --color-darken 이 밝은 색이라
      글자가 알아서 뒤집힌다. 남는 것은 판 자체의 색뿐이다.
   ================================ */
[data-theme=dark] #aside {
  background: linear-gradient(180deg, #1A2030 0%, #151A27 40%, #0F1420 100%);
  border-right-color: rgba(255, 255, 255, 0.06);
}
[data-theme=dark] #aside h1 {
  border-bottom-color: rgba(255, 255, 255, 0.06);
}
[data-theme=dark] {
  /* 아이콘은 <img> 라 색을 못 물려받는다 — 어두운 판 위에서 밝게.
     ⚠️ 지금 보고 있는 줄이라고 따로 칠하지 않는다. 채우지 않는 강조라
        아이콘까지 뒤집으면 그 줄만 색이 둘이 된다. */
}
[data-theme=dark] .aside-nav .depth1 img {
  filter: brightness(0) saturate(100%) invert(85%) sepia(0%) saturate(500%) hue-rotate(180deg) brightness(95%) contrast(90%);
}

/* =====================================================
 * 1200px 아래 — LNB 는 덮개 서랍이 된다
 *
 * ⚠️ **덮개다. 밀어내지 않는다**(2026-09-10 결정). 본문을 옆으로 밀면
 *    서랍을 열고 닫을 때마다 본문 폭이 249px 씩 바뀌고, 그때마다 표가
 *    다시 계산된다 — 메뉴를 여는 동안 뒤에서 줄이 출렁인다.
 *    덮으면 본문은 제자리에 그대로 있다.
 *
 * ⚠️ `position: fixed` 다. 격자에서 빠져 나오므로 `#wrapper` 의 첫 칸은
 *    0 이 된다(_global.scss). absolute 로 두면 본문을 굴릴 때 함께 굴러간다.
 *
 * ⚠️ **`display: none` 으로 감추지 않는다.** 감췄다 되살리면 미끄러질 거리가
 *    없어 툭 나타난다. 왼쪽 밖으로 밀어 두고 `visibility` 로 막는다 —
 *    닫힌 동안 탭 키가 그 안의 링크 열여덟 개를 훑고 지나가는 것을 막는 것도
 *    `visibility: hidden` 이 한다.
 * ===================================================== */
@media (max-width: 1199px) {
  #aside {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 100; /* 막(90)보다 위 */
    width: 260px;
    max-width: 82vw; /* 390px 화면에서 뒤가 손가락만큼은 보여야 닫을 수 있다 */
    height: 100vh;
    overflow-y: auto;
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 0.26s cubic-bezier(0.22, 0.9, 0.3, 1), visibility 0.26s;
    box-shadow: var(--elev-2);
    /*
      ⚠️ 서랍에서는 로고 칸이 「닫기」 자리를 겸한다. 헤더의 햄버거는 본문
         위에 있어 서랍이 덮고 있는 동안 보이지 않는다 — 닫을 길이 막을
         누르는 것 하나뿐이면, 그것이 닫는 동작인 줄 모르는 사람이 막힌다.
    */
  }
  #aside .aside-close {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 1;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid currentColor;
    border-radius: var(--radius-sm);
    background: transparent;
    /* ⚠️ LNB 글자색을 그대로 따른다 — 이 색은 사용자가 고른다 */
    color: var(--aside-text);
    cursor: pointer;
    /* ✕ — 두 막대를 엇갈려 그린다. currentColor 라 색을 따로 정하지 않는다 */
  }
  #aside .aside-close .x {
    position: relative;
    width: 14px;
    height: 14px;
  }
  #aside .aside-close .x::before, #aside .aside-close .x::after {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 100%;
    height: 1.6px;
    background: currentColor;
    border-radius: 1px;
  }
  #aside .aside-close .x::before {
    transform: rotate(45deg);
  }
  #aside .aside-close .x::after {
    transform: rotate(-45deg);
  }
  #aside .aside-close:hover {
    background: rgba(127, 127, 127, 0.18);
  }
  #aside .aside-close:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
  }
  #aside {
    /*
      ⚠️ **메뉴 칸이 화면 높이를 통째로 먹지 않게 한다.** `.aside-nav` 는
         `height: calc(100vh - 로고칸)` 인데, 서랍에서는 그 아래에 「내 것」
         묶음이 더 붙는다. 그대로 두면 메뉴가 끝난 자리부터 **빈 화면 한 장**이
         이어지고 로그아웃은 그 아래로 밀려, 있는 줄도 모르고 지나친다.
    */
  }
  #aside .aside-nav {
    height: auto;
    overflow-y: visible;
  }
  body.aside-drawer-open #aside {
    transform: translateX(0);
    visibility: visible;
  }
}
/* 1200 이상에서는 닫기 단추가 설 자리가 없다 — LNB 가 늘 떠 있다 */
@media (min-width: 1200px) {
  #aside .aside-close {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  #aside {
    transition: none;
  }
}
/* =====================================================
 * 「준비」 메뉴 — **개발본 전용**
 *
 * 퍼블에는 없다. 개발본은 퍼블 LNB 를 먼저 세워 두고 화면을 하나씩 붙이므로,
 * **자리는 두되 끄는** 상태가 필요하다(components/aside.jsp 머리 주석 · README).
 * 화면이 붙는 날 href 를 채우고 `is-soon` 만 지운다.
 *
 * ⚠️ 이 규칙은 원래 **컴파일된 index.css 에만** 손으로 적혀 있었다.
 *    scss 를 다시 구우면 조용히 사라지는 자리였다(2026-09-18 실제로 사라졌다).
 *    그래서 원본인 여기로 옮겨 둔다 — 고칠 곳은 이제 한 곳이다.
 * ⚠️ 퍼블 자산을 다시 반영할 때 이 블록은 지우지 말 것.
 * ===================================================== */
.aside-nav a.is-soon {
  opacity: 0.4;
  cursor: default;
  /* 꺼진 메뉴는 hover 로 반응하지 않는다 — 누를 수 있는 것처럼 보이면 안 된다 */
}
.aside-nav a.is-soon:hover::before {
  opacity: 0;
}
.aside-nav {
  /* 메뉴 이름 오른쪽에 붙는 「준비」 표 */
}
.aside-nav .lnb-soon {
  flex: 0 0 auto;
  margin-left: auto;
  height: 18px;
  padding: 0 6px;
  border: 1px solid currentColor;
  border-radius: var(--radius-sm);
  font-size: 10px;
  font-weight: 600;
  line-height: 16px;
  letter-spacing: 0;
  white-space: nowrap;
}

/* LNB 를 접으면 이름이 사라지므로 표도 함께 감춘다 */
.aside_hide .aside-nav .lnb-soon {
  display: none;
}

#header {
  border-bottom: 1px solid var(--gray-600);
  width: 100%;
  grid-area: header;
}
#header .container {
  padding: 0 20px;
  /*
    ⚠️ .gnb 가 height:100% 인데 이 칸에 높이가 없으면 100% 가 auto 로 풀려
       내용 높이(38px)만큼만 차지한다. 그러면 56px 헤더 안에서 위로 붙고
       아래 18px 이 빈다. 여기서 높이를 이어 줘야 세로 가운데가 잡힌다.
  */
  height: 100%;
}
#header .container .gnb {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-left: auto;
  gap: 20px;
  height: 100%; /* 줄 높이는 #wrapper 의 --header-h 가 정한다 */
}
#header .container .gnb #asideToggleBtn {
  flex: 0 0 auto;
}
#header .container .gnb #asideToggleBtn .icon {
  filter: var(--filter-white);
}
#header .container .gnb {
  /*
    화면 제목 — 브레드크럼 + 제목 + (기관 탭)
    ------------------------------------------------------------------
    ⚠️ 예전에는 각 화면 본문 맨 위에 있었다. 화면마다 같은 줄을 다시 그렸고,
       본문 첫 카드가 그만큼 아래로 밀렸다. 지금은 헤더가 한 번만 그린다
       (마크업은 components/header.jsp, 값은 각 화면이 넘긴다).
    ⚠️ 접기 단추 바로 오른쪽에 둔다 — 「어디에 있는가」가 「무엇을 접는가」
       다음에 오는 순서다.
    ⚠️ min-width:0 이 있어야 제목이 길 때 오른쪽 묶음을 밀어내지 않고
       자기 칸 안에서 줄어든다(플렉스 기본이 min-width:auto 라서).
  */
}
#header .container .gnb .page-head {
  min-width: 0;
  /*
    ⚠️ 브레드크럼과 제목을 위아래로 쌓고 있었다(13 + 2 + 28). 그래서 이 줄만
       48px 이 필요했고 헤더가 75px 이어야 했다. LNB 로고 칸(56px)과 눈높이가
       어긋난 원인이 이것이다.
       한 줄로 눕히면 가장 높은 것이 기관 탭(38px)뿐이라 56px 에 들어간다.

    ⚠️ row-reverse 다. 마크업 순서는 「브레드크럼 → 제목」인데(낭독기에는
       위치가 먼저 오는 편이 맞다), 눈으로는 제목이 먼저 와야 한다.
       순서를 바꾸지 않고 방향만 뒤집는다.
  */
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  gap: 10px;
  /*
    ⚠️ 색은 --gray-* 에서 고르지 않는다. 그 눈금은 전부 밝아서 글자에 쓰면
       흰 바탕에서 읽히지 않는다 — 처음에 --gray-600 으로 칠했더니 1.41:1 이었다
       (WCAG AA 본문 기준 4.5:1). 글자용 --text-muted 를 쓴다(5.22:1).
    ⚠️ 12px 였는데 13px 로 올렸다. 위치를 알려 주는 줄이라 흘려봐도 읽혀야 한다.
    ⚠️ 호버는 브랜드 파랑으로 바꾸지 않는다. #289DD2 는 흰 바탕에서 3.07:1 이라
       **누르려는 순간 오히려 흐려진다.** 검정으로 진해지고 밑줄이 붙는다.
  */
}
#header .container .gnb .page-head .breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-muted);
  /*
    한 줄로 누우면서 아래 여백이 필요 없어졌다.
    ⚠️ 좁아지면 여기부터 줄어든다 — 제목은 「지금 어느 화면인가」라 끝까지
       남아야 한다. wrap 을 끄는 것도 중요하다. 두 줄로 접히면 이 줄이
       높아져 헤더 높이가 무너진다.
  */
  margin-bottom: 0;
  flex: 0 1 auto;
  flex-wrap: nowrap;
  min-width: 0;
  overflow: hidden;
  padding: 5px 10px;
  border-radius: var(--radius-pill);
  background-color: var(--gray-300);
}
#header .container .gnb .page-head .breadcrumb a {
  color: var(--text-muted);
  text-decoration: none;
}
#header .container .gnb .page-head .breadcrumb a:hover {
  color: var(--color-darken);
  text-decoration: underline;
}
#header .container .gnb .page-head .breadcrumb {
  /* 구분 기호는 aria-hidden 인 장식이라 한 단 연하게 둔다(3.30:1) */
}
#header .container .gnb .page-head .breadcrumb .sep {
  color: var(--gray-900);
}
#header .container .gnb .page-head .breadcrumb .current {
  color: var(--color-darken);
  font-weight: 600;
}
#header .container .gnb .page-head .page-title-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
#header .container .gnb .page-head .page-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#header {
  /*
    「내 것 · 나가기」 묶음 — 화면 모드 · 나 · 메뉴 구조도 · 내 비밀번호 · 로그아웃
    ------------------------------------------------------------------
    ⚠️ **이 그릇에 `display: flex` 가 반드시 있어야 한다.** 2026-09-10 에
       반응형으로 짜면서 다섯을 `.gnb-mine` 으로 감쌌는데 여기에 기본
       레이아웃을 안 주었다 — 그릇이 그냥 블록이라 **다섯이 세로로 쌓였고,
       로그아웃은 헤더 아래로 밀려 보이지 않았다.**
       좁은 화면만 보고 넓은 화면을 확인하지 않아 놓친 것이다.

    ⚠️ **오른쪽으로 미는 일을 이 그릇이 맡는다.** 전에는 묶음의 첫 번째였던
       `.theme-switch` 가 `margin-left: auto` 로 밀었다. 그것이 그릇 안으로
       들어간 지금은 **그릇 안에서만** 밀어, 화면 모드가 나머지 넷과 벌어진다.
       미는 것은 늘 **줄에 직접 놓인 것**이 맡아야 한다.
  */
}
#header .gnb-mine {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-left: auto;
}
#header .user {
  display: flex;
  align-items: center;
  gap: 5px;
}
#header .user .icon {
  width: 30px;
  height: 30px;
}
#header .user .icon::before {
  background-image: url(../images/icon/icon-user.svg);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
#header .user p {
  font-size: 18px;
  color: var(--color-darken);
}
#header {
  /*
    비밀번호 변경 — 로그아웃 왼쪽의 단추.

    ⚠️ 한때 테두리 없는 글자였다. 「로그아웃이 이 줄의 마지막 행동이니
       무게를 달리한다」는 뜻이었는데, 실제로는 **눌러도 되는 것으로 안 읽혔다.**
       옆에 테두리 두른 단추가 있으면 테두리 없는 것은 설명 글로 보인다.
       둘 다 단추로 두고, 무게는 **자리**로 가른다 — 마지막이 로그아웃이다.
    ⚠️ 링크(a)지만 단추로 그린다. 가는 곳이 있으니 a 가 맞고, 하는 일이
       행동이라 모양은 단추가 맞다.
  */
}
#header .btn-pw {
  flex: 0 0 auto;
  white-space: nowrap;
}
#header .btn-logout {
  /* ⚠️ padding 만으로 높이를 만들다 34px 이 됐다. 바로 옆 아이콘 단추가
     36px 이라 두 개가 2px 어긋나 보였다. 규격 높이를 그대로 쓴다 */
  display: inline-flex;
  align-items: center;
  height: var(--btn-h);
  padding: 0 16px;
  border: 1px solid var(--border-darken);
  border-radius: var(--radius-sm);
  background-color: transparent;
  font-size: 14px;
  color: var(--color-darken);
  cursor: pointer;
  transition: all 0.3s;
}
#header .btn-logout:hover {
  background-color: var(--gray-100);
  color: var(--color-primary);
  border-color: var(--color-primary);
}

/* =====================================================
 * 반응형 (2026-09-10)
 * ===================================================== */
/*
  1200px 아래 — LNB 가 서랍이 되면서 헤더가 화면 폭을 다 쓴다.
  ⚠️ 간격 20px 은 넓은 화면에서 정한 값이다. 그대로 두면 제목이 먼저 줄어들어
     「어느 화면인지」가 안 보인다. **사이를 줄여 제목을 지킨다.**
*/
@media (max-width: 1199px) {
  #header .container .gnb {
    gap: 12px;
  }
  #header .container .gnb .gnb-mine {
    gap: 12px;
  }
}
/*
  768px 아래 — 「내 것 · 나가기」 다섯이 서랍 아래로 내려간다
  (자리를 옮기는 것은 assets/js/headerMine.js 다).

  ⚠️ **감추는 것이 아니다.** 감추면 휴대폰에서 로그아웃할 길이 없어진다.
  ⚠️ 헤더에는 햄버거와 제목만 남는다. 빵부스러기는 접는다 — 제목이 바로 옆에
     있고, 좁은 화면에서 두 줄이 겹쳐 놓일 자리가 없다.
*/
@media (max-width: 767px) {
  #header .container {
    padding: 0 14px;
  }
  #header .container .gnb {
    gap: 10px;
    /*
      ⚠️ 빵부스러기 숨김은 여기 있었다. **900px 규칙이 이미 한다** —
         두 곳에 적으면 한쪽을 고칠 때 다른 쪽이 남는다.
    */
  }
  #header .container .gnb .page-head {
    flex: 1 1 auto;
    /* 제목은 칸이 좁아지면 줄이지 말고 말줄임으로 넘긴다 */
  }
  #header .container .gnb .page-head .page-title-row .page-title {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
/*
  서랍 안으로 내려간 모습 — 가로 줄이 아니라 세로 목록이다.
  ⚠️ 메뉴 위가 아니라 **맨 아래**다. 메뉴가 이 화면의 본론이고, 내 것은
     그다음이다. 위에 두면 메뉴를 보려고 늘 지나쳐야 한다.
*/
.gnb-mine.is-in-drawer {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  margin-top: 20px;
  padding: 16px 20px 24px;
  border-top: 1px solid var(--gray-600);
}
.gnb-mine.is-in-drawer .user {
  color: var(--aside-text);
}
.gnb-mine.is-in-drawer .user p {
  color: inherit;
}
.gnb-mine.is-in-drawer {
  /* 가로로 둘씩 놓던 단추를 세로로 편다 — 좁은 서랍에서 두 칸은 글자가 깨진다 */
}
.gnb-mine.is-in-drawer .flex.align-center.gap8 {
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}
.gnb-mine.is-in-drawer .btn {
  width: 100%;
  justify-content: center;
}
.gnb-mine.is-in-drawer .btn-logout {
  width: 100%;
}
.gnb-mine.is-in-drawer {
  /* 화면 모드는 제 크기가 있는 부품이라 늘리지 않고 왼쪽에 세운다 */
}
.gnb-mine.is-in-drawer .theme-switch {
  align-self: flex-start;
}

/*
  1200px 아래 — 기관 탭이 본문으로 내려간 뒤의 헤더
  (옮기는 것은 assets/js/headerMine.js 다)

  ⚠️ **빵부스러기를 줄바꿈하지 않는다.** 1024px 에서 「시스템 / 관리」,
     「이력 / 관리」로 마디마다 두 줄이 됐다. 56px 헤더에서 두 줄은 곧
     삐져나오는 것이고, 무엇보다 **한 마디가 두 줄이면 마디로 안 읽힌다.**
     칸이 모자라면 줄바꿈이 아니라 말줄임으로 넘긴다.
  ⚠️ 단추 이름도 같다 — 「메뉴 / 구조도」가 됐다.
*/
/*
  ⚠️ **폭을 가리지 않고 못 박는다.** 처음에는 좁은 폭에서만 걸었는데,
     눈금을 잘못 잡은 폭에서 그대로 깨졌다. 56px 한 줄짜리 헤더에서
     **줄바꿈은 어느 폭에서도 옳지 않다** — 조건을 달 일이 아니다.
  ⚠️ 빵부스러기는 마디마다 꺾였다(「시스템 / 관리」 · 「이력 / 관리」).
     한 마디가 두 줄이면 마디로 읽히지 않는다. 줄어들 때는 말줄임으로 넘긴다.
  ⚠️ 제목은 이 줄에서 가장 중요한 글이라 **줄지 않는다**(`flex: 0 0 auto`).
     줄어드는 것은 빵부스러기 쪽이다.
*/
#header .container .gnb .page-head {
  /* 줄어드는 쪽은 빵부스러기 하나다 — 그러려면 이 그릇이 줄 수 있어야 한다 */
  min-width: 0;
  /*
    ⚠️ **제목은 절대 줄지 않는다.** `.page-title` 에만 걸었더니 부모인
       `.page-title-row` 가 줄면서 제목이 잘렸다 —
       900px 에서 「관리자 접속 이력」이 「관리자 접속 이」가 됐다.
       줄을 세우는 것은 줄(row)이므로 못 박는 자리도 줄이다.
  */
}
#header .container .gnb .page-head .page-title-row {
  flex: 0 0 auto;
}
#header .container .gnb .page-head .page-title {
  white-space: nowrap;
}
#header .container .gnb .page-head .breadcrumb {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  /*
    ⚠️ **`flex-wrap: wrap` 이 위에 걸려 있었다.** 바로 위 주석이
       「wrap 을 끄는 것도 중요하다」고 적어 두었는데 값은 wrap 이었다 —
       그래서 마디마다 두 줄로 꺾였다(「시스템 / 관리」 · 「이력 / 관리」).
  */
  flex-wrap: nowrap;
  /*
    ⚠️ **`text-overflow: ellipsis` 는 여기서 듣지 않는다.** 이 줄은 flex
       컨테이너이고 글자가 자식 요소 안에 있어, 말줄임은 컨테이너 제 글에만
       걸린다. 실제로 아무 표시 없이 딱 잘렸다.
       오른쪽 끝을 흐리게 덮어 **「더 있다」**로 읽히게 한다.
    ⚠️ 잘리는 것은 **마지막 마디**(지금 화면)인데, 그 이름은 바로 왼쪽
       제목이 이미 말한다. 이 줄이 홀로 하는 말은 **그 위 마디들**이라
       잘리는 순서가 맞다.
  */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent 100%);
}
#header .container .gnb .page-head .breadcrumb > * {
  flex: 0 0 auto;
  white-space: nowrap;
}
#header .container .gnb .gnb-mine .btn,
#header .container .gnb .gnb-mine .btn-logout {
  white-space: nowrap;
}

/*
  900px 아래 — 빵부스러기를 접는다.

  ⚠️ **LNB 가 켜져 있는 동안에는 접지 않는다.** 왼쪽 메뉴의 강조가 같은 말을
     하기 때문이다. 여기는 이미 서랍 구간(<1200)이라 **어디에 있는지 말하는
     것이 이것뿐**인데, 그래도 접는 것은 이 폭에서 제목까지 잘리기 때문이다 —
     제목이 먼저다. 대신 서랍을 열면 지금 있는 줄이 강조돼 있다.
*/
@media (max-width: 899px) {
  #header .container .gnb .page-head .breadcrumb {
    display: none;
  }
}
/* ================================================= */
/* 1. 폰트 가중치 Map 및 기본 변수 정의 (핵심 유틸리티) */
/* ================================================= */
/* ============================================== */
/* 2. 타이포그래피 스타일 Map 정의 (디자인 시스템) */
/* ============================================== */
/* ================================================= */
/* 2-1. 반응형 size Map (PC 대비 size만 오버라이드) */
/* ================================================= */
/* ============================================= */
/* 3. 공용 유틸: 레벨별 size 조회 (브레이크포인트) */
/* ============================================= */
/* ============================================= */
/* 4. 범용 믹스인: @include body-1-1 형태로 사용 */
/* - 핵심: selector 컨텍스트(&)로 미디어를 함께 출력 */
/* ============================================= */
/* ============================================= */
/* 5. 레벨별 믹스인: 최종 사용 형태 유지 */
/* ============================================= */
/* ========================================== */
/* 6. 클래스 자동 생성(선택): 기존 형태 유지 */
/* ========================================== */
.display-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 72px;
}

.title-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 48px;
}

.title-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 40px;
}

.title-3 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 32px;
}

.title-4 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 24px;
}

.body-1-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 24px;
}

.body-1-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 24px;
}

.body-2-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
}

.body-2-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 20px;
}

.body-3-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}

.body-3-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
}

.body-4-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
}

.body-4-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}

.body-5-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 14px;
}

.body-5-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
}

/*
  본문 맨 위 제목.

  ⚠️ title-3(32px) 이었다. 그런데 헤더의 화면 이름(.page-title)이 20px 이라
     본문 제목이 화면 이름보다 컸다 — 위계가 뒤집혀 있었다.
  ⚠️ 크기를 줄이면 제목처럼 안 보이므로 굵기로 메운다(600 → 700).
     이 프로젝트의 규칙이다 — 키울 수 없으면 굵기로 포인트를 준다.
*/
.section-title {
  /*
    ⚠️ @include body-2-1 로 쓰고 굵기만 덮으면 컴파일 결과에 font-weight 가
       두 번 나온다(600 뒤에 700). 동작은 맞지만 다음 사람이 어느 쪽이 참인지
       한 번 더 확인하게 된다. 스케일 함수로 값만 꺼내 쓴다 —
       크기의 출처는 여전히 $typography-scale 한 곳이다.
  */
  font-family: "Pretendard", sans-serif;
  font-size: 20px; /* 20px */
  font-weight: 700; /* 700 */
  margin-bottom: 24px;
}

.field-title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
  margin-bottom: 12px;
}

.box-title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
  margin-bottom: 12px;
}

.title-with-tabs {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-bottom: 24px;
}
.title-with-tabs .section-title {
  margin-bottom: 0;
}
.title-with-tabs .tab-label {
  color: var(--color-white);
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
  margin-right: 8px;
}

/* -----------------------------------------------------
 * 묶음 제목 줄
 *
 * .title-wrap        제목만
 * .title-wrap.has-btn 제목 왼쪽 · 단추(또는 링크) 오른쪽 한 줄
 *
 * ⚠️ 대시보드 안에만 있던 규칙이다. 「다른 화면이 같은 이름을 쓰기 시작하면
 *    공통으로 올린다」고 적어 뒀고, 다른 화면이 쓰기 시작해 옮겼다.
 *    옮기기 전에는 그 화면에서 단추가 제목 아래로 떨어졌다 — 클래스는
 *    붙어 있는데 규칙이 그 화면까지 닿지 않았다.
 * ⚠️ 아래 여백은 화면마다 다르다. 여기서는 잡지 않고 각 화면이 정한다.
 * --------------------------------------------------- */
.title-wrap {
  margin-bottom: 12px;
}
.title-wrap.has-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* =====================================================
 * 좁은 화면 (2026-09-10 반응형)
 *
 * ⚠️ 제목과 단추를 **위아래로 쌓는다.** 한 줄에 두면 제목이 먼저 눌려
 *    「관리자 계정 목록」이 「관리자 계…」가 된다 — 무슨 화면인지가
 *    단추 이름보다 먼저다.
 * ===================================================== */
@media (max-width: 767px) {
  .title-wrap.has-btn {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
}
.attachment-box .attachment-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 20px;
}
.attachment-box .attachment-header .attachment-title {
  font-size: 20px;
}
.attachment-box .attachment-header .icon-box .icon::before {
  content: "";
  width: 24px;
  height: 24px;
}
.attachment-box .attachment-header .btn-down {
  gap: 10px;
}

.attachment-list ul {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.attachment-list .file-item {
  display: flex;
  align-items: center;
  padding: 12px;
  gap: 8px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
}
.attachment-list .file-item:hover {
  background-color: var(--gray-200);
  border: 1px solid var(--color-primary);
}
.attachment-list .file-item:hover .file-name {
  color: var(--color-darken);
}
.attachment-list .file-item .file-icon {
  width: 36px;
  height: 36px;
  display: block;
  flex-shrink: 0;
}
.attachment-list .file-item .file-icon::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
}
.attachment-list .file-item .file-icon.pdf:before {
  background-image: url(../images/icon/icon-pdf.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-icon.xls:before {
  background-image: url(../images/icon/icon-xls.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-icon.doc:before {
  background-image: url(../images/icon/icon-doc.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-icon.jpg:before {
  background-image: url(../images/icon/icon-jpg.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-icon.png:before {
  background-image: url(../images/icon/icon-png.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-icon.hwp:before {
  background-image: url(../images/icon/icon-hwp.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-icon.zip:before {
  background-image: url(../images/icon/icon-zip.svg);
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}
.attachment-list .file-item .file-name {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  color: var(--gray-600);
  max-width: 100%;
}
.attachment-list .file-item .btn {
  margin-left: auto;
  flex-shrink: 0;
}

/* Pagination (Light/Dark 공용) */
.pagination {
  --pg-size: 36px;
  --pg-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.pagination .pager-btn,
.pagination .pager-item {
  min-width: var(--pg-size);
  height: var(--pg-size);
  padding: 0 12px;
  border: 1px solid var(--border-darken);
  border-radius: var(--pg-radius);
  background: var(--color-white); /* light: #fff / dark: #121212 */
  color: var(--color-darken); /* light: #3a3a3a / dark: #f5f5f5 */
  font-size: 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.pagination .pager-btn:hover, .pagination .pager-btn:focus,
.pagination .pager-item:hover,
.pagination .pager-item:focus {
  border-color: var(--color-primary);
  background-color: var(--gray-200); /* 라이트: 연회색 / 다크: 카드톤 */
  outline: none;
}
.pagination .pager-btn:focus-visible,
.pagination .pager-item:focus-visible {
  box-shadow: 0 0 0 3px rgba(var(--color-primary-rgb), 0.2);
}
.pagination .pager-btn:disabled, .pagination .pager-btn.is-disabled,
.pagination .pager-item:disabled,
.pagination .pager-item.is-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
  border-color: var(--border-disabled);
  color: var(--color-disabled);
  background-color: var(--bg-disabled);
}
.pagination .pager-btn,
.pagination .pager-item {
  /* 좌/우 화살표: mask로 currentColor를 따르게 */
}
.pagination .pager-btn.prev, .pagination .pager-btn.next, .pagination .pager-btn.prev-end, .pagination .pager-btn.next-end,
.pagination .pager-item.prev,
.pagination .pager-item.next,
.pagination .pager-item.prev-end,
.pagination .pager-item.next-end {
  font-size: 0; /* 텍스트 숨김 */
  padding: 0;
  width: var(--pg-size);
  /* 아이콘 공통(24px) */
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 24px 24px;
  mask-size: 24px 24px;
  background: currentColor; /* 아이콘 색상 = 글자색 */
}
.pagination .pager-btn.prev,
.pagination .pager-item.prev {
  -webkit-mask-image: url(../../assets/images/icon/icon-arrow-left-rec.svg);
  mask-image: url(../../assets/images/icon/icon-arrow-left-rec.svg);
}
.pagination .pager-btn.next,
.pagination .pager-item.next {
  -webkit-mask-image: url(../../assets/images/icon/icon-arrow-right-rec.svg);
  mask-image: url(../../assets/images/icon/icon-arrow-right-rec.svg);
}
.pagination .pager-btn.prev-end,
.pagination .pager-item.prev-end {
  -webkit-mask-image: url(../../assets/images/icon/icon-arrow-left-end-rec.svg);
  mask-image: url(../../assets/images/icon/icon-arrow-left-end-rec.svg);
}
.pagination .pager-btn.next-end,
.pagination .pager-item.next-end {
  -webkit-mask-image: url(../../assets/images/icon/icon-arrow-right-end-rec.svg);
  mask-image: url(../../assets/images/icon/icon-arrow-right-end-rec.svg);
}
.pagination .pager-list {
  display: flex;
  align-items: center;
  gap: 6px;
}
.pagination .pager-item.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--bg-white); /* 다크/라이트 공용 대비 확보 */
  cursor: default;
}
.pagination .pager-item.is-active:hover, .pagination .pager-item.is-active:focus {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.pagination {
  /* 비활성 prev/next도 시각적으로 약하게 */
}
.pagination .pager-btn.is-disabled.prev,
.pagination .pager-btn.is-disabled.next,
.pagination .pager-btn:disabled.prev,
.pagination .pager-btn:disabled.next,
.pagination .pager-btn:disabled.prev-end,
.pagination .pager-btn:disabled.next-end {
  background: var(--gray-800);
}

/* =====================================================
 * 좁은 화면 (2026-09-10 반응형)
 *
 * ⚠️ **번호를 줄바꿈한다.** 열 개가 한 줄에 서면 390px 에서 102px 이 넘쳤다.
 *    페이지 번호는 순서대로 읽는 것이라 **줄이 바뀌어도 뜻이 상하지 않는다** —
 *    표처럼 열이 맞아야 하는 것이 아니다.
 * ⚠️ 처음 · 이전 · 다음 · 마지막 넉 점은 **줄바꿈에서 떼어 놓지 않는다.**
 *    번호와 함께 흐르게 두면 「다음」이 어디로 갈지 매번 달라져 손이 헤맨다.
 *
 * ⚠️ **처음에 「목록만 안에서 접는다」로 적었는데 그게 안 됐다.** 번호 목록이
 *    늘어나는 칸이라, 375px 에서 넉 점이 셋으로 쪼개져 섰다 —
 *      ‹‹ ‹        (첫 줄)
 *      1 2 … 10    (둘째 줄)
 *      › ››        (셋째 줄)
 *    「다음」이 세 줄 아래로 내려가 손이 헤매는, 막으려던 바로 그 꼴이었다.
 *    번호 목록에 **제 줄을 통째로** 주면 넉 점이 한 줄에 모인다.
 *      1 2 … 10
 *      ‹‹ ‹  › ››
 * ===================================================== */
/*
  ⚠️ **크기를 줄이지 않는다.** 예전에 `--pg-size: 32px` · `font-size: 13px` 로
     줄여 두었는데, 「번호 열 개가 한 줄에 안 선다」를 아래 줄바꿈으로 해결한
     뒤에도 그 값이 남아 있었다. 결과가 거꾸로였다 — **손가락으로 쓰는 폭에서
     쪽 번호가 PC(36px)보다 작아졌다**(375px 에서 32px, 재서 확인).
     크기는 `_touch.scss` 가 44px 로 올린다. 여기서는 **줄바꿈만** 맡는다.
*/
@media (max-width: 767px) {
  .pagination {
    flex-wrap: wrap;
    gap: 6px;
  }
  .pagination .pager-list {
    order: -1; /* 번호가 먼저, 넉 점이 그 아래 */
    flex: 1 1 100%; /* 제 줄을 통째로 쓴다 — 넉 점이 쪼개지지 않는다 */
    flex-wrap: wrap;
    justify-content: center;
  }
  .pagination .pager-btn,
  .pagination .pager-item {
    padding: 0 8px;
  }
}
/* Modal (theme-aware) */
.modal {
  /* ✨ 모달 전용 변수: 테마별로 표면/전경/오버레이 제어 */
  --modal-surface: var(--color-white);
  --modal-foreground: var(--color-darken);
  --modal-overlay: rgba(0, 0, 0, .45);
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none; /* aria-hidden="true"일 때 숨김 */
}
.modal[aria-hidden=false] {
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal .modal-overlay {
  position: absolute;
  inset: 0;
  background: var(--modal-overlay);
  backdrop-filter: blur(2px); /* 어둠 속에서도 레이어 분리감 */
}
.modal .modal-container {
  position: relative;
  width: min(720px, 100% - 32px);
  max-height: calc(100dvh - 80px);
  margin: 40px auto;
  display: flex;
  flex-direction: column;
  background: var(--modal-surface);
  color: var(--color-darken);
  border: 1px solid var(--border-darken);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-2);
  outline: none;
  transform: translateY(16px);
  opacity: 0;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.modal[aria-hidden=false] .modal-container {
  transform: translateY(0);
  opacity: 1;
}
.modal .modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--gray-500);
}
.modal .modal-header .modal-title {
  /*
    ⚠️ body-1-1(24px) 이었다. 본문 제목(.section-title)이 20px 인데 모달 제목이
       24px 이면 **작은 창의 제목이 화면 제목보다 크다.** 위계가 뒤집힌다.
       .section-title 과 같은 20px/700 으로 맞춘다.
  */
  font-family: "Pretendard", sans-serif;
  font-size: 20px; /* 20px */
  font-weight: 700; /* 700 */
  color: var(--color-darken);
}
.modal .modal-header .modal-close {
  width: 32px;
  height: 32px;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: var(--radius-sm);
  position: relative;
  color: var(--color-darken);
  border: 1px solid var(--color-darken);
}
.modal .modal-header .modal-close::before, .modal .modal-header .modal-close::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 2px;
  background: currentColor; /* 테마에 따라 자동 적응 */
  transform-origin: 50% 50%;
}
.modal .modal-header .modal-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}
.modal .modal-header .modal-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}
.modal .modal-header .modal-close:hover {
  background: var(--gray-200);
}
.modal .modal-header .modal-close:focus-visible {
  outline: 2px solid rgba(var(--color-primary-rgb), 0.4);
  outline-offset: 2px;
}
.modal .modal-body {
  padding: 20px;
  overflow: auto;
  color: inherit; /* ✅ 전경색 상속 */
}
.modal .modal-body .table {
  min-width: 100%;
}
.modal .modal-body .box-title {
  padding: 20px;
  text-align: center;
  background-color: rgba(var(--color-primary-rgb), 0.1);
}
.modal .modal-body .image-load-box {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}
.modal .modal-body .image-load-box .thumb-img {
  width: 120px;
  height: 180px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--gray-600);
}
.modal .modal-body .image-load-box .thumb-img img {
  -o-object-fit: contain;
     object-fit: contain;
}
.modal .modal-body .image-load-box .text-box {
  width: 100%;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--gray-600);
}
.modal .modal-body .attachment-list ul {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}
.modal .modal-body .img-box img {
  width: 100%;
  -o-object-fit: cover;
     object-fit: cover;
}
.modal .modal-body .img-box.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.modal .modal-body .left-taps {
  flex-direction: column;
  width: 30%;
  flex-shrink: 0;
  border-bottom: 0;
}
.modal .modal-body .left-taps .tab {
  width: 100%;
  text-align: left;
  display: flex;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
}
.modal .modal-body .left-taps .tab .icon {
  width: 16px;
  height: 16px;
  margin-left: auto;
}
.modal .modal-body .left-taps .tab.is-active {
  border: 0;
  background-color: rgba(var(--color-primary-rgb), 0.1);
}
.modal .modal-body .left-taps .tab.is-active .icon {
  filter: var(--filter-primary);
}
.modal .modal-body .left-panels {
  width: 70%;
  margin-top: 0;
  margin-bottom: 20px;
  margin-left: 20px;
}
.modal .modal-body .drag-drop-wrap .drag-drop-title {
  margin-bottom: 12px;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}
.modal .modal-body .drag-drop-wrap .drag-item-list {
  padding: 12px;
  margin-top: 12px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
}
.modal .modal-body .drag-drop-wrap .drag-item-list.align-start .drag-item {
  align-items: start;
}
.modal .modal-body .drag-drop-wrap .drag-item-list.align-start .drag-item .field-title {
  margin-bottom: 0;
  width: 80px;
  text-align: right;
}
.modal .modal-body .drag-drop-wrap .drag-item-list.align-start .drag-contents .flex {
  width: 100%;
}
.modal .modal-body .drag-drop-wrap .drag-item {
  display: grid;
  grid-template-columns: 36px 40px 1fr 36px;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  padding: 12px;
  min-width: 0;
}
.modal .modal-body .drag-drop-wrap .drag-item:hover {
  border: 1px solid var(--color-primary);
}
.modal .modal-body .drag-drop-wrap .drag-item + .drag-item {
  margin-top: 4px;
}
.modal .modal-body .drag-drop-wrap .drag-item * {
  min-width: 0;
}
.modal .modal-body .drag-drop-wrap .drag-item .icon.icon-dotdot {
  width: 24px;
  height: 24px;
}
.modal .modal-body .drag-drop-wrap .drag-item .icon {
  width: 16px;
  height: 16px;
}
.modal .modal-body .drag-drop-wrap .drag-item .num {
  padding: 8px;
  border-radius: var(--radius-sm);
  background-color: var(--gray-600);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal .modal-body .drag-drop-wrap .drag-item .drag-contents {
  display: flex;
  align-items: center;
  flex-direction: column;
  gap: 8px;
}
.modal .modal-body .drag-drop-wrap .drag-item .drag-contents.left {
  align-items: flex-start;
}
.modal .modal-body .linebox-wrap {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  padding: 8px;
}
.modal .modal-body .linebox-wrap .title-box {
  background-color: var(--gray-300);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px;
  margin-bottom: 8px;
}
.modal .modal-body .linebox-wrap .title-box .title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}
.modal .modal-body .linebox-wrap .title-box .guide {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}
.modal .modal-body .linebox-wrap .linebox {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  padding: 12px;
}
.modal .modal-body {
  /* ===============================
  * Sortable: 내려놓을 자리(placeholder)
  * =============================== */
}
.modal .modal-body .dnd-placeholder {
  border: 2px dashed rgba(0, 0, 0, 0.25) !important;
  background: rgba(0, 0, 0, 0.02) !important;
  border-radius: var(--radius-md) !important;
  display: grid !important;
  grid-template-columns: 36px 40px 1fr 36px !important;
  align-items: center !important;
  gap: 8px !important;
  padding: 12px !important;
  box-sizing: border-box !important;
  color: transparent !important;
  box-shadow: none !important;
}
.modal .modal-body .dnd-placeholder * {
  opacity: 0 !important;
  pointer-events: none !important;
}
.modal .modal-body {
  /* ===============================
  * Sortable: 드래그 중 따라다니는 카드(틀어짐 방지)
  * =============================== */
}
.modal .modal-body .dnd-drag {
  display: grid !important;
  grid-template-columns: 36px 40px 1fr 36px !important;
  align-items: center !important;
  gap: 8px !important;
  box-sizing: border-box !important;
  border-radius: var(--radius-md) !important;
  box-shadow: var(--elev-2);
  background: rgba(223, 225, 230, 0.95);
}
.modal .modal-body .dnd-drag * {
  pointer-events: none;
}
.modal .modal-body {
  /* (선택) 드래그 시작 시 선택된 원본 */
}
.modal .modal-body .dnd-chosen {
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.06);
}
.modal .modal-body {
  /* (선택) 핸들 커서 */
}
.modal .modal-body .move-order {
  cursor: grab;
}
.modal .modal-body .move-order:active {
  cursor: grabbing;
}
.modal .modal-body {
  /* taglist */
}
.modal .modal-body .tag-list {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.modal .modal-body .tag-list .tag {
  padding: 4px 12px;
  background-color: var(--gray-600);
  color: var(--color-darken);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  gap: 4px;
}
.modal .modal-body .tag-list .tag .icon {
  width: 12px;
  height: 12px;
}
.modal .modal-footer {
  padding: 12px 20px;
  border-top: 1px solid var(--gray-500);
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.modal .modal-footer .add-btnwrap {
  margin-right: auto;
}
.modal {
  /* 사이즈 변형 */
}
.modal.size-sm .modal-container {
  width: min(420px, 100% - 32px);
}
.modal.size-lg .modal-container {
  width: min(1000px, 100% - 32px);
}
.modal {
  /* 드로어형 (오른쪽 슬라이드) */
}
.modal-drawer .modal-container {
  margin: 0 0 0 auto;
  height: 100dvh;
  width: min(480px, 100%);
  border-radius: 0;
  transform: translateX(24px);
  opacity: 1;
}
.modal-drawer[aria-hidden=false] .modal-container {
  transform: translateX(0);
}
.modal .box-wrap {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}
.modal .box-wrap.col1 {
  grid-template-columns: repeat(1, 1fr);
}
.modal .box-wrap.col2 {
  grid-template-columns: repeat(2, 1fr);
}
.modal .box-wrap.col3 {
  grid-template-columns: repeat(3, 1fr);
}
.modal .box-wrap.col4 {
  grid-template-columns: repeat(4, 1fr);
}
.modal .box-wrap .box.col1 {
  grid-column: span 1;
}
.modal .box-wrap .box.col2 {
  grid-column: span 2;
}
.modal .box-wrap .box.col3 {
  grid-column: span 3;
}
.modal .box-wrap .box.col4 {
  grid-column: span 4;
}
.modal .box-wrap .box.type-line {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  padding: 12px;
}
.modal .box-wrap .box.type-line .depth2 {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  padding: 12px;
}
.modal .box-wrap .box.type-line .depth2.all {
  background-color: rgba(var(--bg-blue-rgb), 0.1);
}
.modal .box-wrap .box.type-line .depth2.indiv {
  background-color: var(--color-white);
}
.modal .box-wrap .box.type-line .depth2.read {
  background-color: rgba(var(--bg-disabled-rgb));
}
.modal .box-wrap .box.type-line .depth2.disabled {
  background-color: rgba(var(--bg-red-rgb), 0.1);
}
.modal .box-wrap .box.type-line .depth2 .field-title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
  margin-bottom: 8px;
}
.modal .box-wrap .box {
  width: 100%;
  min-width: 0;
}
.modal .box-wrap .box .flex * {
  min-width: 0;
}
.modal .box-wrap + .box-wrap {
  margin-top: 24px;
}
.modal .box-wrap + .box-title {
  margin-top: 24px;
}

/* 바디 스크롤 잠금 */
.body-lock {
  overflow: hidden;
}

/* 🌙 다크 테마 전용 오버라이드 */
:root {
  /* 폴백: color-mix 미지원 시 사용될 약간 어두운 표면색 */
  --modal-surface-dark-fallback: #f2f2f5;
}

/* 최신 브라우저: color-mix 사용 (OKLab 추천) */
@supports (color: color-mix(in oklab, white, black)) {
  :root {
    --modal-surface-dark: color-mix(in oklab, var(--color-white), black 16%);
  }
}
/* 다크 테마
   - 표면은 화이트를 16% 블랙으로 톤다운
   - 전경은 진한 #121212
   - 오버레이는 조금 더 진하게 */
[data-theme=dark] .modal {
  --modal-surface: var(--modal-surface-dark, var(--modal-surface-dark-fallback));
  --modal-foreground: #121212;
  --modal-overlay: rgba(0, 0, 0, .6);
}

/* 다크 테마 디테일 튜닝: 보더/호버 대비 과하지 않게 */
[data-theme=dark] .modal .modal-container {
  border-color: color-mix(in oklab, var(--border-darken), white 28%);
}

[data-theme=dark] .modal .modal-header,
[data-theme=dark] .modal .modal-footer {
  border-color: color-mix(in oklab, var(--gray-500), white 30%);
}

[data-theme=dark] .modal .modal-header .modal-close:hover {
  background: color-mix(in oklab, var(--gray-200), black 12%);
}

/* =====================================================
 * 모달 발의 단추는 **접힌다** (2026-09-11 · 2026-09-12 고쳐 씀)
 *
 * ⚠️ `.modal-footer` 에 `flex-wrap` 이 없었다. 375px 발행 검수 모달에서
 *    단추 넷(삭제 · 닫기 · 지금 발행 · 저장)이 303px 자리에 349px 을
 *    요구해, **왼쪽으로 22px 삐져나갔다.**
 *
 * ⚠️ **왼쪽 넘침은 `scrollWidth` 로 안 잡힌다.** `justify-content: flex-end`
 *    인 줄이 넘치면 시작 쪽으로 밀려 나가는데, 그것은 스크롤 폭에 안 들어간다.
 *    → 검사를 고쳤다(bounds.js): 양쪽을 견준다.
 *
 * ─ 처음 고친 것이 지나쳤다
 *   「지우는 단추는 제 줄을 갖는다」를 `.add-btnwrap { flex: 1 1 100% }` 로
 *   **폭과 상관없이** 걸었더니, **자리가 넉넉한 700px 에서도 삭제가 한 줄을
 *   혼자 먹었다**(발 666px · 단추 합 349px · 재서 확인).
 *
 * ─ 지금 하는 것
 *   `flex-wrap` 만 둔다. **들어가면 한 줄, 안 들어가면 접힌다.**
 *   대신 확인 단추 셋을 마크업에서 `.foot-main` 으로 묶어, 접힐 때
 *   **묶음이 통째로** 내려가게 한다 — 감싸지 않으면 「저장」 하나만 떨어져
 *   나가서 그 줄에서 가장 중요한 단추가 홀로 남는다.
 *
 *     768px 이상   [삭제] ……… [닫기] [지금 발행] [저장]
 *     그 아래      [삭제]
 *                 [닫기] [지금 발행] [저장]
 * ===================================================== */
.modal .modal-footer {
  flex-wrap: wrap;
  /* 확인 단추 묶음 — 통째로 움직인다 */
}
.modal .modal-footer .foot-main {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.modal .modal-footer .btn {
  flex: 0 0 auto;
}

/* =====================================================
 * 모달 안 **가로형 표** — 좁은 폭에서 열 폭을 되살린다 (2026-09-11)
 *
 * ─ 무엇이 깨졌나 (발행 내역 · #modal-post-view 의 「채널별 성과」)
 *
 *   colgroup    150 + 110 + **auto** + 100 + 100 + 140  → 고정합 600px
 *   1366px      표 956 → auto 열이 356px            ✓
 *    375px      표 600 → auto 열이 **0px**           ✗
 *
 *   `table-layout: fixed`(_reset.scss)에서는 **고정 폭이 먼저 자리를 잡고**
 *   남는 것을 auto 열이 받는다. 좁아지면 남는 것이 없어 0 이 되고, 그 칸의
 *   글자가 옆 칸 위로 쏟아진다 — 「게시물 링⊂출」처럼 머리줄까지 포개졌다.
 *
 * ⚠️ **이건 넘침이 아니라 겹침이다.** `.table-wrap` 이 굴러가고 있어서
 *    경계 검사(bounds.js)로도 안 잡혔다 — 굴러가는 그릇 안은 건너뛰기 때문이다.
 *    겹침은 따로 세야 한다(overlap.js).
 *
 * ─ 왜 세로로 쌓지 않나
 *   이 표는 **채널을 견주는** 표다(X 와 LinkedIn 의 노출·좋아요를 나란히 본다).
 *   세로로 쌓으면 견줄 수가 없다. 상세 세로형 표(`.table-vertical`)와 성격이
 *   다르므로 **굴러가게 두고 열 폭을 살린다.**
 *
 * ⚠️ `!important` 가 필요하다 — 폭이 `<col style="width: 150px">` 로 박혀 있어
 *    인라인 style 은 어떤 선택자로도 못 이긴다.
 * ===================================================== */
@media (max-width: 1199px) {
  .modal .table:not(.table-vertical):not(.is-list) {
    table-layout: auto;
    min-width: 0;
  }
  .modal .table:not(.table-vertical):not(.is-list) > colgroup > col {
    width: auto !important;
  }
}
.tabs {
  display: flex;
  border-bottom: 1px solid var(--gray-600);
  gap: 8px;
}
.tabs .tab {
  padding: 12px 24px;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
  color: var(--color-darken);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.tabs .tab:hover, .tabs .tab:focus {
  color: var(--color-primary);
}
.tabs .tab.is-active {
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.tabs .tab:disabled {
  color: var(--gray-700);
  cursor: not-allowed;
}
.tabs.type-round {
  align-items: center;
  background-color: var(--color-primary);
  padding: 10px;
  border-radius: var(--radius-pill);
  gap: 4px;
  /*
    묶음 이름(「기관 선택」).
    ⚠️ 예전에는 `.title-with-tabs .tab-label` 로만 색이 잡혀 있었다. 제목 줄이
       헤더로 옮겨가며 그 래퍼가 사라지자 파란 알약 위에 검은 글자가 남았다.
       이름은 알약 안에 있으면 늘 흰 글자여야 하므로 여기로 옮겼다.
  */
}
.tabs.type-round .tab-label {
  margin-right: 8px;
  padding-left: 6px;
  font-weight: 600;
  font-size: 20px;
  color: var(--color-white);
}
.tabs.type-round .tab {
  border-radius: var(--radius-pill);
  background: transparent;
  padding: 5px 24px;
  color: #fff;
}
.tabs.type-round .tab.is-active {
  background: var(--color-white);
  box-shadow: none;
  color: var(--color-primary);
}
.tabs.type-round .tab:hover {
  background: var(--gray-200);
  color: var(--color-primary);
}
.tabs.type-round {
  /*
    낮은 변형 — 헤더 안에서만 쓴다.
    ⚠️ 기본 크기(높이 54px)는 헤더(--header-h, 56px)에
       여백이 남지 않는다. 알약 모양은 그대로 두고 높이만 38px 로 줄인다.
  */
}
.tabs.type-round.is-compact {
  padding: 5px;
}
.tabs.type-round.is-compact .tab-label {
  font-size: 14px;
  margin-right: 4px;
}
.tabs.type-round.is-compact .tab {
  padding: 4px 16px;
  font-size: 14px;
}

.tab-panels {
  margin-top: 12px;
}
.tab-panels .tab-panel {
  display: none;
  background: var(--color-white);
}
.tab-panels .tab-panel.is-active {
  display: block;
}

/* =====================================================
 * 기관 탭이 본문 맨 위로 내려왔을 때 (1500px 아래)
 * 옮기는 것은 assets/js/headerMine.js 다.
 *
 * ⚠️ 헤더 안에서는 낮은 변형(.is-compact)이었다. 본문에서는 위에 아무것도
 *    없으므로 제 높이로 서도 된다 — 다만 아래 첫 카드와의 사이는 줘야 한다.
 * ===================================================== */
.tabs.is-in-body {
  margin-bottom: 16px;
  overflow-x: auto;
  /* ⚠️ 기관이 넷 이상으로 늘면 한 줄에 못 선다. 굴러가게 두고 줄바꿈은 안 한다 —
        탭은 한 줄로 보여야 「고르는 것」으로 읽힌다. */
  flex-wrap: nowrap;
}
.tabs.is-in-body .tab {
  flex: 0 0 auto;
}

.chart-wrap {
  width: 100%; /* 필요 시 100%로 */
  height: 300px; /* 낮은 차트 높이 */
}

.list-box .list-head {
  height: 50px;
  display: flex;
  align-items: center;
  border: 1px solid var(--gray-600);
  background-color: var(--gray-300);
  border-radius: var(--radius-sm);
}
.list-box .list-head > div {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 10px 15px;
  font-weight: 700;
}
.list-box .list-head > div.num {
  width: 80px;
  flex-shrink: 0;
}
.list-box .list-head > div.date {
  width: 150px;
  flex-shrink: 0;
}
.list-box .list-tr {
  height: 50px;
  display: flex;
  align-items: center;
  border: 1px solid var(--gray-600);
  background-color: var(--color-white);
  border-radius: var(--radius-sm);
  margin-top: 5px;
}
.list-box .list-tr:hover {
  border: 1px solid var(--border-primary);
  box-shadow: var(--elev-1);
  color: var(--color-primary);
}
.list-box .list-tr > div {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.list-box .list-tr > div.num {
  width: 80px;
  flex-shrink: 0;
}
.list-box .list-tr > div.title {
  display: -webkit-box;
  text-align: left;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  word-break: break-all;
  overflow: hidden;
}
.list-box .list-tr > div.date {
  width: 150px;
  flex-shrink: 0;
  position: relative;
}
.list-box .list-tr > div.date::after {
  content: "";
  display: block;
  width: 24px;
  height: 24px;
  background-image: url(../../assets/images/icon/icon-clock.svg);
  background-size: contain;
  background-repeat: no-repeat;
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
}

.doc-partment-box {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.doc-partment-box .doc-partment-item {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-sm);
  padding: 12px;
}
.doc-partment-box .doc-partment-item:hover {
  border-color: var(--color-primary);
  background-color: rgba(var(--color-primary-rgb), 0.1);
}
.doc-partment-box .doc-partment-item .doc-partment-name {
  display: flex;
  align-items: center;
}
.doc-partment-box .doc-partment-item .doc-partment-name span {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 24px;
  color: var(--color-primary);
}
.doc-partment-box .doc-partment-item .doc-partment-name .btn {
  margin-left: auto;
  position: relative;
}
.doc-partment-box .doc-partment-item .doc-partment-specialty {
  margin-top: 12px;
}
.doc-partment-box .doc-partment-item .doc-partment-specialty p {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
  margin-bottom: 8px;
}
.doc-partment-box .doc-partment-item .doc-partment-specialty span {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
  color: var(--color-darken);
}

.drag-drop-wrap .drag-drop-title {
  margin-bottom: 12px;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}
.drag-drop-wrap .drag-item-list {
  padding: 12px;
  margin-top: 12px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
}
.drag-drop-wrap .drag-item {
  display: grid;
  grid-template-columns: 36px 40px 1fr 36px;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  padding: 12px;
  min-width: 0;
}
.drag-drop-wrap .drag-item:hover {
  border: 1px solid var(--color-primary);
}
.drag-drop-wrap .drag-item + .drag-item {
  margin-top: 4px;
}
.drag-drop-wrap .drag-item * {
  min-width: 0;
}
.drag-drop-wrap .drag-item .icon.icon-dotdot {
  width: 24px;
  height: 24px;
}
.drag-drop-wrap .drag-item .icon {
  width: 16px;
  height: 16px;
}
.drag-drop-wrap .drag-item .num {
  padding: 8px;
  border-radius: var(--radius-sm);
  background-color: var(--gray-600);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
}
.drag-drop-wrap .drag-item .drag-contents {
  display: flex;
  align-items: center;
  flex-direction: column;
  gap: 8px;
}
.drag-drop-wrap .drag-item .drag-contents.left {
  align-items: flex-start;
}

/* ===============================
 * Sortable: 내려놓을 자리(placeholder)
 * =============================== */
.dnd-placeholder {
  border: 2px dashed rgba(0, 0, 0, 0.25) !important;
  background: rgba(0, 0, 0, 0.02) !important;
  border-radius: var(--radius-md) !important;
  display: grid !important;
  grid-template-columns: 36px 40px 1fr 36px !important;
  align-items: center !important;
  gap: 8px !important;
  padding: 12px !important;
  box-sizing: border-box !important;
  color: transparent !important;
  box-shadow: none !important;
}
.dnd-placeholder * {
  opacity: 0 !important;
  pointer-events: none !important;
}

/* ===============================
 * Sortable: 드래그 중 따라다니는 카드(틀어짐 방지)
 * =============================== */
.dnd-drag {
  display: grid !important;
  grid-template-columns: 36px 40px 1fr 36px !important;
  align-items: center !important;
  gap: 8px !important;
  box-sizing: border-box !important;
  border-radius: var(--radius-md) !important;
  box-shadow: var(--elev-2);
  background: rgba(223, 225, 230, 0.95);
}
.dnd-drag * {
  pointer-events: none;
}

/* (선택) 드래그 시작 시 선택된 원본 */
.dnd-chosen {
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.06);
}

/* (선택) 핸들 커서 */
.move-order {
  cursor: grab;
}

.move-order:active {
  cursor: grabbing;
}

.thumb-list {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 24px;
}
.thumb-list.check-on .thumb-item .select {
  display: block;
}
.thumb-list.check-on .thumb-item .hov-box {
  display: none;
}
.thumb-list.mode-chan .thumb-item {
  will-change: transform;
  backface-visibility: hidden;
  transform: translateZ(0);
  border: 1px dashed var(--color-primary);
  cursor: grab;
}
.thumb-list.mode-chan .thumb-item:active {
  cursor: grabbing;
}
.thumb-list.mode-chan .thumb-item .hov-box {
  display: none;
}
.thumb-list {
  /* =======================
  순서 변경 드래그 (Sortable · banner.js)
  =======================
    ⚠️ 전역 .dnd-placeholder / .dnd-drag (_list.scss) 를 쓰지 않는다.
       그쪽은 행 목록용이라 4열 그리드를 !important 로 강제해서, 카드에 걸면
       크기가 어긋나고 끌 때마다 그리드가 튄다. 카드 전용으로 따로 둔다.
  */
}
.thumb-list .thumb-item {
  /* 내려놓을 자리 — 크기는 그대로 두고 내용만 감춘다 */
}
.thumb-list .thumb-item.is-dnd-ghost {
  border: 2px dashed var(--color-primary);
  background-color: rgba(var(--color-primary-rgb), 0.06);
  /* ⚠️ display:none 이 아니라 visibility — 자리(크기)가 남아야 옆 카드가 안 밀린다 */
}
.thumb-list .thumb-item.is-dnd-ghost > * {
  visibility: hidden;
}
.thumb-list .thumb-item {
  /* 잡은 원본 */
}
.thumb-list .thumb-item.is-dnd-chosen {
  box-shadow: 0 0 0 2px rgba(var(--color-primary-rgb), 0.35);
}
.thumb-list .thumb-item {
  /* 손끝을 따라다니는 카드 */
}
.thumb-list .thumb-item.is-dnd-drag {
  box-shadow: var(--elev-2);
  opacity: 0.95;
}
.thumb-list .add-item {
  display: flex;
  align-items: center;
  justify-content: center;
}
.thumb-list .add-item .add-btn {
  flex-direction: column;
  border-radius: var(--radius-md);
  border: 2px dashed var(--gray-600);
  width: 240px;
  height: 240px;
  position: relative;
}
.thumb-list .add-item .add-btn:hover {
  background-color: rgba(var(--color-primary-rgb), 0.1);
}
.thumb-list .add-item .add-btn:hover .icon {
  filter: var(--filter-dark);
}
.thumb-list .add-item .add-btn .icon {
  width: 56px;
  height: 56px;
}
.thumb-list .add-item .add-btn p {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
  color: var(--color-darken);
}
.thumb-list .thumb-item {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  overflow: hidden;
  background-color: var(--color-white);
}
.thumb-list .thumb-item.no-use .top,
.thumb-list .thumb-item.no-use .text-box {
  background-color: var(--gray-600);
}
.thumb-list .thumb-item .top {
  position: relative;
  overflow: hidden;
  padding: 12px;
}
.thumb-list .thumb-item .top:hover .hov-box {
  opacity: 1;
}
.thumb-list .thumb-item .numbadge {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}
.thumb-list .thumb-item .num {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
  background-color: #000;
  color: #fff;
  border: 1px solid var(--color-darken);
}
.thumb-list .thumb-item .select {
  display: none;
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 1;
}
.thumb-list .thumb-item .img-box {
  /*
    ⚠️ 높이를 잡지 않으면 카드 높이가 '올린 이미지의 비율'을 그대로 따라간다.
       메인 16:9(1920×1080) · 미니 4:3(588×439) · 팝업 세로형(340×390) 으로
       화면마다 비율이 다르고, 한 목록 안에서도 규격을 벗어난 이미지가 섞일 수
       있다(등록 화면의 권장 크기는 권장일 뿐 무엇도 막지 않는다).
       그러면 카드마다 높이가 달라져 5열 그리드의 줄이 들쭉날쭉해진다.
       무엇이 올라와도 흔들리지 않도록 여기서 높이를 고정한다.

    216px = 등록 타일 240px − .top 의 상하 padding 24px
            → 「등록」 타일과 카드의 이미지 영역이 같은 높이가 된다.
  */
  height: 216px;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--gray-600);
}
.thumb-list .thumb-item .img-box img {
  width: 100%;
  height: 100%;
  /*
    ⚠️ cover 로 채우지 않는다. 배너·팝업은 글자가 그림 안에 들어 있어서
       잘라내면 목록에서 무슨 배너인지 알아볼 수 없게 된다.
       남는 자리는 비워 두고 전체를 보여 준다.
  */
  -o-object-fit: contain;
     object-fit: contain;
}
.thumb-list .thumb-item .badgebox {
  position: absolute;
  bottom: 16px;
  left: 16px;
  background-color: var(--color-primary);
  border-radius: var(--radius-sm);
  padding: 8px;
  font-size: 14px;
  color: #fff;
}
.thumb-list .thumb-item .hov-box {
  width: 100%;
  height: 100%;
  border-radius: var(--radius-md);
  background-color: rgba(var(--color-darken-rgb), 0.5);
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  position: absolute;
  left: 0;
  top: 0;
  transition: all 0.4s;
  opacity: 0;
}
.thumb-list .thumb-item .hov-box .btn {
  min-width: 200px;
}
.thumb-list .thumb-item .text-box {
  padding: 12px;
  border-top: 1px solid var(--gray-600);
}
.thumb-list .thumb-item .text-box p {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
}
.thumb-list .thumb-item .text-box p + p {
  margin-top: 4px;
}

.thumb-upload-box.is-dragover .top {
  border-color: var(--color-primary);
}
.thumb-upload-box .top {
  min-height: 200px;
  background-color: var(--gray-200);
  border-radius: var(--radius-md);
  padding: 24px;
  border: 2px dashed var(--gray-600);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 8px;
  position: relative;
  overflow: hidden;
}
.thumb-upload-box .filename {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
  padding-top: 12px;
  padding-bottom: 12px;
}
.thumb-upload-box .bot {
  font-size: 14px;
  margin-top: 12px;
}
.thumb-upload-box .bot .flex {
  flex-wrap: wrap;
  gap: 8px;
}
.thumb-upload-box .bot .flex span {
  width: calc(50% - 8px);
}

.datepicker {
  position: relative;
  padding-right: 44px; /* 버튼 자리 확보 */
}
.datepicker.is-open {
  overflow: visible;
}
.datepicker .dp-input {
  height: 100%;
  width: 100%;
  background: transparent;
}
.datepicker .dp-btn {
  right: 8px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
  background-image: url("../images/icon/icon-calander.svg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  transition: background-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}
.datepicker .dp-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary), #fff 70%);
}
.datepicker:hover .dp-btn, .datepicker:focus-within .dp-btn {
  background-color: color-mix(in srgb, var(--color-primary), #fff 85%);
}
.datepicker {
  /* 버튼 활성 강조 */
}
.datepicker [data-dp-toggle][aria-expanded=true] {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary), #fff 60%);
}
.datepicker {
  /* 에러/비활성 상태 */
}
.datepicker.error .dp-btn {
  opacity: 0.55;
  pointer-events: none;
}
.datepicker:disabled .dp-btn {
  opacity: 0.4;
  pointer-events: none;
}
.datepicker {
  /* size 연동 */
}
.datepicker.size-lg {
  padding-right: 56px;
}
.datepicker.size-lg .dp-btn {
  width: 36px;
  height: 36px;
  right: 12px;
}
.datepicker.size-md .dp-btn {
  width: 32px;
  height: 32px;
  right: 10px;
}
.datepicker.size-md .dp-input {
  font-size: 18px;
  font-weight: 600;
}
.datepicker.size-sm .dp-btn {
  width: 28px;
  height: 28px;
  right: 8px;
}
.datepicker.size-sm .dp-input {
  font-size: 16px;
  font-weight: 600;
}

/* DatePicker Popup (전역/분리 영역) */
/* 팝업 박스 */
.dp-pop {
  position: fixed; /* 래퍼 내부에 넣는다면 absolute로 변경 */
  z-index: 9999;
  width: 328px;
  padding: 10px;
  background: var(--color-white);
  border: 1px solid var(--border-darken);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-2);
  animation: dp-fade 0.12s ease-out;
}

/* 위로 펼칠 때 */
.dp-pop.flipY {
  transform-origin: bottom center;
  margin-top: 0;
  margin-bottom: 6px;
}

/* 등장 애니메이션 */
@keyframes dp-fade {
  from {
    opacity: 0;
    transform: translateY(-2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* 헤더 */
.dp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}
.dp-head .title {
  font: 600 14px/1.2 system-ui;
  color: var(--color-darken);
}
.dp-head .nav {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-darken);
  background: var(--color-white);
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.dp-head .nav:hover {
  background: var(--gray-200);
  border-color: var(--color-primary);
}
.dp-head .nav:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary), #fff 70%);
}

/* 요일 행 */
.dp-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin: 6px 0 4px;
}
.dp-week span {
  font: 600 12px/1 system-ui;
  color: var(--gray-600);
  text-align: center;
}

/* 날짜 그리드 */
.dp-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}

/* 날짜 셀 */
.dp-day {
  height: 38px;
  border-radius: var(--radius-sm);
  display: grid;
  place-items: center;
  font: 600 13px/1 system-ui;
  color: var(--color-darken);
  cursor: pointer;
  outline: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.dp-day:hover {
  background: var(--gray-200);
}
.dp-day:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary), #fff 70%);
}
.dp-day[data-out="1"] {
  color: var(--gray-500);
}

/* 선택 & 범위 */
.dp-day.is-selected {
  background: var(--color-primary);
  color: #fff;
}

.dp-day.in-range {
  background: color-mix(in srgb, var(--color-primary), #fff 85%);
}

.dp-day.range-start {
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
}

.dp-day.range-end {
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
}

/* 다크 모드 */
[data-theme=dark] .datepicker .dp-pop {
  background: #121212;
  border-color: rgba(255, 255, 255, 0.12);
  /* ⚠️ 그림자를 여기서 다시 적지 않는다 — `--elev-2` 가 다크에서 스스로 짙어진다
        (_elevation.scss). 두 곳에 적으면 한쪽만 고쳐지는 날이 온다. */
}
[data-theme=dark] .datepicker .dp-week span {
  color: #a9adc0;
}
[data-theme=dark] .datepicker .dp-day {
  color: #e6e8f0;
}
[data-theme=dark] .datepicker .dp-day:hover {
  background: rgba(255, 255, 255, 0.06);
}
[data-theme=dark] .datepicker .dp-day.in-range {
  background: rgba(108, 124, 255, 0.18);
}
[data-theme=dark] .datepicker .dp-input {
  color: var(--color-darken);
}

.keyword-box {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-sm);
  padding: 12px;
  min-height: 300px;
  overflow-y: auto;
}
.keyword-box .keyword-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  background-color: var(--gray-300);
  border-radius: var(--radius-sm);
}
.keyword-box .keyword-item .btn {
  border: 0;
  width: 24px;
  height: 24px;
}
.keyword-box .keyword-item .btn.btn-icon-only svg, .keyword-box .keyword-item .btn.btn-icon-only i {
  width: 12px;
  height: 12px;
}

.timetable-wrap {
  display: flex;
  align-items: stretch;
  gap: 12px;
}
.timetable-wrap .timetable-box,
.timetable-wrap .doclist-box {
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.timetable-wrap .timetable-box {
  width: 75%;
}
.timetable-wrap .timetable-box.col5 .title-box {
  grid-template-columns: repeat(5, 1fr);
}
.timetable-wrap .timetable-box.col5 .time-list-item {
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.timetable-wrap .timetable-box.col5 .time-list-item .time-box {
  width: auto;
}
.timetable-wrap .timetable-box.col5 .time-list-item .list-boxouter {
  width: 100%;
}
.timetable-wrap .timetable-box.col5 .time-list-item .list-box.rest {
  width: 100%;
  flex-shrink: 1;
}
.timetable-wrap .title-box {
  background-color: rgba(var(--color-primary-rgb), 0.1);
  display: grid;
  grid-template-columns: 174px 1fr 300px;
  align-items: center;
  padding: 12px;
}
.timetable-wrap .title-box .title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
  text-align: center;
}
.timetable-wrap .timelist-box {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
}
.timetable-wrap .timelist-box .time-list-item {
  display: flex;
  align-items: center;
  padding: 12px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-md);
}
.timetable-wrap .timelist-box .time-list-item .time-box {
  width: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 4px;
  border-radius: var(--radius-sm);
  margin-right: 12px;
  flex-shrink: 0;
}
.timetable-wrap .timelist-box .time-list-item .time-box p {
  text-align: center;
}
.timetable-wrap .timelist-box .time-list-item .time-box p:first-child {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
}
.timetable-wrap .timelist-box .time-list-item .list-boxouter {
  width: calc(100% - 150px);
  display: flex;
  align-items: stretch;
  gap: 8px;
}
.timetable-wrap .timelist-box .time-list-item .list-box {
  width: 100%;
  min-height: 100px;
  background-color: var(--gray-300);
  border-radius: var(--radius-sm);
  position: relative;
  padding: 12px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  gap: 2px;
  position: relative;
}
.timetable-wrap .timelist-box .time-list-item .list-box.rest {
  width: 275px;
  flex-shrink: 0;
}
.timetable-wrap .timelist-box .time-list-item .list-box .dnd-placeholder {
  align-self: flex-start;
}
.timetable-wrap .timelist-box .time-list-item .list-box .empty-text {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
  color: var(--color-darken);
  text-align: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;
}
.timetable-wrap .doc-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  background-color: var(--color-white);
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-sm);
}
.timetable-wrap .doc-item .doc-name {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
}
.timetable-wrap .doc-item .btn {
  width: 24px;
  height: 24px;
}
.timetable-wrap .doc-item .btn .icon {
  width: 12px;
  height: 12px;
}
.timetable-wrap .doc-item .delete {
  border: 0;
}
.timetable-wrap .doc-item .delete .icon {
  filter: brightness(0) saturate(100%) invert(71%) sepia(69%) saturate(7419%) hue-rotate(336deg) brightness(91%) contrast(93%);
}
.timetable-wrap .doc-item:hover {
  background-color: var(--color-primary);
  color: #fff;
}
.timetable-wrap .doc-item.new {
  border: 1px solid var(--color-primary);
  background-color: rgba(var(--color-primary-rgb), 0.2);
}
.timetable-wrap .doc-item.new:hover {
  background-color: var(--color-primary);
  color: #fff;
}
.timetable-wrap .doclist-box {
  width: 25%;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.timetable-wrap .doclist-box .box-wrap,
.timetable-wrap .doclist-box .title-box {
  flex-shrink: 0;
}
.timetable-wrap .doclist-box .title-box {
  display: flex;
  justify-content: center;
}
.timetable-wrap .doclist-box .box-wrap {
  border-bottom: 1px solid var(--gray-600);
}
.timetable-wrap .doclist-box .doclist {
  height: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 12px;
  align-items: flex-start;
  align-content: flex-start;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.timetable-wrap .doclist-box .doclist.col1 .doc-item {
  width: 100%;
}
.timetable-wrap .doclist-box .doclist.col2 .doc-item {
  width: calc(50% - 4px);
}
.timetable-wrap .doclist-box .doclist .doc-center-title:first-child {
  margin-top: 0;
}
.timetable-wrap .doclist-box .doc-center-title {
  width: 100%;
  text-align: center;
  padding: 8px;
  border-radius: var(--radius-pill);
  background-color: var(--color-primary);
  color: #fff;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
  margin-top: 24px;
}
.timetable-wrap .doclist-box .doc-item {
  flex-wrap: wrap;
  min-height: 110px;
  gap: 4px 8px;
  align-items: center;
  align-content: flex-start;
}
.timetable-wrap .doclist-box .doc-item .btn {
  width: 36px;
  height: 36px;
}
.timetable-wrap .doclist-box .doc-item .btn .icon {
  width: 18px;
  height: 18px;
}
.timetable-wrap .doclist-box .doc-item .doc-state-box {
  width: 100%;
}
.timetable-wrap .doclist-box .doc-item .doc-state-box b {
  padding: 8px;
  border-radius: var(--radius-sm);
  background-color: var(--color-darken);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state p {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state .badge {
  width: auto;
  padding: 4px;
  border-radius: var(--radius-sm);
  color: var(--color-darken);
  display: flex;
  align-items: center;
  justify-content: center;
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state .badge.blue {
  background-color: var(--color-blue);
  color: var(--color-white);
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state .badge.red {
  background-color: var(--color-red);
  color: var(--color-white);
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state .badge.point {
  background-color: var(--color-point);
  color: var(--color-white);
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state .badge.dark {
  background-color: var(--color-darken);
  color: var(--color-white);
}
.timetable-wrap .doclist-box .doc-item .doc-state-box .doc-state .badge.line {
  border: 1px solid var(--color-darken);
}

.doc-drag-preview,
.source-doclist .doc-item.dnd-drag,
.source-doclist .doc-item.dnd-chosen {
  width: auto !important;
  min-height: auto !important;
  height: auto !important;
  display: inline-flex !important;
  align-items: center !important;
  align-content: center !important;
  flex-wrap: nowrap !important;
  gap: 8px !important;
  padding: 8px !important;
  background-color: var(--color-white) !important;
  border: 1px solid var(--gray-600) !important;
  border-radius: var(--radius-sm) !important;
  box-sizing: border-box !important;
}
.doc-drag-preview .doc-state-box,
.source-doclist .doc-item.dnd-drag .doc-state-box,
.source-doclist .doc-item.dnd-chosen .doc-state-box {
  display: none !important;
}
.doc-drag-preview .doc-name,
.doc-drag-preview > span,
.source-doclist .doc-item.dnd-drag .doc-name,
.source-doclist .doc-item.dnd-drag > span,
.source-doclist .doc-item.dnd-chosen .doc-name,
.source-doclist .doc-item.dnd-chosen > span {
  flex: 1 1 auto;
  min-width: 0;
  width: auto !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  word-break: keep-all;
}
.doc-drag-preview .btn,
.source-doclist .doc-item.dnd-drag .btn,
.source-doclist .doc-item.dnd-chosen .btn {
  flex-shrink: 0;
}
.doc-drag-preview,
.source-doclist .doc-item.dnd-drag,
.source-doclist .doc-item.dnd-chosen {
  /* 드롭 위치 placeholder */
}
.doc-drag-preview .dnd-placeholder,
.source-doclist .doc-item.dnd-drag .dnd-placeholder,
.source-doclist .doc-item.dnd-chosen .dnd-placeholder {
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  width: auto !important;
  min-width: auto !important;
  height: auto !important;
  padding: 8px !important;
  border: 2px dashed var(--gray-500) !important;
  border-radius: var(--radius-sm) !important;
  background: transparent !important;
  flex: 0 0 auto !important;
}
.doc-drag-preview,
.source-doclist .doc-item.dnd-drag,
.source-doclist .doc-item.dnd-chosen {
  /* placeholder 내부 텍스트 숨김 */
}
.doc-drag-preview .dnd-placeholder *,
.source-doclist .doc-item.dnd-drag .dnd-placeholder *,
.source-doclist .doc-item.dnd-chosen .dnd-placeholder * {
  visibility: hidden;
}

.reservation-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  align-items: start;
}
.reservation-wrap .calendar-card,
.reservation-wrap .time-select-box {
  border: 1px solid var(--gray-600);
  background-color: var(--color-white);
}

.reservation-calendar .calendar-card {
  padding: 12px;
  background: #f8f8f8;
}
.reservation-calendar .calendar-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 24px;
}
.reservation-calendar .calendar-title {
  min-width: 100px;
  text-align: center;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
  color: var(--color-darken);
}
.reservation-calendar .calendar-nav {
  width: 24px;
  height: 24px;
  border: 0;
  background: transparent;
  position: relative;
  cursor: pointer;
}
.reservation-calendar .calendar-nav::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 8px;
  height: 8px;
  border-top: 1.5px solid #666;
  border-right: 1.5px solid #666;
  transform: translate(-50%, -50%) rotate(45deg);
}
.reservation-calendar .calendar-nav.prev::before {
  transform: translate(-50%, -50%) rotate(-135deg);
}
.reservation-calendar .calendar-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 12px;
}
.reservation-calendar .calendar-week span {
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  color: #555;
}
.reservation-calendar .calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 10px 6px;
}
.reservation-calendar .calendar-day {
  min-height: 44px;
  border: 0;
  background: transparent;
  font-size: 24px;
  font-weight: 600;
  color: #333;
  border-radius: var(--radius-pill);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  line-height: 1.1;
  margin: 0 auto;
  min-width: 44px;
  position: relative;
}
.reservation-calendar .calendar-day .sub {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: #2f80ed;
  margin-top: 2px;
}
.reservation-calendar .calendar-day.is-empty {
  visibility: hidden;
  pointer-events: none;
}
.reservation-calendar .calendar-day.is-closed {
  background: #666;
  color: #fff;
}
.reservation-calendar .calendar-day.is-available {
  color: #b63b46;
  border: 1px solid #e6aab0;
  background: #fff;
}
.reservation-calendar .calendar-day.is-selected {
  background: #8f1025;
  color: #fff;
}
.reservation-calendar .calendar-day:hover:not(:disabled):not(.is-empty) {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12) inset;
}
.reservation-calendar .calendar-legend {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 18px;
  font-size: 13px;
  color: #666;
}
.reservation-calendar .calendar-legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.reservation-calendar .calendar-legend .dot {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-circle);
  display: inline-block;
}
.reservation-calendar .calendar-legend .dot.is-closed {
  background: #666;
}
.reservation-calendar .calendar-legend .dot.is-available {
  background: #f3a7ae;
}
.reservation-calendar .calendar-legend .dot.is-selected {
  background: #8f1025;
}

.reservation-time {
  height: 100%;
}
.reservation-time .time-select-box {
  position: relative;
  min-height: 100%;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
}
.reservation-time .time-display {
  width: 100%;
  height: 90px;
  padding: 0 16px;
  border: 0;
  background: #f8f8f8;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  border-bottom: 1px solid var(--gray-600);
}
.reservation-time .time-display .placeholder,
.reservation-time .time-display .value {
  font-size: 36px;
  font-weight: 500;
  color: #555;
  line-height: 1;
}
.reservation-time .time-display .icon-time {
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
}
.reservation-time .time-inline-check {
  padding: 12px;
  margin-top: auto;
}
.reservation-time .time-guide {
  margin-top: 8px;
  font-size: 16px;
  color: #555;
  padding: 12px;
  padding-top: 0;
}
.reservation-time .time-picker-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 332px;
  border: 1px solid var(--gray-600);
  background: #fff;
  z-index: 20;
  box-shadow: var(--elev-2);
}
.reservation-time .time-picker-head {
  height: 70px;
  padding: 0 16px;
  border-bottom: 1px solid var(--gray-600);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.reservation-time .time-picker-head .selected-time-text {
  font-size: 24px;
  font-weight: 700;
  color: #444;
}
.reservation-time .time-picker-head .icon-time {
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
}
.reservation-time .time-picker-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.reservation-time .time-col {
  min-width: 0;
}
.reservation-time .time-col:first-child {
  border-right: 6px solid #7a7a7a;
}
.reservation-time .time-col-title {
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: #888;
  border-bottom: 1px solid #ddd;
}
.reservation-time .time-list {
  max-height: 380px;
  overflow-y: auto;
}
.reservation-time .time-item {
  width: 100%;
  height: 52px;
  border: 0;
  border-bottom: 1px solid #f0f0f0;
  background: #fff;
  font-size: 24px;
  font-weight: 500;
  color: #555;
  cursor: pointer;
}
.reservation-time .time-item.is-active {
  background: #8f1025;
  color: #fff;
}
.reservation-time .time-item.is-disabled {
  background: #d9d9d9;
  color: #666;
  cursor: not-allowed;
}
.reservation-time .time-picker-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid #eee;
}

/* =======================
1) 페이지 로더 오버레이
======================= */
#page-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: opacity 0.3s ease;
}
#page-loader.is-done {
  opacity: 0;
  pointer-events: none;
}

/* 3겹 동심원 호 스피너 */
.page-loader-svg {
  width: 120px;
  height: 120px;
}

.pl-arc {
  stroke: var(--color-primary, #289DD2);
  fill: none;
  stroke-linecap: round;
  /* note. 없으면 각 원이 SVG 좌상단 기준으로 회전함 */
  transform-box: fill-box;
  transform-origin: center;
}
.pl-arc.pl-arc-1 {
  /* 외부 호 — 가장 느리게, 시계 방향 */
  stroke-width: 3;
  stroke-dasharray: 63, 126; /* r=20, C≈126 */
  animation: pl-spin 2s linear infinite;
}
.pl-arc.pl-arc-2 {
  /* 중간 호 — 중간 속도, 반시계 방향 */
  stroke-width: 3;
  stroke-dasharray: 35, 88; /* r=14, C≈88 */
  opacity: 0.65;
  animation: pl-spin 1.4s linear infinite reverse;
}
.pl-arc.pl-arc-3 {
  /* 내부 호 — 가장 빠르게, 시계 방향 */
  stroke-width: 3;
  stroke-dasharray: 18, 51; /* r=8, C≈50 */
  opacity: 0.35;
  animation: pl-spin 0.9s linear infinite;
}

@keyframes pl-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
/* =======================
2) 스켈레톤
======================= */
.skeleton {
  display: block;
  background: linear-gradient(90deg, #e0e0e0 25%, #f5f5f5 50%, #e0e0e0 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.skeleton.skeleton-text {
  /* 텍스트 한 줄 */
  display: inline-block;
  width: 100%;
  height: 14px;
}
.skeleton.skeleton-circle {
  /* 아바타·아이콘 (width/height 직접 지정) */
  border-radius: var(--radius-circle);
}
.skeleton.skeleton-rounded {
  /* 카드·썸네일 */
  border-radius: var(--radius-sm);
}
.skeleton.skeleton-rect {
  /* 각진 블록 */
  border-radius: 0;
}
.skeleton {
  /*
    표 칸 안에서 쓰는 둘 — **곧 올 것의 모양을 흉내 낸다.**

    ⚠️ 그냥 회색 막대를 놓으면 무엇이 올지 모른다. 알약이면 배지가,
       네모면 단추가 온다는 것을 모양만으로 알 수 있어야 읽힌다.
       (page/translate/translate.jsp 의 [번역 요청],
        page/contents/mng-contents.jsp 의 영문 상태 줄)
  */
  /*
    ⚠️ 둘 다 inline-block 이다. .skeleton 은 block 이라 그대로 두면 칸의
       text-align 을 따르지 않고 늘 왼쪽에 붙는다 — 가운데 정렬한 표에서
       배지·단추만 가운데인데 스켈레톤만 왼쪽으로 튀어 자리가 흔들려 보인다.
  */
}
.skeleton.skel-badge {
  /* 상태 배지가 올 자리 — .state-badge 의 높이·둥글기·폭에 맞춘다 */
  display: inline-block;
  width: 78px;
  height: 24px;
  border-radius: var(--radius-pill);
}
.skeleton.skel-btn {
  /* size-sm 단추가 올 자리 */
  display: inline-block;
  width: 68px;
  height: 32px;
  border-radius: var(--radius-sm);
}

/* 테이블 스켈레톤 행 — 실데이터 행과 높이 맞춤 */
.skeleton-row td {
  padding-top: 14px;
  padding-bottom: 14px;
}

@keyframes skeleton-shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}
/* =======================
3) 버튼 로딩 상태
======================= */
.icon-loading {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-circle);
  animation: btn-spin 0.7s linear infinite;
  vertical-align: middle;
}

/* note. btn-icon-* 의 filter 가 border 스피너 색을 뭉개므로 해제
   (currentColor 라 버튼 텍스트 색을 이미 따라감) */
.btn.btn-icon-left .icon-loading,
.btn.btn-icon-right .icon-loading {
  filter: none;
}

@keyframes btn-spin {
  to {
    transform: rotate(360deg);
  }
}
/* darkmode */
[data-theme=dark] .skeleton {
  background: linear-gradient(90deg, #2a2a2a 25%, #3a3a3a 50%, #2a2a2a 75%);
  background-size: 200% 100%;
}

/* =====================================================
 * Toast — 자동 사라짐 안내
 *
 * 저장·삭제처럼 되돌릴 것도 고를 것도 없는 안내를 우측 하단에 잠깐 띄운다.
 * 확인 버튼을 눌러야 사라지는 모달은 '읽었다'는 확인이 필요할 때만 쓴다.
 *
 * 배경 #747474 · 라운드 6 · padding 12px 13px
 * 그림자 0 4px 30px rgba(0,0,0,.35) · 글자 14px 흰색
 *
 * ⚠️ 배경 #747474 는 회색 토큰 어디에도 없다(gray-900 #8b8d98 보다 어둡다).
 *    토큰으로 갈음하면 대비가 달라지므로 값을 그대로 둔다.
 *
 * ⚠️ 라이트/다크 어느 테마에서도 같은 색이다. 토스트는 화면 위에 잠깐 떴다 사라지는
 *    안내라 본문 표면과 대비를 유지해야 한다. 그래서 테마 토큰을 쓰지 않는다.
 * ===================================================== */
.toast-area {
  /* 우측 하단 고정. 모달(z-index 1000)보다 위에 떠야 모달 안에서 저장해도 보인다 */
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 1100;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  /* 토스트가 없을 때 이 영역이 클릭을 먹으면 안 된다 */
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: min(420px, 100vw - 48px);
  padding: 12px 13px;
  border-radius: var(--radius-sm);
  background: #747474;
  box-shadow: var(--elev-2);
  font-size: 14px;
  font-weight: 400;
  line-height: normal;
  color: #fff;
  /*
    시안은 한 줄(whitespace-nowrap)이다. 다만 실제 문구는 길이가 제각각이라
    max-width 를 넘으면 줄을 바꾼다 — 잘라내면 안내가 사라지기 때문이다.
  */
  word-break: keep-all;
  /* 들어올 때: 아래에서 살짝 올라오며 나타난다 */
  animation: toast-in 0.25s ease both;
}
.toast.is-leaving {
  animation: toast-out 0.2s ease both;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes toast-out {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(4px);
  }
}
/* 움직임을 줄여 달라는 설정이면 애니메이션 없이 그냥 나타났다 사라진다 */
@media (prefers-reduced-motion: reduce) {
  .toast,
  .toast.is-leaving {
    animation: none;
  }
}
@media (max-width: 768px) {
  .toast-area {
    right: 16px;
    bottom: 16px;
    left: 16px;
    align-items: stretch;
  }
  .toast {
    max-width: none;
  }
}
/* =====================================================
 * 안내 띠 — 「이 화면은 개인정보를 다룬다」를 알린다
 *
 * 쓰는 곳
 * ------------------------------------------------------------------
 *   page/memberList/memberList.jsp   회원 목록 (병원 CMS)
 *   page/lmsMember/lmsMember.jsp     회원 관리 (LMS)
 *   두 화면의 상세 팝업 안에도 같은 것이 들어간다.
 *
 * ⚠️ **index.css 에 둔다.** 처음에 page/_course.scss 에 넣었는데, 그러면
 *    page.css 를 링크하지 않는 화면(회원 목록이 그렇다)에서는 모양이 안 잡힌다.
 *    두 제품이 같이 쓰는 부품은 공용 자리에 있어야 한다.
 *
 * ⚠️ **빨강이 아니라 파랑이다.** 빨강은 「잘못됐다」인데 이건 잘못이 아니라
 *    알아 두어야 할 사실이다. 경고를 남발하면 정작 위험할 때 안 읽힌다.
 *
 * 왜 이런 띠가 필요한가
 * ------------------------------------------------------------------
 * 「개인정보의 안전성 확보조치 기준」 제8조가 개인정보취급자의 접속기록을
 * 남기고 보관·점검하도록 정하고 있다. 이 CMS 에는 그 기록을 보는 화면
 * (관리자 · 설정 › 접속 · 작업 기록)이 이미 있다.
 * 미리 알려 주지 않으면, 나중에 그 이력에서 자기 이름을 보고 감시당했다고 느낀다.
 * 기록은 담당자를 의심하려는 장치가 아니라 **의심받을 때 지켜 주는 장치**이기도 하다.
 *
 * 마크업
 * ------------------------------------------------------------------
 *   <div class="member-notice">
 *     <p><b>개인정보 화면</b> … <b>연 기록이 남습니다.</b></p>
 *     <a class="btn btn-dark-line size-sm">접근 이력 보기</a>
 *   </div>
 *
 *   팝업 안에서는 오른쪽에 붙일 단추가 없으므로 `is-in-modal` 을 더한다.
 * ===================================================== */
.member-notice {
  /*
    ⚠️ **아래 여백을 부품이 갖는다.** 화면들이 `mb16` 을 붙여 두었는데 그런
       유틸리티는 없다(_global.scss 의 사다리는 8 · 12 · 24 … 로 16 을 건너뛴다).
       그래서 다섯 화면에서 이 상자가 아래 검색 카드에 붙어 있었다.
       바로 위 형제인 `.page-guide` 도 제 아래 여백을 스스로 갖는다 — 같은 자리에
       서는 같은 모양의 상자이므로 규칙도 같아야 한다.
    ⚠️ 화면이 더 벌리고 싶으면 `mb24` 를 붙인다(!important 라 이 값을 이긴다).
  */
  /*
    ⚠️ **여기가 「참고」와 「본론」이 갈리는 자리다.** 아래로 벌려 층을 만든다 —
       위(안내)와는 12px, 아래(검색·표)와는 32px 이다.
       예전에는 위아래가 다 16px 이라 갈리는 자리가 안 보였다.
  */
  margin-bottom: var(--rhythm-loose);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  border: 1px solid rgba(var(--color-blue-rgb), 0.35);
  border-radius: var(--radius-md);
  background-color: rgba(var(--color-blue-rgb), 0.06);
}
.member-notice p {
  margin: 0;
}
.member-notice b {
  margin-right: 6px;
  color: var(--color-blue);
}
.member-notice {
  /* 팝업 안 — 단추가 없어 양끝 정렬이 뜻을 잃는다 */
}
.member-notice.is-in-modal {
  justify-content: flex-start;
}

/* =====================================================
 * 좁은 화면 (2026-09-10 반응형)
 *
 * ⚠️ 글과 단추가 한 줄에 서 있다. 390px 에서 단추가 76px 로 눌려
 *    「접속 / 이력 / 보기」 **세 줄로 꺾였다.** 위아래로 쌓는다.
 * ===================================================== */
@media (max-width: 767px) {
  .member-notice {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 12px 14px;
  }
  .member-notice .btn {
    width: 100%;
    justify-content: center;
  }
}
/* =====================================================
 * 화면 안내 — 「이 화면은 무엇을 하는 곳인가」
 *
 * 쓰는 곳: 소셜 미디어 · 관리자 · 설정 아래의 모든 화면.
 *
 * ⚠️ 화면 맨 위, 검색 카드보다 **앞**에 둔다. 표를 먼저 보고 나서
 *    「이게 뭐 하는 표지?」를 묻게 되면 이미 늦다.
 * ⚠️ 접을 수 있게 한다. 매일 쓰는 사람에게는 같은 안내가 매일 80px 를
 *    먹는다. 접은 상태는 화면마다 따로 기억한다(pageGuide.js).
 * ⚠️ 경고 빨강을 쓰지 않는다. 이건 잘못이 아니라 알아 두면 좋은 사실이다.
 *    빨강을 남발하면 정작 위험할 때 안 읽힌다.
 * ===================================================== */
.page-guide {
  /*
    ⚠️ **참고 상자끼리는 가깝게 붙인다**(2026-09-10 층 정리).
       안내 → 고지 → 검색 이 모두 16px 이라, **성격이 바뀌는 자리와 안 바뀌는
       자리가 같은 간격**이었다. 그래서 넷이 줄줄이 쌓인 것으로 보였다.
       안내와 고지는 둘 다 「읽고 지나가는 것」이므로 한 묶음으로 붙인다.
  */
  margin-bottom: var(--rhythm-tight);
  padding: 14px 18px;
  border: 1px solid rgba(var(--color-blue-rgb), 0.35);
  border-radius: var(--radius-md);
  background-color: rgba(var(--color-blue-rgb), 0.06);
  /*
    ⚠️ **여기서 32px 로 벌리던 것을 걷었다**(2026-09-23 대표님 — 간격을 일정하게).
       「고지가 없으면 안내가 벌리는 일을 맡는다」며 `:not(:has(~ .member-notice))`
       에 32px 을 주었는데, 그 값이 `.section-content` 의 위 여백과 **겹쳐 무너지면서**
       (맞닿은 여백은 큰 쪽만 남는다) 본문 여백을 12px 로 줄여도 화면은 32px 그대로였다.
       자리마다 다른 값을 두면 어디가 무엇을 정하는지 알 수 없게 된다 —
       **간격은 한 값(12px)으로 둔다.**
  */
}

.page-guide-head {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}
.page-guide-head p {
  flex: 1;
  min-width: 0;
  margin: 0;
  word-break: keep-all;
}
.page-guide-head b {
  margin-right: 6px;
  color: var(--color-blue);
}

/*
  접기 단추.
  ⚠️ 글자로 둔다. 아이콘만 두면 「접기」인지 「닫기(영영 없애기)」인지
     구분되지 않아, 다시 볼 방법을 찾다 포기한다.
*/
.page-guide-toggle {
  flex: 0 0 auto;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--color-blue);
  font-size: 14px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.page-guide-steps {
  margin: 10px 0 0;
  padding-left: 20px;
  color: var(--color-darken);
  /*
    ⚠️ 본문보다 **한 눈금 작다**(16 → 14). 이 목록은 「지금 읽을 것」이 아니라
       「막혔을 때 펴 보는 것」이다. 본문과 같은 크기면 화면을 열 때마다
       가장 먼저 눈에 걸려, 정작 읽어야 할 값보다 앞선다.
    ⚠️ 표 · 입력칸과 같은 눈금이다(body-5-2). 눈금을 새로 만들지 않는다.
  */
}
.page-guide-steps li {
  list-style: decimal;
  margin-top: 4px;
  word-break: keep-all;
  line-height: 1.6;
  font-size: 14px;
}
.page-guide-steps b {
  font-weight: 700;
}

/* 접힌 상태 — 첫 줄만 남는다 */
.page-guide[data-open=false] .page-guide-steps,
.page-guide[data-open=false] .page-guide-body {
  display: none;
}

/* =====================================================
 * page-guide-body — 안내는 **두 덩이**다
 *
 *   위(.page-guide-head)   이 화면이 무슨 화면인가   — 늘 보인다
 *   아래(.page-guide-body) 이 화면을 어떻게 쓰는가   — 눌러서 편다
 *
 * ⚠️ 늘 보이는 자리에 **역할만** 둔다. 쓰는 법까지 펼쳐 두면 화면을 열
 *    때마다 읽어야 할 값보다 안내가 먼저 눈에 걸린다.
 * ⚠️ 아래 덩이에 **이름표(이용 방법)를 붙인다.** 이름표가 없으면 위 문장과
 *    아래 목록이 한 덩어리로 읽혀, 무엇이 설명이고 무엇이 할 일인지 갈리지
 *    않는다. 접기 단추 글자와 같은 말을 쓴다 — 누른 것과 열린 것이 같아야 한다.
 * ===================================================== */
.page-guide-body {
  margin-top: 12px;
}

.guide-label {
  margin: 0;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 14px;
  color: var(--color-blue);
}

/* 이름표 아래 목록은 위쪽 여백을 이름표가 준다 */
.page-guide-body .page-guide-steps {
  margin-top: 6px;
}

/*
  이용 방법에 들지 않는 한 줄.
  ⚠️ **「여기서 하지 않는 일」만 적는다.** 사람이 가장 자주 헤매는 것이
     「그건 여기 없나」다. 그 밖의 곁들이는 말은 적지 않는다.
*/
.guide-aside {
  margin: 10px 0 0;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  color: var(--text-muted);
  word-break: keep-all;
}

/* ================================================= */
/* 1. 폰트 가중치 Map 및 기본 변수 정의 (핵심 유틸리티) */
/* ================================================= */
/* ============================================== */
/* 2. 타이포그래피 스타일 Map 정의 (디자인 시스템) */
/* ============================================== */
/* ================================================= */
/* 2-1. 반응형 size Map (PC 대비 size만 오버라이드) */
/* ================================================= */
/* ============================================= */
/* 3. 공용 유틸: 레벨별 size 조회 (브레이크포인트) */
/* ============================================= */
/* ============================================= */
/* 4. 범용 믹스인: @include body-1-1 형태로 사용 */
/* - 핵심: selector 컨텍스트(&)로 미디어를 함께 출력 */
/* ============================================= */
/* ============================================= */
/* 5. 레벨별 믹스인: 최종 사용 형태 유지 */
/* ============================================= */
/* ========================================== */
/* 6. 클래스 자동 생성(선택): 기존 형태 유지 */
/* ========================================== */
.display-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 72px;
}

.title-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 48px;
}

.title-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 40px;
}

.title-3 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 32px;
}

.title-4 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 24px;
}

.body-1-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 24px;
}

.body-1-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 24px;
}

.body-2-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
}

.body-2-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 20px;
}

.body-3-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}

.body-3-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
}

.body-4-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
}

.body-4-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}

.body-5-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 14px;
}

.body-5-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
}

/* =====================================================
 * 목록 카드 — 머리 · 표 · 발  (2026-09-10)
 *
 * 목록 화면 아홉 개가 함께 쓰는 짜임. 견본에서 고른 **A안**이다.
 * ⚠️ 견본 화면(`page/guide/tableSample.jsp` 의 `.ts-a`)은 안을 고른 뒤
 *    지웠다(2026-09-14). 네 안을 견주던 기록은 `문서/다음-작업-지시문.md` 에 있다.
 *
 * ─ 예전 짜임의 문제 (재서 나온 것 · 여덟 화면이 모두 같았다)
 *
 *   검색결과 10건                    [엑셀]      ↕12
 *   표(제 테두리를 가진다)                       ↕16
 *   [행 수]            ※ 클릭하면 조회…          ↕12
 *   보관 안내                                   ↕24
 *              ‹‹ ‹ 1 2 › ››
 *
 *   ① 간격이 12 · 16 · 12 · 24 라 **무엇끼리 한 묶음인지** 안 보인다.
 *   ② 표를 다루는 도구가 **표를 사이에 두고 갈라져** 있다 — 위에 결과수·엑셀,
 *      아래에 행 수·페이지. 같은 일인데 두 곳이다.
 *   ③ 카드 여백 24px 안에서 표가 **또 테두리를 갖는다** — 테두리가 두 겹이다.
 *   ④ 「클릭하면 조회가 가능합니다」가 **표 아래**에 있다. 다 읽고 나서 안다.
 *
 * ─ A안이 하는 일
 *   카드를 세 켜로 나눈다. 표는 카드 폭을 **끝까지** 쓰고(테두리 한 겹),
 *   도구는 머리와 발에 나눠 서고, 클릭 안내는 **머리로 올린다.**
 *
 * ⚠️ **카드 여백을 0 으로 하고 머리·발만 여백을 갖는다.** 그래야 표가 카드
 *    끝에 붙어 테두리 두 겹이 사라진다.
 * ⚠️ `.section-content.is-list` 는 (0,2,0) 이라 `.section-content`(0,1,0) 을
 *    이긴다 — **좁은 화면의 `padding: 16px` 도 이긴다.** 미디어 쿼리는
 *    특정도를 더하지 않는다(이 제품에서 이미 한 번 걸려 넘어졌다).
 * ===================================================== */
.section-content.is-list {
  padding: 0;
  overflow: hidden; /* 표 모서리를 카드가 깎는다 */
}
.section-content.is-list .list-head,
.section-content.is-list .list-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 20px;
}
.section-content.is-list .list-head {
  border-bottom: 1px solid var(--surface-line);
}
.section-content.is-list .list-foot {
  border-top: 1px solid var(--surface-line);
}
.section-content.is-list .list-head-left,
.section-content.is-list .list-head-right,
.section-content.is-list .list-foot-left,
.section-content.is-list .list-foot-right {
  display: flex;
  align-items: center;
  gap: 12px;
}
.section-content.is-list {
  /* 표는 카드가 이미 테두리를 가지므로 제 테두리를 버린다 */
}
.section-content.is-list .table-wrap {
  border: 0;
  border-radius: 0;
  background: transparent;
}
.section-content.is-list .table {
  border-radius: 0;
}
.section-content.is-list {
  /* =====================================================
   * 고른 뒤에만 서는 줄
   *
   * ⚠️ **「선택한 …」 단추는 체크를 해야 쓸 수 있다.** 고르기 전에 세워 두면
   *    375px 에서 도구 줄이 두 줄이 되고 **쓸 수 없는 단추가 자리를 먹는다.**
   *    재서 나온 것 — 세 화면에서 단추가 셋이었고(엑셀 · 주된 동작 · 선택한 …),
   *    발행 검수는 그중 **둘**이 고르기를 먼저 해야 하는 것이었다.
   *
   * ⚠️ 이 줄이 서면 검색결과 · 안내 · 나머지 단추는 **물러난다.** 그 순간
   *    하는 일이 「고른 것을 어떻게 할까」 하나이기 때문이다.
   *
   * ⚠️ **CSS 가 감추고 JS 가 켠다**(`.is-selecting`). `hidden` 을 마크업에
   *    적지 않은 까닭 — 스크립트가 꺼지면 이 줄이 **늘 보인다.** 고른 것으로
   *    할 수 있는 일이 사라지는 쪽보다 단추가 하나 더 보이는 쪽이 낫다.
   * ===================================================== */
}
.section-content.is-list .list-select {
  display: none;
  align-items: center;
  gap: 16px;
  flex: 1 1 100%;
  flex-wrap: wrap;
}
.section-content.is-list {
  /* ⚠️ `.is-selecting` 은 **머리 줄**에 붙는다 — 카드가 아니다 */
}
.section-content.is-list .list-head.is-selecting .list-head-left,
.section-content.is-list .list-head.is-selecting .list-head-right {
  display: none;
}
.section-content.is-list .list-head.is-selecting .list-select {
  display: flex;
}
.section-content.is-list .list-select-count {
  margin: 0;
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
  color: var(--color-darken);
}
.section-content.is-list .list-select-count b {
  color: var(--color-primary);
}
.section-content.is-list {
  /* 머리로 올라온 클릭 안내 — 단추 왼쪽에 선다 */
}
.section-content.is-list .list-hint {
  margin: 0;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  color: var(--text-muted);
}
.section-content.is-list {
  /*
    ⚠️ 좁은 화면에서 머리·발이 **두 줄로 접힌다.** 감추지 않는다 —
       엑셀·등록·정지는 이 화면의 일이고, 행 수·페이지는 목록의 일이다.
       접히면 왼쪽 묶음이 한 줄, 오른쪽 묶음이 다음 줄에 선다.
  */
}
@media (max-width: 767px) {
  .section-content.is-list .list-head,
  .section-content.is-list .list-foot {
    flex-wrap: wrap;
    align-items: stretch;
    padding: 12px 14px;
  }
  .section-content.is-list .list-head-left,
  .section-content.is-list .list-head-right,
  .section-content.is-list .list-foot-left,
  .section-content.is-list .list-foot-right {
    flex: 1 1 100%;
    flex-wrap: wrap;
  }
  .section-content.is-list {
    /* 발의 페이지는 가운데로 — 좁은 줄에서 오른쪽에 붙으면 한쪽으로 쏠린다 */
  }
  .section-content.is-list .list-foot-right {
    justify-content: center;
  }
}

/* =====================================================
 * 표의 최소 폭 — **박지 않는다.** min-content 가 이미 그 일을 한다
 *
 * ⚠️ 예전 값 `min-width: 1300px` 은 **근거가 없었다.** min-content 를 재 보니
 *    진짜 필요한 폭은 407 ~ 725px 이었다 — 가장 큰 것이 1300 의 절반이다.
 *    그 탓에 표가 「반응형」이 아닌 노트북 폭에서도 굴러갔다:
 *      1690px 0 · 1600px 40 · 1512px 128 · 1440px 200 · 1366px 274 · 1280px 360
 *
 * ⚠️ **실측값을 박는 대신 0 으로 둔다.** 표는 min-content 보다 좁아질 수 없고,
 *    `.table-wrap` 이 이미 `overflow: auto` 다. 즉 브라우저가 화면마다 그 값을
 *    스스로 지킨다 — 아홉 화면에 아홉 개의 숫자를 적어 두고 열이 바뀔 때마다
 *    같이 고치는 일이 없어진다.
 *    ⚠️ 어느 화면이 특별히 더 필요하면 그 표에만 `style="--table-min: 000px"`
 *       을 적는다. **재고 나서** 적는다.
 * ===================================================== */
.table.is-list {
  min-width: var(--table-min, 0);
  /*
    ⚠️ **체크 칸의 클릭 영역이 25 × 0 이었다.** label 안이 `.blind` 하나뿐이라
       높이가 0 이다 — 보이는 상자(`label::before`)를 눌러도 먹기는 하지만
       실제 크기는 그 상자 20 × 20 이 전부다. 재서 나온 값이다.
  */
}
.table.is-list thead th .control.checkbox label,
.table.is-list tbody td .control.checkbox label {
  display: block;
  min-width: 20px;
  min-height: 20px;
}

/* =====================================================
 * 열 폭 — **`table-layout` 을 `auto` 로 되돌린다**
 *
 * ⚠️ **`_reset.scss` 가 모든 표에 `table-layout: fixed` 를 걸어 두었다.**
 *    이것이 표가 반응형으로 안 되던 **진짜 원인**이다 —
 *      · 고정 배치는 **열 폭을 내용이 아니라 `<col>` 이 정한다.** 그래서
 *        `min-width: 1300px` 과 `<colgroup>` 의 박힌 폭이 필요했다.
 *      · 칸을 `display: none` 으로 숨겨도 **`<col>` 이 자리를 그대로 잡는다.**
 *        390px 의 작업 이력에서 숨긴 셋의 180px 이 빈자리로 남았다.
 *      · 어느 칸에 `width` 를 주면 **나머지가 0 으로 밀린다.** 글자가 칸을
 *        넘쳐 서로 포개졌다 — 머리줄이 「일시분」으로 보였다.
 *
 * ⚠️ `_table.scss` 의 `max-width: 0` 주석은 「자동 배치 표에서」라고 적혀
 *    있었다. **그 전제가 깨져 있었다** — reset 이 fixed 로 덮고 있어서 그
 *    속성은 아무 일도 하지 않았다. 주석과 코드가 어긋난 채로 남아 있었다.
 *
 * ⚠️ 자동 배치의 대가 — **열 폭이 자료에 따라 바뀐다.** 실제 자료가 들어가면
 *    지금 견본과 폭이 달라진다. 그것을 받아들이는 것이 「좁아지면 접힌다」를
 *    얻는 조건이다. 고정 배치로는 접을 수가 없다.
 * ===================================================== */
.table.is-list {
  table-layout: auto;
}

/*
  문장 칸의 최대 폭 — 견본(A2)에서 쓴 값 420px 그대로.
  ⚠️ **`max-width: 0` 이면 자동 배치에서 칸이 자라지 않는다.** 남는 가로가
     옆 칸으로 몰려 문장이 90px 에서 잘렸다(1366px 에서 재서 확인).
  ⚠️ 그래도 **한계는 있어야 한다.** 없으면 긴 문장 한 줄이 열을 통째로 벌린다.
*/
/*
  ⚠️ **가리는 기준을 `tc-main` 으로 통일했다.** 처음에 `cell-title` 로 적었는데,
     그 클래스는 네 화면에만 있다 — 접속 이력(사유) · 권한 변경(사유) ·
     다운로드(사유)에는 없다. 그래서 그 세 화면에서는 이 규칙이 **한 번도
     걸리지 않았고**, 사유 칸이 제 글자 길이만큼 열을 벌려 1366px 에서부터
     굴러갔다(접속 이력 34px · 권한 변경 80px · 재서 확인).
  ⚠️ `cell-title` 은 `_table.scss` 에서 **PC 말줄임**을 맡는 다른 일이다.
     주인공을 가리는 일은 `tc-main` 이 한다.
*/
.table.is-list tbody td.tc-main {
  max-width: 420px;
}

/* =====================================================
 * 좁은 폭에서는 문장을 **자르지 않고 흘린다**
 *
 * ⚠️ 문장 칸은 안쪽 `<a>` 가 `white-space: nowrap` 이라, 그 칸의 최소폭이
 *    **문장 전체 길이**가 된다. `max-width: 420px` 이 그것을 420 에서 막아 주는데
 *    **420 아래로는 줄지 않는다.** 그래서 작업 이력이 900px 부터 굴러갔다 —
 *    900px 32 · 834px 98 · 768px 164 · 390px 210 (재서 나온 값).
 *
 * ⚠️ **말줄임 대신 두 줄을 고른다.** 휴대폰에서 「발행 예정을 09-08 …」로 자르면
 *    남는 것이 없다. 문장이 그 화면의 주인공인데 주인공만 안 보이는 셈이다.
 *    흘리면 줄이 높아지는 대신 문장을 다 읽는다.
 *
 * ⚠️ 흘리면 최소폭이 **가장 긴 낱말**로 떨어진다(45px 안팎). 그래서 문장 칸이
 *    남는 가로에 맞춰 자유롭게 줄어든다 — 굴림이 사라지는 까닭이 이것이다.
 *
 * ⚠️ **자리가 넉넉하면 그대로 한 줄이다.** 흘리게 두는 것은 「꺾어라」가 아니라
 *    「꺾어도 된다」는 뜻이라, 넓은 폭에서는 예전과 똑같이 한 줄로 선다.
 *    그래서 **1690 미만**에서 켠다. 처음에 1200 으로 잡았다가 올렸다 —
 *    발행 내역이 1280px 에서 31px · 발행 검수가 17px 넘쳤다. 420px 로 묶인
 *    문장 칸이 그 아래로 줄지 못해서다(재서 확인).
 *    `$bp-xl`(1690) 은 「지금 모습을 조금도 바꾸지 않는 자리」이고, 그 아래는
 *    자리가 넉넉하면 어차피 한 줄로 선다.
 * ===================================================== */
@media (max-width: 1689px) {
  .table.is-list tbody td.tc-main {
    max-width: none;
  }
  .table.is-list tbody td.tc-main > a,
  .table.is-list tbody td.tc-main > b,
  .table.is-list tbody td.tc-main > span {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    word-break: keep-all; /* 낱말 안에서 꺾지 않는다 — 한글은 띄어쓰기에서 꺾인다 */
  }
}
/*
  ⚠️ **사건 목록에서만** 문장 칸을 뺀 나머지를 한 줄로 둔다. 그대로 두면
     날짜가 「2026-\A 09-07\A 09:41:\A 02」 네 줄로 꺾인다(390px 에서 그랬다).
  ⚠️ **값 격자에는 걸지 않는다.** 처음에 둘 다 걸었는데, 권한 변경 이력은
     글자 열이 셋(변경 전 · 변경 후 · 사유)이라 그 셋의 최소폭이 문장 전체
     길이가 되어 1280px 에서부터 굴러갔다(80px · 재서 확인).
     값 격자에서는 긴 값이 꺾이는 쪽이 맞다.
*/
.table.is-list.is-event tbody td:not(.tc-main) {
  white-space: nowrap;
}

/*
  ⚠️ **나열인 칸은 꺾이게 둔다.** 위 규칙은 날짜가 네 줄로 꺾이는 것을 막으려는
     것인데, 「LinkedIn · Instagram · Facebook」 같은 **나열**에까지 걸면 그 칸의
     최소폭이 목록 전체 길이가 된다 — 게시물 작성이 600px 에서 57px 넘쳤다.
  ⚠️ 어느 열이 그런가는 **머리줄이 정한다**(`th.tc-wrap`). 칸 내용으로 가리면
     줄마다 달라진다 — 상태 열에서 이미 그렇게 걸려 넘어졌다.
  ⚠️ 위 규칙과 특정도가 같다((0,4,2)). **순서로 이긴다** — 반드시 뒤에 둔다.
*/
.table.is-list.is-event tbody td.tc-wrap {
  white-space: normal;
}

/* =====================================================
 * 좁아지면 열을 접는다 — 칸 셋
 *
 * 머리줄 `<th>` 에만 `tc-p1`~`tc-p3` 을 적는다. 그 표시를 그 열의 모든 `<td>`
 * 로 뿌리는 일은 assets/js/tableResponsive.js 가 한다.
 *
 *   tc-p4   900px 미만에서 사라진다   가장 먼저 (곁다리)
 *   tc-p3   768px 미만
 *   tc-p2   600px 미만
 *   tc-p1   480px 미만               마지막으로 접히는 것
 *   (표시없음)                       끝까지 남는다
 *
 * ⚠️ **900 칸을 지웠다가 되돌렸다.** 「min-width 를 바로잡으면 768 부터 접어도
 *    된다」고 적었는데, 계정 관리(9열)가 **834px 에서 5px · 768px 에서 13px**
 *    넘쳤다 — 재기 전에 칸을 지운 것이 틀렸다.
 *
 * ⚠️ **접힌 값은 상세 모달이 맡는다.** 줄 아래에 펼침 줄을 또 만들면 같은 말이
 *    두 자리에 있게 되고, 한쪽만 고쳐지는 날이 온다.
 *    → 상세 모달이 **없는** 화면(채널 관리)만 예외로 펼침 줄을 켠다.
 *
 * ⚠️ **JS 가 꺼지면 아무 열도 안 접힌다.** 표는 지금처럼 격자로 남아 좁은
 *    화면에서 굴러갈 뿐 깨지지 않는다 — 층이 하나 얹히는 것이다.
 * ===================================================== */
@media (max-width: 899px) {
  .table.is-collapsible .tc-p4 {
    display: none;
  }
}
@media (max-width: 767px) {
  .table.is-collapsible .tc-p3 {
    display: none;
  }
}
@media (max-width: 599px) {
  .table.is-collapsible .tc-p2 {
    display: none;
  }
}
@media (max-width: 479px) {
  .table.is-collapsible .tc-p1 {
    display: none;
  }
}

/* =====================================================
 * 줄 전체를 클릭 영역으로
 *
 * ⚠️ **이것이 접기의 전제다.** 예전에는 줄에서 클릭되는 곳이 글자 한 덩이뿐이고,
 *    그 칸이 화면마다 달랐다 — 작업 내용 · 사유 · 대상 화면 · 대상 · 아이디 · 내용.
 *    열을 접으면 **그 칸과 함께 클릭 영역이 사라진다**(접속 이력의 「사유」,
 *    계정 관리의 「아이디」에서 실제로 그랬다).
 *    줄 전체를 클릭 영역으로 두면 어느 열을 접어도 상관없어진다.
 *
 * ⚠️ 글자를 긁어 복사하는 것은 그대로 된다 — 끌어서 고른 뒤 떼는 것은
 *    클릭으로 세지 않는다(assets/js/tableRowLink.js 가 가린다).
 * ===================================================== */
.table tbody tr[data-row-target] {
  cursor: pointer;
  /* 누르는 순간 줄이 내려앉는다 — 눌린 것이 이 줄이라는 것을 보여준다 */
}
.table tbody tr[data-row-target]:active > td {
  background-color: var(--gray-300);
}

/* =====================================================
 * 좁은 화면의 표 — 여백과 손가락 크기
 *
 * ⚠️ **칸 여백을 15px 에서 8px 로 줄인다.** 열 여섯 개면 좌우 여백만 180px 인데,
 *    390px 화면에서 그것은 본문의 절반이다. 줄여서 84px 를 되찾는다.
 * ⚠️ **체크박스는 44 × 44 를 확보한다.** 지금 클릭 영역이 label 뿐이라
 *    25 × 24 다 — 손가락으로는 자주 빗나간다. 상자(20px)는 가운데 둔다:
 *    12 + 20 + 12 = 44.
 * ===================================================== */
@media (max-width: 767px) {
  .table.is-list thead th,
  .table.is-list tbody td {
    padding: 12px 8px;
  }
  .table.is-list {
    /* 체크 칸은 제 자리만 갖는다 — 줄 클릭과 부딪히지 않게 넓게 잡는다 */
  }
  .table.is-list thead th .control.checkbox,
  .table.is-list tbody td .control.checkbox {
    justify-content: center;
    min-height: 44px;
    /*
      ⚠️ `width` 만으로는 **눌린다.** `.control` 이 flex 라서 칸이 좁아지면
         label 이 44px 아래로 줄어든다 — 390px 에서 24 × 44 로 재였다.
         `flex: 0 0 44px` 으로 줄지 않게 묶는다.
    */
  }
  .table.is-list thead th .control.checkbox label,
  .table.is-list tbody td .control.checkbox label {
    display: block;
    flex: 0 0 44px;
    width: 44px;
    min-width: 44px;
    height: 44px;
    padding-left: 0;
  }
  .table.is-list thead th .control.checkbox label::before, .table.is-list thead th .control.checkbox label::after,
  .table.is-list tbody td .control.checkbox label::before,
  .table.is-list tbody td .control.checkbox label::after {
    left: 12px;
  }
}
/* =====================================================
 * 펼침 줄 — **상세 모달이 없는 화면만** 켠다
 *
 * `<table data-collapse-row>` 를 적은 표에서만 tableResponsive.js 가 만든다.
 * 지금 대상은 채널 관리 하나다 — 4열이지만 상세 모달이 없어서(연동 해제 확인
 * 모달뿐) 접으면 값을 볼 곳이 아예 없다.
 * ===================================================== */
.table .tr-collapse > td {
  padding: 0 14px 12px;
  background: var(--gray-200);
}

.tc-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px 16px;
  margin: 0;
  padding: 12px 0 0;
}
.tc-list > div {
  display: flex;
  gap: 8px;
  align-items: baseline;
}
.tc-list dt {
  flex: 0 0 auto;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  color: var(--text-muted);
}
.tc-list dd {
  margin: 0;
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
  color: var(--color-darken);
  word-break: break-all;
}

/* 펼치기 단추 — 줄의 첫 칸에 붙는다 */
.tc-toggle {
  width: 24px;
  height: 24px;
  border: 1px solid var(--gray-600);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  position: relative;
  vertical-align: middle;
  margin-right: 6px;
  /*
    ⚠️ 아이콘 파일을 쓰지 않고 currentColor 로 그린다. `filter` 는 CSS 변수를
       읽지 못해서, 이 제품에서 서랍 닫기 ✕ 가 흰 바탕에 흰색이 된 적이 있다.
  */
}
.tc-toggle::before, .tc-toggle::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
}
.tc-toggle::before {
  width: 10px;
  height: 2px;
}
.tc-toggle::after {
  width: 2px;
  height: 10px;
  transition: opacity 0.15s;
}
tr.is-open .tc-toggle::after {
  opacity: 0;
}

/* =====================================================
 * 600px 미만 — **열을 감추지 않고 줄을 세로로 쌓는다**
 *
 * ⚠️ 왜 바꿨나. 375px 에서 재 보니 **「일시」 하나가 줄의 절반을 먹는데도
 *    감춘 열이 셋**이었다. 좁아질수록 값을 더 많이 감추는데, 이 제품의 열은
 *    곁다리가 아니라 **전부 쓰이는 값**이다 — 감추는 쪽으로 계속 가면
 *    휴대폰에서는 목록이 세 칸짜리 껍데기가 된다.
 *
 * ⚠️ **세로로 쌓으면 가로 한계가 없어진다.** 그래서 이 폭에서는 아홉 열이든
 *    여섯 열이든 **하나도 감추지 않는다.** tc-p1~p4 는 여기서 「감추는 순서」가
 *    아니라 「머리 줄에 설 것과 아래에 깔릴 것」을 가르는 표시가 된다.
 *
 *      900 미만   tc-p4 감춤
 *      768 미만   tc-p3 감춤
 *      600 미만   감추지 않는다 · 세로로 쌓는다   ← 여기
 *
 * ⚠️ 특정도를 맞춰야 한다. 감추는 규칙이 `.table.is-collapsible .tc-p3`(0,3,0)
 *    이므로, 되살리는 쪽은 그보다 세야 한다 — `.table.is-list.is-event tbody td`
 *    는 (0,3,2) 라 이긴다. **미디어 쿼리는 특정도를 더해 주지 않는다.**
 *
 * ⚠️ `<table>` 을 버리지 않는다. `display` 만 바꾸므로 머리줄·`scope`·`caption`
 *    이 그대로 남는다 — Tabulator 를 쓰지 않기로 한 까닭이 이것이었다.
 * ===================================================== */
@media (max-width: 599px) {
  /* ---------- 두 종류가 함께 쓰는 것 ---------- */
  .table.is-list.is-event,
  .table.is-list.is-grid {
    /* ⚠️ 머리줄은 `_table.scss` 에서 **지우지 않고 감춘다**(낭독기에 남긴다) */
  }
  .table.is-list.is-event tbody,
  .table.is-list.is-grid tbody {
    display: block;
  }
  .table.is-list.is-event tbody tr,
  .table.is-list.is-grid tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 12px;
    padding: 14px;
    border-bottom: 1px solid var(--gray-500);
  }
  .table.is-list.is-event tbody tr:last-child,
  .table.is-list.is-grid tbody tr:last-child {
    border-bottom: 0;
  }
  .table.is-list.is-event,
  .table.is-list.is-grid {
    /* 칸은 더 이상 격자가 아니다 */
  }
  .table.is-list.is-event tbody td,
  .table.is-list.is-grid tbody td {
    display: block;
    width: auto;
    max-width: none;
    padding: 0;
    border: 0;
    text-align: left;
    white-space: normal;
    vertical-align: baseline;
  }
  .table.is-list.is-event,
  .table.is-list.is-grid {
    /*
      자리 사다리 — **「체크 · 번호 · 클릭하는 것」이 앞, 나머지가 뒤.**

      ⚠️ **마크업 순서를 바꿔도 쌓는 화면은 안 바뀐다.** 여기서 `order` 로 자리를
         따로 정하기 때문이다 — PC 만 고쳐 놓고 「모바일은 안 변했다」는 지적을
         받았다. 순서를 바꿀 때는 **두 곳을 함께** 봐야 한다.

        -4  체크      tc-check
        -3  번호      tc-num
        -2  클릭하는 것  tc-main
        -1  상태      tc-state   (그리고 줄을 끊는 tr::after)
         0  나머지     마크업 순서 그대로
    */
  }
  .table.is-list.is-event tbody td.tc-check,
  .table.is-list.is-grid tbody td.tc-check {
    order: -4;
    flex: 0 0 auto;
  }
  .table.is-list.is-event tbody td.tc-check .control.checkbox,
  .table.is-list.is-grid tbody td.tc-check .control.checkbox {
    min-height: 44px;
  }
  .table.is-list.is-event,
  .table.is-list.is-grid {
    /* 번호 — 체크 다음. 숫자 폭을 맞춰 줄마다 자리가 흔들리지 않게 한다 */
  }
  .table.is-list.is-event tbody td.tc-num,
  .table.is-list.is-grid tbody td.tc-num {
    order: -3;
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
  }
  .table.is-list.is-event tbody td.tc-num::before,
  .table.is-list.is-grid tbody td.tc-num::before {
    content: none;
  }
  .table.is-list.is-event tbody td.tc-num,
  .table.is-list.is-grid tbody td.tc-num { /* 번호에는 이름표를 붙이지 않는다 */ }
  .table.is-list.is-event,
  .table.is-list.is-grid {
    /*
      머리 줄과 그 아래 묶음 사이를 끊는 **빈 칸.**

      ⚠️ **flex 에는 「여기서 줄을 바꿔라」가 없다.** 폭을 100% 차지하는 빈 항목을
         끼워 넣는 것이 유일한 길이고, `tr` 의 `::after` 가 그 항목이 된다
         (flex 그릇의 가상 요소는 flex 항목이 된다).

      ⚠️ 먼저 **배지를 늘려** 머리 줄을 채우려 했는데 안 됐다. flex 는 **어느
         항목을 이 줄에 놓을지 먼저 정하고, 그다음에** 남은 자리를 나눠 준다 —
         다음 칸은 제 기본 폭이 들어가니 이미 그 줄에 올라탄 뒤였다
         (599px 에서 「관리자 번호」가 끼어들었다 · 재서 확인).

      ⚠️ `order: -1` 이라 배지와 같은 칸인데, 같은 `order` 안에서는 `::after` 가
         맨 뒤다. 그래서 머리 줄 다음, 아래 묶음(`order: 0`) 앞에 선다.

      ⚠️ **두 종류가 함께 쓴다.** 사건 목록에서도 필요했다 — 체크가 `order: -4`,
         문장이 `-2` 인데 문장에 `flex-basis: 100%` 를 주면 **체크가 문장 위
         한 줄을 혼자 차지한다**(발행 검수 375px 에서 그랬다). 문장을 늘어나는
         칸으로 두고 이 빈 칸으로 끊으면 체크와 문장이 한 줄에 선다.
    */
  }
  .table.is-list.is-event tbody tr::after,
  .table.is-list.is-grid tbody tr::after {
    content: "";
    order: -1;
    flex: 0 0 100%;
    height: 0;
  }
  /* =====================================================
   * 사건 목록 — 문장 위, 꼬리표 아래
   *
   *   발행 예정을 09-08 09:00 에서 09-09 14:00 으로 바꿈
   *   2026-09-07 09:41:02 · 김운영 (A0010) · [수정] · 게시물 작성 · 기관1
   *
   * ⚠️ 꼬리표에는 **이름표를 붙이지 않는다.** 날짜는 날짜로, 이름은 이름으로,
   *    배지는 배지로 읽힌다 — 「일시:」를 붙이면 말이 값보다 길어진다.
   *    이름표가 필요한 것은 값 격자 쪽이다.
   * ===================================================== */
  .table.is-list.is-event {
    /*
      ⚠️ **주인공 칸은 `tc-main` 으로 가린다.** 처음에 `cell-title` 로 가렸는데,
         그 클래스는 **PC 에서 말줄임을 걸는 다른 일**을 한다. 접속 이력의
         「사유」 칸에는 배지와 둘째 줄이 함께 들어 있어 말줄임을 걸 수 없다 —
         그래서 그 화면에는 `cell-title` 이 없고, 주인공은 있다.
         머리줄에 `tc-main` 을 적고 JS 가 칸으로 뿌린다.
    */
  }
  .table.is-list.is-event tbody td.tc-main {
    order: -2;
    /*
      남는 가로를 다 먹는다 — 줄을 끊는 일은 위의 `tr::after` 가 맡는다.
      ⚠️ **기본 폭이 `0` 이어야 한다.** `auto` 로 두면 그 값이 **내용 크기**라,
         문장이 길어 체크 옆에 못 들어가고 다음 줄로 꺾인다 — 체크가 한 줄을
         혼자 차지했다(발행 검수 375px 에서 두 번 겪었다).
         `0` 으로 두면 체크 옆에 들어간 뒤 남는 가로만큼 늘어난다.
    */
    flex: 1 1 0;
    /*
      ⚠️ **`min-width: 0` 이 없으면 줄지 않는다.** flex 항목의 기본값은
         `min-width: auto`(= 내용의 최소폭)라, 배지가 여럿 든 칸은 그 최소폭이
         커서 100% 를 넘어 버린다 — 접속 이력의 「사유」가 375px 에서 431px 을
         잡고 99px 넘쳤다(재서 확인).
         이 제품에서 `1fr`·`flex-basis` 로 같은 것을 세 번 밟았다.
    */
    min-width: 0;
    /*
      ⚠️ **문장을 16px 로 올린다.** 값 격자의 머리 줄(이름 · 아이디)이 16px 인데
         사건 목록의 문장은 14px 이었다 — 둘 다 그 줄의 주인공이라 크기가
         같아야 한다. 표 글자 14px 은 **격자를 훑을 때**의 눈금이고, 세로로
         쌓으면 훑을 격자가 없다.
      ⚠️ 꼬리표(일시 · 관리자 · 대상 화면 · 기관)는 그대로 14px 이다.
         주인공만 올린다 — 다 올리면 위계가 없어진다.
    */
  }
  .table.is-list.is-event tbody td.tc-main > a,
  .table.is-list.is-event tbody td.tc-main > b,
  .table.is-list.is-event tbody td.tc-main > span {
    font-size: 16px;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    word-break: keep-all;
  }
  .table.is-list.is-event {
    /*
      꼬리표 — 한 눈금 작고 흐리게.
      ⚠️ **배지를 꼬리표 맨 앞에 세운다.** 「무슨 일이 있었나」가 그 줄에서
         가장 먼저 읽혀야 하고, 배지는 폭이 좁고 눈에 띄어 줄머리에 알맞다.
    */
  }
  .table.is-list.is-event tbody td.tc-state {
    order: -1;
    flex: 0 0 auto;
  }
  .table.is-list.is-event tbody td:not(.tc-main):not(.tc-check) {
    font-family: "Pretendard", sans-serif;
    font-weight: 400;
    font-size: 14px;
    color: var(--text-muted);
    flex: 0 0 auto;
  }
  .table.is-list.is-event {
    /* 일시는 그 줄의 기준점이라 조금 진하게, 숫자 폭을 맞춘다 */
  }
  .table.is-list.is-event tbody td:not(.tc-main):not(.tc-check):first-child {
    color: var(--color-darken);
    font-variant-numeric: tabular-nums;
  }
  .table.is-list.is-event {
    /*
      ⚠️ **가운뎃점으로 잇지 않는다.** `·` 를 `::before` 로 붙여 봤는데,
         꼬리표가 두 줄로 꺾이면 **둘째 줄이 점으로 시작한다** — 값 없는
         점 하나가 줄머리에 떠 있게 된다(375px 에서 그랬다).
         `::after` 로 바꿔도 마지막 칸을 visual 순서로 골라낼 수가 없다.
         사이(12px)와 배지의 무게로 가르는 것이 조용하고 깨질 데가 없다.
    */
  }
  /* =====================================================
   * 값 격자 — 머리 줄 하나, 그 아래 「이름표 : 값」
   *
   *   ☐  김관리  kimadmin              [사용]
   *      관리자 번호  A0010      권한 그룹  최고 관리자
   *      마지막 접속  2026-09-01  기관      기관1
   *      등록일      2025-04-22
   *
   * ⚠️ **표시가 없는 열이 머리 줄에 선다**(이름 · 아이디 · 상태 · 체크).
   *    끝까지 남기기로 정한 열이 그것이라, 따로 정할 것이 없다.
   * ⚠️ **이름표가 반드시 필요하다.** 「2025-04-22」만 있으면 등록일인지
   *    마지막 접속인지 알 수 없다. 사건 목록과 갈리는 지점이다.
   * ===================================================== */
  .table.is-list.is-grid {
    /*
      머리 줄에 서는 것 — **주인공 · 배지 · 체크 셋뿐**이다.
      ⚠️ 처음에는 「이름표가 없는 열」을 머리 줄로 삼았는데, 그러면 이름표를
         얻으려고 그 열을 접어야 했다(JS 쪽 주석 참고). 이제 이름표는 모든
         열에 붙고, 머리 줄은 `tc-main` 이 정한다.
    */
  }
  .table.is-list.is-grid tbody td.tc-main {
    order: -2;
    flex: 0 1 auto;
    min-width: 0;
    font-family: "Pretendard", sans-serif;
    font-weight: 600;
    font-size: 16px;
    color: var(--color-darken);
    /* 이름이 길면 줄여서 넣는다 — 배지 자리를 뺏지 않는다 */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .table.is-list.is-grid tbody td.tc-main::before {
    content: none;
  }
  .table.is-list.is-grid tbody td.tc-main { /* 주인공에는 이름표를 붙이지 않는다 */ }
  .table.is-list.is-grid {
    /*
      상태 배지는 머리 줄 오른쪽 끝으로.
      ⚠️ **어느 열이 상태인가는 머리줄이 정한다**(`th.tc-state`). 칸에 배지가
         들어 있는지로 가리면 **줄마다 달라진다** — 게시물 작성의 채널 칸이
         채널 하나인 줄만 상태로 잡혀 그 줄만 머리 줄로 올라갔다.
    */
  }
  .table.is-list.is-grid tbody td.tc-state {
    order: -1;
    flex: 0 0 auto;
    margin-left: auto;
  }
  .table.is-list.is-grid {
    /* 아래에 깔리는 칸 — 두 벌씩 나란히 */
  }
  .table.is-list.is-grid tbody td[data-label]:not(.tc-main):not(.tc-state):not(.tc-num) {
    order: 0;
    flex: 1 1 calc(50% - 10px);
    min-width: 0;
    font-family: "Pretendard", sans-serif;
    font-weight: 400;
    font-size: 14px;
    color: var(--color-darken);
  }
  .table.is-list.is-grid tbody td[data-label]:not(.tc-main):not(.tc-state):not(.tc-num)::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 2px;
    /* ⚠️ 가장 작은 눈금이 body-5-2 다 — body-6-* 는 없다 */
    font-family: "Pretendard", sans-serif;
    font-weight: 400;
    font-size: 14px;
    font-size: 12px;
    color: var(--text-muted);
  }
}
/* =====================================================
 * 768px 이하 — 클릭하는 문장을 **두 줄에서 자른다** (2026-09-11)
 *
 * 그 아래에서는 문장을 자르지 않고 흘려 두었는데, 긴 글이 들어오면 줄이
 * 네 줄 · 다섯 줄까지 자란다. 목록에서 하는 일은 **여러 줄을 훑어 견주는 것**
 * 이라, 한 줄이 화면의 절반을 먹으면 목록이 목록이 아니게 된다.
 * 잘린 뒤는 줄을 눌러 모달에서 다 읽는다.
 *
 * ⚠️ **여기만 「768 이하」(포함)다.** 이 제품의 다른 눈금은 `under()` 를 써서
 *    767 부터인데, 이 규칙은 768 도 포함해 달라는 요청이라 직접 적는다.
 *
 * ⚠️ **`cell-title` 이 붙은 네 화면에만 건다** — 작업 이력 · 발행 내역 ·
 *    발행 검수 · 게시물 작성. 거기만 문장이 길다.
 *    접속 이력 · 다운로드 · 권한 변경의 주인공은 「잠긴 계정」·「발행 내역」
 *    같은 **짧은 말**이고, 그 칸에는 배지와 둘째 줄이 형제로 들어 있어
 *    `-webkit-box` 로 바꾸면 배지가 아래로 떨어진다.
 *
 * ⚠️ `-webkit-line-clamp` 를 쓴다. 이 제품에 「쓰지 않는다」고 적어 둔 적이
 *    있는데 그것은 **한 줄**을 자를 때의 이야기였다(세로 가운데 정렬이
 *    어긋난다). 두 줄에는 다른 방법이 없고, 쌓인 줄에서는 가운데 정렬을
 *    쓰지 않는다.
 * ===================================================== */
@media (max-width: 768px) {
  .table.is-list tbody td.tc-main.cell-title > a,
  .table.is-list tbody td.tc-main.cell-title > b,
  .table.is-list tbody td.tc-main.cell-title > span {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: normal;
  }
}
/*
  검색 상자 — **내려 둔다**(2026-09-10 층 정리).

  ⚠️ 이 상자는 **도구**다. 목록 화면에서 주인공은 표이고(높이의 82% —
     표 850px 대 나머지 셋 181px), 도구는 그 표를 좁히는 데 쓰는 것이다.
     둘이 같은 높이로 떠 있으면 **어느 것을 먼저 봐야 하는지 화면이 말하지
     않는다.** `--elev-0` 으로 내리고 경계는 테두리가 말한다.
  ⚠️ **배경은 흰색 그대로다.** 회색으로 내리면 「비활성」으로 읽힌다 —
     내리는 것은 높이지 상태가 아니다.
*/
.section-header {
  border-radius: var(--radius-md);
  background-color: var(--color-white);
  padding: 24px;
  border: 1px solid var(--surface-line);
  box-shadow: var(--elev-0);
}
.section-header .box-wrap {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}
.section-header .box-wrap + .box-wrap {
  margin-top: 12px;
}
.section-header .box-wrap.col1 {
  grid-template-columns: repeat(1, 1fr);
}
.section-header .box-wrap.col2 {
  grid-template-columns: repeat(2, 1fr);
}
.section-header .box-wrap.col3 {
  grid-template-columns: repeat(3, 1fr);
}
.section-header .box-wrap.col4 {
  grid-template-columns: repeat(4, 1fr);
}
.section-header .box-wrap .box {
  width: 100%;
  min-width: 0;
}
.section-header .box-wrap .box .flex * {
  min-width: 0;
}
.section-header .box-wrap .box.col1 {
  grid-column: span 1;
}
.section-header .box-wrap .box { /* 2칸 차지 */ }
.section-header .box-wrap .box.col2 {
  grid-column: span 2;
}
.section-header .box-wrap .box { /* 2칸 차지 */ }
.section-header .box-wrap .box.col3 {
  grid-column: span 3;
}
.section-header .box-wrap .box { /* 3칸 차지 */ }
.section-header .box-wrap .box.col4 {
  grid-column: span 4;
}
.section-header .box-wrap .box { /* 전체 차지 */ }
.section-header .btn-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 24px;
  gap: 12px;
}
.section-header .btn-wrap .btn {
  min-width: 200px;
}

.section-content {
  /* ⚠️ 24px 이었다(2026-09-23 대표님). 참고 상자와 본문 사이가 너무 벌어져
        화면이 성기게 읽혔다. 제품 전체의 기본 간격을 12px 로 맞춘다. */
  margin-top: 12px;
  background-color: var(--color-white);
  border-radius: var(--radius-md);
  padding: 24px;
  box-shadow: var(--elev-1);
}
.section-content .btn-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}
.section-content .btn-wrap .btn {
  flex-shrink: 0;
}

.text-wrap .box {
  /*
    ⚠️ **테두리와 그림자를 함께 두지 않는다.** 둘 다 「별개의 물건」이라고
       말하는 수단이라, 겹치면 한 번 말할 것을 두 번 말한 셈이 된다.
       이 상자는 카드 안에 놓이는 것이므로 테두리 쪽을 남긴다.
  */
  border: 1px solid var(--surface-line);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-0);
  padding: 24px;
}
.text-wrap .box + .box {
  margin-top: 24px;
}
.text-wrap .box .title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 24px;
}

/* =====================================================
 * 좁은 화면 (2026-09-10 반응형)
 *
 * ⚠️ **단추 줄은 접는다.** 「저장 · 취소」 둘이면 390px 에서도 서지만,
 *    「승인 · 수정 요청 · 반려」 셋이 되면 넘친다. 화면마다 몇 개인지 세지
 *    않고, 넘치면 접히게 둔다.
 * ⚠️ `.btn { min-width: 200px }` 이 걸려 있다. 390px 에서 200px 짜리 둘이면
 *    한 줄에 하나씩 서는데, 그 줄이 가운데 정렬이라 **어긋나 보인다.**
 *    좁은 화면에서는 폭을 다 쓰게 한다 — 세로로 쌓인 단추는 폭이 같아야
 *    한 묶음으로 읽힌다.
 * ===================================================== */
@media (max-width: 767px) {
  .section .btn-wrap {
    flex-wrap: wrap;
  }
  .section .btn-wrap .btn {
    flex: 1 1 100%;
    min-width: 0;
  }
  .section-content {
    padding: 16px;
    /*
      ⚠️ **카드 안의 단추는 늘리지 않는다.** 위 `.section .btn-wrap`(화면 바닥의
         저장·취소)은 세로로 쌓이는 **짝**이라 폭이 같아야 한 묶음으로 읽힌다.
         여기는 목록을 다루는 **도구 줄**이라 성격이 다르다.
      ⚠️ `flex: 1 1 auto` 로 두었더니 마지막 단추가 혼자 남는 줄에서 **319px
         짜리 띠**가 됐다(375px 게시물 작성의 「게시물 추가」 · 재서 확인).
         손가락 크기는 높이 44px 가 맡는다 — 폭까지 늘릴 이유가 없다.
    */
  }
  .section-content .btn-wrap {
    flex-wrap: wrap;
  }
  .section-content .btn-wrap .btn {
    flex: 0 0 auto;
  }
}
/* ================================================= */
/* 1. 폰트 가중치 Map 및 기본 변수 정의 (핵심 유틸리티) */
/* ================================================= */
/* ============================================== */
/* 2. 타이포그래피 스타일 Map 정의 (디자인 시스템) */
/* ============================================== */
/* ================================================= */
/* 2-1. 반응형 size Map (PC 대비 size만 오버라이드) */
/* ================================================= */
/* ============================================= */
/* 3. 공용 유틸: 레벨별 size 조회 (브레이크포인트) */
/* ============================================= */
/* ============================================= */
/* 4. 범용 믹스인: @include body-1-1 형태로 사용 */
/* - 핵심: selector 컨텍스트(&)로 미디어를 함께 출력 */
/* ============================================= */
/* ============================================= */
/* 5. 레벨별 믹스인: 최종 사용 형태 유지 */
/* ============================================= */
/* ========================================== */
/* 6. 클래스 자동 생성(선택): 기존 형태 유지 */
/* ========================================== */
.display-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 72px;
}

.title-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 48px;
}

.title-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 40px;
}

.title-3 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 32px;
}

.title-4 {
  font-family: "Pretendard", sans-serif;
  font-weight: 700;
  font-size: 24px;
}

.body-1-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 24px;
}

.body-1-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 24px;
}

.body-2-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 20px;
}

.body-2-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 20px;
}

.body-3-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 18px;
}

.body-3-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 18px;
}

.body-4-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 16px;
}

.body-4-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 16px;
}

.body-5-1 {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 14px;
}

.body-5-2 {
  font-family: "Pretendard", sans-serif;
  font-weight: 400;
  font-size: 14px;
}

/* =====================================================
 * pageHeader — 컴팩트 페이지 헤더 (전 목록 화면 공용)
 *
 * 구조
 *   .page-extras      카드 밖 상단 — 요약 타일 · 화면 설명
 *   .section-header.is-filter   흰 카드 — 검색 한 줄 + 접이 필터
 *   (브레드크럼 · 제목 · 기관 탭은 헤더로 갔다 — _header.scss)
 *     .filter-bar     늘 보이는 한 줄 (검색어 · 검색 · 상세 필터 토글)
 *     .filter-panel   접힘/펼침 상세 필터 (data-filter-panel)
 *       .filter-grid > .fld   항목마다 박스(칩)로 구분
 *
 * ⚠️ 검색을 .section-header 안에 둔다 — box-wrap 격자가 이 스코프에만 있어서다.
 *    (기존 목록 화면과 같은 규칙)
 * ⚠️ 접기/펼치기는 assets/js/filterToggle.js 가 data-filter-toggle 로 위임 처리.
 * ===================================================== */
/* ---------- .page-head 는 여기 없다 ----------
   브레드크럼·제목·기관 탭은 **헤더**로 옮겼다(components/header.jsp).
   각 화면이 값만 넘기고 그리기는 헤더가 한 번만 한다.
   → 모양은 assets/scss/components/_header.scss 의 #header .page-head
   ------------------------------------------------------------ */
/* ---------- 본문 맨 위, 검색 카드 위 ----------
   요약 타일·「무엇을 보는 화면인지」 설명이 서는 자리.
   ⚠️ 예전에는 이것들이 검색 카드(.section-header) 안에 들어 있었다. 카드는 이제
      검색만 담으므로 밖으로 나왔고, 아래 카드와 세로선을 맞추려고 좌우 4px 를 준다. */
.page-extras {
  margin: 0 4px 16px;
}

/* ---------- 흰 카드: 검색만 담는다 ---------- */
.section-header.is-filter {
  padding: 0;
  overflow: hidden;
  /* 늘 보이는 한 줄 */
}
.section-header.is-filter .filter-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 16px 24px;
}
.section-header.is-filter .filter-bar .search-field {
  position: relative;
  /*
    ⚠️ flex: 1 1 0 이라 남는 가로를 전부 먹었다. 1920 짜리 화면에서는 검색어
       한 줄을 받는 칸이 1,400px 을 넘는다. 그 칸에 실제로 들어가는 것은
       「제목 · 내용으로 검색」 정도의 낱말 몇 개다.
       칸이 넓으면 넓은 만큼 채워야 할 것처럼 보이고, 옆의 [검색]·[상세 필터]
       단추는 화면 끝으로 밀려 눈이 왼쪽 끝과 오른쪽 끝을 오간다.
    ⚠️ 고정 폭(width)이 아니라 basis 다. 좁은 화면에서는 줄어들어야 한다.
  */
  flex: 0 1 420px;
  min-width: 0;
}
.section-header.is-filter .filter-bar .search-field .icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  opacity: 0.5;
  pointer-events: none;
}
.section-header.is-filter .filter-bar .search-field .text-field {
  padding-left: 38px;
  width: 100%;
}
.section-header.is-filter .filter-bar .btn {
  flex: 0 0 auto;
}
.section-header.is-filter .filter-bar {
  /* 검색어 칸이 없는 화면에서 단추를 오른쪽 끝으로 미는 빈 칸 */
}
.section-header.is-filter .filter-bar .filter-spacer {
  flex: 1 1 auto;
}
.section-header.is-filter .filter-bar {
  /* 축이 되는 조건(늘 보임). 담기는 이름이 길어 검색칸보다 먼저·넓게 잡는다 */
}
.section-header.is-filter .filter-bar .fld {
  flex: 0 0 auto;
  padding: 6px 12px;
}
.section-header.is-filter .filter-bar .fld .dropdown {
  min-width: 260px;
}
.section-header.is-filter {
  /* 상세 필터 토글 단추 */
}
.section-header.is-filter .filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.section-header.is-filter .filter-toggle .caret {
  display: inline-block;
  transition: transform 0.2s ease;
  font-size: 11px;
  line-height: 1;
}
.section-header.is-filter .filter-toggle[aria-expanded=true] .caret {
  transform: rotate(180deg);
}
.section-header.is-filter {
  /* 접이 상세 필터 */
}
.section-header.is-filter .filter-panel {
  padding: 16px 24px 18px;
  border-top: 1px dashed var(--gray-300);
  background: var(--gray-200);
}
.section-header.is-filter .filter-panel[hidden] {
  display: none;
}
.section-header.is-filter {
  /* 항목을 박스(칩)로 감싸 또렷하게 구분
     ⚠️ .fld 는 .filter-grid 밖에도 쓴다 — 화면의 축이 되는 조건(예: 수강 관리의
        「교육」)은 접히면 안 되므로 .filter-bar 에 그대로 놓는다. 그래서 여기서
        스코프를 한 단 올려 둔다. */
}
.section-header.is-filter .fld {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: var(--color-white);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  /*
    ⚠️ 공통 .field-title 은 18px 이다(body-3-1). 옆의 드롭다운·입력칸을
       14px 로 내리고 나니 **이름이 값보다 커졌다** — 「발행 채널」이
       「전체」보다 크고 굵어, 눈이 이름부터 읽고 값을 나중에 찾는다.
       칩 안에서는 값이 주인공이므로 이름을 값과 같은 눈금으로 내린다.
       굵기(600)와 회색은 그대로 둬서 이름과 값은 여전히 갈린다.
    ⚠️ 공통 .field-title 은 건드리지 않는다 — 폼(모달·설정)에서는 이름이
       한 줄을 통째로 이끌기 때문에 18px 이 맞다.
  */
}
.section-header.is-filter .fld .field-title {
  font-family: "Pretendard", sans-serif;
  font-weight: 600;
  font-size: 14px;
  margin: 0;
  white-space: nowrap;
  color: var(--gray-900);
}
.section-header.is-filter .fld .dropdown {
  min-width: 140px;
}
.section-header.is-filter .fld .text-field {
  width: 150px;
}
.section-header.is-filter .fld {
  /* ⚠️ 데이트피커는 위 150px 에서 뺀다.
     .datepicker 는 오른쪽 44px 을 달력 단추 자리로 비워 두므로 150px 이면
     글자 칸이 왼 패딩 10px 을 빼고 94px 밖에 안 남는다. 14px 로 내린 지금
     「YYYY-MM-DD」는 88px 쯤이라 아슬아슬하게 들어가지만, 폰트가 대체
     글꼴로 떨어지면 다시 넘친다 — 여유를 남긴다. */
}
.section-header.is-filter .fld .text-field.datepicker {
  width: 172px;
}
.section-header.is-filter .filter-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: stretch;
}
.section-header.is-filter .filter-foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}

/* =====================================================
 * 좁은 화면 (2026-09-10 반응형)
 * ===================================================== */
@media (max-width: 767px) {
  .section-header.is-filter .filter-bar {
    flex-wrap: wrap;
    padding: 14px 16px;
    /*
      ⚠️ 검색칸을 **한 줄 통째로** 준다. 단추와 나란히 두면 390px 에서 칸이
         196px 이라 「관리자명 또는 …」이 「관리자명 또」에서 끊긴다 —
         무엇으로 찾는 칸인지 읽히지 않는다.
    */
  }
  .section-header.is-filter .filter-bar .search-field {
    flex: 1 1 100%;
  }
  .section-header.is-filter .filter-bar {
    /* 조건 드롭다운도 한 줄. min-width 260px 은 좁은 화면에서 넘친다 */
  }
  .section-header.is-filter .filter-bar .fld {
    flex: 1 1 100%;
    padding: 0;
  }
  .section-header.is-filter .filter-bar .fld .dropdown {
    min-width: 0;
    width: 100%;
  }
  .section-header.is-filter .filter-bar {
    /* 남는 자리를 만드는 빈 칸은 접힌 줄에서 뜻이 없다 */
  }
  .section-header.is-filter .filter-bar .filter-spacer {
    display: none;
  }
  .section-header.is-filter .filter-bar .btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}
/* =====================================================
 * 요약 타일 — 화면 맨 위에서 「지금 상태」를 숫자 몇 개로 말한다
 *
 * 쓰는 곳
 * ------------------------------------------------------------------
 *   page/accessibility/accessibility.jsp   점검 통과율 · 설명 없는 이미지 …
 *   page/translate/translate.jsp           영문 발행률 · 검수 대기 …
 *
 * ⚠️ 처음에는 접근성 화면 전용(.a11y-tile)으로 만들었는데 번역 목록에서도
 *    같은 물건이 필요했다. 이름에 화면 이름이 박혀 있으면 두 번째 화면에서
 *    쓸 때마다 「여기가 접근성 화면인가?」 하게 된다. 그래서 공용으로 옮겼다.
 *
 * ⚠️ 숫자는 마크업에 박지 말 것. 아래 표를 세어서 채운다
 *    (assets/js/a11yCheck.js · translate.js). 화면에 두 번 적힌 같은 값은
 *    반드시 언젠가 서로 달라진다.
 * ===================================================== */
.sum-tiles {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.sum-tile {
  flex: 1 1 180px;
  min-width: 0;
  padding: 20px;
  border: 1px solid var(--gray-500);
  border-radius: var(--radius-md);
  background-color: var(--color-white);
  /*
    대표 수치 — 하나만 앞세운다.
    ⚠️ 면을 채우지 않는다. 이 CMS 에서 짙은 면은 LNB·헤더(껍데기)의 몫이라,
       본문 한가운데 색 덩어리가 서면 자리를 잘못 찾은 머리말처럼 보인다.
       테두리와 숫자 색으로만 앞세운다.
  */
}
.sum-tile.is-lead {
  border-color: var(--color-primary);
}
.sum-tile.is-lead .sum-tile__v {
  font-size: 34px;
  color: var(--color-primary);
}
.sum-tile__k {
  font-size: 14px;
  color: var(--gray-900);
}
.sum-tile__v {
  margin-top: 8px;
  font-size: 30px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--color-darken);
}
.sum-tile__v em {
  margin-left: 2px;
  font-size: 15px;
  font-style: normal;
  font-weight: 500;
}
.sum-tile__v {
  /* 값이 들어오기 전에도 높이가 흔들리지 않게 */
}
.sum-tile__v:empty::before {
  content: "–";
}
.sum-tile__sub {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--gray-900);
  word-break: keep-all;
}

/* media */
/* ⚠️ **맨 마지막에 둔다.** 손가락 크기(44px) 규칙은 부품 규칙과 특정도가 같은
      것이 있어 순서로 갈린다 — 앞에 두면 먹지 않는다. */
/* =====================================================
 * 분기 — 이 제품의 반응형 눈금 (2026-09-10 확정)
 *
 * ⚠️ **숫자를 여기서만 정한다.** 예전에 _shorts.scss 가 1360 · 900 · 640 을,
 *    _toast.scss 가 768 을 제각기 적고 있었다. 한 곳을 고쳐도 나머지가
 *    옛 눈금에 남아, 같은 폭에서 화면마다 다르게 접힌다.
 *
 * ─ 눈금을 이렇게 고른 근거 (전 화면을 재서 나온 값이다)
 *
 *   본문이 버티는 바닥        900px 안팎 (표 여덟 · 검수 · 계정 관리)
 *   LNB 가 늘 떼어 가는 폭    250 + 좌우 여백 40 = 290px
 *
 *   그래서 1200px 이 갈림길이다 —
 *     1200px  LNB 켜짐 → 본문 910   바닥에 딱 닿는다
 *     1199px  LNB 서랍 → 본문 1159  접는 순간 249px 를 되찾는다
 *   1200 아래에서 LNB 를 켜 두면 본문이 바닥을 뚫는다. 그 자리에서 서랍으로
 *   바꾸면 오히려 넓어진다. **여기가 햄버거가 서는 자리다.**
 *
 *   ⚠️ 노트북(1512 · 1440 · 1366 · 1280)에서는 LNB 가 그대로 보인다.
 *      흔한 폭에서 메뉴를 감추지 않는 것이 이 선의 요점이다.
 *
 * ─ 넷으로 나눈 까닭
 *   XL(1690 이상)을 따로 두면 **지금 모습이 조금도 안 바뀐다.**
 *   반응형을 넣다가 멀쩡한 것을 건드리는 사고를 막는 자리다.
 * ===================================================== */
/*
  ⚠️ **1400 이 아니라 1690 이다.** 처음에 1400 으로 적었다가 재서 잡았다 —
     `.section` 이 1400px 을 담으려면 뷰포트가 그만큼이면 안 되고 **LNB 250 +
     여백 40 을 더한 1690px** 이어야 한다. 1400px 로 두었더니 1400px 창에서
     290px 이 넘쳤다. 고치려던 것을 그 폭에서 그대로 남긴 셈이었다.
*/
/* 이상 — 본문이 1400 을 담는다. 지금 모습 그대로 */
/* 미만 — LNB 가 덮개 서랍이 된다 (햄버거) */
/* 미만 — 본문에서 **두 칸이 뜻을 잃는다.** 나란히 두었을 때
   좁은 쪽이 제 일을 못 하는 폭이다 — 대시보드의 「차트 · 최근
   발행 게시물」 줄이 여기서 위아래로 쌓인다.
   ⚠️ 재서 나온 값이다: 2fr : 1fr 이라 목록 칸은 (헤더폭-20)/3 이고,
      834px 에서 259px · 768px 에서 237px 이 됐다. 그 칸에는
      로고 · 날짜 · 제목 · 노출 · 좋아요 다섯이 들어간다. */
/* 미만 — 한 단. 헤더의 「내 것」 묶음이 서랍으로 내려간다 */
/* ---------- 표 전용 눈금 둘 ----------
   ⚠️ **표만 이 아래가 더 필요하다.** 위의 넷은 「칸이 몇 줄로 서나」를 정하는
      눈금인데, 표는 그 아래에서도 **열을 하나씩 접어야** 한다.
      $bp-m(900) 부터 시작해 네 칸으로 접는다 — 900 · 768 · 600 · 480.

   ⚠️ 왜 768 부터인가. `min-width` 를 실측값으로 바로잡으면 가장 큰 표가
      725px(관리자 접속 이력)이다. 768px 뷰포트에서 본문은 728px 이라
      **거기까지는 아무것도 안 접어도 들어간다.** 그 아래부터가 진짜다.

   ⚠️ 예전 견본에는 1024 · 900 · 768 · 600 넷이 적혀 있었다. `min-width: 1300px`
      시절에 잡은 값이라 **1024 칸은 허깨비였다** — 멀쩡히 들어가는 열을 그
      폭에서 감추고 있었다. 그 하나만 지운다.
   ⚠️ **처음에 900 칸까지 지웠다가 되돌렸다.** 「768 부터 시작하면 된다」고
      적었는데, 계정 관리(9열)를 재 보니 **834px 에서 5px · 768px 에서 13px**
      넘쳤다. 열이 아홉이고 값이 한 줄로 서면 900 아래에서 이미 자리가 없다.
      재기 전에 칸을 지운 것이 틀렸다.
   ---------------------------------------- */
/* 미만 — 표에서 두 번째 곁열이 사라진다 (tc-p2) */
/* ⚠️ 900 칸은 $bp-m 을 그대로 쓴다 (tc-p4) — 본문이 두 칸을
      잃는 폭과 표가 곁열을 잃는 폭이 같은 자리다 */
/* 미만 — 표가 「언제 · 무엇 · 상태」 셋만 남는다 (tc-p1) */
/* ---------- 헤더 전용 눈금 둘 ----------
   ⚠️ **헤더는 뷰포트가 아니라 「제 폭」이 문제다.** LNB 가 켜져 있으면 290px 을
      먼저 떼이므로, 같은 뷰포트에서도 헤더에 남는 자리가 다르다.
        LNB 켜짐(≥1200)   헤더 = 뷰포트 - 290
        LNB 서랍(<1200)   헤더 = 뷰포트 -  40
      그래서 위의 셋과 눈금이 겹치지 않는다. 재서 나온 값은 이렇다.

        햄버거                       36
        빵부스러기                  236 ~ 273  (화면 이름에 따라)
        제목                         73 ~ 128
        기관 탭                     276
        「내 것」 다섯               496
        사이(20 × 2)                 40

        넷 다 서려면              1179   ← 기관 탭까지
        탭을 빼면                  983
        빵부스러기까지 빼면         645

   ⚠️ **이 숫자는 재서 나온 것이다.** 처음에는 눈대중으로 1030 이라고 적고
      눈금을 1400 으로 잡았는데, **1440px 에서 여전히 깨졌다** — 제목이
      「작업 …」으로 잘리고 빵부스러기가 「시스템 / 관리」로 두 줄이 됐다.
      실제로는 1179px 이 필요했다.

   ⚠️ 눈금을 이 둘로 고른 셈. 처음에 **탭도 768 에서 내렸다가** 1024px 에서
      헤더가 깨져 잡았다 — 제목이 「작…」으로 잘리고 빵부스러기가
      「시스템 / 관리」로, 단추가 「메뉴 / 구조도」로 두 줄이 됐다.
   ---------------------------------------- */
/* 기관 탭이 헤더에 설 수 있는 최소 뷰포트.
   여기는 LNB 가 켜진 구간이라 헤더 = 뷰포트 - 290 이고, 탭까지 서려면 1179 다.
     1179 + 290 = 1469  ← 계산상 바닥
   1500 으로 둔 것은 그 여유 31px 이 **화면 이름 한 글자**도 못 되기 때문이다. */
/* 빵부스러기를 접는 폭. 여기는 LNB 가 이미 서랍이라 헤더 = 뷰포트 - 40.
   ⚠️ **여기 위에서는 하드 눈금으로 지키지 않는다.** 빵부스러기는 줄바꿈 없이
      말줄임으로 줄어들게 해 두었다(_header.scss) — 「홈 › 시스템 관리 › …」가
      한 마디씩 두 줄로 꺾이는 것을 막는 것이 먼저다. 900 은 **줄어들어도
      읽을 것이 남지 않는 지점**이다(헤더 860, 빵을 뺀 나머지가 645).
   ⚠️ **LNB 가 켜져 있을 때 접지 않는다.** 그때는 왼쪽 메뉴의 강조가 같은 말을
      하지만, 서랍이 되면 **어디에 있는지 말하는 것이 이것뿐**이다. */
/*
  쓰는 법 — `@include under($bp-l) { ... }`
  ⚠️ **max-width 는 1px 을 뺀다.** 빼지 않으면 1200px 에서 두 규칙이 함께
     걸려, 그 폭에서만 LNB 가 켜진 채로 본문이 전폭이 되는 어긋난 그림이 뜬다.
  ⚠️ 0.02px 이 아니라 1px 이다. 이 제품은 정수 폭만 다룬다.
*/
/* 사이 — [$a, $b) */
/* =====================================================
 * 손가락 크기 — 누를 것을 44 × 44 로 (2026-09-11)
 *
 * ─ 재서 나온 것 (작업 이력 · 계정 관리 · 375px · 본문 단추 37개)
 *
 *     이용 방법 보기        84 × 16    ← 24 × 24 에도 미달
 *     기관 탭              63 × 26
 *     접속 이력 보기       317 × 30    가로는 다 쓰는데 높이는 30
 *     검색 · 엑셀 · 등록   130 × 36
 *     행 수 선택           200 × 40
 *     쪽 번호               32 × 32    ← PC 36 에서 **작아졌다**
 *
 *     44 × 44 를 넘는 것   0개 / 37개
 *
 * ⚠️ **쪽 번호는 방향이 거꾸로였다.** 「번호 열 개가 한 줄에 안 선다」고 32px 로
 *    줄여 뒀는데, 줄바꿈으로 그것을 해결한 뒤에도 값이 남아 있었다. 손가락으로
 *    쓰는 폭에서 더 작아지는 셈이었다.
 *
 * ─ 어느 자리에 적용하나 — **폭이 아니라 입력 방식**이다
 *
 *   손가락 크기는 화면이 좁아서 필요한 것이 아니라 **손가락으로 누르기 때문에**
 *   필요하다. 1024px 태블릿은 넓어도 44px 이 필요하고, 노트북에서 창을 375px
 *   로 줄인 사람은 마우스를 쓴다. 그래서 `pointer: coarse` 로 가린다.
 *
 *   ⚠️ 다만 **폭 조건도 함께 둔다.** 개발·검수에서 창을 줄여 확인하는 일이 많고,
 *      그때 「안 고쳐졌다」로 보이면 같은 것을 두 번 재게 된다.
 *      둘 중 하나만 맞아도 켜진다(`,` 는 or 다).
 *
 * ⚠️ **높이는 토큰으로 바꾼다.** `--btn-h` 넷을 여기서 올리면 `.btn` 뿐 아니라
 *    그 토큰을 쓰는 전용 단추까지 함께 따라온다 — 값을 스물 몇 곳에 흩어
 *    적지 않는다(_button.scss 의 규격 주석 참고).
 *
 * ⚠️ **이 파일을 마지막에 불러온다.** 부품 규칙과 특정도가 같은 것이 있어
 *    순서로 갈린다(`.dropdown_button` 등).
 * ===================================================== */
@media (pointer: coarse), (max-width: 599px) {
  /* =====================================================
   * 단추 넷 — **40px** (2026-09-11 에 44 에서 한 단 내렸다)
   *
   * ⚠️ 처음에 전부 44 로 올렸다가 「한 사이즈씩 작아져도 될 것 같다」는
   *    말을 듣고 이 제품의 눈금(50 · 40 · 36 · 30)에서 한 단 내렸다.
   *    40px 은 WCAG 2.2 AA 의 바닥(24 × 24)을 넉넉히 넘고, 44 와 견주어
   *    손가락으로 빗나가는 일이 늘지 않는 크기다.
   *
   * ⚠️ **`--btn-h-sm` 만 44 로 남긴다**(요청). 본값이 30px 이라 한 단 내리면
   *    36px 이 되어 다시 작아진다 — 이 단추는 글·표 칸에 붙는 것이라
   *    가장 맞히기 어렵다.
   *    ⚠️ 그래서 좁은 폭에서는 **sm(44)이 기본(40)보다 크다.** 어긋난 것이
   *       아니라 「작은 단추」라는 이름이 **넓은 폭의 이야기**이기 때문이다.
   *       손가락으로 쓰는 폭에서는 붙어 있는 자리가 좁을수록 더 커야 한다.
   * ===================================================== */
  :root {
    --btn-h: 40px; /* 36 → 40 */
    --btn-h-sm: 44px; /* 30 → 44 · 여기만 그대로 (위 주석) */
    --btn-h-md: 40px; /* 본값과 같다 — 입력칸과 눈을 맞춘다 */
    /* --btn-h-lg(50)는 그대로 */
  }
  /*
    단추 글자 — size-sm 만 13px 이었다.
    ⚠️ 단추가 작아질 이유는 있어도 **글자까지 작아질 이유는 없다.** 옆의 본문이
       14px 인데 그보다 작으면 「덜 중요한 것」으로 읽힌다.
  */
  .btn.size-sm {
    font-size: 14px;
  }
  /* ---------- 입력 컨트롤 ---------- */
  /*
    ⚠️ 드롭다운은 단추가 아니라 입력 컨트롤이라 토큰을 쓰지 않는다(_select.scss).
       입력칸(.text-field)과 눈을 맞춰 함께 올린다.
  */
  .dropdown_button,
  .dropdown.size-sm .dropdown_button {
    height: 40px;
  }
  .text-field,
  input.text-field,
  select.text-field {
    min-height: 40px;
  }
  /* ---------- 쪽 번호 ---------- */
  .pagination {
    --pg-size: 40px;
  }
  /* ---------- 기관 탭 ---------- */
  /*
    ⚠️ 높이를 직접 주지 않고 `min-height` 로 둔다. 탭은 아래 테두리 2px 로
       고른 것을 보이므로, 높이를 박으면 그 선의 자리가 달라진다.
  */
  .tabs .tab {
    min-height: 40px;
  }
  /* ---------- 글 안에 붙은 단추 ---------- */
  /*
    「이용 방법 보기」 — 밑줄 친 글이라 높이가 글자만큼(16px)이었다.
    ⚠️ 모양은 그대로 둔다. **누를 자리만** 위아래로 넓힌다.
  */
  .page-guide-toggle {
    min-height: 40px;
    padding: 0 6px;
  }
  /* ---------- 가장 작은 글자 ---------- */
  /*
    ⚠️ 11px 은 이 제품에서 가장 작은 글자였다(상세 필터의 「▾」 하나).
       장식이라도 11px 은 눈금 밖이다 — 가장 작은 눈금인 12px 로 올린다.
    ⚠️ **`.filter-toggle .caret`(0,2,0) 만으로는 안 먹었다.** 원래 규칙이
       `.section-header.is-filter .filter-toggle .caret`(0,3,0) 이라 더 세다.
       이 파일이 뒤에 있어도 특정도가 낮으면 순서로 이기지 못한다.
  */
  .section-header.is-filter .filter-toggle .caret {
    font-size: 12px;
  }
}
/* =====================================================
 * ⚠️ 여기서 **내리지 않은 것** — 표 안의 체크박스 44 × 44
 *
 * `components/_tableList.scss` 가 좁은 폭에서 44 × 44 로 잡아 둔다.
 * 단추가 아니라 **고르는 칸**이고, 목록에서 가장 맞히기 어려운 것이다
 * (예전에는 25 × 0 이었다). 옆에 글자도 없어 빗나가면 다시 찾아야 한다.
 * 단추는 글자가 넓은 자리를 함께 만들어 주지만 체크박스는 그렇지 않다.
 * ===================================================== */
