@charset "UTF-8";
/* ==========================================================================
   u_components.css — 포털 중립 공용 컴포넌트 (2026-07-16, "컴포넌트 진짜 1벌")
   ----------------------------------------
   L1(mgr_top)·사용자단(head.jsp) 양 셸이 로드하는 유일 공용 컴포넌트 CSS.
   canonical "컴포넌트 1벌 + 토큰 2벌" 의 컴포넌트 정본이 여기 산다 —
   같은 마크업이 variables.css(L1 인디고 고정) / user_variables.css(사용자 파랑 커스터마이즈)
   토큰으로 포털별 렌더된다. 색은 반드시 양 셸 공통 --u-* 토큰만(리터럴 hex 금지).
   ⚠ 여기 두는 것은 '진짜 양 포털이 쓰는' 컴포넌트만. 포털 전용(rv-·mo-·mgr-)은 각자 파일에.

   [빈 상태] u-empty(아이콘+텍스트) / u-empty-inline(-sm)(중앙 muted 안내문).
   user_components.css 에서 이관(2026-07-16 reinvented-empty 이주 — 도메인 {prefix}-empty 통일 정본).
   --u-text-sm/md 는 공용이라 admin·user 양쪽 토큰파일에 정의(2026-07-16 admin 신설).
   ========================================================================== */
.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: rgba(0,0,0,0.45);   /* 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 rgba(0,0,0,0.12);
    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; }


/* ===== 버튼 (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;
}
.u-btn:disabled, .u-btn[disabled] { opacity: 0.4; cursor: not-allowed; }
.u-btn:disabled:hover, .u-btn[disabled]:hover { background: var(--u-bg-card); border-color: var(--u-border-strong); }
.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); }

/* ===== 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 상중하
     user_mobile `.u-mgr-content #opfRoot ...` = 의견폼 등급
   소비: assess_view ×5(모바일) · opinion_form ×2 · _opinion_modal(L1). 값은 옛 정의 그대로(무회귀).
   ===== */
.rv-risk-seg { display: flex; justify-content: center; gap: 10px; margin-top: 4px; }
.rv-risk-seg-btn {
    flex: 1; max-width: 100px; height: 48px;
    font-size: 0.9375rem; font-weight: 700; text-align: center;
    border: 2px solid var(--u-border); border-radius: 8px;
    background: var(--u-bg-card); 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); color: var(--u-on-accent); border-color: var(--u-danger); }
.rv-risk-seg-btn.active-mid  { background: var(--u-warning); color: var(--u-on-accent); border-color: var(--u-warning); }
.rv-risk-seg-btn.active-low  { background: var(--u-success); color: var(--u-on-accent); border-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: rgba(255,255,255,0.85); }


.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; }
/* admin 위저드 콘텐츠 크롬 — 항상표시 질문헤딩·리스트박스·폼테이블(옛 cw-panel-q/sub/list/frm-table).
   사용자단 위저드는 데스크톱서 헤딩 없이 wz-mo-q(모바일 전용)·u-select-* 를 쓰므로 이 클래스를 쓰지 않는다. */
.u-wizard-q { font-size: 15px; font-weight: 700; margin-bottom: 2px; }
.u-wizard-sub { font-size: 12px; color: var(--u-ink-muted); margin-bottom: 12px; }
.u-wizard-list { max-height: 340px; overflow-y: auto; border: 1px solid var(--u-bg-gray); border-radius: 8px; padding: 8px; background: var(--u-bg-gray); }
.u-wizard-frm-table { width: 100%; }
.u-wizard-frm-table th { text-align: left; padding: 7px 0; width: 120px; font-size: 13px; color: var(--u-ink-strong); font-weight: 600; vertical-align: middle; }
.u-wizard-frm-table td { padding: 7px 0; font-size: 13px; }


/* ==========================================================================
   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 rgba(0,0,0,0.08);
}

/* ── §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 무회귀). */

/* 본문 — 기인물 chip + 위험 + 감소대책 + 메타 */
.u-modal-overlay.is-wizard .mo-risk-card .risk-obj {
    display: inline-block;
    background: var(--u-bg-card);
    color: var(--u-mo-ink);
    font-weight: 700;
    font-size: 0.8125rem;
    padding: 4px 10px;
    border-radius: 999px;
    margin-bottom: 8px;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-hazard {
    color: var(--u-mo-ink);
    font-size: 0.9375rem;
    line-height: 1.55;
    font-weight: 500;
    margin-top: 4px;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--u-mo-grey-faint);
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red-hd {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--u-accent);
    font-size: 0.8125rem;
    font-weight: 700;
    margin-bottom: 6px;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red-hd i {
    color: var(--u-accent);
    font-size: 0.875rem;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red-list {
    list-style: none;
    padding: 0; margin: 0;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red-item {
    display: flex;
    gap: 6px;
    color: var(--u-mo-ink);
    font-size: 0.875rem;
    line-height: 1.55;
    padding: 2px 0;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red-item::before {
    content: '·';
    color: var(--u-mo-grey);
    flex-shrink: 0;
}
.u-modal-overlay.is-wizard .mo-risk-card .risk-red-item .body { flex: 1; min-width: 0; }

/* 메타 — 담당/기한/상태 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 스코프 = 사용자단 위저드 전용(모바일 높이채움). 모든 사용자단 위저드 오버레이가
   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;
}

/* 패널 내 카드: 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 > p {
    flex-shrink: 0;
}
/* 결재선 등: 내부 .wz-scroll-area 가 남은 높이 차지 */
.u-modal-overlay.is-wizard .u-wizard-panel.active > .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; }

/* ==========================================================================
   전자서명 법적동의 모달 (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: rgba(15, 23, 42, 0.5); 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 rgba(0,0,0,0.04), 0 24px 48px rgba(15,23,42,0.16), 0 8px 16px rgba(15,23,42,0.08); }
.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; }
.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; }
.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, 24px) var(--u-radius-sheet, 24px) 0 0;
        padding-bottom: env(safe-area-inset-bottom, 0px);
        box-shadow: 0 -8px 30px rgba(15, 23, 42, 0.18);
    }
    .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;
    }
    /* 옛 파란 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, 14px);
        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;
    }
}

/* ── 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; }

/* ══════════════════════════════════════════════════════════════════════
   코멘트 스레드 — 공용 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;
    height: 40px; padding: 0 16px; border-radius: 10px;
    font-weight: 700;
}

/* ── 결재선/참석자 "명단 조립" 통일 위젯 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; }
/* 골격 picker(u-picker) 판 — 설정 3화면이 2026-08-18 에 이 마크업으로 옮겼다.
   래퍼가 행의 유연 칸이 되고, 버튼(.u-picker-open)은 래퍼를 꽉 채운다. */
.rn-signer-row .u-picker { flex: 1; min-width: 160px; }
