@charset "UTF-8";
/* ==========================================================================
   u_components.css — 포털 중립 공용 컴포넌트("컴포넌트 1벌 + 토큰 2벌" 의 컴포넌트 정본)
   ----------------------------------------
   L1(mgr_top)·사용자단(head.jsp) 양 셸이 로드하는 유일 공용 컴포넌트 CSS.
   같은 마크업이 variables.css(L1 인디고 고정) / user_variables.css(사용자 파랑 커스터마이즈)
   토큰으로 포털별 렌더된다. 색은 반드시 양 셸 공통 --u-* 토큰만(리터럴 hex 금지).
   여기 두는 것은 '진짜 양 포털이 쓰는' 컴포넌트만. 포털 전용(rv-·mo-·mgr-)은 각자 파일에.

   [빈 상태] u-empty(아이콘+텍스트) / u-empty-inline(-sm)(중앙 muted 안내문) — 도메인 {prefix}-empty 통일 정본.
   --u-text-sm/md 는 공용이라 admin·user 양쪽 토큰파일에 정의.
   ========================================================================== */
.u-empty-inline {
    text-align: center;
    color: var(--u-ink-muted);
    padding: 20px;
    /* font-size 미지정 — 부모 상속 (기존 동작 유지) */
}
.u-empty-inline-sm {
    text-align: center;
    color: var(--u-ink-muted);
    padding: 12px;
    font-size: 0.75rem;
}
/* 모달 안 빈상태 — u-empty-inline 은 font-size 미지정(부모 상속)이라, 초소형 폰트 모달
   (u-text-xs 0.6875 · u-btn-md 0.75) 안에서 body 1rem 을 상속해 홀로 커 보인다.
   모달 본문은 좌측 정렬(intro·버튼) 흐름이므로 빈상태도 좌측·타이트로 맞춘다 — 기본값
   center+20px 는 좌측 콘텐츠와 정렬축이 어긋나 붕 떠 보인다. 리스트 문맥의 기본값은 불변.
   위저드 모달(.is-wizard)은 자체 카드 규칙이 더 높은 특이도로 이김(user_wizard.css §4-7-p). */
.u-modal-body .u-empty-inline { font-size: 0.75rem; text-align: left; padding: 8px 0; }

.u-empty {
    text-align: center;
    padding: 40px 20px;
    color: var(--u-ink-light);
    grid-column: 1 / -1;   /* grid/flex 컨테이너 안에서도 전체 폭 중앙 정렬 */
    width: 100%;
}
.u-empty .empty-icon { font-size: 2.25rem; margin-bottom: 10px; color: var(--u-border-strong); }
.u-empty .empty-text { font-size: var(--u-text-md); margin-bottom: 14px; }
.u-empty .empty-sub  { font-size: var(--u-text-sm); margin-top: 4px; }

/* ===== 모달 (2026-07-16 컴포넌트 통합 파운데이션: user u-modal → common 1벌로 이관. **user 원본값 그대로**(무회귀).
   z-index 만 셸 토큰 --u-modal-z(user 1000 / admin 9000) — 포털별 스택 보존.
   바텀시트(user_mobile `:not(.is-wizard)`)·위저드(user_wizard `.is-wizard`)는 user 셸 CSS 확장 유지.
   admin mgr-modal → u-modal 치환은 후속(2패턴 공유·mgr_common.js body-lock 결합). title-i/hint/search-row 는 admin 흡수용.
   plans/active/component_unification_2026-07-16.md ===== */
.u-modal-overlay {
    display: none; position: fixed; inset: 0; background: var(--u-black-a45);   /* B1 드리프트 정본: backdrop .3→.45(admin 값) */
    z-index: var(--u-modal-z, 1000); align-items: center; justify-content: center;
}
.u-modal-overlay.open { display: flex; animation: u-fade-in 0.15s; }             /* B1: 등장 애니(admin mgrFadeIn 흡수) */
.u-modal {
    background: var(--u-bg-card); border-radius: 12px;                           /* B1 드리프트 정본: radius 8→12(admin 값) */
    width: 90%; max-width: 480px; max-height: 90vh;
    display: flex; flex-direction: column;
    box-shadow: 0 8px 30px var(--u-black-a12);
    animation: u-slide-up 0.2s;                                                  /* B1: 등장 애니(admin mgrSlideUp 흡수) */
}
@keyframes u-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes u-slide-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.u-modal input, .u-modal select, .u-modal textarea, .u-modal button { font-family: inherit; }   /* B1: admin .mgr-modal 폼 컨트롤 font-inherit 흡수 */

/* ===== 폼 컨트롤 (admin mgr-form-* + user u-form-* → common 1벌 · B1 2026-07-20) =====
   font-size 0.8125rem = rem 이 셸 root 로 폰트정책 자동 처리(admin root 16px→13px / user root 17px→13.8px = 각 현행 유지, 셸토큰 불필요).
   색은 var(--u-*) 토큰(2벌 테마). focus ring = var(--u-accent-light)(셸별 accent). ===== */
.u-form-group { margin-bottom: 12px; }
.u-form-label, .u-form-group label { display: block; font-size: 0.75rem; font-weight: 600; color: var(--u-ink-strong); margin-bottom: 4px; }
.u-form-input, .u-form-select, .u-form-textarea {
    border: 1px solid var(--u-border-strong); border-radius: 6px;
    font-family: inherit; font-size: 0.8125rem;
    color: var(--u-ink-strong); background: var(--u-bg-card);
    transition: border-color 0.15s;
}
.u-form-input   { width: 100%; height: 36px; padding: 0 10px; }
.u-form-select  { height: 36px; padding: 0 10px; min-width: 100px; }
.u-form-textarea{ width: 100%; padding: 8px 10px; resize: vertical; min-height: 70px; }
.u-form-input:focus, .u-form-select:focus, .u-form-textarea:focus { outline: none; border-color: var(--u-accent); }
.u-form-input:focus, .u-form-textarea:focus { box-shadow: 0 0 0 2px var(--u-accent-light); }
.u-form-group .u-form-select, .u-form-group .u-form-input { width: 100%; box-sizing: border-box; }
.u-form-help  { font-size: 0.6875rem; color: var(--u-ink-muted); margin-top: 4px; }
/* 목록·대시보드 머리 필터 칸 — 한 규격(높이 34px · 글자 0.8125rem · 테두리·모서리 = 위 기본값). 두 셸 공용.
   #searchform = 목록 페이저 계약(form="searchform") · #filterForm = 현황 대시보드(머리가 .u-page-header 가 아닌 L1 회사 미선택 판 포함) · .u-filter-bar = 회원·교육 목록.
   폭은 화면마다(user_components.css · dashboard.css) · 모바일 높이는 user_mobile.css. */
#filterForm .u-form-select, #filterForm .u-form-input,
.u-page-header #searchform .u-form-select, .u-page-header #searchform .u-form-input,
.u-filter-bar .u-form-select, .u-filter-bar .u-form-input { height: 34px; font-size: 0.8125rem; }


/* ===== 버튼 (admin mgr-btn + user u-btn → common 1벌 · B1 2026-07-20) =====
   bare .u-btn = md 기본 크기(admin 은 mgr-btn 을 사이즈클래스 없이 단독 사용 → 기본 크기 필요). -sm/-lg 가 override.
   font-size rem 이 셸 root 로 정책 자동처리(admin root 16px→12px / user 17px→12.75px = 각 현행). 색 = var(--u-*) 토큰. ===== */
.u-btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 5px; border: none; border-radius: 6px;
    height: 34px; padding: 0 14px; font-size: 0.75rem; font-weight: 600;   /* 기본 = md (admin mgr-btn 베이스 흡수) */
    cursor: pointer; transition: all 0.15s; text-decoration: none;
    line-height: 1; white-space: nowrap; letter-spacing: -0.2px;
}
/* 비활성 = 변형 색 그대로 흐릿게만. hover 를 막는 것은 pointer-events 이다 — 예전 `:disabled:hover { background: card }` 는 primary 버튼을
   클릭 순간(마우스가 위에 있을 때) 흰 배경 + 흰 글자로 만들어 «사라진 것처럼» 보였다(2026-09-18 스모크 · training_qr 생성). */
.u-btn:disabled, .u-btn[disabled] { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.u-btn-sm { height: 28px; padding: 0 10px; font-size: 0.6875rem; }
.u-btn-md { height: 34px; padding: 0 14px; font-size: 0.75rem; }
.u-btn-lg { height: 40px; padding: 0 20px; font-size: 0.8125rem; }

.u-btn-primary { background: var(--u-accent); color: var(--u-on-accent); }
.u-btn-primary:hover { background: var(--u-accent-hover); }
.u-btn-secondary { background: var(--u-bg-card); color: var(--u-ink-strong); border: 1px solid var(--u-border-strong); }
.u-btn-secondary:hover { background: var(--u-bg-gray); border-color: var(--u-ink-muted); }
.u-btn-danger { background: var(--u-bg-card); color: var(--u-danger); border: 1px solid var(--u-danger-border); }
.u-btn-danger:hover { background: var(--u-danger-soft); }

/* ===== 배지 (user_components.css → common 이관 · 2026-07-24) =====
   버튼과 같은 이유로 옮긴다: L1(`fnc_mgr/training_qr/training_qr_view.jsp`)이 `u-badge` 를 쓰는데
   정의가 `user_components.css`(사용자 셸 전용)에만 있어 admin 셸에서 조용히 안 먹었다.
   색 변형은 전부 `--u-*` 토큰 — 셸별 토큰값이 알아서 스킨을 가른다. ===== */
.u-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    background: var(--u-bg);
    color: var(--u-ink-strong);
}
.u-badge-red    { background: var(--u-danger-soft); color: var(--u-danger); }
.u-badge-orange { background: var(--u-safety-soft); color: var(--u-safety); }
.u-badge-yellow { background: var(--u-warning-soft); color: var(--u-warning); }
.u-badge-green  { background: var(--u-success-soft); color: var(--u-success); }
.u-badge-blue   { background: var(--u-accent-light); color: var(--u-accent); }
.u-badge-cyan   { background: var(--u-rep-soft); color: var(--u-rep); }
.u-badge-sky    { background: var(--u-sky-soft); color: var(--u-sky); }   /* status phase 'sent'(전송됨) */
.u-badge-gray   { background: var(--u-bg); color: var(--u-ink-light); }
/* purple = 정의 없이 10개 JSP(양 셸)에서 쓰이고 있었다(2026-07-24 적발). 보라 의도가 기본 회색으로
   렌더 중이었다. `--u-cat-violet` 은 이미 bg/text 쌍으로 설계된 카테고리 색 — 다른 변형의 soft/기본 쌍과 동형. */
.u-badge-purple { background: var(--u-cat-violet-bg); color: var(--u-cat-violet-text); }

/* ===== 안내 배너 — 화면 안 한 줄 경고·막힘 안내(아이콘 + 문구) · 양 셸 공용 =====
   값 = 페이지마다 따로 있던 노랑 배너 두 벌(보고서 위저드 읽기 전용)의 값 그대로 · 색 변형은 배지와 같은 접미사 형. */
.u-notice {
    display: flex; align-items: flex-start; gap: var(--u-sp-8);
    margin: 0 0 var(--u-sp-12);
    padding: var(--u-sp-8) var(--u-sp-12);
    border-radius: 6px;
    font-size: 0.8125rem; line-height: 1.45; word-break: keep-all; overflow-wrap: anywhere;
}
.u-notice .ti { font-size: 1rem; line-height: 1.3; flex-shrink: 0; }
.u-notice-warn   { background: var(--u-warning-soft); color: var(--u-warning-deep); }
.u-notice-danger { background: var(--u-danger-soft);  color: var(--u-danger-strong); }

/* ===== 탭 (user_components.css → common 이관 · 2026-09-28) =====
   양 셸 공용 서명 모달이 탭을 쓴다 — admin 셸(fnc_mgr)은 user_components.css 를 싣지 않아 u-badge(07-24)와 같은 이유로 옮긴다.
   모바일 형(굵은 글씨·잉크 밑줄)은 user_mobile.css 가 사용자 셸에서 덮는다. ===== */
.u-tabs {
    display: flex; flex-wrap: wrap; border-bottom: 1px solid var(--u-border);
    margin-bottom: 20px; background: var(--u-bg-card); padding: 0;
    /* 넘치면 탭 단위로 다음 줄 wrap. overflow-x 는 쓰지 않음 —
       .u-tab 의 margin-bottom:-1px 가 overflow-y(=auto 계산값) 에 걸려 헛스크롤바가 생김. */
}
.u-tab {
    padding: 10px 18px; font-size: 0.8125rem; font-weight: 600; color: var(--u-ink-light);
    cursor: pointer; border: none; background: none;
    border-bottom: 2px solid transparent; margin-bottom: -1px;
    transition: color 0.15s, border-bottom-color 0.15s;   /* all 금지 — font-size 변경이 애니메이션되면 FOUC */
    white-space: nowrap; flex-shrink: 0;   /* 탭은 줄바꿈 안 함 → 행 넘치면 .u-tabs flex-wrap 으로 다음 줄 */
    text-decoration: none;                 /* <a class="u-tab"> 로도 사용 — 밑줄 제거 (button/div 엔 무영향) */
}
.u-tab:hover { color: var(--u-ink-strong); }
.u-tab.active { color: var(--u-accent); border-bottom-color: var(--u-accent); }

.u-tab-panel { display: none; }
.u-tab-panel.active { display: block; }

/* ===== 3단계 세그먼트 rv-risk-seg (상·중·하 위험도 / A·B·C 등급 · 2026-07-29) =====
   배지와 같은 경위로 common 1벌. 같은 "3단계 택1" 을 네 벌이 하고 있었다:
   `user_common.css` 의 .grade-selector .grade-btn · .grade-btn (둘 다 **소비처 0** — 제거),
   L1 `_opinion_modal.jsp` 인라인, 그리고 살아있는 정본인 이것(옛 pages/opinion_form.css).
   PC base 만 여기 둔다 — 모바일 톤은 셸 CSS 확장이다(u-modal 과 같은 분업):
     user_mobile `.u-mgr-content .u-mo ...`  = assess_view 상중하
   소비: assess_view ×5(모바일) · _opinion_grade_seg(의견 등급 PC·모바일) · _opinion_modal(L1).
   ===== */
.rv-risk-seg { display: flex; justify-content: center; gap: 10px; margin-top: 4px; }
/* 톤 = 모바일 셸 확장(user_mobile `.u-mgr-content .u-mo .rv-risk-seg-btn`)과 같은 값 — 연한 면 + 색 글자 */
.rv-risk-seg-btn {
    flex: 1; max-width: 100px; height: 48px;
    font-size: 0.9375rem; font-weight: 800; text-align: center;
    border: none; border-radius: 13px;
    background: var(--u-mo-band); color: var(--u-mo-tab-idle); cursor: pointer; transition: all .15s;
    display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
@media (min-width: 981px) {
    .rv-risk-seg-btn { max-width: none; }
}
.rv-risk-seg-btn .rv-risk-seg-sub { font-size: 0.625rem; font-weight: 500; color: var(--u-ink-light); }
.rv-risk-seg-btn.active-high { background: var(--u-danger-soft); color: var(--u-danger); }
.rv-risk-seg-btn.active-mid  { background: var(--u-safety-soft); color: var(--u-amber); }
.rv-risk-seg-btn.active-low  { background: var(--u-success-soft); color: var(--u-success); }
.rv-risk-seg-btn.active-high .rv-risk-seg-sub,
.rv-risk-seg-btn.active-mid  .rv-risk-seg-sub,
.rv-risk-seg-btn.active-low  .rv-risk-seg-sub { color: inherit; }


.u-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px; border-bottom: 1px solid var(--u-border);
    flex-shrink: 0;
}
.u-modal-title { font-size: 0.9375rem; font-weight: 700; color: var(--u-ink); letter-spacing: -0.3px; }
.u-modal-title i { color: var(--u-accent); margin-right: 6px; }
.u-modal-close {
    width: 28px; height: 28px; border: none; background: none;
    font-size: 1.125rem; color: var(--u-ink-light); cursor: pointer; border-radius: 4px;
    display: flex; align-items: center; justify-content: center;
}
.u-modal-close:hover { background: var(--u-bg); }
.u-modal-body { padding: 20px; flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; overscroll-behavior: contain; }
/* 비-위저드(일반) 모달 바디 = 내용 스크롤 (admin .mgr-modal-body 흡수 · B1 2026-07-20). 양 셸·전 폭 단일 정의.
   base(flex column + overflow:hidden)는 위저드 전용 — 일반 모달은 flex-child 압축으로 눌리므로 block+scroll 로 되돌린다.
   위저드(.is-wizard)는 base + user_wizard:1096/user_mobile:1517 규칙이 flex 유지. 옛 user_mobile @media 중복은 이 규칙으로 흡수(제거). */
.u-modal-overlay:not(.is-wizard) .u-modal-body { display: block; overflow-y: auto; -webkit-overflow-scrolling: touch; flex: 1 1 auto; }
.u-modal-footer {
    display: flex; gap: 8px; justify-content: flex-end;
    padding: 14px 20px; border-top: 1px solid var(--u-border);
    flex-shrink: 0;
}
/* 모달 상단 검색행 (admin .mgr-modal-search-row 흡수 · B1 2026-07-20) */

.u-modal-hint { margin-top: 10px; font-size: 0.6875rem; color: var(--u-ink-muted); line-height: 1.5; }
.u-modal-hint i { margin-right: 3px; color: var(--u-border-strong); }

/* ==========================================================================
   위저드(단계별 입력) — 스테퍼·패널 공용 컴포넌트 (2026-07-20, B1 wizard 페어)
   ----------------------------------------
   엔진 = RN.wizardTabs(user_wizard_tabs.js). 옛 L1 mgr_wizard.css(cw-*)를 흡수하고
   사용자단 u-wizard-* 를 정본화 — 양 셸(mgr_top·head.jsp) 이 이 파일을 로드해 1벌 공유.
   스테퍼 값은 user_wizard.css 원본 그대로(사용자단 렌더 무변). 패널 flex-fill(모바일
   높이채움)은 사용자단 전용 → user_wizard.css 가 `.u-modal-overlay.is-wizard` 스코프로
   override. admin 위저드(is-wizard 없음)는 여기 base(display 토글)만 받아 데스크톱 block.
   ========================================================================== */
.u-wizard-progress { display: flex; align-items: center; padding: 16px 16px 12px; background: var(--u-bg-card); flex-shrink: 0; }
.u-wizard-step { display: flex; flex-direction: column; align-items: center; gap: 4px; flex-shrink: 0; }
.u-wizard-step .step-num { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.75rem; font-weight: 700; border: 2px solid var(--u-border); color: var(--u-ink-muted); background: var(--u-bg-card); transition: all 0.2s; }
.u-wizard-step .step-label { font-size: 0.625rem; color: var(--u-ink-muted); text-align: center; max-width: 60px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transition: color 0.2s; }
.u-wizard-line { flex: 1; height: 2px; background: var(--u-border); margin: 0 4px; margin-bottom: 18px; transition: background 0.2s; }
.u-wizard-step.completed .step-num { background: var(--u-accent); border-color: var(--u-accent); color: var(--u-on-accent); }
.u-wizard-step.completed .step-label { color: var(--u-accent); }
.u-wizard-line.completed { background: var(--u-accent); }
.u-wizard-step.active .step-num { border-color: var(--u-accent); color: var(--u-accent); box-shadow: 0 0 0 3px var(--u-accent-light); }
.u-wizard-step.active .step-label { color: var(--u-accent); font-weight: 600; }
/* 패널 base — 표시 토글(엔진 계약, 양 셸). 사용자단 flex-fill 은 user_wizard.css 가 .is-wizard 스코프로 override. */
.u-wizard-panel { display: none; padding: 0 4px; }
.u-wizard-panel.active { display: block; }


/* ==========================================================================
   weekly 이행 picker 카드 (implPicker step2 + weekly step3 공용) — B2 Stage B (2026-07-20)
   user_wizard.css 에서 이관. .u-modal-overlay.is-wizard 스코프 그대로 — 양 셸 로드로 fnc(admin) picker 도 동일 렌더.
   ========================================================================== */
/* ── §4-7-e ip-card → 회색 라운드 행 + 우측 ● (weekly·implPicker 본문) ──
   기존 .ip-card (border 2px·체크박스 좌측) 을 .is-wizard 한정 토스 톤으로 override.
   .ip-card.checked 는 JS toggleClass — 그대로 사용. */
.u-modal-overlay.is-wizard .ip-card {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    background: var(--u-mo-surface);
    border: none;
    border-radius: 12px;
    margin-bottom: 8px;
    cursor: pointer;
    transition: background .15s;
}
.u-modal-overlay.is-wizard .ip-card:hover { border: none; background: var(--u-mo-surface); }
.u-modal-overlay.is-wizard .ip-card.checked {
    background: var(--u-accent-light);
    border: none;
}
.u-modal-overlay.is-wizard .ip-card input[type="checkbox"] {
    /* 토스 = 우측 ● — 기본 checkbox 시각 숨김 (label click 은 그대로 동작) */
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0;
    margin: 0; padding: 0;
    pointer-events: none;
}
.u-modal-overlay.is-wizard .ip-card-body {
    flex: 1; min-width: 0;
    order: 1;
}
.u-modal-overlay.is-wizard .ip-card-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--u-mo-ink);
    letter-spacing: -0.2px;
}
.u-modal-overlay.is-wizard .ip-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}
/* meta 안 span 을 토스 chip 으로 — mo-risk-card .ip-pick-meta 와 정합 (한 사람 코드, P6.6 2026-05-26).
   JS 가 박은 inline `style="color:var(--u-success|danger|accent)"` 는 attribute selector 로 override. */
.u-modal-overlay.is-wizard .ip-card-meta span {
    background: var(--u-bg-card);
    color: var(--u-mo-grey-strong);
    font-size: 0.75rem;
    padding: 3px 10px;
    border-radius: 999px;
    font-weight: 600;
}
.u-modal-overlay.is-wizard .ip-card-meta span[style*="u-success"] {
    background: var(--u-success-soft);
    color: var(--u-success-strong) !important;
}
.u-modal-overlay.is-wizard .ip-card-meta span[style*="u-danger"] {
    background: var(--u-danger-soft);
    color: var(--u-danger-strong) !important;
}
.u-modal-overlay.is-wizard .ip-card-meta span[style*="u-accent"] {
    background: var(--u-accent-light);
    color: var(--u-accent) !important;
}
/* 우측 ● 체크 (pseudo) — 도넛 형태 (선택 시 안쪽 흰 도트) */
.u-modal-overlay.is-wizard .ip-card::after {
    content: '';
    width: 20px; height: 20px;
    border: 2px solid var(--u-mo-grey-faint);
    border-radius: 50%;
    flex-shrink: 0;
    order: 2;
    background: transparent;
    transition: all .15s;
}
.u-modal-overlay.is-wizard .ip-card.checked::after {
    background: var(--u-accent);
    border-color: var(--u-accent);
    box-shadow: inset 0 0 0 4px var(--u-bg-card);   /* 도넛 = 파란 ● */
}
.u-modal-overlay.is-wizard .ip-card.disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background: var(--u-mo-line);
}
.u-modal-overlay.is-wizard .ip-card.disabled:hover {
    background: var(--u-mo-line);
}

/* ── §4-7-f ip-list-wrap — wz-scroll-area 동형 (flex:1 필수, 없으면 overflow만으로 스크롤 안 됨) ── */
.u-modal-overlay.is-wizard .u-wizard-panel.active > .ip-list-wrap,
.u-modal-overlay.is-wizard .u-wizard-panel.active .ip-list-wrap.wz-scroll-area {
    flex: 1;
    min-height: 0;
    max-height: none;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    border: none;
    border-radius: 0;
    padding: 0;
    background: transparent;
}
.u-modal-overlay.is-wizard .ip-status-row {
    display: flex;
    gap: 6px;
    margin-bottom: 12px;
    padding: 4px;
    background: var(--u-mo-surface);
    border-radius: 12px;
}
.u-modal-overlay.is-wizard .ip-status-row label {
    flex: 1;
    text-align: center;
    padding: 10px 0;
    border: none;
    border-radius: 10px;
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--u-mo-grey);
    cursor: pointer;
    background: transparent;
    transition: background .15s, color .15s;
}
.u-modal-overlay.is-wizard .ip-status-row input[type="radio"] { display: none; }
.u-modal-overlay.is-wizard .ip-status-row label:has(input:checked) {
    background: var(--u-bg-card);
    color: var(--u-mo-ink);
    box-shadow: 0 1px 3px var(--u-black-a09);
}

/* ── §4-7-h mo-risk-card (이행관리 picker 항목 — weekly step3 + implPicker step2 통일) ──
   P6.3 (2026-05-26): 옛 tbm-risk-item 평문(br) 폐기, mo-risk-card 구조형으로 통일.
   마크업: label > input[hidden] > .risk-obj > .risk-sub > .risk-hazard > .risk-red > .ip-pick-meta
   토스 톤 = 회색 라운드 카드 + 우상단 ● 도넛. label 자체 클릭 = check 토글 (체크박스 시각 hide). */
.u-modal-overlay.is-wizard .mo-risk-card {
    display: block;
    position: relative;
    background: var(--u-mo-surface);
    border: none;
    border-radius: 14px;
    padding: 18px;
    padding-right: 48px;        /* 우상단 ● 도넛 공간 */
    margin-bottom: 10px;
    cursor: pointer;
    transition: background .15s;
}
.u-modal-overlay.is-wizard .mo-risk-card:hover { background: var(--u-mo-surface); }
/* .checked 클래스 토글 + :has(input:checked) 둘 다 활성 — 마크업/JS 가
   .checked 토글 안 하는 도메인(TBM 위험요인 picker = cOnRiskCheck) 도 자동 정합 */
.u-modal-overlay.is-wizard .mo-risk-card.checked,
.u-modal-overlay.is-wizard .mo-risk-card:has(input:checked) {
    background: var(--u-accent-light);
}
.u-modal-overlay.is-wizard .mo-risk-card.disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background: var(--u-mo-line);
    pointer-events: none;
}
/* 기본 checkbox 시각 hide (label click 그대로 동작) */
.u-modal-overlay.is-wizard .mo-risk-card > input[type="checkbox"] {
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0;
    margin: 0; padding: 0;
    pointer-events: none;
}
/* 우상단 ● 도넛 체크 */
.u-modal-overlay.is-wizard .mo-risk-card::after {
    content: '';
    position: absolute;
    top: 18px; right: 18px;
    width: 20px; height: 20px;
    border: 2px solid var(--u-mo-grey-faint);
    border-radius: 50%;
    background: transparent;
    transition: all .15s;
}
.u-modal-overlay.is-wizard .mo-risk-card.checked::after,
.u-modal-overlay.is-wizard .mo-risk-card:has(input:checked)::after {
    background: var(--u-accent);
    border-color: var(--u-accent);
    box-shadow: inset 0 0 0 4px var(--u-bg-card);
}
.u-modal-overlay.is-wizard .mo-risk-card.disabled::after { display: none; }

/* risk-sub 서브트리(ri-level chip · ri-status · ri-src) + ri-accident 제거(2026-07-20 P5-d):
   tbm_list·weekly_list 문서 위저드가 계획(규칙) 방식으로 대체되며 유일 렌더러(cRenderRiskPreview·
   cwRenderItemsList) 소멸 → risk-sub/ri-status/ri-src/ri-accident JSP·JS 사용 0(죽은 정본).
   ri-level*·st-* 는 tbm.css·weekly_view.css·user_mobile.css 정의 생존(dead-class 무회귀). */

/* 위험 정보 내부(.risk-obj·.risk-hazard·.risk-red*) = base/risk_auto_card.css 한 벌 — 위저드 안에서도 덮지 않는다. */

/* 메타 — 담당/기한/상태 chip 묶음 */
.u-modal-overlay.is-wizard .mo-risk-card .ip-pick-meta {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--u-mo-grey-faint);
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.u-modal-overlay.is-wizard .mo-risk-card .ip-pick-meta span {
    background: var(--u-bg-card);
    color: var(--u-mo-grey-strong);
    font-size: 0.75rem;
    padding: 3px 10px;
    border-radius: 999px;
    font-weight: 600;
}
.u-modal-overlay.is-wizard .mo-risk-card .ip-pick-meta .st-done {
    background: var(--u-success-soft); color: var(--u-success-strong);
}
.u-modal-overlay.is-wizard .mo-risk-card .ip-pick-meta .st-wait {
    background: var(--u-warning-soft); color: var(--u-warning-text);
}
.u-modal-overlay.is-wizard .mo-risk-card .ip-pick-meta .ipm-already {
    background: var(--u-accent-light); color: var(--u-accent); font-weight: 700;
}

/* ── 위저드 body/패널 레이아웃 (모바일 높이채움 스크롤) — B2 Stage B 이관(2026-07-20) ──
   user_wizard.css 에서. is-wizard 스코프 flex-fill = 사용자단 위저드+양 셸 impl-picker 공용.
   admin 문서 위저드는 is-wizard 없어 무영향(common base=block 유지). ── */
/* ── 단계 콘텐츠 ── */
.u-wizard-body {
    position: relative;
    flex: 1;                /* modal-body flex column 안에서 진행바 외 남은 공간 차지 */
    min-height: 0;
    overflow: hidden;       /* 안 panel.active 의 wz-scroll-area 만 스크롤 */
    display: flex;          /* 자식 panel.active 가 flex:1 로 wizard-body 의 height 차지 */
    flex-direction: column;
}

/* .u-wizard-panel base(display:none/.active display:block) = common/u_components.css.
   active panel: flex column 으로 panel 안 헤더(p/input) 고정 + wz-scroll-area 가 남은 공간 차지.
   부모 wizard-body 가 display:flex 라 flex:1 로 부모 height 모두 차지 (height:100% 순환의존 회피).
   .is-wizard 스코프 = 사용자단 위저드 전용(모바일 높이채움). admin 위저드는 is-wizard 가 없어 common base(block) 유지. */
.u-modal-overlay.is-wizard .u-wizard-panel.active {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    /* 검색·포커스링(2px)이 wizard-body overflow:hidden 상단에 잘리지 않게 */
    padding-top: 4px;
}
/* 패널의 좌우 padding 4px 를 스크롤 상자 안쪽으로 이동 — overflow 가 포커스링(2px) 좌우를 잘라내지 않게.
   음수 margin 으로 내용 폭은 그대로. */
.u-modal-overlay.is-wizard .u-wizard-panel.active > .wz-scroll-area {
    margin-left: -4px;
    margin-right: -4px;
    padding-left: 4px;
    padding-right: 4px;
}

/* 패널 내 카드: flex column으로 버튼 하단 배치 */
.u-wizard-panel > .u-card-panel {
    display: flex;
    flex-direction: column;
}

/* 그리드·폼·테이블: panel.active flex column 안 남은 공간 + 자체 스크롤 */
.wz-scroll-area {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    -webkit-overflow-scrolling: touch;
}
/* wz-mo-q/sub·필터 등 — 스크롤 영역 위 고정 */
.u-wizard-panel.active > .wz-mo-q,
.u-wizard-panel.active > .wz-mo-sub,
.u-wizard-panel.active > .u-select-filter,
.u-wizard-panel.active > .ip-status-row,
.u-wizard-panel.active > .panel-title,
.u-wizard-panel.active > p {
    flex-shrink: 0;
}
/* 결재선 등: 내부 .wz-scroll-area 가 남은 높이 차지 — 위저드 단계와 단계 없는 행 편집 모달(_sign_line_modal · 공지 대상) 둘 다 */
.u-modal-overlay.is-wizard .u-wizard-panel.active > .u-form-group.wz-panel-fill,
.u-modal-overlay.is-wizard .u-modal-body > .u-form-group.wz-panel-fill {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    margin-bottom: 0;
}
.wz-mo-bar, .wz-mo-step, .wz-mo-q, .wz-mo-sub { display: none; }
/* 진행 막대 — 양 셸 한 자리. -fill 폭은 RN.wizardTabs 가 채운다. ≤980 에서만 보인다(PC 진행 표시 = u-wizard-progress). */
@media (max-width: 980px) {
    .u-modal-overlay.is-wizard .wz-mo-bar { display: block; flex-shrink: 0; height: 4px; background: var(--u-mo-line); border-radius: 2px; overflow: hidden; margin: 0 16px 4px; }
    .u-modal-overlay.is-wizard .wz-mo-bar-fill { height: 100%; background: var(--u-accent); width: 0; transition: width .25s ease; }
}

/* ==========================================================================
   전자서명 법적동의 모달 (sig-legal-*) — 공용 컴포넌트 정본 (2026-07-20, A1 크로스셸 통합)
   마크업 = signature-legal-modal.js 단일 주입(19 JSP 공유). 양 셸 로드(u_components.css).
   옛 admin.css ↔ user_components.css 두 벌 발산(backdrop/shadow/border/title/px-rem) 통합 → cascade 충돌 소멸.
   셸 전용은 각 파일 유지: admin.css=.sig-legal-meta 표시(IP/UA/해시) / user_components.css=meta 숨김 + 모바일 바텀시트.
   ========================================================================== */
.sig-legal-backdrop { display: none; position: fixed; inset: 0; background: var(--u-slate-a50); z-index: 10040; -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
.sig-legal-modal { display: none; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 10050; box-sizing: border-box; max-width: 400px; width: calc(100vw - 24px); padding: 0; margin: 0; max-height: min(92vh, 640px); overflow: hidden; background: var(--u-bg-card); border-radius: 14px; border: 1px solid var(--u-border); box-shadow: 0 0 0 1px var(--u-black-a04), 0 24px 48px var(--u-slate-a18), 0 8px 16px var(--u-slate-a08); }
.sig-legal-modal__scroll { padding: 20px 22px 18px; overflow-y: auto; max-height: calc(min(92vh, 640px) - 72px); }
.sig-legal-modal .sig-legal-title { font-size: 1.0625rem; font-weight: 700; color: var(--u-ink); margin: 0 0 6px; line-height: 1.35; letter-spacing: -0.02em; }
.sig-legal-modal .sig-legal-sub { font-size: 0.8125rem; color: var(--u-ink-light); margin: 0 0 10px; line-height: 1.45; }
.sig-legal-modal .sig-legal-hint { font-size: 0.75rem; line-height: 1.5; color: var(--u-info-strong); background: var(--u-accent-soft); border: 1px solid var(--u-accent-soft); border-radius: 8px; padding: 10px 12px; margin: 0 0 14px; }
.sig-legal-modal .sig-legal-hint:empty { display: none; margin: 0; padding: 0; border: none; }
/* 점선 보조 버튼 — 표·목록 바로 아래 «추가·수정»(주간·TBM·보고서·평가·작업허가서 공용 한 벌). 사용자단 모바일 크기는 user_mobile.css `.u-mo .rv-wk-add`. */
.rv-wk-add {
    display: block; width: 100%; border: 1px dashed var(--u-border-strong); background: transparent;
    color: var(--u-ink-muted); cursor: pointer; font-size: 0.625rem; padding: 3px 0; border-radius: 3px; margin-top: 2px; text-align: center;
}
.rv-wk-add:hover { border-color: var(--u-mgr); color: var(--u-mgr); background: var(--u-accent-soft); }
.rv-wk-add-row { display: flex; gap: 6px; margin-top: 4px; }
@media print { .rv-wk-add, .rv-wk-add-row { display: none !important; } }
/* 한 줄 입력 항목(주간 «회의 내용» · TBM 편집판 새 줄·체크리스트) — 공용 한 벌. 사용자단 모바일 크기는 user_mobile.css. */
.rv-wk-item { display: flex; align-items: center; gap: 4px; padding: 3px 0; border-bottom: 1px solid var(--u-bg); }
.rv-wk-item:last-child { border-bottom: none; }
.rv-wk-item-input {
    flex: 1; border: none; background: transparent; font-size: 0.6875rem; color: var(--u-ink);
    padding: 3px 4px; outline: none; font-family: inherit; min-width: 0;
}
.rv-wk-item-input:focus { background: var(--u-accent-soft); border-radius: 3px; }
.rv-wk-item-input::placeholder { color: var(--u-border-strong); font-style: italic; }
.rv-wk-item-del { border: none; background: none; color: var(--u-ink-muted); cursor: pointer; font-size: 0.625rem; padding: 2px; flex-shrink: 0; line-height: 1; }
.rv-wk-item-del:hover { color: var(--u-danger); }
.sig-legal-preview-wrap { background: var(--u-bg); border: 1px dashed var(--u-border-strong); border-radius: 10px; padding: 14px 12px; text-align: center; margin: 0 0 14px; min-height: 80px; display: flex; align-items: center; justify-content: center; }
/* 손서명 캔버스(signature-legal-modal.js) — 획 색은 JS 가 캔버스의 CSS color 를 읽는다. */
/* 탭 두 개 — [직접 서명](기본) · [등록 서명]. 탭 = 공용 .u-tabs/.u-tab(아래 «탭» 블록) 그대로 · 모달 안에서는 두 탭이 행을 반씩 나눈다. 패널 표시는 JS 모델 → .active. */
.sig-legal-modal .u-tabs { flex-wrap: nowrap; margin: 0 0 14px; background: none; }
.sig-legal-modal .u-tab { flex: 1 1 0; text-align: center; font-family: inherit; }
/* 활성 탭 = 파란 글자·밑줄 — 모바일 목록 탭(user_mobile.css 잉크색)과 달리 모달 안에선 PC 와 같은 accent(사용자 09-28). */
.sig-legal-modal .u-tabs .u-tab.active { color: var(--u-accent); border-bottom-color: var(--u-accent); }
.sig-legal-draw { margin: 0 0 12px; }
/* 정자 안내 = 등록 서명 탭 안내(.sig-legal-hint)와 같은 안내 상자 + 빨간 강조 + 앞머리 ※ (사용자 09-28) — 기호는 CSS 가 붙여 번들 문구는 문장만 든다. */
.sig-legal-modal .sig-legal-hint.sig-legal-draw__guide { color: var(--u-danger); font-weight: 600; }
.sig-legal-draw__guide::before { content: "\203B\00A0"; }
.sig-legal-draw__canvas { display: block; width: 100%; aspect-ratio: 2 / 1; max-height: 180px; background: var(--u-bg-card); border: 1px dashed var(--u-border-strong); border-radius: 8px; color: var(--u-ink); touch-action: none; cursor: crosshair; }
/* 지우기 = 아래 동의 줄(.sig-legal-agree)처럼 한 줄 전체를 차지한다. */
.sig-legal-draw__clear { display: flex; width: 100%; justify-content: center; margin-top: 8px; }
.sig-legal-preview-wrap img { display: block; max-width: 100%; width: auto; max-height: 100px; height: auto; object-fit: contain; vertical-align: middle; }
/* 동의 체크박스 — grid 2컬럼(체크박스 + 텍스트) + 커스텀 박스. 양 셸 공용(옛 admin 미보유=agree 무성실패 정정). */
.sig-legal-agree { display: grid; grid-template-columns: 22px 1fr; align-items: center; gap: 10px; font-size: 0.8125rem; line-height: 1.45; color: var(--u-ink); cursor: pointer; user-select: none; padding: 10px 12px; background: var(--u-bg-gray); border: 1px solid var(--u-border); border-radius: 8px; }
.sig-legal-agree input[type="checkbox"] { appearance: none; -webkit-appearance: none; width: 22px; height: 22px; margin: 0; flex-shrink: 0; border: 2px solid var(--u-border-strong); border-radius: 6px; background: var(--u-bg-card); position: relative; cursor: pointer; transition: background .15s, border-color .15s; }
.sig-legal-agree input[type="checkbox"]:hover { border-color: var(--u-accent); }
.sig-legal-agree input[type="checkbox"]:checked { background: var(--u-accent); border-color: var(--u-accent); }
.sig-legal-agree input[type="checkbox"]:checked::after { content: ''; position: absolute; left: 5px; top: 1px; width: 6px; height: 12px; border: solid var(--u-bg-card); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.sig-legal-agree input[type="checkbox"]:focus-visible { outline: 2px solid var(--u-accent); outline-offset: 2px; }
.sig-legal-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: flex-end; padding: 14px 22px 16px; border-top: 1px solid var(--u-bg); background: var(--u-bg-gray); border-radius: 0 0 14px 14px; }
.sig-legal-actions .u-btn { min-width: 96px; }
@media (max-width: 480px) { .sig-legal-actions { flex-direction: column-reverse; } .sig-legal-actions .u-btn { width: 100%; min-width: 0; } }

/* sig-legal 모바일 바텀시트 (≤980) — base 와 같은 파일이라 dup-selector 회피. admin 은 데스크톱이라 무영향. */
/* ── 모바일 바텀시트 변환 (목업 v3 #22 서명 패드, 2026-05-27) ──
   중앙 모달 → 하단 바텀시트(슬라이드 업). 큰 제목·회색 면 미리보기·풀폭 CTA.
   마크업 무변경 (sig-legal-modal__scroll::before pseudo 로 grip handle 추가).
   19 JSP 가 같은 마크업 공유라 한 곳 수정으로 일괄 정합. */
@media (max-width: 980px) {
    .sig-legal-modal {
        left: 0; right: 0; bottom: 0; top: auto;
        transform: none;
        max-width: none; width: 100%;
        border-radius: var(--u-radius-sheet) var(--u-radius-sheet) 0 0;
        padding-bottom: env(safe-area-inset-bottom, 0px);
        box-shadow: 0 -8px 30px var(--u-slate-a18);
    }
    .sig-legal-modal__scroll {
        padding: 6px 20px 16px;
        max-height: 70vh;
    }
    /* grip handle — 마크업 변경 없이 pseudo 로 */
    .sig-legal-modal__scroll::before {
        content: '';
        display: block;
        width: 40px; height: 4px;
        margin: 4px auto 14px;
        background: var(--u-mo-grey-faint, var(--u-mo-grey-faint));
        border-radius: 2px;
    }
    .sig-legal-modal .sig-legal-title {
        font-size: 1.25rem;
        font-weight: 800;
        letter-spacing: -0.02em;
        margin-bottom: 6px;
    }
    .sig-legal-modal .sig-legal-sub {
        font-size: 0.875rem;
        color: var(--u-ink-light);
        margin-bottom: 16px;
    }
    /* 탭 모바일 형은 user_mobile.css .u-tabs/.u-tab 이 준다 — 모달 안 간격만. */
    .sig-legal-modal .u-tabs { margin-bottom: 16px; gap: 0; }
    /* 옛 파란 hint 박스 → 옅은 회색 면 (토스 톤) */
    .sig-legal-modal .sig-legal-hint {
        background: var(--u-bg-gray);
        border: none;
        color: var(--u-ink-light);
        font-size: 0.8125rem;
        border-radius: 10px;
        padding: 12px 14px;
        margin-bottom: 14px;
    }
    /* 옛 점선 미리보기 박스 → 회색 면 라운드 + 더 크게 (목업 188 톤) */
    .sig-legal-preview-wrap {
        background: var(--u-bg-gray);
        border: none;
        border-radius: var(--u-radius-xl);
        padding: 20px;
        min-height: 140px;
        margin-bottom: 16px;
        display: flex; align-items: center; justify-content: center;
    }
    .sig-legal-preview-wrap img {
        max-height: 140px;
    }
    /* 옛 회색 박스 동의 → 인라인 한 줄 (체크 + 텍스트만) */
    .sig-legal-agree {
        background: transparent;
        border: none;
        padding: 4px 0;
        font-size: 0.875rem;
        color: var(--u-ink);
    }
    /* 우하단 2 버튼 → 하단 풀폭 CTA (서명합니다 primary, 취소 secondary) */
    .sig-legal-actions {
        padding: 4px 20px 16px;
        border-top: none;
        flex-direction: column-reverse;
        gap: 8px;
    }
    .sig-legal-actions .u-btn {
        width: 100%;
        min-width: 0;
        height: 52px;
        border-radius: 12px;
        font-size: 1rem;
        font-weight: 700;
    }
    /* 취소는 부드럽게 — 보더 없는 옅은 톤 */
    .sig-legal-actions .u-btn-secondary {
        background: transparent;
        color: var(--u-ink-light);
        border: none;
    }
}
/* 키 낮은 폰 — 시트가 스크롤 없이 한 화면에 들도록 간격을 줄이고 버튼을 한 줄 [취소][서명]으로. 높이는 보이는 화면(dvh) 기준. */
@media (max-width: 980px) and (max-height: 800px) {
    .sig-legal-modal { max-height: 96vh; max-height: min(96dvh, 640px); }
    .sig-legal-modal__scroll {
        padding: 4px 18px 10px;
        max-height: calc(96vh - 72px - env(safe-area-inset-bottom, 0px));
        max-height: calc(min(96dvh, 640px) - 72px - env(safe-area-inset-bottom, 0px));
    }
    .sig-legal-modal__scroll::before { margin: 2px auto 8px; }
    .sig-legal-modal .sig-legal-title { font-size: 1.125rem; margin-bottom: 2px; }
    .sig-legal-modal .sig-legal-sub { margin-bottom: 8px; }
    .sig-legal-modal .u-tabs { margin-bottom: 10px; }
    .sig-legal-modal .sig-legal-hint { padding: 8px 12px; margin-bottom: 8px; }
    .sig-legal-draw { margin-bottom: 8px; }
    .sig-legal-draw__canvas { max-height: 130px; }
    .sig-legal-draw__clear { margin-top: 6px; }
    .sig-legal-preview-wrap { padding: 12px; min-height: 100px; margin-bottom: 10px; }
    .sig-legal-preview-wrap img { max-height: 100px; }
    .sig-legal-agree { padding: 2px 0; }
    .sig-legal-actions { flex-direction: row; gap: 8px; padding: 4px 18px 10px; }
    .sig-legal-actions .u-btn { flex: 1 1 0; height: 46px; }
}

/* ── av-photo — 사진 첨부 썸네일/업로드 컴포넌트 · 단일 출처(2026-07-21). desktop base(80px 정본).
   assess_view·impl_view·opinion_form·opinion_view.css 4벌 복제(+opinion_view 96px 드리프트) 흡수.
   모바일 반응형(@media≤980, --u-mo-* 토큰·rgba)은 user_mobile.css 유지(user 셸 전용)·첫 페인트 사이징=user_mobile_critical.css. ── */
.av-photo-panel { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px 0; align-items: flex-end; }
.av-photo-thumb { position: relative; display: inline-block; }
.av-photo-thumb img { width: 80px; height: 80px; object-fit: cover; border: 1px solid var(--u-border); border-radius: 6px; cursor: pointer; transition: border-color .15s; }
.av-photo-thumb img:hover { border-color: var(--u-accent); }
.av-photo-thumb .photo-del { position: absolute; top: 2px; right: 2px; background: var(--u-danger); color: var(--u-on-accent); border: none; border-radius: 50%; width: 18px; height: 18px; font-size: 0.625rem; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.av-photo-upload { width: 80px; height: 80px; border: 2px dashed var(--u-border-strong); border-radius: 6px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--u-ink-muted); font-size: 1.25rem; transition: border-color .15s; }
button.av-photo-upload { background: none; padding: 0; font: inherit; }
.av-photo-upload:hover { border-color: var(--u-accent); color: var(--u-accent); }
.av-photo-upload.is-disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.av-photo-empty { color: var(--u-ink-muted); font-size: 0.75rem; padding: 4px 0; }
/* 이행 증빙 조치 전/후 그룹 (2026-07-22, phase 축). av-photo-panel 을 전/후 라벨로 감쌈. 양 셸 공용. */
.av-photo-phase { margin-bottom: 10px; }
.av-photo-phase:last-child { margin-bottom: 0; }
.av-photo-phase-label { font-size: 0.75rem; font-weight: 600; color: var(--u-ink-light); margin-bottom: 4px; }

/* ── 문서 별지 표 — 상세 화면 데스크탑 별지 표 한 벌. 표 이름만 화면마다(공지 bd · 안내 gd · 이행 imp(사용자)·iv(L1) · 의견 op · 주간 wk · TBM tbm)
   칸 클래스 td-title·td-lbl·td-section·td-body·read 는 canonical §3.3. 표 고유(입력·사인 칸·인쇄)는 그 화면 CSS. ── */
.bd-doc, .gd-doc, .imp-doc, .op-doc, .iv-doc, .wk-doc, .tbm-doc { width: 100%; border-collapse: collapse; border: 2px solid var(--u-ink); background: var(--u-bg-card); }
.bd-doc td, .gd-doc td, .imp-doc td, .op-doc td, .iv-doc td, .wk-doc td, .tbm-doc td { border: 1px solid var(--u-ink-muted); padding: 10px 14px; font-size: 0.8125rem; vertical-align: middle; line-height: 1.6; color: var(--u-ink); }
.bd-doc .td-title, .gd-doc .td-title, .imp-doc .td-title, .op-doc .td-title, .iv-doc .td-title, .wk-doc .td-title, .tbm-doc .td-title { background: var(--u-border); font-weight: 800; font-size: 0.9375rem; text-align: center; padding: 12px; }
.bd-doc .td-lbl, .gd-doc .td-lbl, .imp-doc .td-lbl, .op-doc .td-lbl, .iv-doc .td-lbl, .wk-doc .td-lbl, .tbm-doc .td-lbl { background: var(--u-bg-gray); font-weight: 700; text-align: center; width: 110px; color: var(--u-ink); font-size: 0.75rem; }
.bd-doc .td-section, .gd-doc .td-section, .imp-doc .td-section, .op-doc .td-section, .iv-doc .td-section, .wk-doc .td-section, .tbm-doc .td-section { background: var(--u-border); color: var(--u-ink); font-weight: 700; padding: 8px 14px; font-size: 0.75rem; letter-spacing: 0; }
.bd-doc .td-body, .gd-doc .td-body, .imp-doc .td-body, .op-doc .td-body, .iv-doc .td-body, .wk-doc .td-body, .tbm-doc .td-body { padding: 14px 16px; background: var(--u-bg-card); }
.bd-doc .read, .gd-doc .read, .imp-doc .read, .op-doc .read, .iv-doc .read, .wk-doc .read, .tbm-doc .read { color: var(--u-ink); }
/* 등급 글자(의견 상세 A/B/C · L1 TBM 위저드 풀 칩) — 두 셸 한 벌. 별지 .read 보다 뒤에 둔다(같은 특이도 · 등급 색이 이긴다). */
.grade-dot { display: inline-flex; align-items: center; gap: 3px; font-size: 0.75rem; font-weight: 600; color: var(--u-ink-light); }
.grade-dot.A { color: var(--u-danger); }
.grade-dot.B { color: var(--u-safety); }
.grade-dot.C { color: var(--u-success); }
/* 별지 칸 안 날짜 입력 — 칸 폭을 따르고 테두리는 hover/focus 때만 */
.imp-doc input.rn-date, .wk-doc input.rn-date, .wk-doc input.rn-date-range {
    border: 1px solid transparent; background: transparent; padding: 4px 6px;
    font-size: 0.8125rem; width: 100%; box-sizing: border-box; cursor: pointer;
}
.imp-doc input.rn-date:hover, .imp-doc input.rn-date:focus,
.wk-doc input.rn-date:hover, .wk-doc input.rn-date:focus,
.wk-doc input.rn-date-range:hover, .wk-doc input.rn-date-range:focus { border-color: var(--u-accent); background: var(--u-bg-card); outline: none; }

/* ── 서명 칸(td.sign-cell) 공용 값 — 서명자 이름(조각 _sign_cell.jsp) · 참석·서명 표의 서명 이미지 높이 ── */
.sign-cell .av-sign-name { font-size: 0.6875rem; }
.imp-att-table td.sign-cell img, .gd-att-table td.sign-cell img, .wk-att-table td.sign-cell img, .tbm-att td.sign-cell img, .iv-doc td.sign-cell img { height: 28px; vertical-align: middle; }

/* ── 강의 진도 막대 (course-prog) — 이수 현황·강의 목록 진도 칸(L1 _course_table · 사용자 강의·교육 현황). 트랙+채움+퍼센트.
   완료만 초록 — 기본을 초록으로 두면 0% 도 완료로 보인다. 모바일 인라인판(.course-prog-mo)·심화 색 = 사용자 화면 CSS. ── */
.course-prog { display: flex; align-items: center; gap: var(--u-sp-8); max-width: 160px; margin: 0 auto; }
.course-prog .cp-track { flex: 1; height: 8px; border-radius: 999px; background: var(--u-border-light); overflow: hidden; }
.course-prog .cp-fill { display: block; height: 100%; width: calc(var(--p, 0) * 1%); border-radius: 999px; background: var(--u-accent); transition: width .3s ease; }
.course-prog .cp-fill.is-done { background: var(--u-success); }
.course-prog .cp-pct { flex: 0 0 auto; min-width: 2.6em; text-align: right; font-size: var(--u-text-sm); color: var(--u-ink-light); }

/* ══════════════════════════════════════════════════════════════════════
   코멘트 스레드 — 공용 fragment 컴포넌트 (weekly 참석자 의견 · impl 이행 의견)
   2026-07-24 weekly_view.css 에서 이관. 값 무변경(그대로 옮김).
   양 셸 공용 파일이라 사용자단(head.jsp)·L1(mgr_top.jsp) 모두에서 먹는다.
   ══════════════════════════════════════════════════════════════════════ */
/* ── 참석자 코멘트 스레드 (rn_minutes_week_meeting_comment) ──
   계획: dosc/plans/done/weekly_meeting_memo_and_attendee_comments_plan_2026-05-22.md
   2026-05-26 토스풍 채팅 정합 — PC 도 모바일과 같은 패턴 (아바타 + 말풍선 회색카드, 본인 = 파랑).
   모바일 변종은 user_mobile.css Phase 8-D 가 폰트만 살짝 키움.
   wizard Step 4 (weekly_list.jsp) 는 같은 마크업을 쓰지만 위치·여백 톤이 달라 user_wizard.css 에 별 복사 (의도적 분리, 2026-05-28). */
.wk-comment-block {
    margin-top: 14px; padding: 0;
    background: transparent; border-radius: 0;
}
.wk-comment-section-title {
    font-size: 0.75rem; font-weight: 700; color: var(--u-ink-light);
    text-align: left; margin-bottom: 10px;
}
.wk-comment-thread { display: flex; flex-direction: column; gap: 10px; }
.wk-comment-row {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 0; border-bottom: none;
}
.wk-comment-avatar {
    flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%;
    background: var(--u-bg-gray); color: var(--u-ink); font-weight: 800; font-size: 0.8125rem;
    display: flex; align-items: center; justify-content: center;
}
.wk-comment-row[data-mine="1"] .wk-comment-avatar {
    background: var(--u-accent); color: var(--u-on-accent);
}
.wk-comment-body { flex: 1; min-width: 0; }
.wk-comment-meta {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    font-size: 0.75rem; margin-bottom: 4px;
}
.wk-comment-name { font-weight: 700; color: var(--u-ink); }
.wk-comment-time { color: var(--u-ink-muted); font-weight: 400; }
.wk-comment-actions { margin-left: auto; display: flex; gap: 4px; }
.wk-comment-actions button {
    border: none; background: none; color: var(--u-ink-light); font-size: 0.6875rem;
    cursor: pointer; padding: 2px 6px; border-radius: 4px;
}
.wk-comment-actions button:hover { background: var(--u-bg); color: var(--u-accent); }
.wk-comment-actions .wk-comment-del-btn:hover { color: var(--u-danger); }
/* 타임코드 칩 — 값이 있는 코멘트에만 뜬다(현재 영상검수). 클릭 시 그 지점으로 이동, 핸들러는 화면 JS. */
.wk-comment-tc {
    display: inline-flex; align-items: center; gap: 3px;
    padding: 1px 8px; border: 1px solid var(--u-info-soft); border-radius: 999px;
    background: var(--u-accent-soft); color: var(--u-info-strong);
    font-size: 0.6875rem; font-weight: 700; line-height: 1.6; cursor: pointer;
}
.wk-comment-tc:hover { background: var(--u-info-soft); }
/* 말풍선 (회색 카드, 본인 = 옅은 파랑) */
.wk-comment-text {
    background: var(--u-bg-gray); border-radius: 12px;
    padding: 10px 14px;
    font-size: 0.8125rem; line-height: 1.5; color: var(--u-ink);
    white-space: pre-wrap; word-break: break-word;
}
.wk-comment-row[data-mine="1"] .wk-comment-text { background: var(--u-accent-soft); }
/* 입력 폼 — 가로 (textarea + 작은 등록 버튼, 메신저식) */
.wk-comment-compose {
    margin-top: 14px; padding-top: 0; border-top: none;
    display: flex; flex-direction: row; gap: 8px; align-items: center;
}
.wk-comment-input {
    flex: 1; min-height: 40px;
    background: var(--u-bg-gray); border: none; border-radius: 12px;
    padding: 10px 14px;
    font-size: 0.8125rem; line-height: 1.4; font-family: inherit;
    color: var(--u-ink); outline: none; resize: none;
}
.wk-comment-input:focus { outline: 2px solid var(--u-accent); outline-offset: -2px; }
.wk-comment-compose .u-btn { flex-shrink: 0; align-self: auto; }

/* ── 결재선/참석자 "명단 조립" 통일 위젯 RN.signerList (§5.7.2) — 양 셸 공용 기본형 ──
   단일 클래스(낮은 특이도)라 L3 settings(.ap-att-row)·위저드(.cp-ap-row)는 셸 CSS 가 후행/고특이도로 레이아웃을
   재정의하고, L1(admin 셸)은 이 기본형을 그대로 쓴다. slot=ap-att-slot-badge·del=ap-att-del-btn 등은 셸 CSS 재사용. */
.rn-signer-list { display: flex; flex-direction: column; gap: 8px; }
.rn-signer-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: var(--u-bg-gray); border-radius: 10px; flex-wrap: wrap; }
.rn-signer-role { font-weight: 700; color: var(--u-ink); min-width: 96px; }
.rn-signer-row .set-mem-pick { flex: 1; min-width: 160px; justify-content: flex-start; }
/* 결재선·참석자 표형 패널(L1 approval_settings · 사용자 settings) — 머리줄·행 같은 4열(No/역할/담당자/삭제). 한쪽만 바꾸지 말 것.
   패널 안 행은 표다 — 간격 0 · 구분선 · 줄무늬 · hover. 모바일 접기·체크리스트 3열 = settings.css · 위저드판 = user_wizard.css. */
.ap-weekly-panel { border: 1px solid var(--u-border); border-radius: 10px; overflow: hidden; background: var(--u-bg-card); box-shadow: 0 1px 2px var(--u-black-a04); }
.ap-weekly-thead {
    display: grid; grid-template-columns: 52px minmax(120px, 1fr) minmax(180px, 1fr) 36px;
    gap: 12px; align-items: center; padding: 12px 14px; background: var(--u-bg-gray);
    font-size: 0.6875rem; font-weight: 700; color: var(--u-ink-light); text-transform: uppercase; letter-spacing: 0.04em;
    border-bottom: 1px solid var(--u-border);
}
.ap-weekly-panel .rn-signer-list { gap: 0; }
.ap-weekly-panel .ap-att-row {
    display: grid; grid-template-columns: 52px minmax(120px, 1fr) minmax(180px, 1fr) 36px;
    gap: 12px; align-items: center; padding: 10px 14px; margin: 0; border-radius: 0;
    border-bottom: 1px solid var(--u-bg); background: var(--u-bg-card);
}
.ap-weekly-panel .ap-att-row:nth-child(even) { background: var(--u-bg-gray); }
.ap-weekly-panel .ap-att-row:last-child { border-bottom: none; }
.ap-weekly-panel .rn-signer-row:hover { background: var(--u-accent-soft); }   /* 결재선·참석자 행(체크리스트 행 .tc-row 제외) */

/* ===== 법적의무 ★ + 근거 조문 팝업 (2026-09-21 · _legal_mark.jsp · RN.legalPopup) =====
   ★ 는 버튼(팝업 있음) 또는 정적 span(키 없는 옛 기록·사용자 작성 행). 팝업은 u-modal 표준 위에 .u-law-* 만 얹는다. */
.u-legal-mark { display: inline-block; color: var(--u-danger); font-weight: 700; line-height: 1; padding: 0 2px; }
/* 누를 수 있는 ★ = 배지(u-badge-red 와 같은 면·모서리·글자) + 끝의 › 로 «눌린다» 를 알린다. 보이는 높이는 줄에 맞추고 누르는 자리는 ::after 로 32px 를 채운다. */
button.u-legal-mark {
    position: relative; display: inline-flex; align-items: center; gap: 2px; vertical-align: middle;
    padding: 4px 4px 4px 6px; margin: 0 2px;
    background: var(--u-danger-soft); border: 0; border-radius: 4px;
    color: var(--u-danger); font: inherit; font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.01em; line-height: 1; white-space: nowrap; cursor: pointer;
}
/* ★·라벨·› 셋 다 줄 높이 1 — 줄 높이가 다르면 가운데 정렬이어도 › 가 글자보다 위아래로 어긋난다. */
button.u-legal-mark > span, button.u-legal-mark .ti { display: block; line-height: 1; }
button.u-legal-mark .ti { font-size: 0.75rem; opacity: 0.7; }
button.u-legal-mark::after { content: ''; position: absolute; left: -2px; right: -2px; top: 50%; height: 32px; min-width: 32px; transform: translateY(-50%); }
button.u-legal-mark:hover, button.u-legal-mark:focus-visible { box-shadow: inset 0 0 0 1px var(--u-danger-border); outline: none; }
button.u-legal-mark:hover .ti, button.u-legal-mark:focus-visible .ti { opacity: 1; }
.u-legal-mark.is-static { cursor: default; }
#u-law-overlay .u-modal { max-width: 720px; width: 94%; max-height: 88vh; display: flex; flex-direction: column; }
#u-law-overlay .u-modal-body { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.u-law-reduction { font-size: 14px; color: var(--u-ink); padding: 10px 12px; background: var(--u-bg-gray); border-radius: 8px; margin-bottom: 12px; }
.u-law-item { border: 1px solid var(--u-border); border-radius: 10px; padding: 12px 14px; margin-bottom: 10px; }
.u-law-item[data-kind="GUIDE"] { border-style: dashed; }
.u-law-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; margin-bottom: 6px; }
.u-law-name { font-size: 12px; color: var(--u-ink-light); }
.u-law-no { font-size: 15px; font-weight: 700; color: var(--u-ink); }
.u-law-tag { font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--u-danger); color: var(--u-on-accent); }
.u-law-tag[data-kind="RELATED"] { background: var(--u-bg-gray); color: var(--u-ink-light); }
.u-law-tag[data-kind="GUIDE"] { background: var(--u-accent); color: var(--u-on-accent); }
.u-law-why { font-size: 12.5px; color: var(--u-ink-light); margin: 0 0 8px; line-height: 1.5; }
.u-law-why b { color: var(--u-ink); }
.u-law-body { font-size: 13px; line-height: 1.65; white-space: pre-line; color: var(--u-ink); max-height: 220px; overflow-y: auto; padding: 8px 10px; background: var(--u-bg-card); border-left: 3px solid var(--u-border); }
.u-law-body mark { background: var(--u-warning-soft); color: inherit; padding: 0 1px; }
.u-law-foot { display: flex; justify-content: space-between; align-items: center; font-size: 11.5px; color: var(--u-ink-light); margin-top: 6px; }
.u-law-foot a { color: var(--u-accent); text-decoration: none; }
@media (max-width: 980px) {
  #u-law-overlay .u-modal { width: 100%; max-width: 100%; max-height: 88vh; border-radius: var(--u-radius-sheet) var(--u-radius-sheet) 0 0; align-self: flex-end; }
  #u-law-overlay { align-items: flex-end; }
}

/* ===== 사진·서명 확대 (img[data-rn-zoom] · user_modal.js) — 누른 한 장만. 서명은 투명 PNG 라 흰 바탕을 깐다. 모바일 바텀시트 규칙보다 id 가 이겨 두 폭 모두 가운데 ===== */
img[data-rn-zoom] { cursor: zoom-in; }
#u-zoom-overlay { align-items: center; justify-content: center; background: var(--u-black-a85); padding: 16px; }
#u-zoom-overlay .u-zoom-img { display: block; background: var(--u-bg-card); max-width: 100%; max-height: calc(100vh - 32px); width: auto; height: auto; object-fit: contain; border-radius: 4px; }
#u-zoom-overlay .u-zoom-close {
    position: absolute; top: 12px; right: 12px; width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%; background: var(--u-black-a50); color: var(--u-on-accent); font-size: 1.5rem; cursor: pointer;
}
#u-zoom-overlay .u-zoom-close:hover, #u-zoom-overlay .u-zoom-close:focus-visible { background: var(--u-black-a75); outline: 2px solid var(--u-on-accent); outline-offset: 2px; }

/* ===== 무한 스크롤 sentinel (RN.infiniteList · rn_core.js) — 두 셸 공용. 모바일 카드 목록은 부모 .u-mo 가 데스크톱에서 숨어 그대로 · 모달 안 목록(QR 영상 검색·인원 피커)은 폭 무관 ===== */
.u-mo-sentinel {
    padding: 24px 0 32px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    cursor: default;
}
.u-mo-sentinel.is-error { cursor: pointer; }
.u-mo-spin {
    width: 26px;
    height: 26px;
    border: 3px solid var(--u-mo-line);
    border-top-color: var(--u-accent);
    border-radius: 50%;
    animation: u-mo-spin 800ms linear infinite;
}
.u-mo-sentinel.is-error .u-mo-spin { display: none; }
@keyframes u-mo-spin { to { transform: rotate(360deg); } }
.u-mo-sentinel-text {
    color: var(--u-mo-tab-idle);
    font-size: 0.875rem;
}
.u-mo-sentinel.is-error .u-mo-sentinel-text {
    color: var(--u-danger);
}
