@charset "utf-8";

/* ======================================================= MOBILE.CSS — 모바일 전용 스타일 breakpoint : max-width 768px desktop에서는 이 파일의 스타일이 전혀 적용되지 않는다. ======================================================= */

/* ── 데스크톱에서 숨겨두는 모바일 전용 엘리먼트 ──────── */

/* 햄버거 버튼 */
/* 햄버거 — 손가락용 36×36 박스 안에 20px 막대. 기하는 여기(기본 규칙)에 두고 @media 는 보이기만 정한다.
   ① align-items:flex-start — 막대를 박스 왼쪽 끝에 붙인다. 줄맞춤의 기준은 눌리는 박스가 아니라
      보이는 막대라, 가운데 두면 본문보다 8px 안쪽에서 시작해 어긋나 보인다(§82).
   ② margin-right:-12px — 그 반대쪽(오른쪽)에 남는 16px 빈 칸이 옆 항목과의 간격처럼 보여
      "너무 떨어져" 보인다. 박스는 그대로 두고 뒤 항목을 당겨 눈에 보이는 간격만 정상으로 만든다
      (박스를 줄이면 누르기 어려워진다). */
.mob_hamburger_btn { display: none; width: 36px; height: 36px; flex-direction: column; align-items: flex-start; justify-content: center; gap: 5px; background: none; border: none; cursor: pointer; padding: 4px 0; margin-right: -12px; border-radius: 4px; flex-shrink: 0; transition: background 0.15s; }
.mob_hamburger_btn:hover { background: rgba(255,255,255,0.08); }
.mob_hamburger_btn span { display: block; width: 20px; height: 2px; background: var(--c-primary); border-radius: 2px; transition: transform 0.22s, opacity 0.22s; }

/* 열린 상태: X 모양 */
.mob_hamburger_btn.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.mob_hamburger_btn.is-open span:nth-child(2) { opacity: 0; }
.mob_hamburger_btn.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* 메뉴 백드롭 */
.mob_menu_backdrop { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.55); z-index: 250; }
.mob_menu_backdrop.on { display: block; }

/* 패널 닫기(← 목록) 버튼 */
.mob_panel_close_btn { display: none; align-items: center; gap: 4px; height: 28px; padding: 0 10px; background: var(--c-grid-hover); border: 1px solid var(--c-border-dark); border-radius: 4px; color: var(--c-text-sub); font-size: 12px; font-weight: 600; cursor: pointer; flex-shrink: 0; white-space: nowrap; transition: background 0.12s; }
.mob_panel_close_btn:hover { background: var(--c-bg-hover); color: var(--c-text); }
.mob_panel_close_btn::before { content: '←'; font-size: 13px; }

/* ======================================================= @media (max-width: 768px) ======================================================= */
@media (max-width: 768px) {
	.moca_slider .msl_input { height: 36px; }
	.moca_slider .msl_input::-webkit-slider-thumb { width: 24px; height: 24px; margin-top: -9px; }
	.moca_slider .msl_input::-moz-range-thumb { width: 24px; height: 24px; }

    /* ── 기본 ── */ body { overflow: hidden; }

    /* ── 햄버거 버튼 표시 ── (기하는 위 기본 규칙에 있다 — 여기서는 보이기만 정한다) */
    .mob_hamburger_btn { display: flex; }

    /* ── 헤더 ── */ .header { padding: 0 var(--m-edge); gap: 6px; height: 48px; }
    .header h3 { display:none;}
    /* 테마·메뉴검색은 폰 헤더에 두지 않는다 — 어디로 옮길지는 프로젝트 셸이 정한다
       (demo 는 자기 전체메뉴 패널로 옮긴다). 엔진은 "헤더에서 감춘다"까지만 책임진다. */
    .header .header_menu_search { display: none; }
    .header .header_theme_select { display: none; }

    .header_username { max-width: 72px; font-size: 11px; display:none }
    .header_logout_btn { padding: 4px 10px; font-size: 11px; }

    /* ── 사이드바: 슬라이드 오버레이 ── */ .left { position: fixed; top: 0; left: 0; width: 240px; height: 100%; z-index: 300; transform: translateX(-100%); transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5); padding-top: 0; }
    .left::before { display: block; height: auto; padding: 56px 16px 10px; }
    .left.mob_open { transform: translateX(0); }


	.menufold {display:none;}
    /* ── MDI 모바일: 탭바 숨기고 간단한 헤더바로 대체 ── */
    .mdi_body {border:none;}
    .mdi_tabbar { display: none; }
    .mdi_split_btn { display: none; }
    .mdi_box.mdi_split { flex-direction: column; }
    .mdi_box.mdi_split .resizingbar { display: none; }
    .mdi_box.mdi_split .mdi_ly:not(.mdi_ly_sub) { flex: 1; width: auto; }
    .mdi_box.mdi_split .mdi_ly_sub { display: flex; }
    .mdi_ly{padding: 0;}
    :root.theme-light .mdi_panel{padding: 0;}
    /* ── 콘텐츠 영역: 높이 체인 확보 ── */ .container { overflow: hidden; }
    .right { overflow: hidden; /* auto → hidden: 내부에서 스크롤 처리 */ width: 100%; padding: 0; /* base.css padding:12px 제거 */ display: flex; flex-direction: column; }

    /* ── 검색 테이블: 조건 한 줄에 하나씩 (CSS Grid) ── */ /* tr → 2컬럼 그리드: 라벨(72px) | 입력(나머지) */ .moca_table_search [data-m-type="tbody"], .moca_table_search [data-m-type="tr"] { display: block; width: 100%; }
    .moca_table_search [data-m-type="tr"] { display: grid; grid-template-columns: max-content 1fr; gap: 6px 6px; align-items: center; }

    /* ★ th(라벨)는 좁은 폭에서 **왼쪽 정렬**이다 (2026-08-31 지시).
       넓은 화면에서는 오른쪽 정렬이 입력칸과 붙어 읽기 좋지만, 폰에서는 라벨 폭이 제각각이라
       글자가 저마다 다른 자리에서 시작해 **시작선이 흐트러진다**(실측: 라벨 글자 x=160,
       바로 아래 조회 버튼 x=78). 왼쪽으로 당겨 조회 버튼·목록과 같은 세로선에서 시작하게 한다.
       남는 폭은 입력 컴포넌트가 가져간다(아래 td). */
    .moca_table_search [data-m-type="th"] { min-width: unset; width: auto; height: 30px; font-size: 12px; font-weight: 600; display: flex; align-items: center; justify-content: flex-start; padding: 0; white-space: nowrap; margin-right: 0; margin-left: 0; }
    /* 입력칸은 남는 폭을 채운다 — 라벨을 당긴 만큼 넓어진다 */
    .moca_table_search [data-m-type="td"] { flex: 1 1 auto; min-width: 0; }
    .moca_table_search [data-m-type="td"] > .moca_input,
    .moca_table_search [data-m-type="td"] > .moca_combo { width: 100%; }

    /* td: 입력 영역 — 전체 너비 */ .moca_table_search [data-m-type="td"] { height: 30px; display: flex; align-items: center; }

    /* 마지막 td (버튼 영역): 두 컬럼 모두 차지, 우측 정렬 */ .moca_table_search [data-m-type="td"]:last-child { grid-column: 1 / -1; justify-content: flex-end; gap: 6px; height: auto; padding-top: 2px; }

    /* 입력 컴포넌트: td 안에서 전체 너비 채우기 */ .moca_table_search [data-m-type="td"] > div { width: 100% !important; min-width: 0; }
    .moca_table_search [data-m-type="td"] > div input, .moca_table_search [data-m-type="td"] > div select { box-sizing: border-box; }
    .moca_table_search [data-m-type="td"] button.btn_search { width: 100% }

    /* ── 그리드 폰트 ── */ .moca_grid_body thead th { font-size: 11px; padding: 0 3px; }
    .moca_grid_body tbody td { font-size: 11px; padding: 0 3px; }
    .grid_title { font-size: 12px; }

    /* ── 그리드 툴바: 커스텀 아이템(input·combo·radio 등, §29)이 많으면 한 줄(38px 고정)을 넘어
       lta 의 overflow:hidden 에 잘려 조작 불가가 된다(TPL013 실측 853px) — 줄바꿈 허용 ── */
    .moca_grid_toolbar { height: auto; min-height: 38px; flex-wrap: wrap; }
    .moca_grid_toolbar > .lta { flex-wrap: wrap; }

    /* ── 푸터 숨김 ── */ .footer { display: none; }

    /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 상하 분할 레이아웃 (bd_split_wrap) bd_panel → 전체화면 오버레이로 변환 display:none 인라인 스타일이 CSS보다 우선하므로 JS가 style.display='' 로 보이게 하면 자동 오버레이 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ .bd_split_wrap { flex: 1; /* 남은 높이 전부 차지 */ min-height: 0; /* flex 자식이 shrink 가능하도록 */ flex-direction: column; overflow: hidden; }

    /* 그리드: 남은 높이 전부 채움 */ .bd_split_wrap > [data-m-type="grid"], .bd_split_wrap > .moca_grid { flex: 1; min-height: 0; }

    /* 패널: 전체화면 오버레이 */ .bd_split_wrap .bd_panel { position: fixed; inset: 0; z-index: 7001; max-height: 100%; border-top: none; display: flex; flex-direction: column; overflow-y: auto; background: var(--c-surface); box-shadow: none; }

    /* bd_panel_body: 폼 영역 스크롤 + 파일업로드 고정 */ .bd_split_wrap .bd_panel .bd_panel_body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }

    /* ── detailPanel 공통: split / LR 둘 다 적용 ───────────── 이 블록만 수정하면 두 레이아웃 모두 반영됨 ──────────────────────────────────────────────────────── */ /* 폼: 남은 공간 채우고 내용이 길면 내부 스크롤 */ .bd_split_wrap .bd_panel .bd_panel_body .moca_table_form, .bd_split_wrap .bd_panel .bd_panel_body div.moca_table_form, .bd_lr_right.mob_lr_active .bd_panel_body .moca_table_form, .bd_lr_right.mob_lr_active .bd_panel_body div.moca_table_form { flex: 1; min-height: 0; overflow-y: auto; }

    /* CKEditor 콘텐츠 영역: 뷰포트 높이 기준으로 남은 공간 채우기 100svh - (헤더 ~66px + 제목행 ~48px + 작성자행 ~48px + 툴바 ~38px + 파일업로드 160px) */ .bd_split_wrap .bd_panel .bd_panel_body .cke_contents, .bd_lr_right.mob_lr_active .bd_panel_body .cke_contents { height: calc(100% - 67px) !important; min-height: 80px !important; }

    /* 파일업로드: 하단 고정 — 해상도와 무관하게 항상 표시 */ .bd_split_wrap .bd_panel .bd_panel_body [data-m-type="fileupload"], .bd_lr_right.mob_lr_active .bd_panel_body [data-m-type="fileupload"] { flex-shrink: 0; height: 160px !important; }

    /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 좌우 분할 레이아웃 (bd_lr_wrap) bd_lr_right → 전체화면 오버레이 .mob_lr_active 클래스가 있을 때만 표시 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ .bd_lr_wrap { flex: 1; /* 남은 높이 전부 차지 */ min-height: 0; flex-direction: column; overflow: hidden; }
    .bd_lr_left { width: 100% !important; flex: 1; min-height: 0; overflow: hidden; /* 그리드 fauto가 작동하도록 */ }

    /* 우측 패널: 기본 숨김 */ .bd_lr_right { display: none; margin-left: 0; }

    /* 우측 패널: 활성화 시 전체화면 오버레이 */ .bd_lr_right.mob_lr_active { display: flex; position: fixed; inset: 0; z-index: 7001; flex-direction: column; background: var(--c-surface); overflow-y: auto; }
    .bd_lr_right.mob_lr_active .bd_panel { border-top: none; flex: 1; display: flex; flex-direction: column; }
    .bd_lr_right.mob_lr_active .bd_panel_body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }

    /* LR 레이아웃 내 그리드는 남은 공간 채움 (폼/파일업로드는 공통 블록에서 처리) */ .bd_lr_right.mob_lr_active .bd_panel_body [data-m-type="grid"] { flex: 1; min-height: 80px; }

    /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 패널 공통 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */ .mob_panel_close_btn { display: flex; }
    .bd_modal_title { display:none; }

    /* 버튼영역: 좁은 폭에서 버튼이 5개쯤 되면 flex 축소로 버튼 글자가 세로로 꺾인다(TPL010 실측 2026-08-14)
       — 버튼은 원래 폭을 지키고(shrink 0) 넘치면 다음 줄로 감는다 */
    .bd_modal_btns { gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
    .bd_modal_btns button { flex-shrink: 0; }

    /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
       레이어 팝업($p.openPop → .bd_overlay .bd_modal) — PC 와 동일한 골격 유지 (2026-07-22)
       ① 타이틀 표시: 위 .bd_modal_title 숨김은 "상세 패널 헤더"용인데 팝업 헤더까지 같이
          숨겨져 제목이 안 보였다 — 팝업(.bd_overlay 하위)만 되살린다.
       ② 팝업 안 레이아웃: 레이아웃 모바일 규칙(세로스택·내용높이·그리드 칸 60vh, moca.css)이
          팝업 안까지 적용되면 바디가 내용보다 작아져 스크롤이 생기고 하단 [닫기]가 가려진다.
          팝업 표준은 루트 고정높이(data-m-height, PART A §15)라 PC 와 같은 비율(flex) 골격을
          그대로 쓰는 게 맞다 — 칸 flex 를 PC 값으로 복원한다. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
    .bd_overlay .bd_modal_header .bd_modal_title { display: flex; }
    .bd_overlay .bd_modal { width: calc(100vw - 16px) !important; max-width: calc(100vw - 16px); max-height: calc(100svh - 24px); }
    .bd_overlay .bd_modal_body { padding: 12px; }
    .moca_popup_body .moca_layout > .moca_layout_pane { flex: var(--m-grow, 1) 1 0; overflow: auto; }
    .moca_popup_body .moca_layout > .moca_layout_pane.moca_layout_pane_fixed { flex: 0 0 var(--m-basis, auto); }
    .moca_popup_body .moca_layout > .moca_layout_pane.moca_layout_pane_fit { flex: 0 0 auto; }
    .moca_popup_body .moca_layout > .moca_layout_pane.moca_grid { height: auto; min-height: 0; }

    /* ── 폼 테이블 ──
       th(라벨)는 숨기지 않고 컴팩트(92px)하게 유지한다 — 구 display:none 은 CRUD 상세폼(입력 하나가
       행 전체) 전제였는데, 라벨이 곧 내용인 설정·데모형 폼(TPL021·042~044 등)에서 행 의미가 통째로
       사라졌다(2026-08-14 실측). td 는 줄바꿈 허용 — 입력+버튼+설명이 한 행인 폼에서 nowrap 이면
       버튼이 화면 밖으로 잘려 접근 불가가 되고, 설명 span 은 min-content 로 짜부라져 글자가 세로로
       한 자씩 떨어진다(TPL042·044 실측). */
    div.moca_table_form [data-m-type="th"] { width: 92px; min-width: 92px; padding: 8px; font-size: 12px; white-space: normal; }
    div.moca_table_form [data-m-type="td"] { font-size: 12px; flex-wrap: wrap; min-width: 180px; }

    /* 한 행에 라벨/입력 2쌍(th td th td)인 CRUD 폼: 좁은 폭에선 쌍 단위로 줄바꿈(라벨 92 + 입력 최소 180
       = 272px 를 못 채우면 다음 줄) — nowrap 이면 뒤 쌍의 입력이 화면 밖으로 잘린다(TPL003 상세 실측) */
    div.moca_table_form [data-m-type="tr"] { flex-wrap: wrap; }

    /* 폼·그리드 툴바 부제목(sublabel, .moca_table_title): 좁은 폭은 라벨+버튼만으로 꽉 차 부제목이
       잘린 채 화면 밖까지 밀린다(453~498px 실측) — 모바일에선 숨긴다(PC 전용 보조설명) */
    .moca_table_title { display: none; }

    /* 기간달력(from~to): 일시형(19자)은 입력 두 개(140px×2)가 좁은 폭 한 줄에 안 들어가 화면 밖으로
       잘린다(TPL043 실측) — 컴포넌트 안에서 줄바꿈(to 입력+달력버튼이 다음 줄로) */
    div[data-m-type="inputMultiCalendar"] > div { flex-wrap: wrap; }

    /* ── page_wrap / page_root: 높이 100% 확보 ── */ .page_wrap, .page_root { height: 100%; overflow: hidden; }

    /* ── 검색 영역: 높이 고정 (flex shrink 방지) ── */ .moca_table_search { flex-shrink: 0; }

    /* ── COM_TITLE 프레임: 높이 고정 ── */ [data-m-type="frame"][data-m-src*="COM_TITLE"] { flex-shrink: 0; }
    .cke_contents { min-height: unset; }

    /* ── 팝업 딤 backdrop: 달력(단일/멀티)·그리드 필터 — 모바일 전용 시각적 딤.
       달력은 body 포탈 직계 팝업의 바깥 그림자로 딤을 만든다. ::before 를 달력 자식으로 두면
       투명한 body/footer 안쪽까지 딤이 칠해져 라이트 테마 내용이 어두워진다.
       그림자는 팝업 바깥에만 그려지고 포인터 대상도 아니어서 기존 바깥클릭 닫기 동작을 보존한다. */
    body > .moca_calendar, body > .moca_calendar_fromto {
        box-shadow: var(--shadow-md), 0 0 0 200vmax rgba(0, 0, 0, 0.55);
    }
    /* 그리드 필터는 기존 구조 유지. pointer-events:none 으로 바깥클릭을 그대로 통과시킨다. */
    .itemTable::before {
        content: ''; position: fixed; inset: 0;
        background: rgba(0, 0, 0, 0.55); z-index: -1; pointer-events: none;
    }

    /* ── 팝업 크기 확대: 모바일에서 화면 폭 거의 전부 + 높이 50% 이상 차지 ──
       width 의 !important 는 JS 인라인 스타일(달력 260px 기본폭, 필터는 컬럼폭)을 이기기 위함.
       .itemTable > ul 높이도 JS 가 인라인(최대 140px)으로 주므로 !important 로 덮는다. */
    /* 터치용으로 키운 치수 — 여기도 em 이라야 글자 배율을 따라간다(§15-3-4). 12px 기준 환산.
       폭은 화면을 넘지 않게 calc(100vw-32px) 가, 과도하게 넓어지지 않게 max-width 가 잡는다. */
    .moca_calendar { width: calc(100vw - 32px) !important; max-width: 35.83em; }
    .moca_calendar_body th { height: 2.5em; font-size: 12px; }
    .moca_calendar_body td { height: 4.17em; }
    .moca_calendar_body td button { font-size: 14px; }
    .moca_calendar_body li button { font-size: 14px; padding: 10px 8px; }
    .moca_calendar_header button { font-size: 13px; padding: 0.46em 0.77em; }

    /* 멀티캘린더: 달력 2벌 + 빠른선택 + 버튼이 세로로 쌓임 — 실기기(아이폰12 Pro 등) 사파리는
       주소창/툴바 때문에 가용 높이가 ~660px 라, 단일 달력 크기 그대로면 [닫기]/[확인]이 스크롤
       아래로 밀린다(2026-07-22 보고). 전체가 한 화면(≤600px)에 들어오도록 셀·헤더·버튼을 압축한다.
       (아래 단일 달력용 .moca_calendar_body 규칙보다 특이도가 높아 멀티에는 이 값이 이긴다) */
    .moca_calendar_fromto .moca_calendar_body th { height: 1.83em; font-size: 11px; }
    .moca_calendar_fromto .moca_calendar_body td { height: 2.17em; }
    .moca_calendar_fromto .moca_calendar_body td button { font-size: 12px; }
    .moca_calendar_fromto .moca_calendar_header button { font-size: 12px; padding: 3px 8px; }

    .itemTable { width: calc(100vw - 32px) !important; max-width: 430px; }
    .itemTable > ul { height: 50svh !important; }
    .itemTable > ul > li { padding: 10px 12px; }
    .itemTable > ul > li label { font-size: 14px; }
    .itemTable > ul > li input[type="checkbox"] { width: 18px; height: 18px; }

    /* 멀티캘린더: 화면 중앙 모달 */ .moca_calendar_fromto { position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; flex-direction: column !important; min-width: unset !important; width: calc(100vw - 32px) !important; max-width: 430px; z-index: 9999 !important; max-height: calc(100svh - 40px); overflow-y: auto; border-radius: var(--radius-md); }

    /* 달력 영역: 위쪽 */ .moca_calendar_fromto .moca_calendar_rta { order: 1; padding: 4px 4px 0; overflow: unset; }
    .moca_calendar_fromto .moca_calendar_row { flex-direction: column; gap: 0; }

    /* 빠른선택 + 버튼: 아래쪽 가로 배열 — contain:size(PC 높이제외용) 유지 시 세로배치에서 높이 0 으로 붕괴하므로 해제 */
    .moca_calendar_fromto .moca_calendar_lta { order: 2; width: 100%; flex-shrink: 0; contain: none; border-right: none; border-top: 1px solid var(--c-border); border-radius: 0 0 var(--radius-md) var(--radius-md); flex-direction: row; align-items: center; }
    .moca_calendar_fromto .moca_calendar_lta .moca_calendar_list { display: flex; flex-direction: row; flex-wrap: wrap; overflow-y: unset; gap: 4px; padding: 6px; }
    .moca_calendar_fromto .moca_calendar_lta .moca_calendar_list li { margin-bottom: 0; }
    .moca_calendar_fromto .moca_calendar_lta .moca_calendar_footer { border-top: none; border-left: 1px solid var(--c-border); flex-shrink: 0; flex-wrap: nowrap; padding: 6px; gap: 6px; }
    .moca_calendar_fromto .moca_calendar_lta .moca_calendar_btn_cancel, .moca_calendar_fromto .moca_calendar_lta .moca_calendar_btn_ok { height: 32px; font-size: 12px; min-width: 56px; }
    .moca_calendar_fromto .moca_calendar_lta .moca_calendar_list button { padding: 5px 7px; font-size: 11px; }
    .chart_row.r3_7 { grid-template-columns: repeat(1, 1fr); }

    /* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
       위젯 대시보드 (TDEMO_WIDGET_DASHBOARD) — 768px
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */

    /* 래퍼 */
    .wdash_inner { padding: 12px; min-width: unset; }

    /* 헤더: 제목 위 / 버튼 아래 2줄 */
    .wdash_hd { flex-wrap: wrap; gap: 8px; align-items: flex-start; }
    .wdash_hd_right { width: 100%; justify-content: flex-end; flex-wrap: wrap; gap: 6px; }
    .wdash_hd_left .wdash_title { font-size: 15px; }
    .btn_dsh_refresh, .btn_dsh_edit { padding: 5px 12px; font-size: 11px; }
    .btn_dsh_save, .btn_dsh_cancel { padding: 5px 10px; font-size: 11px; }
    .btn_dsh_add { padding: 5px 10px; font-size: 11px; }

    /* 편집 배너 */
    .edit_banner_txt { font-size: 11px; line-height: 1.5; }

    /* 그리드: 2컬럼, 모바일에서는 높이 고정 해제 — 콘텐츠 높이만큼 자동 */
    /* 모바일 행 높이는 auto(내용 기반) — 그래서 카드가 **로드 전에 자기 크기를 미리 잡아야** 한다.
       아래 min-height 가 없으면 카드들이 빈 채로 접혀 위로 몰렸다가 위젯이 로드되는 순서대로
       아래로 펼쳐져 화면 전체가 출렁였다(2026-08-27 지적 — "특히 모바일"). 크기 군은 PC 의
       행 스팬(ws_*)을 그대로 따르되 폰 화면에 맞게 줄인 값. 내용이 더 크면 auto 로 늘어난다. */
    .widget_grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: auto; gap: 10px; }
    .widget_item        { min-height: 220px; }   /* 기본 1행(차트·리스트) */
    .widget_item.ws_rh  { min-height: 84px;  }   /* ½행(KPI) */
    .widget_item.ws_r2  { min-height: 320px; }   /* 2행(달력 등) */
    .widget_item.ws_r3  { min-height: 400px; }
    /* 모든 높이 클래스 무효화 — 모바일에선 내용 크기대로 */
    .widget_item,
    .widget_item.ws_rh,
    .widget_item.ws_r2,
    .widget_item.ws_r3 { grid-row: auto; }
    .widget_item.ws_c2, .widget_item.ws_c3,
    .widget_item.ws_c4 { grid-column: span 2; }

    /* KPI 카드 작게 */
    .widget_kpi_inner { padding: 14px 12px; gap: 10px; }
    .widget_kpi_icon  { width: 38px; height: 38px; font-size: 15px; }
    .widget_kpi_value { font-size: 18px; }
    .widget_kpi_label { font-size: 10px; }

    /* 편집 바: 드래그 핸들 숨기고 ↑↓ 버튼 표시 (터치에서 drag API 미지원) */
    .widget_drag_handle { display: none; }
    .widget_move_btns   { display: flex; }
    .widget_move_btn    { width: 28px; height: 28px; font-size: 15px; }
    .widget_remove_btn  { width: 28px; height: 28px; font-size: 13px; }
    .widget_edit_bar    { padding: 7px 10px; }

    /* 카드 헤더 */
    .widget_card_hd    { padding: 10px 12px 8px; }
    .widget_card_title { font-size: 12px; }

    /* 위젯 추가 패널: 거의 전체화면 */
    .add_widget_overlay { align-items: flex-end; }
    .add_widget_panel   { width: 100%; max-width: 100%; border-radius: var(--radius-lg) var(--radius-lg) 0 0; max-height: 70vh; overflow-y: auto; }
    
    
    .widget_grid { grid-template-columns: 1fr; grid-auto-rows: auto; gap: 12px; }
    .widget_item,
    .widget_item.ws_rh,
    .widget_item.ws_r2,
    .widget_item.ws_r3 { grid-column: span 2; grid-row: auto; }
}

/* (구 모바일 전역 스크롤바 숨김 규칙 삭제 — 2026-07-22 결정: 스크롤바 스타일은 PC/모바일 구분 없이
   base.css 전역 규칙 하나로 통일한다. 그리드 세로는 엔진 썸(moca.css .moca_grid_swipethumb)이 담당) */

/* ======================================================= MDI 분할 패널 전용 반응형 — .mdi_ly.mdi_narrow 뷰포트가 아닌 "패널(.mdi_ly) 자신의 너비" 기준이다. ResizeObserver(mdi.js)가 패널 가용폭 < 768px 이면 .mdi_narrow 를 토글 → PC에서도 리사이징바로 패널을 좁히면 내부 화면이 모바일처럼 reflow 된다. (position:fixed 전체화면 오버레이 계열은 패널 안에서 부적절하므로 제외) ======================================================= */

.mdi_ly.mdi_narrow .moca_slider .msl_input { height: 36px; }
.mdi_ly.mdi_narrow .moca_slider .msl_input::-webkit-slider-thumb { width: 24px; height: 24px; margin-top: -9px; }
.mdi_ly.mdi_narrow .moca_slider .msl_input::-moz-range-thumb { width: 24px; height: 24px; }

/* ── 검색 테이블: 조건 한 줄에 하나씩 (라벨 | 입력 2컬럼 그리드) ── */
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="tbody"], .mdi_ly.mdi_narrow .moca_table_search [data-m-type="tr"] { display: block; width: 100%; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="tr"] { display: grid; grid-template-columns: max-content 1fr; gap: 6px; align-items: center; }
/* 좁은 MDI 칸도 폰과 같은 규칙 — 라벨 왼쪽 정렬 + 입력이 남는 폭 채움(위 @media 블록과 쌍) */
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="th"] { min-width: unset; width: auto; height: 30px; font-size: 12px; font-weight: 600; display: flex; align-items: center; justify-content: flex-start; padding: 0; white-space: nowrap; margin-right: 0; margin-left: 0; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] { flex: 1 1 auto; min-width: 0; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] > .moca_input,
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] > .moca_combo { width: 100%; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] { height: 30px; display: flex; align-items: center; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"]:last-child { grid-column: 1 / -1; justify-content: flex-end; gap: 6px; height: auto; padding-top: 2px; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] > div { width: 100% !important; min-width: 0; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] > div input, .mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] > div select { width: 100% !important; box-sizing: border-box; }
.mdi_ly.mdi_narrow .moca_table_search [data-m-type="td"] button.btn_search { width: 100%; }

/* ── 그리드 폰트 축소 ── */
.mdi_ly.mdi_narrow .moca_grid_body thead th { font-size: 12px; padding: 0 3px; }
.mdi_ly.mdi_narrow .moca_grid_body tbody td { font-size: 12px; padding: 0 3px; }
.mdi_ly.mdi_narrow .grid_title { font-size: 12px; }

/* ── 그리드 툴바 줄바꿈 — 위 @media 블록과 동일 사유 ── */
.mdi_ly.mdi_narrow .moca_grid_toolbar { height: auto; min-height: 38px; flex-wrap: wrap; }
.mdi_ly.mdi_narrow .moca_grid_toolbar > .lta { flex-wrap: wrap; }

/* ── 그리드 툴바: mobilehide 지정 버튼/라벨 숨김 (재렌더에도 유지) ── */
.mdi_ly.mdi_narrow .grid_btn[data-m-mobilehide="true"], .mdi_ly.mdi_narrow .grid_label_span[data-m-mobilehide="true"] { display: none !important; }

/* ── 폼 테이블: 컴팩트 라벨(92px) + td 줄바꿈 — 위 @media 블록과 동일 사유(쌍 규칙, §0-9) ── */
.mdi_ly.mdi_narrow div.moca_table_form [data-m-type="th"] { width: 92px; min-width: 92px; padding: 8px; font-size: 12px; white-space: normal; }
.mdi_ly.mdi_narrow div.moca_table_form [data-m-type="td"] { font-size: 12px; flex-wrap: wrap; min-width: 180px; }
.mdi_ly.mdi_narrow div.moca_table_form [data-m-type="tr"] { flex-wrap: wrap; }

/* ── 폼·그리드 툴바 부제목 숨김 — 위 @media 블록과 동일 사유 ── */
.mdi_ly.mdi_narrow .moca_table_title { display: none; }

/* ── 기간달력(from~to) 줄바꿈 — 위 @media 블록과 동일 사유 ── */
.mdi_ly.mdi_narrow div[data-m-type="inputMultiCalendar"] > div { flex-wrap: wrap; }

/* ── 상세 패널 헤더: 제목 숨겨 버튼 공간 확보 + 버튼 줄바꿈(짜부라짐 방지 — 위 @media 블록과 동일 사유) ── */
.mdi_ly.mdi_narrow .bd_modal_title { display: none; }
.mdi_ly.mdi_narrow .bd_modal_btns { gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.mdi_ly.mdi_narrow .bd_modal_btns button { flex-shrink: 0; }

/* ── 좌우 분할 레이아웃: 세로로 쌓기 (그리드 fauto가 높이를 잡도록 flex:1) ── */
.mdi_ly.mdi_narrow .bd_lr_wrap { flex-direction: column; }
.mdi_ly.mdi_narrow .bd_lr_left { width: 100%; flex: 1; min-height: 0; }
.mdi_ly.mdi_narrow .bd_lr_right { width: 100%; margin-left: 0; }

/* ── 좁은 패널: 상세(pop)를 기본 숨김 → 행 클릭 시 팝업 오버레이로 표시 ── */
.mdi_ly.mdi_narrow .mob_panel_close_btn { display: flex; }
.mdi_ly.mdi_narrow [data-m-mobileview="pop"].mob_lr_active { position: absolute; inset: 0; z-index: 50; display: flex !important; flex-direction: column; background: var(--c-surface); overflow-y: auto; }
.mdi_ly.mdi_narrow [data-m-mobileview="pop"].mob_lr_active .bd_panel { flex: 1; min-height: 0; display: flex; flex-direction: column; border-top: none; }
.mdi_ly.mdi_narrow [data-m-mobileview="pop"].mob_lr_active .bd_panel_body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.mdi_ly.mdi_narrow [data-m-mobileview="pop"].mob_lr_active .bd_panel_body .moca_table_form { flex: 1; min-height: 0; overflow-y: auto; }
.mdi_ly.mdi_narrow [data-m-mobileview="pop"].mob_lr_active .bd_panel_body [data-m-type="fileupload"] { flex-shrink: 0; }

/* 레이아웃(.moca_layout) 화면: 좁은 패널(mdi_narrow)에서도 뷰포트 모바일과 "동일한" 목록→상세오버레이 UX. 사이드바 때문에 창 ~1007px 이하에서 패널이 768 미만이 되는 구간을 포함해, 768~1007 에서 상세가 먼저 뜨던 문제를 제거한다. 오버레이는 패널 내부 absolute. */
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"] { display: none; }
/* pop 칸이 중첩 레이아웃이면 layout.js(_ensurePageWrap)가 pane 역할(--m-grow 비율)을 .page_wrap 래퍼로 옮겨둠 —
   안쪽만 display:none 하면 비율을 가진 래퍼가 빈 칸으로 남아 영역 절반이 빈공간이 됨(그리드 50% 현상).
   래퍼를 display:contents 로 박스 제거 → 숨김(공간 0)/오버레이(absolute) 모두 래퍼 없이 직접 동작 */
.mdi_ly.mdi_narrow .moca_layout .page_wrap:has(> [data-m-mobileview="pop"]) { display: contents; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"].mob_lr_active { display: flex !important; position: absolute; inset: 0; z-index: 50; flex-direction: column; background: var(--c-surface); overflow-y: auto; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"].mob_lr_active .lay_bd_detail { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"].mob_lr_active .lay_bd_detail_body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"].mob_lr_active .moca_table_form { flex: 1; min-height: 0; overflow-y: auto; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"].mob_lr_active .cke_contents { height: calc(100% - 67px) !important; min-height: 80px !important; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"].mob_lr_active [data-m-type="fileupload"] { flex-shrink: 0; height: 160px !important; }
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"] .mob_panel_close_btn { display: flex; }

/* 신규 FAB(buttonGroup 자동 렌더, 기본 숨김=moca.css): 좁은 패널에선 패널 내부 absolute — 오버레이(z 50)보다 아래라 상세가 열리면 자연히 덮인다 */
.mdi_ly.mdi_narrow .moca_layout .moca_btg_fab { display: flex; position: absolute; right: 16px; bottom: 16px; z-index: 40; }
/* FAB 가 신규 진입을 대신하므로 상세 오버레이 안의 신규 버튼은 숨김(중복 제거). FAB 가 생기는 조건과 동일하게 레이아웃 pop 한정 — 옛 비레이아웃 화면은 FAB 가 없어 숨기면 신규 진입이 사라진다. !important 는 applyStatus 의 인라인 display 를 이기기 위함 */
.mdi_ly.mdi_narrow .moca_layout [data-m-mobileview="pop"] .bd_modal_btns button[data-m-role="new"] { display: none !important; }

/* ======================================================= 레이아웃 컴포넌트(data-m-layout) 화면의 모바일 반응형 — 뷰포트 768px 이하에서 예전 게시판과 동일: 목록 그리드만 보이고, 행 클릭 시 상세(pop)가 전체화면 오버레이, "목록" 버튼으로 복귀. 표시/숨김은 오직 .mob_lr_active 클래스 + 이 미디어쿼리로만 제어(순수 CSS 라 "줄여서 열든 / 열고 줄이든" 동작 동일). 클래스 토글은 mdi.js 의 폭무관 상시 핸들러가 담당. ======================================================= */
@media (max-width: 768px) {

    /* 상세(pop) 칸: 기본 숨김 → 목록 그리드만 보임 (로드/리사이즈 무관 동일) */
    .moca_layout [data-m-mobileview="pop"] { display: none; }
    /* pop 칸이 중첩 레이아웃일 때의 .page_wrap 래퍼도 박스 제거(위 mdi_narrow 규칙과 동일 사유 — 빈 flex 아이템/여분 gap 방지) */
    .moca_layout .page_wrap:has(> [data-m-mobileview="pop"]) { display: contents; }

    /* 행 클릭 활성화 시에만 전체화면 오버레이 (index.html 잔여 inline display 를 이기려 !important — 닫기는 클래스 제거로) */
    .moca_layout [data-m-mobileview="pop"].mob_lr_active { display: flex !important; position: fixed; inset: 0; z-index: 7001; flex-direction: column; background: var(--c-surface); overflow-y: auto; }

    /* 오버레이 내부: 상세(폼+CKEditor)는 남은 높이 채움 / 첨부는 하단 고정 */
    .moca_layout [data-m-mobileview="pop"].mob_lr_active .lay_bd_detail { flex: 1; min-height: 0; display: flex; flex-direction: column; }
    .moca_layout [data-m-mobileview="pop"].mob_lr_active .lay_bd_detail_body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
    .moca_layout [data-m-mobileview="pop"].mob_lr_active .moca_table_form { flex: 1; min-height: 0; overflow-y: auto; }
    .moca_layout [data-m-mobileview="pop"].mob_lr_active .cke_contents { height: calc(100% - 67px) !important; min-height: 80px !important; }
    .moca_layout [data-m-mobileview="pop"].mob_lr_active [data-m-type="fileupload"] { flex-shrink: 0; height: 160px !important; }

    /* "목록" 복귀 버튼 표시 (평소 display:none) */
    .moca_layout [data-m-mobileview="pop"] .mob_panel_close_btn { display: flex; }

    /* 신규 FAB(buttonGroup 자동 렌더, 기본 숨김=moca.css): 뷰포트 fixed(base 위치 그대로) — 오버레이(z 7001)보다 아래라 상세가 열리면 자연히 덮인다 */
    .moca_layout .moca_btg_fab { display: flex; }
    /* FAB 가 신규 진입을 대신하므로 상세 오버레이 안의 신규 버튼은 숨김(중복 제거 — 위 mdi_narrow 규칙과 동일 사유·동일 한정) */
    .moca_layout [data-m-mobileview="pop"] .bd_modal_btns button[data-m-role="new"] { display: none !important; }
}

/* ── Echart 컴포넌트: 모바일 세로스택에서는 칸이 내용 높이라 height:100% 가 0 으로 붕괴 → 고정 높이 부여 ── */
@media (max-width: 768px) {
    .moca_layout .moca_echart { height: 320px; }
}


/* ── scheduleCalendar — 좁은 폭에서 명시 높이 ──
   모바일/좁은 패널에선 레이아웃이 세로스택(내용높이)으로 풀리므로(§10-3-3 그리드 체인은 그리드 전용)
   달력이 6주 그리드를 펼칠 명시 높이를 컴포넌트가 직접 갖는다. §0-9 규칙 — @media 와 .mdi_narrow 쌍. */
@media (max-width: 768px) {
  .moca_schcal { height: calc(100vh - 150px); height: calc(100dvh - 150px); }
  /* 오늘 깃발 — 좁은 칸에 맞춰 축소(셀 위로 넘치는 배치는 유지) */
  .msc_flag {left: calc(50% - 23px); }
}
.mdi_narrow .moca_schcal { height: calc(100vh - 150px); height: calc(100dvh - 150px); }
.mdi_narrow .msc_flag { width: 46px; height: 23px; top: -12px; left: calc(50% - 23px); }

/* 540px 이하 page_wrap 여백은 12px인데 개발용 골격 FAB가 -14px 돌출되면 2px 문서 스크롤이 생긴다. */
@media (max-width: 540px) {
  .page_wrap > .moca_layout > .moca_layout_debug_fab { left: 0; bottom: 0; }
}
.mdi_narrow .page_wrap > .moca_layout > .moca_layout_debug_fab { left: 0; bottom: 0; }

/* ── 장시간 데이터 수집 상태 카드 ── */
@media (max-width: 768px) {
    .ain_collect_status { align-items: flex-start; padding: 10px; }
    .ain_collect_signal { width: 32px; height: 32px; flex-basis: 32px; }
    .ain_collect_signal::before { inset: 6px; }
    .ain_collect_heading { flex-wrap: wrap; gap: 6px 8px; }
    .ain_collect_step { order: 3; flex-basis: 100%; }
    .ain_collect_meta { display: block; }
    .ain_collect_meta span:last-child { display: block; margin-top: 4px; }
}
.mdi_narrow .ain_collect_status { align-items: flex-start; padding: 10px; }
.mdi_narrow .ain_collect_signal { width: 32px; height: 32px; flex-basis: 32px; }
.mdi_narrow .ain_collect_signal::before { inset: 6px; }
.mdi_narrow .ain_collect_heading { flex-wrap: wrap; gap: 6px 8px; }
.mdi_narrow .ain_collect_step { order: 3; flex-basis: 100%; }
.mdi_narrow .ain_collect_meta { display: block; }
.mdi_narrow .ain_collect_meta span:last-child { display: block; margin-top: 4px; }

/* ── Demo login ───────────────────────────────────────── */
@media (max-width: 900px) {
    .demo_login_page { padding: 28px; }
    .demo_login_card { grid-template-columns: minmax(0, 0.9fr) minmax(360px, 1.1fr); width: min(100%, 820px); }
    .demo_login_showcase { padding: 38px 34px 32px; }
    .demo_login_features li { grid-template-columns: 28px 1fr; }
    .demo_login_features small { display: none; }
    .demo_login_panel { padding: 48px 42px 30px; }
}

@media (max-width: 768px) {
    .moca_layout > .moca_layout_pane.demo_login_page { min-height: 100vh; min-height: 100svh; }
    .demo_login_page { padding: 24px; overflow-y: auto; }
    .demo_login_card { display: block; width: min(100%, 470px); min-height: 0; border-radius: 24px; }
    .demo_login_showcase { display: none; }
    .demo_login_panel { min-height: 560px; padding: 38px 40px 28px; }
    .demo_login_mobile_brand { display: flex; }
}

@media (max-width: 480px) {
    .demo_login_page { padding: max(18px, env(safe-area-inset-top)) 16px max(18px, env(safe-area-inset-bottom)); }
    .demo_login_card { border-radius: 20px; }
    .demo_login_panel { min-height: 0; padding: 28px 24px 24px; }
    .demo_login_home { margin-bottom: 25px; }
    .demo_login_mobile_brand { margin-bottom: 27px; }
    .demo_login_header { margin-bottom: 25px; }
    .demo_login_header h2 { font-size: 26px; }
    .demo_login_footer { padding-top: 24px; }
}

/* ── 개인정보 처리방침 ─────────────────────────────────── */
@media (max-width: 900px) {
    .policy_shell { grid-template-columns: 1fr; width: min(calc(100% - 36px), 780px); margin-top: -68px; }
    .policy_toc { position: relative; top: auto; padding: 18px; }
    .policy_toc nav { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px; }
    .policy_toc a { background: #F3F8F9; }
}

@media (max-width: 640px) {
    .policy_hero { min-height: 330px; padding: 30px 20px 92px; }
    .policy_brand { margin-bottom: 40px; }
    .policy_brand img { width: 136px; }
    .policy_hero h1 { font-size: 34px; }
    .policy_shell { width: calc(100% - 24px); margin-top: -52px; margin-bottom: 48px; gap: 14px; }
    .policy_toc { border-radius: 15px; }
    .policy_toc nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .policy_toc a { min-height: 42px; }
    .policy_document { padding: 34px 24px 26px; border-radius: 18px; }
    .policy_document_head { padding-bottom: 30px; }
    .policy_document_head h2 { font-size: 23px; }
    .policy_document_head p { padding: 17px 18px; }
    .policy_section { padding: 31px 0 27px; }
    .policy_section h2 { font-size: 18px; }
    .policy_section ul, .policy_section ol { margin-left: 18px; }
    .policy_contact { margin-inline: -8px; padding: 24px 22px; }
    .policy_footer { align-items: flex-start; flex-direction: column; }
}

/* 운영체제 강제 고대비에서는 네이티브 range 표현을 우선한다. */
@media (forced-colors: active) {
    .moca_slider .msl_input { -webkit-appearance: auto; appearance: auto; }
}

/* ── VirtualTree — 터치 타깃만 넓힌다 (행 높이는 절대 바꾸지 않는다: JS 가 스크롤 계산에 쓰는 상수) ── */
@media (max-width: 768px) {
    .moca_vtree .mvt_toggle::after { content: ''; position: absolute; inset: -8px; }
    .moca_vtree .mvt_label { font-size: 13px; }
}

.mdi_narrow .moca_vtree .mvt_toggle::after { content: ''; position: absolute; inset: -8px; }

/* ── Calendar(붙박이 달력) — 좁은 폭에서 칸을 터치 타깃 크기로 키운다.
      뷰포트(≤768px)와 좁은 패널(.mdi_narrow) 두 경로를 쌍으로 둔다(PART C §0-9). ── */
@media (max-width: 768px) {
    .moca_cal .mcal_day { height: 40px; }
    .moca_cal .mcal_mon, .moca_cal .mcal_yr { height: 52px; }
    .moca_cal .mcal_nav, .moca_cal .mcal_todaybtn { width: 34px; height: 34px; }
}

.mdi_narrow .moca_cal .mcal_day { height: 40px; }
.mdi_narrow .moca_cal .mcal_mon, .mdi_narrow .moca_cal .mcal_yr { height: 52px; }
.mdi_narrow .moca_cal .mcal_nav, .mdi_narrow .moca_cal .mcal_todaybtn { width: 34px; height: 34px; }
