/* ============================================================
   SYWorks CMS - Custom Design System (No Bootstrap)
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

:root {
    --sidebar-width: 250px;
    --sidebar-bg: #ffffff;              /* 화이트 테마 — 사이드바 본체 */
    --sidebar-text: #475569;            /* 일반 메뉴 텍스트 (slate-600) */
    --sidebar-text-strong: #0f172a;     /* 활성/강조 텍스트 (slate-900) */
    --sidebar-muted: #94a3b8;           /* 그룹 헤더 라벨/아이콘 (slate-400) */
    --sidebar-hover-bg: #f1f5f9;        /* 호버 배경 (slate-100) */
    --sidebar-active-bg: #eff6ff;       /* 활성 배경 (blue-50) — 화이트 위에서 옅은 블루 틴트 */
    --sidebar-active: #1d4ed8;          /* 활성 텍스트 (blue-700) */
    --sidebar-accent: #3b7ff5;          /* 활성 좌측 액센트 바 — CMS primary 블루 */
    --sidebar-border: #e5e7eb;          /* 분리선 (gray-200) */
    --topbar-height: 60px;
    --cms-tabbar-height: 0px;
    --cms-stuck-bottom: var(--topbar-height);
    /* [DS Stage A] 레거시 색 변수를 cms.tokens.css 토큰의 별칭으로 통일(토큰 단일 출처).
       success/danger/info 는 기존 레거시값과 미세 달라 전역 색조가 토큰값으로 통일됨(의도된 변경). */
    --primary:      var(--cms-action-primary);  /* #3b7ff5 (동일) */
    --primary-dark: var(--cms-action-strong);   /* #2563c9 (동일) */
    --success:      var(--cms-success);          /* #1a9e5c → #198754 통일 */
    --danger:       var(--cms-danger);           /* #d94040 → #dc3545 통일 */
    --warning:      var(--cms-warning);          /* #d97706 (동일) */
    --info:         var(--cms-info);             /* #0891b2 → #1d4ed8 통일 */
    --secondary:    var(--cms-secondary);        /* #6b7280 (동일) */
    --content-bg: var(--cms-white);          /* 화이트 톤 — 모든 페이지 공통 본문 배경 (토큰 별칭) */
    --card-shadow: var(--cms-shadow-1);      /* 0 1px 4px rgba(0,0,0,.08) — 토큰 별칭(값 동일) */
    --border: var(--cms-border-subtle);     /* #e5e7eb — 토큰 별칭(Stage A 연장) */
    --text: var(--cms-text);                 /* #1e2a3b — 토큰 별칭 */
    --text-muted: var(--cms-text-muted);     /* #6b7280 — 토큰 별칭 */
    --radius: var(--cms-radius-2);       /* 6px — 토큰 별칭(비색 Stage-A 수렴, 값 동일) */
    --radius-lg: var(--cms-radius-3);    /* 10px — 토큰 별칭 */
    /* [Phase E-1] spacing 토큰 — 2-Panel·가이드 모달 공통. 토큰 별칭(비색 Stage-A 수렴, 값 동일) */
    --cms-space-xs: var(--cms-space-1);  /* 4px */
    --cms-space-sm: var(--cms-space-2);  /* 8px */
    --cms-space-md: var(--cms-space-4);  /* 16px */
    --cms-space-lg: var(--cms-space-5);  /* 24px */
    --cms-space-xl: var(--cms-space-6);  /* 32px */
    /* [Phase E-1] 2-Panel 기본 좌측 폭 (페이지별 override 가능) */
    --layout-2panel-left: 320px;
    /* [DS] z-index 토큰은 cms.tokens.css 가 단일 출처(--cms-z-*). 로드 순서상 먼저 정의되어
       전역 적용되므로 이 파일의 미러 정의는 제거함(중복 출처 정리). */
}

/* 본문 높이 변화에 따른 세로 스크롤바 등장/소멸로 인한 가로 시프트 차단.
   로그인(body.login-body, overflow:hidden)에는 적용 불필요 — CMS 페이지만 한정. */
html:has(body.cms-body) { scrollbar-gutter: stable; }
body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', sans-serif; font-size: var(--cms-fs-body); color: var(--text); }

/* ============================================================
   [iframe shell] /shell 안에 iframe 으로 마운트된 페이지 — 외곽 chrome 숨김.
   부모 쉘이 topbar/sidebar/cmsTabbar 를 이미 제공하므로 자식은 본문만 보여준다.

   selector 두 종류 모두 지원 (모두 동일 효과):
     · html.cms-iframe-mode  — head 인라인 스크립트가 body 파싱 전에 부여 (FOUC 차단용)
     · body.cms-body-iframe  — cms.js 가 DOMContentLoaded 시점에 부여 (호환용)
   ============================================================ */
html.cms-iframe-mode .cms-sidebar,
html.cms-iframe-mode .cms-topbar,
html.cms-iframe-mode #cmsTabbar,
body.cms-body-iframe .cms-sidebar,
body.cms-body-iframe .cms-topbar,
body.cms-body-iframe #cmsTabbar { display: none !important; }

/* iframe 모드 — sticky 상단 chrome 이 없으므로 viewport-fit 계산용 변수도 0 */
html.cms-iframe-mode,
body.cms-body-iframe { --cms-stuck-bottom: 0px; --topbar-height: 0px; --cms-tabbar-height: 0px; }

/* ★iframe 자식 문서 자체 스크롤 차단 — 셸 부모(.cms-body-shell)와 동일 정책. 미적용 시
   (1) 차트 라이브러리 등이 만드는 phantom 높이로 문서 스크롤이 .cms-content 내부 스크롤과 겹쳐 "스크롤 2개"(예: analytics)
   (2) 페이지가 자체적으로 body overflow 를 잠그지 못한 상태(예: content 편집뷰)서 문서가 밀려 내용이 "위로 말려올라감".
   모든 세로 스크롤은 .cms-content(또는 페이지 내부 스크롤 영역) 한 곳에서만. */
html:has(body.cms-body-iframe),
html.cms-iframe-mode,
body.cms-body-iframe { overflow: hidden; }

html.cms-iframe-mode .cms-main,
body.cms-body-iframe .cms-main {
    margin-left: 0 !important;
    /* iframe 내부 .cms-main 을 뷰포트 높이에 가둔다(=standalone 규칙과 동일 원리).
       min-height:100vh 만 주면 flex 컬럼이 콘텐츠만큼 자라(예: 대시보드 SYSTEM 위젯 3446px)
       자식 .cms-content 의 height:100vh·overflow-y:auto 가 무력화되어 어디서도 세로 스크롤이 안 생긴다.
       height:100vh + min-height:0 로 캡해야 .cms-content 가 잔여 높이 안에서 내부 스크롤한다. */
    height: 100vh !important;
    min-height: 0 !important;
}
/* 자식 페이지의 .cms-content 는 iframe 내부 전체 높이를 사용 */
html.cms-iframe-mode .cms-content,
body.cms-body-iframe .cms-content {
    height: 100vh;
    overflow-y: auto;
}

/* 직접 URL(standalone) 진입 페이지 — 풀 chrome(사이드바+topbar+tabbar) 유지하되
   .cms-main 을 뷰포트 높이에 가두고 .cms-content 가 내부에서 세로 스크롤(위 iframe 모드와 동일 원리).
   미적용 시 .cms-content 가 콘텐츠 높이만큼 자라 페이지/컨테이너 어디서도 스크롤이 생기지 않음. */
body.cms-body:not(.cms-body-shell):not(.cms-body-iframe) .cms-main {
    height: 100vh;
    min-height: 0;
}
body.cms-body:not(.cms-body-shell):not(.cms-body-iframe) .cms-content {
    min-height: 0;
    overflow-y: auto;
}

/* ------------------------------------------------------------
   리스트/그리드 페이지 표준 레이아웃 — 툴바·페이지네이션은 고정, 목록만 내부 스크롤.
   페이지 루트에 .cms-page(=.cms-content 잔여 높이를 채우는 flex 컬럼)를 두고,
   목록/그리드 영역에 .cms-grid-host(flex:1; min-height:0)를 주면 그 영역만 스크롤되고
   위(검색/툴바)·아래(페이지네이션) chrome 은 항상 보인다. 해상도가 작아도 페이저가 묻히지 않음.
   .cms-content 자체 overflow-y:auto 는 .cms-page 를 쓰지 않는 단순 폼 페이지의 fallback.
   ------------------------------------------------------------ */
.cms-page {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}
.cms-grid-host {
    flex: 1 1 auto;
    min-height: 0;
}

/* ============================================================
   Reset / Base
   ============================================================ */
h1,h2,h3,h4,h5,h6 { margin: 0; }
p { margin: 0 0 8px; }
a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-dark); }
ul, ol { margin: 0; padding: 0; list-style: none; }
table { border-collapse: collapse; width: 100%; }
input, select, textarea, button { font-family: inherit; font-size: var(--cms-fs-body); }

/* ============================================================
   Utility Classes
   ============================================================ */
.d-flex       { display: flex !important; }
.d-none       { display: none !important; }
.d-block      { display: block !important; }
.d-inline     { display: inline !important; }
.d-inline-flex{ display: inline-flex !important; }
.d-grid       { display: grid !important; }
.flex-1       { flex: 1; }
.flex-wrap    { flex-wrap: wrap; }
.align-items-center   { align-items: center !important; }
.align-items-start    { align-items: flex-start !important; }
.justify-content-between { justify-content: space-between !important; }
.justify-content-center  { justify-content: center !important; }
.justify-content-end     { justify-content: flex-end !important; }
.gap-1 { gap: 4px; }
.gap-2 { gap: 8px; }
.gap-3 { gap: 12px; }
.gap-4 { gap: 16px; }
.w-100 { width: 100% !important; }
.h-100 { height: 100% !important; }
.text-center  { text-align: center !important; }
.text-end     { text-align: right !important; }
.text-muted   { color: var(--text-muted) !important; }
.text-primary { color: var(--primary) !important; }
.text-success { color: var(--success) !important; }
.text-danger  { color: var(--danger) !important; }
.text-warning { color: var(--warning) !important; }
.text-info    { color: var(--info) !important; }
.text-secondary { color: var(--secondary) !important; }
.text-white   { color: var(--cms-white) !important; }
.fw-bold      { font-weight: 700 !important; }
.fw-semibold  { font-weight: 600 !important; }
.fw-normal    { font-weight: 400 !important; }
.fs-sm        { font-size: var(--cms-fs-xs) !important; }
.fs-xs        { font-size: 11px !important; }
.small        { font-size: var(--cms-fs-xs); }
.font-monospace { font-family: 'Courier New', monospace; font-size: var(--cms-fs-sm); }
.mt-0 { margin-top: 0 !important; }
.mt-1 { margin-top: 4px !important; }
.mt-2 { margin-top: 8px !important; }
.mt-3 { margin-top: 12px !important; }
.mt-4 { margin-top: 16px !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: 4px !important; }
.mb-2 { margin-bottom: 8px !important; }
.mb-3 { margin-bottom: 12px !important; }
.mb-4 { margin-bottom: 16px !important; }
.me-1 { margin-right: 4px !important; }
.me-2 { margin-right: 8px !important; }
.me-3 { margin-right: 12px !important; }
.ms-1 { margin-left: 4px !important; }
.ms-2 { margin-left: 8px !important; }
.ms-auto { margin-left: auto !important; }
.p-0  { padding: 0 !important; }
.p-2  { padding: 8px !important; }
.p-3  { padding: 12px !important; }
.py-3 { padding-top: 12px !important; padding-bottom: 12px !important; }
.py-4 { padding-top: 16px !important; padding-bottom: 16px !important; }
.py-5 { padding-top: 32px !important; padding-bottom: 32px !important; }
.px-3 { padding-left: 12px !important; padding-right: 12px !important; }
.rounded { border-radius: var(--radius) !important; }
.border { border: 1px solid var(--border) !important; }
.bg-light { background: var(--cms-gray-60) !important; }
.overflow-hidden { overflow: hidden; }
.position-relative { position: relative; }

/* Grid Layout
   Bootstrap 5 의 .row(flex) / .row > *(width:100% + horizontal padding) /
   .col-md-N(width:%) 등이 충돌하므로 cms.css 의 CSS Grid 시스템이
   완전히 적용되도록 충돌 속성을 reset 한다. */
.row {
    display: grid;
    gap: 16px;
    margin: 0;
}
.row > * {
    width: auto;
    max-width: none;
    padding-left: 0;
    padding-right: 0;
    margin-top: 0;
}
.row.g-2 { gap: 8px; }
.row.g-3 { gap: 12px; }
.row.g-4 { gap: 16px; }
.col-12 { grid-column: span 1; }

@media (min-width: 576px) {
    .row { grid-template-columns: repeat(12, 1fr); }
    .col-6  { grid-column: span 6; }
    .col-12 { grid-column: span 12; }
}
@media (min-width: 768px) {
    .col-md-1  { grid-column: span 1; }
    .col-md-2  { grid-column: span 2; }
    .col-md-3  { grid-column: span 3; }
    .col-md-4  { grid-column: span 4; }
    .col-md-5  { grid-column: span 5; }
    .col-md-6  { grid-column: span 6; }
    .col-md-7  { grid-column: span 7; }
    .col-md-8  { grid-column: span 8; }
    .col-md-9  { grid-column: span 9; }
    .col-md-10 { grid-column: span 10; }
    .col-md-11 { grid-column: span 11; }
    .col-md-12 { grid-column: span 12; }
}
@media (min-width: 992px) {
    .col-lg-1  { grid-column: span 1; }
    .col-lg-2  { grid-column: span 2; }
    .col-lg-3  { grid-column: span 3; }
    .col-lg-4  { grid-column: span 4; }
    .col-lg-5  { grid-column: span 5; }
    .col-lg-6  { grid-column: span 6; }
    .col-lg-7  { grid-column: span 7; }
    .col-lg-8  { grid-column: span 8; }
    .col-lg-9  { grid-column: span 9; }
    .col-lg-10 { grid-column: span 10; }
    .col-lg-11 { grid-column: span 11; }
    .col-lg-12 { grid-column: span 12; }
}
@media (min-width: 1200px) {
    .col-xl-1  { grid-column: span 1; }
    .col-xl-2  { grid-column: span 2; }
    .col-xl-3  { grid-column: span 3; }
    .col-xl-4  { grid-column: span 4; }
    .col-xl-5  { grid-column: span 5; }
    .col-xl-6  { grid-column: span 6; }
    .col-xl-7  { grid-column: span 7; }
    .col-xl-8  { grid-column: span 8; }
    .col-xl-9  { grid-column: span 9; }
    .col-xl-10 { grid-column: span 10; }
    .col-xl-11 { grid-column: span 11; }
    .col-xl-12 { grid-column: span 12; }
}

/* ============================================================
   Buttons
   ============================================================ */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px 14px;
    border-radius: var(--radius);
    border: 1px solid transparent;
    cursor: pointer;
    font-size: var(--cms-fs-sm);
    font-weight: 500;
    line-height: 1.4;
    transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
    white-space: nowrap;
    text-decoration: none;
    background: transparent;
}
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
/* 다크: 비활성(복사·삭제 등) 아이콘이 어두운 표면에서 0.55 불투명도로 과도하게 묻혀 안 보임 → 불투명도 상향(비활성 구분은 유지) */
html[data-cms-theme="dark"] .btn:disabled,
html[data-cms-theme="dark"] .btn[disabled] { opacity: 0.72; }
.btn-sm  { padding: 4px 10px; font-size: var(--cms-fs-xs); }
.btn-lg  { padding: 10px 20px; font-size: 15px; }
.btn-xs  { padding: 2px 7px; font-size: 11px; }

.btn-primary      { background: var(--primary); color: var(--cms-white); border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: var(--cms-white); }
.btn-success      { background: var(--success); color: var(--cms-white); border-color: var(--success); }
.btn-success:hover { background: var(--cms-success-strong); border-color: var(--cms-success-strong); color: var(--cms-white); }
.btn-danger       { background: var(--danger); color: var(--cms-white); border-color: var(--danger); }
.btn-danger:hover  { background: var(--cms-danger-strong); border-color: var(--cms-danger-strong); color: var(--cms-white); }
.btn-warning      { background: var(--warning); color: var(--cms-white); border-color: var(--warning); }
.btn-warning:hover { background: var(--cms-warning-strong); border-color: var(--cms-warning-strong); color: var(--cms-white); }
.btn-secondary    { background: var(--secondary); color: var(--cms-white); border-color: var(--secondary); }
.btn-secondary:hover { background: var(--cms-secondary-strong); border-color: var(--cms-secondary-strong); color: var(--cms-white); }
.btn-info         { background: var(--info); color: var(--cms-white); border-color: var(--info); }
.btn-info:hover    { background: var(--cms-info-strong); border-color: var(--cms-info-strong); color: var(--cms-white); }
.btn-light        { background: var(--cms-gray-110); color: var(--text); border-color: var(--cms-border-subtle); }
.btn-light:hover   { background: var(--cms-border-subtle); color: var(--text); }

.btn-outline-primary  { color: var(--primary); border-color: var(--primary); }
.btn-outline-primary:hover  { background: var(--primary); color: var(--cms-white); }
.btn-outline-secondary { color: var(--cms-secondary); border-color: var(--cms-border-input); }
.btn-outline-secondary:hover { background: var(--cms-secondary); color: var(--cms-white); border-color: var(--cms-secondary); }
.btn-outline-danger   { color: var(--danger); border-color: var(--danger); }
.btn-outline-danger:hover   { background: var(--danger); color: var(--cms-white); }
.btn-outline-success  { color: var(--success); border-color: var(--success); }
.btn-outline-success:hover  { background: var(--success); color: var(--cms-white); }
.btn-outline-info     { color: var(--info); border-color: var(--info); }
.btn-outline-info:hover     { background: var(--info); color: var(--cms-white); }
.btn-outline-warning  { color: var(--warning); border-color: var(--warning); }
.btn-outline-warning:hover  { background: var(--warning); color: var(--cms-white); }

/* Button group */
.btn-group { display: inline-flex; }
.btn-group .btn { border-radius: 0; border-right-width: 0; }
.btn-group .btn:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.btn-group .btn:last-child  { border-radius: 0 var(--radius) var(--radius) 0; border-right-width: 1px; }
.btn-group.btn-group-sm .btn { padding: 3px 8px; font-size: var(--cms-fs-xs); }

/* ============================================================
   Forms
   ============================================================ */
.form-label { display: block; margin-bottom: 5px; font-size: var(--cms-fs-sm); font-weight: 500; color: var(--text); }
.form-control, .form-select {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: 1px solid var(--cms-border-input);
    border-radius: var(--radius);
    background: var(--cms-bg-surface);   /* surface 토큰 = 다크모드 추종(라이트값 동일) */
    color: var(--text);
    font-size: var(--cms-fs-sm);
    transition: border-color 0.15s, box-shadow 0.15s;
    outline: none;
}
.form-control:focus, .form-select:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(59,127,245,.15);
}
/* placeholder — muted 토큰(다크모드 추종). opacity:1 로 Firefox 기본 흐림 보정 */
.form-control::placeholder, .form-select::placeholder { color: var(--cms-text-muted); opacity: 1; }
textarea.form-control { resize: vertical; }
/* select 는 네이티브 렌더링(appearance:auto)이 author 배경을 무시해 다크에서 흰 박스로 남던 문제 →
   appearance:none + 커스텀 화살표(위 공유 규칙의 background 쇼트핸드가 bootstrap 화살표 이미지를 지우므로 재지정). */
.form-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 14px 10px;
    padding-right: 32px;
}
html[data-cms-theme="dark"] .form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23aab4c5' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}
select[multiple].form-select { background-image: none; padding-right: 10px; }

/* Checkbox / Radio */
.form-check { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.form-check-input { width: 15px; height: 15px; cursor: pointer; accent-color: var(--primary); }
.form-check-label { font-size: var(--cms-fs-sm); cursor: pointer; }
.form-switch .form-check-input { width: 32px; height: 18px; }

/* Input group */
.input-group { display: flex; }
.input-group .form-control { flex: 1; border-radius: 0; }
.input-group .form-control:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.input-group .form-control:last-child { border-radius: 0 var(--radius) var(--radius) 0; }
.input-group-text {
    display: flex; align-items: center; padding: 7px 10px;
    background: var(--cms-gray-110); border: 1px solid var(--cms-border-input); font-size: var(--cms-fs-sm);
    border-radius: var(--radius) 0 0 var(--radius);
}
.input-group .form-control { border-left: none; }

/* ============================================================
   Badge
   ============================================================ */
.badge {
    display: inline-flex; align-items: center;
    padding: 2px 8px; border-radius: 20px;
    font-size: 11px; font-weight: 600; line-height: 1.4;
}
.bg-primary   { background: var(--primary) !important; color: var(--cms-white); }
.bg-success   { background: var(--success) !important; color: var(--cms-white); }
.bg-danger    { background: var(--danger) !important; color: var(--cms-white); }
.bg-warning   { background: var(--warning) !important; color: var(--cms-white); }
.bg-info      { background: var(--info) !important; color: var(--cms-white); }
.bg-secondary { background: var(--cms-secondary) !important; color: var(--cms-white); }
.bg-light-tag { background: var(--cms-border-subtle); color: var(--text); }

/* ============================================================
   Card
   ============================================================ */
.card {
    background: var(--cms-bg-surface);   /* surface 토큰 = 다크모드 추종(라이트값 동일) */
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.cms-card { border: none; border-radius: var(--radius-lg); box-shadow: var(--card-shadow); }
.card-header {
    padding: 14px 20px;
    background: transparent;
    border-bottom: 1px solid #f0f0f0;
    font-weight: 600;
    display: flex;
    align-items: center;
}
.card-body { padding: 20px; }
.card.p-3 { padding: 12px; }

/* ============================================================
   Table
   ============================================================ */
.table { width: 100%; border-collapse: collapse; font-size: var(--cms-fs-sm); }
.table th, .table td { padding: 10px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table th { background: var(--cms-gray-60); font-weight: 600; white-space: nowrap; }
.table tbody tr:hover { background: var(--cms-gray-60); }
.table-sm th, .table-sm td { padding: 6px 10px; }
.table-hover tbody tr:hover { background: var(--cms-bg-hover); }
.table-bordered td, .table-bordered th { border: 1px solid var(--border); }
.table-light { background: var(--cms-gray-60); }
/* 다크 — Bootstrap 테이블 셀은 vendor --bs-table-bg(흰색)을 배경으로 써 다크 미추종 → surface 토큰으로 수렴 */
html[data-cms-theme="dark"] .table { --bs-table-bg: var(--cms-bg-surface); --bs-table-color: var(--cms-text); color: var(--cms-text); }

/* ============================================================
   Modal (Custom)
   ============================================================ */
.cms-modal-overlay {
    display: none;
    position: fixed; inset: 0; z-index: 2000;
    background: rgba(0,0,0,.45);
    align-items: center; justify-content: center;
}
.cms-modal-overlay.open { display: flex; }
.cms-modal {
    background: var(--cms-bg-surface);   /* surface 토큰 = 다크모드 추종(라이트값 동일) */
    border-radius: var(--radius-lg);
    box-shadow: 0 20px 60px rgba(0,0,0,.25);
    width: 90%;
    max-width: 560px;
    max-height: 90vh;
    display: flex; flex-direction: column;
    animation: modalIn 0.2s ease;
}
.cms-modal.modal-lg  { max-width: 800px; }
.cms-modal.modal-xl  { max-width: 1100px; }
.cms-modal.modal-sm  { max-width: 420px; }
@keyframes modalIn {
    from { opacity: 0; transform: translateY(-20px) scale(.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.cms-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px; border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.cms-modal-header h5 { font-size: 15px; font-weight: 600; margin: 0; }
.cms-modal-body { padding: 20px; overflow-y: auto; flex: 1; }
.cms-modal-footer {
    padding: 12px 20px; border-top: 1px solid var(--border);
    display: flex; justify-content: flex-end; gap: 8px;
    flex-shrink: 0;
}
.btn-modal-close {
    background: none; border: none; cursor: pointer;
    font-size: 18px; color: var(--text-muted); line-height: 1;
    padding: 2px 6px; border-radius: 4px;
}
.btn-modal-close:hover { background: var(--cms-gray-110); color: var(--text); }

/* 다크 — Bootstrap 모달(.modal-content)은 vendor 흰 배경/보더라 다크 미추종 → surface 토큰으로 수렴
   (.cms-modal 과 동일 정책). 적용처: site/page/layout-tpl/head-tpl/styleguide 의 .modal-content. */
html[data-cms-theme="dark"] .modal-content { background: var(--cms-bg-surface); color: var(--cms-text); border-color: var(--cms-border-subtle); }
html[data-cms-theme="dark"] .modal-header,
html[data-cms-theme="dark"] .modal-footer { border-color: var(--cms-border-subtle); }

/* ============================================================
   Tabs (Custom)
   ============================================================ */
.cms-tabs { display: flex; border-bottom: 2px solid var(--border); margin-bottom: 16px; }
.cms-tab {
    padding: 8px 16px; font-size: var(--cms-fs-sm); font-weight: 500; cursor: pointer;
    border-bottom: 2px solid transparent; margin-bottom: -2px;
    color: var(--text-muted); transition: color 0.15s, border-color 0.15s;
    background: none; border-top: none; border-left: none; border-right: none;
}
.cms-tab:hover { color: var(--text); }
.cms-tab.active { color: var(--cms-info-text); border-bottom-color: var(--cms-select-border); }
.cms-tab-pane { display: none; }
.cms-tab-pane.active { display: block; }

/* ============================================================
   Alert / Notification bar
   ============================================================ */
.alert {
    padding: 10px 14px; border-radius: var(--radius);
    font-size: var(--cms-fs-sm); margin-bottom: 12px; border: 1px solid transparent;
}
.alert-danger  { background: var(--cms-alert-danger-bg); color: var(--cms-alert-danger-text); border-color: var(--cms-red-border); }
.alert-success { background: var(--cms-alert-success-bg); color: var(--cms-alert-success-text); border-color: var(--cms-alert-success-border); }
.alert-warning { background: var(--cms-warn-tint); color: var(--cms-warn-text); border-color: var(--cms-alert-warning-border); }
.alert-info    { background: var(--cms-blue-tint); color: var(--cms-info-text); border-color: var(--cms-alert-info-border); }

/* ============================================================
   List Group
   ============================================================ */
.list-group { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.list-group-item {
    padding: 10px 14px; border-bottom: 1px solid var(--border);
    background: var(--cms-bg-surface); font-size: var(--cms-fs-sm); display: flex;
    align-items: center; justify-content: space-between;
}
.list-group-item:last-child { border-bottom: none; }

/* ============================================================
   Breadcrumb
   ============================================================ */
.breadcrumb { display: flex; align-items: center; gap: 6px; font-size: var(--cms-fs-sm); padding: 0; }
.breadcrumb-item + .breadcrumb-item::before { content: '/'; color: var(--text-muted); }
.breadcrumb-item a { color: var(--text-muted); }
.breadcrumb-item.active { color: var(--text); }

/* ============================================================
   Progress
   ============================================================ */
.progress { height: 8px; background: var(--cms-border-subtle); border-radius: 10px; overflow: hidden; }
.progress-bar {
    height: 100%; background: var(--primary);
    border-radius: 10px; transition: width 0.3s ease;
}
.progress-bar-animated {
    background: repeating-linear-gradient(
        45deg, var(--primary), var(--primary) 10px,
        var(--primary-dark) 10px, var(--primary-dark) 20px
    );
    background-size: 40px 40px;
    animation: progressStripes 0.6s linear infinite;
}
@keyframes progressStripes { from { background-position: 40px 0; } to { background-position: 0 0; } }

/* ============================================================
   CMS Layout
   ============================================================ */
.cms-body { margin: 0; background: var(--content-bg); }
.cms-wrapper { display: flex; min-height: 100vh; }

/* Sidebar */
.cms-sidebar {
    width: var(--sidebar-width); height: 100vh;
    background: var(--sidebar-bg); display: flex; flex-direction: column;
    position: fixed; top: 0; left: 0; z-index: 1000;
    transition: transform 0.25s ease; overflow: hidden;   /* 자체 스크롤 끔 — 로고 헤더는 고정, 스크롤은 .sidebar-menu 한 곳만 */
    border-right: 1px solid var(--cms-border-strong);   /* topbar/tabbar/sidebar-header 와 검정 라인 통일 */
    box-shadow: none;            /* 너무 강한 그림자 제거 — Soft Light 무드 */
}
/* 사이드바 스크롤 affordance — Mac 오버레이 스크롤바가 숨겨져 "스크롤 불가"로 오인되는 것 방지.
   메뉴가 뷰포트보다 길 때(작은 해상도/창 축소) 보이는 얇은 스크롤바 노출. 들어맞으면 미표시(레이아웃 영향 없음).
   스크롤 주체를 .cms-sidebar → .sidebar-menu 로 이동(로고 헤더 고정). */
.sidebar-menu { scrollbar-width: thin; scrollbar-color: rgba(100,116,139,.45) transparent; }
.sidebar-menu::-webkit-scrollbar { width: 8px; }
.sidebar-menu::-webkit-scrollbar-thumb { background: rgba(100,116,139,.45); border-radius: 4px; }
.sidebar-menu::-webkit-scrollbar-track { background: transparent; }
.cms-sidebar.collapsed { transform: translateX(calc(-1 * var(--sidebar-width))); }
.sidebar-header {
    height: var(--topbar-height);
    flex: 0 0 auto;                  /* 로고 헤더 고정 — 메뉴가 길어도 축소/스크롤 안 됨 */
    padding: 0 20px;
    display: flex; align-items: center;
    box-sizing: border-box;
    border-bottom: 1px solid var(--cms-border-strong);   /* topbar border-bottom 과 가로 라인 연속 — 로고/헤더와 LNB 분리 */
}
.sidebar-logo {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    width: 100%; height: 100%; text-decoration: none;
}
.sidebar-logo img {
    display: block;
    max-width: 100%; max-height: 100%;
    width: auto; height: auto;
    object-fit: contain;
}
/* 다크 — 로고는 검정 'CMS' 텍스트 라스터라 어두운 사이드바에서 안 보임 → 밝은 플레이트로 가독 보존(브랜드색 유지) */
html[data-cms-theme="dark"] .sidebar-logo {
    background: var(--cms-white);
    border-radius: var(--radius);
    padding: 6px 10px;
}
.sidebar-logo-suffix {
    color: #1e293b; font-size: 1rem; font-weight: 500; letter-spacing: 0.5px;
    line-height: 1; margin-top: 5px;
}
.sidebar-menu { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 0 12px; }   /* 잔여 높이만큼 메뉴만 내부 스크롤 — 로고 헤더는 위에 고정 */
.menu-category {
    padding: 12px 20px 6px; font-size: 10px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 1.2px; color: var(--sidebar-muted);
}
.menu-list { list-style: none; margin: 0; padding: 0; }
.menu-link {
    display: flex; align-items: center; gap: 10px; padding: 9px 20px 9px 32px;
    color: var(--sidebar-text); text-decoration: none; transition: background .15s, color .15s;
    font-size: var(--cms-fs-body); font-weight: 700;
    border-left: 3px solid transparent;
    border-radius: 0;
}
.menu-link:hover {
    background: var(--sidebar-hover-bg);
    color: var(--sidebar-text-strong);
}
.menu-link.active {
    background: var(--sidebar-active-bg);
    color: var(--sidebar-active);
    border-left-color: var(--sidebar-accent);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .06);   /* 화이트 톤 위 카드처럼 미세 양각 */
    /* font-weight: 일반 menu-link 와 동일하게 500 유지 — 강조는 색/배경/좌측 보더로 처리 */
}
.menu-link .fa {
    width: 18px; text-align: center; font-size: var(--cms-fs-body);
    color: var(--sidebar-muted);
    transition: color .15s;
}
.menu-link:hover .fa,
.menu-link.active .fa {
    color: var(--sidebar-accent);
}
/* 즐겨찾기 별표 — hover 시 노출, is-fav 면 항상 채움(노랑) */
.cms-sidebar .menu-item { position: relative; }
.menu-fav-star {
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    background: none; border: 0; padding: 4px; line-height: 1; cursor: pointer;
    color: var(--sidebar-muted); opacity: 0;
    transition: opacity .15s, color .15s;
}
.menu-item:hover .menu-fav-star { opacity: 1; }
.menu-fav-star:hover,
.menu-fav-star.is-fav { opacity: 1; color: var(--cms-warn-text); }

/* ── 아코디언 그룹 LNB ─────────────────────────────────────── */
.cms-sidebar .menu-group {
    border-top: 1px solid var(--sidebar-border);
}
.cms-sidebar .menu-group:last-child {
    border-bottom: 1px solid var(--sidebar-border);
}
.cms-sidebar .menu-group-header {
    width: 100%;
    background: transparent;
    border: none;
    cursor: pointer;
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 20px;
    /* Why: 한국어 그룹명(사이트 개발/리소스 관리 등) 가독성 향상 — 11px uppercase 였던 라벨 톤을
       14px 일반 케이스 + 진한 색으로 강조. 좌측 4px 컬러 막대로 시각 무게 추가. */
    font-size: var(--cms-fs-body);
    font-weight: 700;
    letter-spacing: -0.2px;
    color: var(--sidebar-text-strong);
    position: relative;
    transition: color .15s, background .15s;
}
.cms-sidebar .menu-group-label {
    display: inline-flex; align-items: center; gap: 8px;
    min-width: 0;
}
.cms-sidebar .menu-group-icon {
    width: 18px; text-align: center; font-size: var(--cms-fs-body);
    color: var(--sidebar-muted);
    transition: color .15s;
}
.cms-sidebar .menu-group-header:hover .menu-group-icon,
.cms-sidebar .menu-group.is-open .menu-group-icon {
    color: var(--sidebar-accent);
}
.cms-sidebar .menu-group-header::before {
    content: '';
    position: absolute;
    left: 0; top: 12px; bottom: 12px;
    width: 3px;
    background: var(--sidebar-muted);
    border-radius: 0 2px 2px 0;
    opacity: .55;
    transition: background .15s, opacity .15s;
}
.cms-sidebar .menu-group-header:hover {
    background: var(--sidebar-hover-bg);
}
.cms-sidebar .menu-group-header:hover::before,
.cms-sidebar .menu-group.is-open .menu-group-header::before {
    background: var(--sidebar-accent);
    opacity: 1;
}
.cms-sidebar .menu-group.is-open .menu-group-header {
    color: var(--sidebar-text-strong);
}
.cms-sidebar .menu-group-arrow {
    font-size: 0.7rem;
    opacity: 0.55;
    transition: transform 0.22s ease;
}
.cms-sidebar .menu-group.is-open .menu-group-arrow {
    transform: rotate(180deg);
    opacity: 0.85;
}
.cms-sidebar .menu-group-body {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.25s ease;
    padding: 0;
    margin: 0;
}
.cms-sidebar .menu-group.is-open .menu-group-body {
    max-height: 600px;          /* 그룹당 메뉴 최대치 (현재 ~5 항목) */
    padding-bottom: 4px;
}

/* GNB topbar 사용자/로그아웃 */
.topbar-user { color: var(--text-muted); font-size: var(--cms-fs-sm); font-weight: 500; }

/* Main Content */
.cms-main {
    margin-left: var(--sidebar-width); flex: 1; min-width: 0;
    display: flex; flex-direction: column; min-height: 100vh;
    transition: margin-left 0.25s ease;
}

/* Tab Bar */
.cms-tabbar {
    display: flex; align-items: flex-end;
    background: var(--cms-bg-surface); border-bottom: 1px solid var(--cms-border-strong);   /* surface 토큰 = 다크 추종(라이트값 동일); topbar/sidebar-header 와 가로 라인 연속 */
    padding: inherit; gap: 3px; overflow-x: auto; flex-wrap: nowrap;
    position: sticky; top: var(--topbar-height); z-index: 99;
    scrollbar-width: none;
}
.cms-tabbar::-webkit-scrollbar { display: none; }
.cms-tabbar:empty { display: none; }
/* ▼ 상단 탭바(.cms-tabbar) 전용 — 모달 안의 .cms-tabs > .cms-tab 와 분리.
   /resource 의 .cms-tab 톤과 동일: 13px / weight 500 / underline-only,
   active 시 텍스트 #1d4ed8 + 언더라인 #3b7ff5. */
.cms-tabbar .cms-tab {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 8px 16px;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    border-radius: 0;
    font-size: var(--cms-fs-sm); font-weight: 500; color: var(--text-muted); text-decoration: none;
    cursor: pointer; white-space: nowrap;
    transition: color 0.15s, border-color 0.15s;
}
.cms-tabbar .cms-tab:hover { background: transparent; color: var(--text); text-decoration: none; }
.cms-tabbar .cms-tab.active {
    background: transparent;
    color: var(--cms-info-text);                  /* blue-700 — .cms-tab.active 와 동일 */
    border-bottom: 2px solid var(--cms-action-primary);     /* --primary — .cms-tab.active 와 동일 */
    box-shadow: none;
    margin-bottom: -2px;
    z-index: auto;
}
.cms-tabbar .cms-tab.dragging   { opacity: 0.4; }
.cms-tabbar .cms-tab.drop-before { box-shadow: inset 3px 0 0 0 var(--primary); }
.cms-tabbar .cms-tab.drop-after  { box-shadow: inset -3px 0 0 0 var(--primary); }
.tab-close {
    font-size: 14px; color: var(--cms-text-muted); padding: 0 2px; line-height: 1;
}
.tab-close:hover { color: var(--cms-danger-text); }
.tab-close-all {
    margin-left: auto; margin-right: 16px; margin-bottom: 0; padding: 5px 13px;
    background: var(--cms-bg-surface); border: 1px solid var(--cms-border-input); border-radius: 4px;
    font-size: 12px; font-weight: 600; color: var(--cms-text-muted); cursor: pointer; white-space: nowrap;
    flex-shrink: 0; align-self: center;
}
.tab-close-all:hover { background: var(--cms-danger-tint); border-color: var(--cms-danger); color: var(--cms-danger-text); }
/* 다크: 모두닫기 hover 의 라이트 danger-tint(연분홍 ≈ 흰색)는 다크 표면에서 튀므로 어두운 hover 표면으로 대체(텍스트/보더는 danger 유지) */
html[data-cms-theme="dark"] .tab-close-all:hover { background: var(--cms-bg-hover); }
/* 활성 탭 텍스트색은 base 가 --cms-info-text(다크 자동 #93c5fd)로 수렴됨 → 별도 다크 오버라이드 불필요(중복 제거). */

/* Session Timer */
.session-timer {
    display: inline-flex; align-items: center;
    font-size: var(--cms-fs-sm); font-weight: 600; font-variant-numeric: tabular-nums;
    padding: 3px 10px; border-radius: 12px; border: 1px solid transparent;
    transition: color 0.5s, background 0.5s;
}
.session-timer.timer-green  { color: var(--cms-success-text); background: var(--cms-timer-green-bg); border-color: var(--cms-timer-green-border); }
.session-timer.timer-yellow { color: var(--cms-warn-text); background: var(--cms-timer-yellow-bg); border-color: var(--cms-timer-yellow-border); }
.session-timer.timer-red    { color: var(--cms-danger-text); background: var(--cms-timer-red-bg); border-color: var(--cms-timer-red-border);
    animation: timerBlink 1s infinite; }
@keyframes timerBlink {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0.4; }
}

.session-extend-btn {
    padding: 3px 10px; font-size: var(--cms-fs-xs); font-weight: 600;
    background: none; border: 1px solid #aaa; border-radius: 12px;
    color: #555; cursor: pointer; transition: all 0.15s;
}
.session-extend-btn:hover { background: var(--cms-timer-green-bg); border-color: var(--cms-success); color: var(--cms-success-text); }

/* Top Bar */
.cms-topbar {
    height: var(--topbar-height); background: var(--cms-bg-surface);   /* surface 토큰 = 다크모드 추종(라이트값 동일) */
    display: flex; align-items: center; padding: 0 20px; gap: 16px;
    position: sticky; top: 0; z-index: 100;
    border-bottom: 1px solid var(--cms-border-strong);            /* topbar ↔ tabbar 사이 1px 분리선 — sidebar-header 와 색 통일 */
}
.sidebar-toggle {
    background: none; border: 1px solid var(--border); border-radius: var(--radius);
    padding: 6px 10px; cursor: pointer; color: var(--text-muted); transition: all 0.15s;
    margin-left: -11px;
}
.sidebar-toggle:hover { background: var(--cms-gray-60); color: var(--text); }
.breadcrumb-nav { flex: 1; }
.topbar-right { display: flex; align-items: center; font-size: var(--cms-fs-sm); gap: 8px; }
.topbar-home-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    border: 1px solid var(--border); border-radius: var(--radius);
    color: var(--text-muted); text-decoration: none;
    transition: all .15s;
}
.topbar-home-btn:hover { background: var(--cms-gray-60); color: var(--text); }
.topbar-home-btn[aria-disabled="true"] { opacity: .4; pointer-events: none; cursor: default; }
/* 다크/라이트 개인 토글 버튼 (topbar-home-btn 과 동일 톤) */
.topbar-theme-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    border: 1px solid var(--cms-border-input); border-radius: var(--radius);
    background: var(--cms-bg-muted); color: var(--text); cursor: pointer;
    transition: all .15s;
}
.topbar-theme-toggle:hover { background: var(--cms-bg-hover); color: var(--primary); border-color: var(--primary); }
/* 다크 — 현재 sun 아이콘(라이트 전환)을 따뜻한 amber 로 표시해 어두운 톱바 위에서 명확히 인지(테두리 대비도 강화) */
html[data-cms-theme="dark"] .topbar-theme-toggle { border-color: var(--cms-border-input); background: var(--cms-bg-hover); color: var(--cms-amber-400); }
html[data-cms-theme="dark"] .topbar-theme-toggle:hover { color: var(--cms-amber-300); border-color: var(--cms-amber-400); }

/* ── GNB topbar 2행 (1행: 사이트 선택 / 2행: 브레드크럼) ─── */
.cms-topbar.cms-topbar-2row {
    height: auto; flex-direction: column; align-items: stretch;
    padding: 0; gap: 0;
}
.cms-topbar-2row .topbar-row {
    display: flex; align-items: center; gap: 12px; padding: 0 20px;
}
.cms-topbar-2row .topbar-row-main { height: var(--topbar-height); }
.cms-topbar-2row .topbar-row-crumb {
    height: 34px; border-top: 1px solid var(--border); background: #fafbfc;
}
.cms-topbar-2row .topbar-row-crumb .breadcrumb-nav { flex: 1; }
.cms-topbar-2row .topbar-row-crumb .breadcrumb { font-size: .85rem; }
.cms-topbar-2row + .cms-tabbar { top: calc(var(--topbar-height) + 34px); }

/* GNB 사이트 선택 영역 */
.topbar-site-picker {
    flex: 1; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.topbar-site-picker > label {
    white-space: nowrap; margin-bottom: 0; font-weight: 600; color: var(--text);
}
.topbar-site-picker #siteSelector { width: 400px; flex: 0 0 auto; }
.topbar-site-picker #siteSelector optgroup { font-weight: 700; color: var(--cms-info-text); }
/* Select2 컨테이너 크기/테두리 — form-select-sm 와 매칭 */
.topbar-site-picker .select2-container { flex: 0 0 auto; }
.topbar-site-picker .select2-container--default .select2-selection--single {
    height: 31px; border: 1px solid var(--cms-border-input); border-radius: var(--radius);
}
.topbar-site-picker .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 29px; padding-left: 10px; padding-right: 24px; font-size: .875rem; color: var(--text);
}
.topbar-site-picker .select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 29px;
}
/* select2 표면/텍스트 — vendor 고정 흰색(#fff/#444)을 토큰으로(라이트 동일값, 다크 자동 추종) */
.select2-container--default .select2-selection--single { background-color: var(--cms-bg-surface); }
.select2-container--default .select2-selection--single .select2-selection__rendered { color: var(--cms-text); }
.select2-dropdown { border-color: var(--cms-border-input); background-color: var(--cms-bg-surface); color: var(--cms-text); }
.select2-search--dropdown .select2-search__field {
    background-color: var(--cms-bg-surface); color: var(--cms-text); border-color: var(--cms-border-input);
}
.select2-results__group { font-weight: 700; color: var(--cms-info-text); }
.select2-container--default .select2-results__option--highlighted[aria-selected] {
    background: var(--primary); color: var(--cms-white);
}

/* [반응형] 좁은 폭(노트북·브라우저 확대 ≈1271/1024px)에서 topbar 가로 오버플로 방지 —
   고정 400px 사이트 셀렉터가 수축 불가라 row 가 뷰포트를 넘겨 .topbar-right 가 잘림.
   가용폭 내에서 셀렉터를 수축(min-width:0)시키되 넓은 화면 폭(400px)은 max-width 로 보존. */
@media (max-width: 1200px) {
    .topbar-site-picker { min-width: 0; }
    .topbar-site-picker #siteSelector,
    .topbar-site-picker .select2-container { width: auto; flex: 1 1 0; min-width: 0; max-width: 400px; }
}

/* Page Content */
.cms-content { flex: 1; padding: 24px; overflow-x: hidden; }
/* 페이지 헤더 — 타이틀 1행 + 우측 액션 1행으로 세로 분리 (전 페이지 통일).
   하단 여백은 토큰 단일 출처(--cms-space-3) — 본문과 너무 붙던 2px 를 여유 있게.
   (구 2px + content/site/layout-tpl 의 +2px override 를 전역 토큰으로 수렴) */
.page-header { margin-bottom: var(--cms-space-3); display: block; }
.page-title { font-size: 1.35rem; font-weight: 700; color: var(--text); margin: 0; }
/* 타이틀 행 — 제목 옆 보조버튼(가이드/새로고침 등) 인라인 배치. pageHeaderRich 프래그먼트 공통 클래스.
   화면별 .XXX-title-row(board/cmmn/post 등 동일 정의)를 단일 공통 클래스로 통합. */
.cms-page-title-row { display: flex; align-items: center; gap: var(--cms-space-3); }
.page-header-actions {
    display: flex; align-items: center; justify-content: flex-end; gap: var(--cms-space-3);
    margin: 0;
}

/* ============================================================
   Dashboard
   ============================================================ */
.stat-card {
    background: var(--cms-bg-surface); border-radius: var(--radius-lg); padding: 16px 20px;
    display: flex; align-items: center; gap: 14px; box-shadow: var(--card-shadow);
    border-left: 4px solid var(--border);
}
.stat-card.border-primary { border-left-color: var(--primary); }
.stat-card.border-success { border-left-color: var(--success); }
.stat-card.border-info    { border-left-color: var(--info); }
.stat-card.border-warning { border-left-color: var(--warning); }
.stat-card.border-danger  { border-left-color: var(--danger); }
.stat-card.border-secondary { border-left-color: var(--secondary); }
.stat-icon { font-size: 1.8rem; width: 44px; text-align: center; }
.stat-value { font-size: 1.6rem; font-weight: 700; line-height: 1; color: var(--text); }
.stat-label { font-size: var(--cms-fs-xs); color: var(--text-muted); margin-top: 2px; }
.quick-link {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: 20px 10px; border: 1px solid var(--border); border-radius: var(--radius-lg);
    text-decoration: none; color: #495057; transition: all 0.2s;
    font-size: var(--cms-fs-sm); font-weight: 600; min-height: 100px;
}
.quick-link:hover {
    background: var(--cms-bg-hover); border-color: var(--primary); color: var(--primary);
    transform: translateY(-2px); box-shadow: 0 4px 12px rgba(59,127,245,.15);
}
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 16px; margin-bottom: 16px; }
.quick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; }
.two-col-grid { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 992px) {
    .two-col-grid { grid-template-columns: 2fr 1fr; }
}

/* ============================================================
   AG Grid overrides
   ============================================================ */
/* ★selector 를 html .ag-theme-alpine(0,1,1)로 — ag-Grid v32 가 [class*="ag-theme-"](0,1,0) 변수 시트를
   cms.css 이후에 동적 주입해 동률-후순위로 이 블록을 덮던 문제(다크에서 그리드 흰색 잔존) 차단. */
html .ag-theme-alpine {
    --ag-font-size: var(--cms-fs-sm);
    --ag-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', sans-serif;
    --ag-header-height: 40px;
    --ag-row-height: 40px;
    --ag-border-color: var(--border);
    /* semantic 토큰으로 통일 → 라이트 동일(bg-surface=white·muted≈gray-60·text=gray-900) + 다크모드 자동 추종 */
    --ag-background-color: var(--cms-bg-surface);
    --ag-foreground-color: var(--cms-text);
    --ag-data-color: var(--cms-text);
    --ag-secondary-foreground-color: var(--cms-text-secondary);
    --ag-header-foreground-color: var(--cms-text-secondary);
    --ag-header-background-color: var(--cms-bg-muted);
    --ag-odd-row-background-color: var(--cms-bg-muted);
    --ag-row-hover-color: var(--cms-bg-hover);
    --ag-selected-row-background-color: var(--cms-bg-hover);
    --ag-control-panel-background-color: var(--cms-bg-muted);
    --ag-input-border-color: var(--cms-border-input);
    --ag-input-focus-border-color: var(--cms-action-primary);
}
.ag-theme-alpine .ag-header-cell-text { font-weight: 600; }
.ag-grid-wrapper { width: 100%; }

/* ============================================================
   Menu Tree
   ============================================================ */
.menu-tree-container { min-height: 300px; }
.jstree-default .jstree-anchor { font-size: 13.5px !important; height: 28px !important; line-height: 28px !important; }
.jstree-default .jstree-icon { line-height: 28px !important; }
/* 다크 — jstree vendor 기본 테마는 dark-on-dark(노드 텍스트 검정·hover/선택 옅은 회색) → 토큰 보정 */
html[data-cms-theme="dark"] .jstree-default .jstree-anchor { color: var(--cms-text); }
html[data-cms-theme="dark"] .jstree-default .jstree-anchor.jstree-hovered { background: var(--cms-bg-hover); color: var(--cms-text); box-shadow: none; border-radius: var(--radius); }
html[data-cms-theme="dark"] .jstree-default .jstree-anchor.jstree-clicked { background: var(--cms-action-primary); color: var(--cms-white); box-shadow: none; border-radius: var(--radius); }

/* 다크 — Jodit 에디터(.jodit_theme_dark) vendor 다크테마의 off-palette 회색을 CMS 토큰으로 재매핑.
   Jodit 사용 5화면(post.write/page/content/popup/board-skin) 공통. vendor 가 background 미설정한 .jodit-workplace 흰 띠도 보정. */
html[data-cms-theme="dark"] .jodit-container.jodit_theme_dark {
    --jd-dark-background-color: var(--cms-bg-surface);
    --jd-dark-background-darknes: var(--cms-bg-muted);
    --jd-dark-border-color: var(--cms-border-subtle);
    --jd-dark-text-color: var(--cms-text);
    --jd-dark-toolbar-color: var(--cms-bg-muted);
    --jd-dark-icon-color: var(--cms-text-secondary);
}
html[data-cms-theme="dark"] .jodit_theme_dark .jodit-workplace { background-color: var(--cms-bg-surface); }

/* 다크 — .form-select 미사용 bespoke <select>(그리드 인라인 토글 등)도 surface 추종 + 인라인 code 가독 */
html[data-cms-theme="dark"] select { background-color: var(--cms-bg-surface); color: var(--cms-text); }
html[data-cms-theme="dark"] code { background-color: var(--cms-bg-muted); color: var(--cms-text); }

/* ============================================================
   Grid 빈상태 (figma NODATA 정합) — window.cmsEmptyState() 와 1:1
   ============================================================ */
.cms-grid-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 32px 16px; }
.cms-grid-empty-ico { width: 56px; height: 56px; border-radius: 50%; background: #f1f5f9; display: flex; align-items: center; justify-content: center; color: #cbd5e1; font-size: 22px; }
.cms-grid-empty-main { color: #475569; font-size: 14px; font-weight: 600; }
.cms-grid-empty-sub { color: #94a3b8; font-size: 12px; }

/* ============================================================
   Toast Notification
   ============================================================ */
.cms-toast-container {
    position: fixed; top: 70px; right: 20px; z-index: var(--cms-z-toast);
    display: flex; flex-direction: column; gap: 8px;
}
.cms-toast {
    background: var(--cms-bg-surface); color: var(--cms-text); border-radius: 8px; padding: 12px 16px;
    box-shadow: 0 4px 20px rgba(0,0,0,.15); display: flex; align-items: center;
    gap: 10px; font-size: var(--cms-fs-sm); min-width: 280px; max-width: 380px;
    animation: slideInRight 0.3s ease; border-left: 4px solid var(--success);
}
.cms-toast.error   { border-left-color: var(--danger); }
.cms-toast.warning { border-left-color: var(--warning); }
.cms-toast.info    { border-left-color: var(--info); }
.toast-close {
    margin-left: auto; background: none; border: none; cursor: pointer;
    color: var(--text-muted); font-size: 16px; line-height: 1; padding: 0 2px;
}
@keyframes slideInRight  { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes slideOutRight { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } }

/* Toast Confirm — sticky 형태, 화면 중앙 정렬, 메시지 + 확인/취소 버튼 */
.cms-toast.confirm {
    position: fixed;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    align-items: flex-start;
    gap: 18px;
    min-width: 560px;
    max-width: 760px;
    padding: 28px 32px;
    border-left-width: 6px;
    border-radius: 12px;
    font-size: 17px;
    z-index: var(--cms-z-toast-top);
    box-shadow: 0 18px 56px rgba(0,0,0,.28);
    animation: confirmFadeIn .18s ease forwards;
}
.cms-toast.confirm.closing { animation: confirmFadeOut .18s ease forwards; }
.cms-toast.confirm > i { margin-top: 4px; font-size: 28px; }
.cms-toast .toast-confirm-body {
    flex: 1; display: flex; flex-direction: column; gap: 20px;
    min-width: 0;
}
.cms-toast .toast-confirm-msg {
    line-height: 1.55; word-break: keep-all; font-size: 17px;
    white-space: pre-line;
}
.cms-toast .toast-confirm-actions {
    display: flex; gap: 10px; justify-content: flex-end;
}
.cms-toast .toast-confirm-actions .btn { padding: 9px 24px; font-size: 15px; min-width: 86px; }

@keyframes confirmFadeIn {
    from { opacity: 0; transform: translate(-50%, -48%); }
    to   { opacity: 1; transform: translate(-50%, -50%); }
}
@keyframes confirmFadeOut {
    from { opacity: 1; transform: translate(-50%, -50%); }
    to   { opacity: 0; transform: translate(-50%, -48%); }
}

/* Toast Center — confirm 과 동일 크기·위치, 자동 닫힘 (showToast 의 중앙·대형 버전) */
.cms-toast.center {
    position: fixed;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    align-items: center;
    gap: 14px;
    min-width: 460px;
    max-width: 640px;
    padding: 22px 26px;
    border-left-width: 5px;
    border-radius: 10px;
    font-size: 15px;
    z-index: var(--cms-z-toast-top);
    box-shadow: 0 14px 48px rgba(0,0,0,.24);
    animation: confirmFadeIn .18s ease forwards;
}
.cms-toast.center.closing { animation: confirmFadeOut .18s ease forwards; }
.cms-toast.center > i      { font-size: 22px; }
.cms-toast.center > span   { line-height: 1.55; word-break: keep-all; font-size: 15px; }
.cms-toast.center .toast-close { font-size: 22px; }

/* ============================================================
   Resource Grid
   ============================================================ */
.upload-area {
    border: 2px dashed var(--border); border-radius: 8px; padding: 40px;
    text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s;
}
.upload-area.dragover { border-color: var(--primary); background: var(--cms-bg-hover); }
.resource-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.resource-item {
    position: relative; border: 1px solid var(--border);
    border-radius: var(--radius); overflow: hidden;
}
.resource-item img { width: 100%; height: 120px; object-fit: cover; display: block; }
.resource-item .resource-info { padding: 6px 8px; background: var(--cms-bg-surface); }
.resource-item .resource-info small { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.resource-item .resource-actions { position: absolute; top: 4px; right: 4px; opacity: 0; transition: opacity 0.2s; }
.resource-item:hover .resource-actions { opacity: 1; }
.upload-progress { display: none; }

/* ============================================================
   Code element
   ============================================================ */
code {
    background: var(--cms-gray-110); border: 1px solid var(--border); border-radius: 3px;
    padding: 1px 5px; font-size: 12px; color: #9333ea; font-family: 'Courier New', monospace;
}

/* ============================================================
   Summernote overrides (lite)
   ============================================================ */
.note-editor.note-frame { border-radius: var(--radius); border-color: var(--cms-border-input); }

/* ============================================================
   Responsive
   ============================================================ */
/* [UI/UX 확대대응] 992~1440px 중간 구간 — 브라우저 확대(≈110~125%) 시 iframe 콘텐츠 폭이
   1271~1480px 로 좁아지는데 기존 breakpoint(992/768)가 미해당이라 여백이 그대로였음.
   콘텐츠 좌우 패딩을 24→16px 로 줄여 좁아진 폭에서 가용 공간을 확보(태블릿 992 이하 구간과 disjoint → 회귀 없음). */
@media (max-width: 1440px) and (min-width: 992px) {
    .cms-content { padding: 16px 16px; }
}
/* [Phase E-4] 992px 이하 — 태블릿 breakpoint. 사이드바 폭 200px 로 축소 (collapse 아님, 좁힘). */
@media (max-width: 991.98px) and (min-width: 769px) {
    :root { --sidebar-width: 200px; }
    .cms-content { padding: 20px; }
}
@media (max-width: 768px) {
    .cms-sidebar { transform: translateX(calc(-1 * var(--sidebar-width))); }
    .cms-sidebar.mobile-open { transform: translateX(0); }
    .cms-main { margin-left: 0; }
    .cms-content { padding: 16px; }
    /* .page-header 는 기본이 display:block 이라 모바일에서도 자식이 세로로 쌓임 — flex-direction 불필요 */
}

/* jstree DnD helper — vendor 기본 테마 CSS 누락 보완.
   pointer-events 가 auto 면 vakata-dnd 헬퍼가 마우스 이벤트를 가로채 dnd_move/dnd_stop 의
   event.target 이 항상 html 로 잡혀 외부 드롭 핸들러가 동작하지 않음. */
#vakata-dnd { pointer-events: none; }

/* ============================================================
   [Phase E-1] 2-Panel 레이아웃 유틸 (전역) + :focus-visible 글로벌
   ============================================================ */
.layout-2panel {
    display: grid;
    grid-template-columns: var(--layout-2panel-left) 1fr;
    gap: var(--cms-space-md);
    align-items: start;
}
.layout-2panel__left  { min-width: 0; }
.layout-2panel__right { min-width: 0; }

/* 992px 이하 — 좌·우 분리 스택 */
@media (max-width: 991.98px) {
    .layout-2panel { grid-template-columns: 1fr; }
}

/* 키보드 포커스 가시화 — 마우스 클릭 시는 표시 안 함(:focus-visible 의 default 동작) */
button:focus-visible,
a:focus-visible,
[role="tab"]:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.ag-cell-focus {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ag-Grid 셀 포커스 시 outline 중복 방지 */
.ag-cell-focus { outline-offset: -2px; }

/* ============================================================
   [Phase E-3] cmsAjax loading 옵션용 visual feedback
   ============================================================ */
.cms-loading {
    position: relative;
    pointer-events: none;
    opacity: 0.7;
}
.cms-loading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border: 3px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: cms-loading-spin 0.8s linear infinite;
    z-index: 10;
}
@keyframes cms-loading-spin {
    to { transform: rotate(360deg); }
}

/* ============================================================
   AJAX 로딩 오버레이 — 전 페이지 공통
   cms.js 가 DOM ready 시 #cmsLoadingOverlay 삽입 + ajaxStart/Stop 바인딩
   ============================================================ */
.cms-loading-overlay {
    position: fixed;
    inset: 0;
    background: rgba(255, 255, 255, 0.82);
    -webkit-backdrop-filter: blur(2px);  /* Safari(WebKit)는 프리픽스 필수 — 없으면 blur 미적용 */
    backdrop-filter: blur(2px);
    z-index: 9500;                  /* sidebar(1000)·modal(2000) 위, toast(9999) 아래 */
    display: none;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
}
.cms-loading-overlay.is-active { display: flex; }
.cms-loading-overlay .cms-loading-spinner {
    width: 88px;
    height: 88px;
    border: 8px solid var(--cms-slate-200);
    border-top-color: var(--cms-action-primary);
    border-radius: 50%;
    animation: cms-loading-spin 0.8s linear infinite;
    box-shadow: 0 6px 18px rgba(15, 23, 42, .12);
}

/* ============================================================
   ag-Grid 컬럼 헤더 — 전 화면 공통 중앙 정렬 (운영 규칙)
   ============================================================ */
.ag-theme-alpine .ag-header-cell .ag-header-cell-label { justify-content: center; }
.ag-theme-alpine .ag-header-group-cell-label { justify-content: center; }

/* ============================================================
   이미지 리소스 선택 다이얼로그 (cms.resource-picker.js)
   ============================================================ */
.crp-toolbar {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 12px;
}
.crp-scope {
    display: flex;
    gap: 12px;
    white-space: nowrap;
}
.crp-hint {
    font-size: 12px;
    color: var(--cms-gray-500);
    margin-bottom: 10px;
}
.crp-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    max-height: 52vh;
    overflow-y: auto;
    padding: 2px;
}
.crp-card {
    border: 1px solid var(--cms-gray-200);
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    background: var(--cms-bg-surface);
    transition: border-color .12s, box-shadow .12s;
}
.crp-card:hover { border-color: var(--cms-blue-300); }
.crp-card.selected {
    border-color: var(--cms-blue-700);
    box-shadow: 0 0 0 2px rgba(37, 99, 235, .25);
}
.crp-thumb {
    width: 100%;
    height: 110px;
    background: var(--cms-gray-110);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.crp-thumb img { width: 100%; height: 100%; object-fit: cover; }
.crp-name {
    padding: 6px 8px;
    font-size: 12px;
    color: var(--cms-gray-750);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.crp-loading,
.crp-empty {
    grid-column: 1 / -1;
    text-align: center;
    color: var(--cms-gray-400);
    padding: 36px 20px;
}
.crp-empty i { font-size: 32px; opacity: .4; display: block; margin-bottom: 10px; }
.crp-empty-sub { font-size: 12px; margin-top: 4px; }

