/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   풀다(FullDa) — Design System
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */

:root {
  --sidebar-w: 192px;
  --header-h: 52px;

  /* Sidebar */
  --sidebar-bg: #1e2638;
  --sidebar-text: #ffffff;
  --sidebar-muted: rgba(255, 255, 255, 0.52);  /* 그룹 라벨·비활성 항목 대비 AA(네이비 위 5.0:1) */

  /* Surface */
  --bg: #f5f6fa;
  --surface: #ffffff;
  --border: #dfe4ed;             /* A+ 헤어라인(구 #e2e6ef) */
  --control-border: #c8cfdb;     /* 컨트롤 외곽선 — surface 위 기본 상태 구분 */
  --border-dash: #c9d0de;

  /* Text */
  --text: #1a2035;
  --text-muted: #596278;   /* A+ 본문 muted — 흰 카드 AA(구 #646d82) */
  --label: #1a2035;

  /* Accent */
  --accent: #1e2638;
  --accent-hover: #2c3a56;
  --accent-ink: #ffffff;   /* accent 채움면 위 글자색(블랙 테마에서 반전) */

  /* Status */
  --data:#6b57b8;
  --data-strong:#54419a;
  --ok:#236b46;
  --warn:#8a5a00;
  --danger:#b3343e;
  --danger-ink:#ffffff;
  --focus-ring:#3157c8;
  --focus-on-shell:#ffffff;
  --selection-outline:#667085;
  --legacy-ok:#22c55e;
  --legacy-warn:#f59e0b;
  --legacy-danger:#ef4444;
  --legacy-good:#0f7a37;
  --legacy-good-bg:#e6f6ec;
  --legacy-good-line:rgba(15,122,55,.30);
  --legacy-warn-2:#d98a04;
  --legacy-warn-bg:#fbf1da;
  --legacy-bad:#c22226;
  --legacy-bad-bg:#fbe9ea;
  --legacy-bad-line:rgba(194,34,38,.35);
  --legacy-qbar:#ab7e17;
  --active-halo:rgba(30,38,56,.12);

  /* Type */
  --type-screen: 24px;
  --type-section: 18px;
  --type-body: 15px;
  --type-button: 13px;
  --type-meta: 12.5px;
  --type-label: 12px;

  /* Control size (버튼·입력 높이. 모바일 hit area 최소 44px) */
  --control-dense: 32px;
  --control-standard: 40px;
  --control-touch: 44px;
  --control-prominent: 48px;

  /* Radius (control 8 / card 11 / overlay 16 / pill 999 — 나머지는 별칭) */
  --radius-control: 8px;
  --radius-card: 11px;
  --radius-overlay: 16px;
  --radius-pill: 999px;
  --radius: var(--radius-card);
  --radius-sm: var(--radius-control);

  /* Bank/detail panel tokens — mapped onto the app's navy palette so the
     문제 은행 panel matches the main shell instead of an undefined purple set */
  --pri: var(--accent);
  --pri-dark: var(--accent-hover);
  --acc: var(--accent);
  --text2: var(--text);
  --text3: var(--text-muted);
  --r: var(--radius-card);
  --rs: var(--radius-control);
  --success: var(--ok);

  /* 스케일 토큰 (DESIGN.md "정밀 계기") */
  --surface-2: #eef1f6;          /* 옛 미정의 --bg2 대체 */
  --radius-lg: var(--radius-overlay);
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;
  --exam-col: 330px;             /* 시험지 한 단 폭 = 은행 카드 폭 */

  /* ── 재디자인 토큰(목업 2026-06-30 기준) ── */
  --ink:#1a2035; --ink-2:#424a60; --ink-3:var(--text-muted); --ink-4:#aab2c2;
  --accent-2:#2c3a56; --accent-soft:#e9ecf3;
  --line-2:#edf0f5;
  /* 목업 컴포넌트 규칙 verbatim 이식용 브리지(기존 토큰에 매핑) */
  --line: var(--border); --r-sm: var(--radius-control);
  --good:var(--ok); --good-bg:#e6f6ec; --good-line:rgba(15,122,55,.30);
  --warn-2:var(--warn); --warn-bg:#fbf1da;
  --bad:var(--danger); --bad-bg:#fbe9ea; --bad-line:rgba(194,34,38,.35);
  --accent-tint:rgba(30,38,56,.05);   /* 네이비 5% 틴트(legal 표 헤더·안내박스). --accent(#1e2638=rgb 30,38,56)의 알파 */
  /* 위 --good/--warn-2/--bad 는 --ok/--warn/--danger 의 짝(배경 포함). 신규 코드는 의미색=--ok/--warn/--danger, 그 배경=--good-bg/--warn-bg/--bad-bg 사용 */
  --card-radius:var(--radius-card);
  --display:'Pretendard Variable',Pretendard,'Segoe UI',system-ui,-apple-system,sans-serif;   /* 제목: 깔끔한 산세리프 통일(구 Noto Serif KR 세리프 폐지) */
  /* Elevation (정적 카드·KPI·표=그림자 0. control/low/high 만 사용) */
  --shadow-static:none;
  --shadow-control:0 1px 2px rgba(26,32,53,.10);
  --shadow-low:0 6px 18px -8px rgba(26,32,53,.18);
  --shadow-high:0 12px 34px -14px rgba(26,32,53,.22);
  --shadow:var(--shadow-static);
  --shadow-lg:var(--shadow-high);
  /* 신설 토큰 (Task 1) */
  --fav:#f43f5e; --surface-3:#f9fafb; --ink-deep:#0f172a;
  /* 범주형 차트 (카테고리 색 — --good/--warn-2/--bad 의미색 재사용 금지)
     승인 팔레트 P6: chart-1 페리윙클(--data, 강사/공유)·chart-2 앰버골드(학생/개인)·
     chart-3 에메랄드(원장)·chart-other 뉴트럴(기타). 4·5번째 계열 없음 → 함수 그래프는 선 패턴으로 확장.
     범주형 색은 순위 램프가 아니라 정체성(identity) 색이다. 색상환에서 서로 떨어져 있어야 하고
     절대 한 색 계열로 합치지 않는다. 순차 스케일은 지도 q-ramp(--map-q0..q5)가 유일하다. */
  --chart-1:var(--data); --chart-2:#eba300; --chart-3:#10b97e; --chart-other:#7b7a8c;
  /* 범주형 채움의 경계 헤어라인. 화이트 표면에서 앰버골드 채움은 2.15:1로 비텍스트 3:1 하한을
     밑돈다. 색을 칙칙하게 죽이는 대신 1px 안쪽 경계로 표면·인접 세그먼트 경계를 확보한다.
     화이트 값은 세 표면(#ffffff/#f5f6fa/#eef1f6) 모두에서 3:1 이상이다. */
  --data-mark-edge:#767c8e;
  /* 온보딩 역할 구분 틴트 (강사=인디고·학생=그린, 하드코딩 제거) */
  --role-teacher-tint:rgba(99,102,241,.07); --role-teacher-tint-sel:rgba(99,102,241,.1);
  --role-student-tint:rgba(34,197,94,.08);
  /* ── 디자인 패스 ①: 산세리프 숫자 스택 + 카드 그림자 ── */
  --font-num:'Pretendard Variable',Pretendard,'Segoe UI',system-ui,-apple-system,sans-serif;
  --shadow-card:var(--shadow-low);
  /* ── 다크 서피스용 텍스트/오버레이 토큰 (홈 히어로) ── */
  --nav:#1e2747; --nav2:#2f3d6b;      /* 홈 히어로 네이비 그라디언트 */
  --on-nav:#fff;
  --on-nav-a12:rgba(255,255,255,.12);
  --on-nav-a18:rgba(255,255,255,.18);
  --on-nav-a20:rgba(255,255,255,.20);
  --on-nav-a25:rgba(255,255,255,.25);
  --overlay: rgba(26,32,53,.45);      /* 모달 백드롭 */

  /* ── z-index 스케일 (동작 불변: 현행 실효값을 그대로 토큰화, 값 재설계 아님) ──
     --z-nav      30     #sidebar (자체 백드롭 .nav-backdrop=28=-2, #header 20 은 하위·별도)
     --z-overlay  300    .lec-modal-ov(299=-1 백드롭)·.chap-editor·.lec-edit-box·.mv-toast
     --z-annc     950    전역 공지 모달 .mv-annc-bg (로그인 오버레이 아래)
     --z-auth     1000   .auth-screen 로그인 오버레이
     --z-player   1000   .cls-player-ov 강의 플레이어 오버레이
     --z-toast    2000   #toast-host 전역 토스트 호스트
     --z-viewer   9998   .file-viewer-ov 자료 뷰어
     --z-lightbox 9999   .img-lightbox 문항 이미지 라이트박스
     --z-picker   10000  .asgn-pick-overlay 문제 피커(최상위)
     (범위 밖 유지: #header 20, 각종 드롭다운/스티키 40~70, bk-* 뱅크 200~230,
      .ui-modal-overlay 9999, 플레이어 유사전체화면(app.js) 2000) */
  --z-nav: 30;
  --z-overlay: 300;
  --z-annc: 950;
  --z-auth: 1000;
  --z-player: 1000;
  --z-toast: 2000;
  --z-viewer: 9998;
  --z-lightbox: 9999;
  --z-picker: 10000;
}

/* ── 환경설정: 글자 크기 ──
   data-font 은 루트 font-size 가 아니라 타입 토큰만 재정의한다(rem 종속 UI 안깨짐).
   모바일(≤768px)에서는 화면/섹션/버튼을 별도로 낮춰 본문 15px·버튼 14px 하한 유지.
   data-font 을 안 거는 단독 페이지(admin/login/onboarding)도 모바일에서 데스크탑 24px 를
   물려받지 않도록 @media 블록 선두에 :root 폴백을 둔다(html[data-font] 은 더 특이도 높아 우선). */
html[data-font="s"]{
  --type-screen:23px;--type-section:17px;--type-body:14px;
  --type-button:13px;--type-meta:12px;--type-label:12px
}
html[data-font="m"]{
  --type-screen:24px;--type-section:18px;--type-body:15px;
  --type-button:13px;--type-meta:12.5px;--type-label:12px
}
html[data-font="l"]{
  --type-screen:27px;--type-section:20px;--type-body:17px;
  --type-button:15px;--type-meta:14px;--type-label:13px
}
@media(max-width:768px){
  :root{
    --type-screen:20px;--type-section:17px;--type-body:15px;
    --type-button:14px;--type-meta:12.5px;--type-label:12px
  }
  html[data-font="s"]{
    --type-screen:20px;--type-section:17px;--type-body:15px;
    --type-button:14px;--type-meta:12px;--type-label:12px
  }
  html[data-font="m"]{
    --type-screen:20px;--type-section:17px;--type-body:15px;
    --type-button:14px;--type-meta:12.5px;--type-label:12px
  }
  html[data-font="l"]{
    --type-screen:23px;--type-section:19px;--type-body:17px;
    --type-button:16px;--type-meta:14px;--type-label:13px
  }
}
/* ── 환경설정: 콘텐츠 밀도(컴팩트) ── */
html[data-density="compact"] .card{padding:10px;}
html[data-density="compact"] .panel{padding:14px;}
html[data-density="compact"] .stat{padding:10px 12px;box-shadow:none;}
html[data-density="compact"] .tbl td,
html[data-density="compact"] .tbl th{padding-top:6px;padding-bottom:6px;}

/* ── Reset ── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: "Pretendard Variable", Pretendard, "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: var(--type-body);
  color: var(--text);
  word-break: keep-all;       /* 한글 어절 중간 끊김(예: 선/택, 문/제) 방지 — 공백에서만 줄바꿈 */
  overflow-wrap: break-word;  /* 단, 한 줄보다 긴 토큰(URL·식별자)은 넘치지 않게 끊음 */
  background: var(--bg);
  display: grid;
  grid-template-rows: var(--header-h) 1fr;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-areas:
    "header header"
    "sidebar main";
  height: 100vh;
  height: 100dvh;   /* 모바일: URL바 포함 실제 가시높이 — 하단 끝까지 스크롤 도달 */
  overflow: hidden;
}

button { cursor: pointer; font: inherit; }
input, textarea, select { font: inherit; }

/* ── 유틸 클래스(재디자인 토큰 소비용) ── */
.disp{font-family:var(--font-num);font-weight:700;letter-spacing:-.02em}
h1.disp{font-size:var(--type-screen);font-family:var(--display)} h2.disp{font-size:var(--type-section)}   /* 페이지 제목만 세리프(h2/h3는 산세리프 유지→위계) */
.ic{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0}
.ic.sm{width:14px;height:14px}
.spin{animation:mv-sp 1s linear infinite;transform-origin:center} @keyframes mv-sp{to{transform:rotate(360deg)}}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Header
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
#app-header {
  grid-area: header;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  z-index: 20;
  min-width: 0;   /* 그리드 아이템 기본 min-width:auto 해제 — 모바일 1fr 트랙이 헤더 내용 폭(422px)에
                     끌려 늘어나며 문서 전체 가로 오버플로를 일으키던 문제 방지 */
}

#brand {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 17px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.02em;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
}
#brand .brand-mark { flex: none; }
#brand:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
#brand .brand-logo { height: 16px; width: auto; display: block; }
.auth-brand .brand-logo { height: 24px; width: auto; display: inline-block; vertical-align: middle; }

/* Coarse pointers need a real 44px hit rectangle even for compact header controls. */
@media (pointer: coarse) {
  #brand[role="button"], #app-header button, #admin-link {
    min-width: 44px;
    min-height: 44px;
  }
  #brand[role="button"] { justify-content: center; }
}

.brand-ai {
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 12px;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 6px;
  letter-spacing: 0.04em;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Sidebar
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
#sidebar {
  grid-area: sidebar;
  background: var(--sidebar-bg);
  display: flex;
  flex-direction: column;
  padding: 24px 0;
  overflow-y: auto;
}

/* ── 앱 셸 헤더 보조: 로고 좌측 + (은퇴한) 햄버거 + 공유 백드롭 ──
   폭 기반 드로어는 6단계 data-shell-mode로 대체됨(아래). .nav-toggle은 어떤 모드에서도
   노출하지 않으므로 사실상 은퇴 상태(HTML 잔존은 무해). .nav-backdrop은 레일 플라이아웃이 재사용한다. */
.header-left{display:flex;align-items:center;gap:10px;flex:none}   /* 로고는 짧으니 고정(잘리지 않음) */
.nav-toggle{display:none;align-items:center;justify-content:center;width:40px;height:40px;border:none;background:none;cursor:pointer;color:var(--text);border-radius:8px}
.nav-toggle:hover{background:rgba(0,0,0,.05)}
.nav-backdrop{display:none;position:fixed;inset:0;background:rgba(15,20,35,.45);z-index:calc(var(--z-nav) - 2)}
.nav-backdrop.open{display:block}

/* ── 6단계 반응형 셸: data-shell-mode가 폭이 아니라 명시 계약으로 레이아웃을 결정한다.
   shell-nav.js가 프리페인트로 <html>에 data-shell-mode·data-input을 새긴다. ── */
html[data-shell-mode="wide-desktop"]{--sidebar-w:216px}
html[data-shell-mode="desktop"]{--sidebar-w:192px}
html[data-shell-mode="tablet-landscape"]{--sidebar-w:72px}
html[data-shell-mode="mobile-landscape"]{--sidebar-w:56px;--header-h:46px}
html[data-shell-mode="tablet-portrait"],html[data-shell-mode="mobile-portrait"]{--sidebar-w:0px}

html[data-shell-mode="wide-desktop"] body,
html[data-shell-mode="desktop"] body,
html[data-shell-mode="tablet-landscape"] body,
html[data-shell-mode="mobile-landscape"] body{
  grid-template-columns:var(--sidebar-w) minmax(0,1fr);
  grid-template-areas:"header header" "sidebar main";
}
html[data-shell-mode="tablet-portrait"] body,
html[data-shell-mode="mobile-portrait"] body{
  grid-template-columns:minmax(0,1fr);
  grid-template-areas:"header" "main";
}

html[data-shell-mode="wide-desktop"] #sidebar,
html[data-shell-mode="desktop"] #sidebar,
html[data-shell-mode="tablet-landscape"] #sidebar,
html[data-shell-mode="mobile-landscape"] #sidebar{display:flex;position:static;transform:none;width:auto;height:auto;box-shadow:none}
html[data-shell-mode="tablet-portrait"] #sidebar,
html[data-shell-mode="mobile-portrait"] #sidebar{display:none}

/* 세로 모드 하단 탭바 — Task 5의 임시 폭 미디어쿼리를 data-shell-mode 선택자로 대체 */
html[data-shell-mode="tablet-portrait"] .mob-tab,
html[data-shell-mode="mobile-portrait"] .mob-tab{
  display:grid;grid-template-columns:repeat(var(--shell-nav-count,6),minmax(0,1fr));
  position:fixed;left:0;right:0;bottom:0;z-index:var(--z-nav);
  min-height:var(--shell-bottom-nav-h);padding:6px 4px env(safe-area-inset-bottom);
  background:var(--surface);border-top:1px solid var(--line);overflow:visible;
}
html[data-shell-mode="tablet-portrait"] #main,
html[data-shell-mode="mobile-portrait"] #main{
  padding-bottom:calc(var(--shell-bottom-nav-h) + env(safe-area-inset-bottom));
}

/* 3=학생 기본, 4=더보기가 붙은 학생, 6=강사 */
.mob-tab[data-count="3"]{--shell-nav-count:3}
.mob-tab[data-count="4"]{--shell-nav-count:4}
.mob-tab[data-count="6"]{--shell-nav-count:6}
html[data-input="touch"] .tool-item,
html[data-input="touch"] .shell-rail-group,
html[data-input="touch"] .mob-tab-item,
html[data-input="touch"] .shell-hub-link{min-height:44px}

/* 태블릿·모바일 가로: 아이콘 레일(#tool-nav) + 사이드바 우측에 붙는 카테고리 플라이아웃 */
html[data-shell-mode="tablet-landscape"] #tool-nav,
html[data-shell-mode="mobile-landscape"] #tool-nav{align-items:stretch;padding:8px 4px;gap:4px}
.shell-rail-group{min-height:52px;border:0;background:transparent;color:var(--sidebar-muted);text-decoration:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;font-size:var(--type-label);border-radius:var(--radius-control);padding:4px}
.shell-rail-group:hover,.shell-rail-group[aria-current="page"]{color:var(--sidebar-text);background:var(--on-nav-a12)}
/* 네이비 레일 위 포커스 링은 공통 셸 포커스 계약에서 관리 */
html[data-shell-mode="tablet-landscape"] .shell-rail-group{min-height:64px}
html[data-shell-mode="mobile-landscape"] .shell-rail-group{min-height:48px}
.shell-rail-flyout{position:fixed;top:var(--header-h);left:var(--sidebar-w);z-index:var(--z-nav);width:min(260px,70vw);max-height:calc(100dvh - var(--header-h));overflow:auto;display:flex;flex-direction:column;gap:6px;background:var(--surface);border:1px solid var(--line);border-radius:0 var(--radius-overlay) var(--radius-overlay) 0;padding:10px;box-shadow:var(--shadow-high)}

#tool-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tool-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: auto;
  margin-right: 10px;
  padding: 11px 18px;
  background: none;
  border: none;
  color: var(--sidebar-muted);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  /* 호버/active 배경이 각지지 않게 — 왼쪽 강조바(::before)는 가장자리에 붙이고 오른쪽만 둥글게 */
  border-radius: 0 10px 10px 0;
  transition: color 0.15s, background 0.15s;
  position: relative;
}

/* 중앙 모델이 <a>로 렌더한다 — 링크 밑줄 제거 + 터치 타깃 하한 */
.tool-item{text-decoration:none;min-height:var(--control-standard)}

.tool-item:hover {
  color: rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.05);
}

.tool-item.active {
  color: var(--sidebar-text);
  font-weight: 700;
}

.tool-icon {
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  opacity: 0.45;
}

.tool-item.active .tool-icon {
  opacity: 1;
}

.tool-label {
  flex: 1;
  white-space: nowrap;
}

.tool-arrow {
  flex-shrink: 0;
  width: 13px;
  height: 13px;
  opacity: 0;
  transition: opacity 0.15s;
}

.tool-item.active .tool-arrow {
  opacity: 1;
}

.tool-group-label{font-size:var(--type-label);font-weight:700;color:var(--sidebar-muted);
  letter-spacing:.08em;text-transform:uppercase;margin:14px 12px 5px;display:block}
.tool-group-label:first-child,
.shell-sb-toggle+.tool-group-label{margin-top:4px}

/* ── 판서. 카드(내비 맨 아래) ──
   도구 항목과 같은 줄에 세우지 않고 테두리 카드로 둔다 — 같은 앱의 화면이 아니라
   건너가는 별도 공간이라는 사실을 ↗ 표시와 함께 형태로 말한다. */
.shell-panseo{display:flex;align-items:center;gap:9px;margin:10px 10px 0;padding:8px 10px;
  border:1px solid var(--on-nav-a25);border-radius:var(--radius-control);
  color:var(--sidebar-text);text-decoration:none;font-size:13px;font-weight:700;
  min-height:var(--control-standard)}
.shell-panseo:hover{background:var(--on-nav-a12)}
.shell-panseo .ic{flex:none;width:15px;height:15px;opacity:.85}
.shell-panseo-label{flex:1;white-space:nowrap}
.shell-panseo-mark{flex:none;font-size:12px;opacity:.6}
:root[data-sb="white"] .shell-panseo{border-color:var(--border);color:var(--ink)}
:root[data-sb="white"] .shell-panseo:hover{background:var(--surface-2)}

/* ── 사이드바 접기 손잡이 + 아이콘 레일 ──
   3칼럼을 쓰는 화면(문제은행 등)에서 좌측 내비가 먹는 폭을 사용자가 직접 돌려받는다.
   접힘은 데스크톱 사이드바에만 있다 — 태블릿 가로·모바일 가로는 이미 레일이고,
   세로 모드는 사이드바 자체가 없다. */
.shell-sb-toggle{margin-bottom:8px;border-bottom:1px solid var(--on-nav-a12);border-radius:0;
  padding-bottom:12px;width:100%;cursor:pointer}
html[data-shell-mode="wide-desktop"][data-sb-collapsed="1"],
html[data-shell-mode="desktop"][data-sb-collapsed="1"]{--sidebar-w:52px}
html[data-sb-collapsed="1"] .tool-group-label{display:none}
html[data-sb-collapsed="1"] .tool-item{justify-content:center;gap:0;margin-right:0;
  padding-left:0;padding-right:0;border-radius:0}
html[data-sb-collapsed="1"] .tool-label,
html[data-sb-collapsed="1"] .tool-arrow{display:none}
/* 좁은 레일(태블릿 가로·모바일 가로)도 접힌 데스크톱과 같은 아이콘 전용 모양이다. */
html[data-sb-collapsed="1"] .shell-panseo,
html[data-shell-mode="tablet-landscape"] .shell-panseo,
html[data-shell-mode="mobile-landscape"] .shell-panseo{margin:10px 6px 0;padding:8px 0;justify-content:center}
html[data-sb-collapsed="1"] .shell-panseo-label,
html[data-sb-collapsed="1"] .shell-panseo-mark{display:none}
/* 데스크톱 사이드바에서 판서. 카드는 항목 뒤가 아니라 바닥에 붙는다.
   nav 가 남은 높이를 채우고 카드가 auto 마진으로 내려간다. 내비가 넘칠 만큼
   길면 auto 마진이 0 이 되어 흐름 순서(맨 마지막)로 자연 강등된다.
   접힘 레일 규칙(위 margin:10px 6px 0)보다 뒤에 두어 캐스케이드에서 이긴다. */
html[data-shell-mode="wide-desktop"] #tool-nav,
html[data-shell-mode="desktop"] #tool-nav{flex:1 1 auto}
html[data-shell-mode="wide-desktop"] .shell-panseo,
html[data-shell-mode="desktop"] .shell-panseo{margin-top:auto}
html[data-shell-mode="wide-desktop"] body,
html[data-shell-mode="desktop"] body{transition:grid-template-columns .18s ease}
@media (prefers-reduced-motion:reduce){
  html[data-shell-mode="wide-desktop"] body,
  html[data-shell-mode="desktop"] body{transition:none}
}

/* ━━━ 사이드바 2종: 흰 변형 (:root[data-sb="white"]) ━━━ */
:root[data-sb="white"] #sidebar{background:#fff;border-right:1px solid var(--line)}
:root[data-sb="white"] .tool-group-label{color:var(--ink-4)}
:root[data-sb="white"] .tool-item{color:var(--ink-2)}
:root[data-sb="white"] .tool-item:hover{background:var(--surface-2);color:var(--ink)}
:root[data-sb="white"] .tool-item.active{background:var(--surface-2);color:var(--ink)}
:root[data-sb="white"] .tool-item.active::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:3px;background:var(--accent)}
:root[data-sb="white"] .tool-icon{opacity:.5}
:root[data-sb="white"] .tool-item.active .tool-icon{opacity:1}

/* ── 사이드바 항목 호버: 왼쪽 강조바(::before) + 배경 + 아이콘 밝게 ──
   Navy(네이비 배경)→바 흰색 / White(흰 배경)→바 accent.
   호버=얇고 옅은 바, active=굵고 또렷한 바로 위계. */
.tool-item::before{content:"";position:absolute;left:0;top:7px;bottom:7px;width:3px;
  border-radius:0 3px 3px 0;background:var(--sidebar-text);opacity:0;
  transform:scaleX(0);transform-origin:left;transition:transform .13s,opacity .13s}
.tool-item:hover::before{opacity:.5;transform:scaleX(.6)}
.tool-item.active::before{opacity:1;transform:scaleX(1)}
.tool-item:hover:not(.active){color:rgba(255,255,255,.92);background:rgba(255,255,255,.09)}
.tool-item:hover:not(.active) .tool-icon{opacity:.75}
/* White 변형: 바=accent, 호버 배경=옅은 틴트(active surface-2와 구분) */
:root[data-sb="white"] .tool-item::before{background:var(--accent)}
:root[data-sb="white"] .tool-item:hover:not(.active){background:var(--accent-tint);color:var(--ink)}
:root[data-sb="white"] .tool-item:hover:not(.active) .tool-icon{opacity:.8}
@media (prefers-reduced-motion:reduce){.tool-item::before{transition:opacity .13s}}

/* ━━━ 화면 테마: 블랙 (:root[data-theme="black"]) — 순흑 뉴트럴 B안
   스펙: docs/superpowers/specs/2026-07-12-theme-black-design.md
   원칙: 토큰만 재정의, 컴포넌트 규칙 불변. 화이트 = 속성 없음(기본). ━━━ */
:root[data-theme="black"]{
  --bg:#09090b; --surface:#141416; --surface-2:#1b1b1f; --surface-3:#18181c;
  --border:#26262c; --control-border:#3a3a42; --border-dash:#33333a; --line-2:#202024;
  --text:#ececf0; --text-muted:#a8a8b4; --label:#ececf0;
  --ink:#ececf0; --ink-2:#c8c8d2; --ink-3:var(--text-muted); --ink-4:#5b5b66; --ink-deep:#f4f4f8;
  --accent:#ececf0; --accent-hover:#ffffff; --accent-2:#d4d4dc;
  --accent-ink:#131316;   /* 주 버튼 반전: 밝은 면 + 검은 글자 (B안 핵심) */
  --accent-soft:#202026; --accent-tint:rgba(236,236,240,.06);
  --overlay:rgba(0,0,0,.6);
  --sidebar-bg:#0e0e11;
  --data:#a08ce8; --data-strong:#c1b2f4;
  --ok:#69b58a; --warn:#d4a447; --danger:#e06b74;
  --danger-ink:#131316; --focus-ring:#92a9ff; --focus-on-shell:#ffffff;
  --selection-outline:#98a2b3;
  --legacy-ok:#4ade80;
  --legacy-warn:#fbbf24;
  --legacy-danger:#f87171;
  --legacy-good:#4ade80;
  --legacy-good-bg:#122a1b;
  --legacy-good-line:rgba(74,222,128,.30);
  --legacy-warn-2:#fbbf24;
  --legacy-warn-bg:#2b230f;
  --legacy-bad:#f87171;
  --legacy-bad-bg:#311618;
  --legacy-bad-line:rgba(248,113,113,.35);
  --legacy-qbar:#ba8508;
  --active-halo:rgba(236,236,240,.16);
  --good-bg:#122a1b; --good-line:rgba(74,222,128,.30);
  --warn-bg:#2b230f;
  --bad-bg:#311618; --bad-line:rgba(248,113,113,.35);
  --nav:#17171b; --nav2:#232329;   /* 홈 히어로: 네이비 → 뉴트럴 그라파이트 */
  --chart-1:var(--data); --chart-2:#ffc94d; --chart-3:#45dba8; --chart-other:#b0aec2;
  /* 블랙 테마 채움은 표면 대비 8:1 이상이라 대비 보정은 불필요하다. 헤어라인은 인접 세그먼트
     분리 목적만 남기므로 어두운 값으로 뒤집는다(같은 규칙, 테마별 토큰). */
  --data-mark-edge:#101014;
  --shadow-control:0 1px 2px rgba(0,0,0,.45);
  --shadow-low:0 6px 18px -8px rgba(0,0,0,.5);
  --shadow-high:0 12px 34px -14px rgba(0,0,0,.6);
}
/* 블랙 테마에서는 흰 사이드바 변형이 의미를 잃음 → navy 기본 거동으로 중화
   (data-sb 저장값은 건드리지 않음 — 화이트 테마 복귀 시 그대로 살아난다)
   값 출처: navy 기본 규칙 실측 — #sidebar(border 없음)·.tool-item=--sidebar-muted·
   :hover:not(.active) rgba(255,255,255,.09)/.92(app.css line 312)·.active=--sidebar-text 무배경·
   .active::before=--sidebar-text·.tool-icon opacity .45(line 266). */
:root[data-theme="black"][data-sb="white"] #sidebar{background:var(--sidebar-bg);border-right:none}
:root[data-theme="black"][data-sb="white"] .tool-group-label{color:var(--sidebar-muted)}
:root[data-theme="black"][data-sb="white"] .tool-item{color:var(--sidebar-muted)}
:root[data-theme="black"][data-sb="white"] .tool-item:hover:not(.active){background:rgba(255,255,255,.09);color:rgba(255,255,255,.92)}
:root[data-theme="black"][data-sb="white"] .tool-item.active{background:transparent;color:var(--sidebar-text)}
:root[data-theme="black"][data-sb="white"] .tool-item.active::before{background:var(--sidebar-text)}
:root[data-theme="black"][data-sb="white"] .tool-icon{opacity:.45}
:root[data-theme="black"][data-sb="white"] .tool-item.active .tool-icon{opacity:1}
/* 워드마크(brand-wordmark.png)는 순흑 모노크롬 → 블랙 표면(#09090b·사이드바)에서 보이지 않음.
   전용 다크 에셋(brand-wordmark-dark.png, 잉크 #ececf0·알파 보존)으로 <img> 소스 교체.
   content:url()은 Chromium/Safari/FF113+/카카오 인앱 지원 — filter invert와 병용 금지(교체본에 재반전=도로 어두워짐). */
:root[data-theme="black"] .brand-logo{content:url("/brand-wordmark-dark.png")}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Main
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
#main {
  grid-area: main;
  overflow-y: auto;
  overflow-x: hidden;
  background: var(--bg);
  min-width: 0;   /* #app-header와 그리드 트랙(column)을 공유 — 헤더만 고쳐도 같은 트랙이라 함께 필요 */
}

#main::-webkit-scrollbar { width: 6px; }
#main::-webkit-scrollbar-track { background: transparent; }
#main::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

/* ── 전역 공지 모달 (배너/토스트 대체) ──
   기존 인앱 모달 관례(.tsm-modal 계열: --surface 카드·--overlay 백드롭·--shadow-lg)를
   따르되 mv-annc-* 로 독립. z-index=950 → 로그인 오버레이(.auth-screen=1000) 아래에 두어
   미인증 화면을 가리지 않음(구 배너가 로그인 뒤로 숨던 동작과 동일). */
.mv-annc-bg {
  position: fixed; inset: 0; z-index: var(--z-annc);
  background: var(--overlay);
  display: none;
  align-items: flex-start; justify-content: center;
  padding: 48px 16px;
  overflow-y: auto;
}
.mv-annc-bg.open { display: flex; }
.mv-annc-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-overlay);
  box-shadow: var(--shadow-lg);
  width: 100%; max-width: 480px;
  max-height: calc(100vh - 96px);
  margin: auto;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.mv-annc-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 20px; border-bottom: 1px solid var(--line);
}
.mv-annc-title { font-size: 15px; font-weight: 700; color: var(--ink); }
.mv-annc-x {
  border: 0; background: transparent; cursor: pointer; color: var(--ink-3);
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; margin: -10px -12px -10px 0;
}
.mv-annc-x:hover { color: var(--ink); }
.mv-annc-body {
  padding: 16px 20px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px;
}
/* 공지 카드 = --surface 평면 카드. 좌측 액센트 바는 걷어냈다(제네릭 콜아웃 문법).
   warn 구분은 바 색이 아니라 카드 자체의 경고 배경·테두리로 준다. */
.mv-annc-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
}
.mv-annc-item.warn { border-color: var(--warn); background: var(--warn-bg); }
.mv-annc-item-t { display: block; color: var(--ink); font-size: 14px; font-weight: 700; line-height: 1.4; word-break: break-word; }
.mv-annc-item-b { color: var(--ink-2); font-size: 13px; line-height: 1.5; margin-top: 4px; white-space: pre-wrap; word-break: break-word; }
.mv-annc-item-d { color: var(--ink-3); font-size: 12px; margin-top: 8px; font-variant-numeric: tabular-nums; }
.mv-annc-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 12px 20px; border-top: 1px solid var(--line);
}
/* 헤더 종 버튼 + 안 본 공지 dot */
.mv-annc-bell { position: relative; }
.mv-annc-dot {
  position: absolute; top: 6px; right: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--warn);
  border: 1.5px solid var(--surface);
}
@media (max-width: 900px) {
  .mv-annc-bg { padding: 16px; align-items: center; }
  .mv-annc-card { max-height: calc(100vh - 32px); }
}

.tool-panel {
  display: none;
  padding: 36px 44px;
  max-width: 820px;
  margin-inline: auto;   /* 넓은 화면에서 좌측 고정 대신 중앙 정렬(우측 공백 해소) */
}

.tool-panel.active {
  display: block;
}

/* 문제 은행은 풀폭/풀하이트 작업대 (820px 캡·패딩 제거) */
#panel-bank {
  padding: 0;
  max-width: none;
  height: calc(100vh - var(--header-h));
  overflow: hidden;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Sections
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.section {
  margin-bottom: 28px;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.section-label {
  font-size: 15px;
  font-weight: 700;
  color: var(--label);
}

.section-hint {
  font-size: var(--type-meta);
  color: var(--ink-2);
}

.label-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Buttons
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.btn{
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  min-height:var(--control-standard);padding:0 16px;
  background:var(--surface);color:var(--ink);
  border:1px solid var(--control-border);border-radius:var(--radius-control);
  box-shadow:var(--shadow-control);font-size:var(--type-button);font-weight:650;
  white-space:nowrap;text-decoration:none;   /* .btn이 <a>에 쓰일 때(설정 등) 밑줄 제거 — 앵커·버튼 시각 통일 */
  transition:background .15s,color .15s,border-color .15s,transform .13s,box-shadow .13s;
}
.btn:disabled{opacity:.55;cursor:not-allowed;box-shadow:none}
.btn-primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);box-shadow:var(--shadow-low)}
.btn-primary:hover:not(:disabled){background:var(--accent-hover);border-color:var(--accent-hover)}
.btn-outline{background:var(--surface);color:var(--accent);border-color:var(--control-border);box-shadow:var(--shadow-control)}
.btn-outline:hover:not(:disabled){border-color:var(--accent);background:var(--accent-tint)}
.btn-ghost{background:transparent;color:var(--ink-2);border-color:transparent;box-shadow:none}
.btn-ghost:hover:not(:disabled){background:var(--surface-2);color:var(--ink)}
.btn-danger{background:var(--surface);color:var(--danger);border-color:var(--danger);box-shadow:var(--shadow-control)}
.btn-danger:hover:not(:disabled){background:var(--surface);border-color:var(--danger)}
.btn-danger-confirm{background:var(--danger);color:var(--danger-ink);border-color:var(--danger);box-shadow:var(--shadow-low)}
.btn-danger-confirm:hover:not(:disabled),
.btn-danger-confirm:active:not(:disabled){background:var(--danger);color:var(--danger-ink);border-color:var(--danger)}
.btn-danger-confirm:disabled{background:var(--surface-2);color:var(--text-muted);border-color:var(--control-border);box-shadow:none}
.btn-dense,.btn-sm{min-height:var(--control-dense);padding:0 12px}
.btn-touch{min-height:var(--control-touch);padding:0 16px}
.btn-prominent,.btn-block{min-height:var(--control-prominent);padding:0 18px;font-size:var(--type-button);font-weight:700}
.btn-block{width:100%}
.btn-compact{min-height:var(--control-dense);padding:0 10px}
.btn-compact::after{content:"";position:absolute;inset:-6px 0}
@media(hover:hover){
  .btn:not(:disabled):not(.btn-ghost):hover{transform:translateY(-1px);box-shadow:var(--shadow-low)}
}
@media(max-width:768px){
  .btn:not(.btn-compact),.btn-sm,.btn-dense{min-height:var(--control-touch);font-size:14px}
}
.btn:not(:disabled):active{transform:translateY(0);box-shadow:var(--shadow-control)}
.btn.btn-danger-confirm:active:not(:disabled){transform:translateY(0);box-shadow:var(--shadow-control)}
@media(prefers-reduced-motion:reduce){
  .btn:not(:disabled):hover,.btn:not(:disabled):active{transform:none}
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Form fields
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.field {
  width: 100%;
  min-height: var(--control-standard);
  padding: 11px 14px;
  border: 1px solid var(--control-border);
  border-radius: var(--radius-control);
  font-size: var(--type-body);
  color: var(--text);
  background: var(--surface);
  box-shadow: var(--shadow-control);
  outline: none;
  transition: border-color 0.15s;
}

.field:focus {
  border-color: var(--accent);
}

.field::placeholder {
  color: var(--text-muted);
}

textarea.field {
  resize: vertical;
  min-height: 88px;
  line-height: 1.65;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Upload zone
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.upload-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
}

.upload-card-hint {
  text-align: right;
  font-size: 12px;
  color: var(--ink-2);
  margin-bottom: 10px;
}

.upload-zone {
  border: 1.5px dashed var(--border-dash);
  border-radius: var(--radius-sm);
  padding: 40px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
  user-select: none;
  color: var(--ink-3);
}

.upload-zone:hover,
.upload-zone.drag-over {
  border-color: var(--accent);
  background: rgba(30, 38, 56, 0.025);
}

.upload-zone.has-file {
  padding: 16px;
  gap: 12px;
}

/* 무스타일 시 아이콘·본문·보조문이 한 줄로 뭉침 → 세로 스택 중앙정렬 (문항 변형·자작·해설 공통) */
.upload-zone-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
}

.upload-zone-text {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
}

.upload-zone-sub {
  font-size: 12px;
  color: var(--ink-2);
  margin-top: -4px;
}

.upload-preview {
  display: none;
  width: 100%;
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.upload-preview.visible {
  display: block;
}

.upload-preview img {
  max-width: 100%;
  max-height: 280px;
  object-fit: contain;
  display: block;
  margin: 0 auto;
}

.upload-replace-hint {
  font-size: var(--type-meta);
  color: var(--text-muted);
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Difficulty dots
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.diff-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 18px;
  background: var(--surface);
}

.diff-label {
  width: 100%;
  font-size: 12px;
  color: var(--accent);
  font-weight: 600;
  text-align: center;
  letter-spacing: -0.01em;
}
.diff-label:empty { display: none; }

.diff-end-label {
  font-size: 12.5px;
  color: var(--ink-2);
  white-space: nowrap;
}

.diff-dots {
  display: flex;
  gap: 10px;
  flex: 1;
  justify-content: center;
}

.dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--border-dash);
  background: transparent;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.12s, border-color 0.12s, transform 0.1s;
}

.dot:hover {
  transform: scale(1.18);
  border-color: var(--accent);
}

.dot.filled {
  background: var(--accent);
  border-color: var(--accent);
}

/* 난이도 점=버튼(키보드·SR 접근). 9점 nowrap 행이라 44px/점은 불가 → 히트영역만 확장 */
.diff-dots .dot { padding: 0; margin: 0; -webkit-appearance: none; appearance: none; font: inherit; position: relative; }
.diff-dots .dot::after { content: ""; position: absolute; inset: -11px; }  /* 터치타깃 확대(≈44px, 시각 무변경) */
.diff-dots .dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Subject dropdown
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.subject-dropdown {
  display: none;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 10px;
  box-shadow: var(--shadow-high);
}

.subject-dropdown.open {
  display: block;
}

/* 개정 탭 */
.subj-tabs {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-card);
}

.subj-tab {
  flex: 1;
  min-height: var(--control-standard);
  padding: 10px 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}

.subj-tab:hover {
  color: var(--text);
}

.subj-tab.active {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--control-border);
  box-shadow: var(--shadow-control);
  font-weight: 700;
}

.subj-body {
  padding: 14px;
}

.subject-group-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 7px;
}

.subject-group {
  margin-bottom: 14px;
}

.subject-group:last-child {
  margin-bottom: 0;
}

.subject-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* 드롭다운 푸터 */
.subj-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface-3);
}

.subj-count {
  font-size: 12px;
  color: var(--text-muted);
  font-weight: 500;
}

/* 선택된 태그 영역 */
.selected-tags {
  min-height: 44px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  padding: 7px 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  background: var(--surface);
  cursor: default;
}

.tags-placeholder {
  color: var(--text-muted);
  font-size: 14px;
}

.selected-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px 4px 10px;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: 5px;
  font-size: 12.5px;
  font-weight: 500;
}

.tag-cur {
  font-size: var(--type-label);
  opacity: 0.7;
  font-weight: 700;
  letter-spacing: 0.03em;
}

.tag-remove {
  background: none;
  border: none;
  color: var(--accent-ink);
  opacity: 0.65;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.12s;
}

.tag-remove:hover { opacity: 1; }

@media (max-width: 768px) {
  .tag-remove { min-height: 36px; min-width: 36px; }
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Keyword dropdown
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.keyword-dropdown {
  display: none;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 10px;
  box-shadow: var(--shadow-high);
}

.keyword-dropdown.open { display: block; }

.keyword-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  padding: 14px;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Mode toggle
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Result area
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.result-area {
  display: none;
  margin-top: 24px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}

.result-area.visible {
  display: block;
}

.result-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-3);
}

.result-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--label);
}

.result-actions {
  display: flex;
  gap: 8px;
}

.result-body {
  padding: 22px;
  font-size: 14px;
  line-height: 1.85;
  min-height: 100px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Loading dots
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.loading-dots {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.loading-dots span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.6;
  animation: ldot 1.1s infinite ease-in-out;
}

.loading-dots span:nth-child(2) { animation-delay: 0.18s; }
.loading-dots span:nth-child(3) { animation-delay: 0.36s; }

@keyframes ldot {
  0%, 80%, 100% { transform: scale(0.75); opacity: 0.4; }
  40%            { transform: scale(1);    opacity: 1; }
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Header right
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
#header-right {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;   /* 중첩 flex 아이템도 동일한 min-width:auto 오버플로를 가짐(연쇄) */
  flex: 1 1 auto;
  justify-content: flex-end;   /* 우측 정렬 + 공간 부족 시 내부(사용자명)가 줄어 겹침 방지 */
  overflow: hidden;
}
#header-right .btn, #header-right .user-avatar, #header-right .user-logout { flex: none; }  /* 아이콘·버튼은 고정, 사용자명만 축소 */
#user-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.engine-badge {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 3px 9px;
}
.engine-badge--empty { opacity: .6; font-weight: 500; }

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Settings panel
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.settings-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.25);
  z-index: 40;
}
.settings-overlay.open { display: block; }

.settings-panel {
  position: fixed;
  top: 0;
  right: -360px;
  width: 340px;
  height: 100vh;
  background: var(--surface);
  border-left: 1.5px solid var(--border);
  z-index: 50;
  display: flex;
  flex-direction: column;
  transition: right 0.25s ease;
  box-shadow: -4px 0 20px rgba(0,0,0,0.08);
}
.settings-panel.open { right: 0; }

.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}

.settings-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--label);
}

.settings-close {
  background: none;
  border: none;
  font-size: 22px;
  color: var(--text-muted);
  cursor: pointer;
  line-height: 1;
  padding: 0 4px;
}
.settings-close:hover { color: var(--text); }

.settings-body {
  padding: 20px;
  overflow-y: auto;
  flex: 1;
}

.settings-group-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 10px;
}

.settings-key-group {
  margin-bottom: 12px;
}

.settings-key-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--label);
  margin-bottom: 6px;
}

.settings-note {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
  margin-top: 20px;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Streaming cursor
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.stream-cursor::after {
  content: '▍';
  animation: blink 0.8s step-end infinite;
  color: var(--accent);
  margin-left: 1px;
}
@keyframes blink { 0%,100% { opacity: 1; } 50% { opacity: 0; } }

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Result body (markdown)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.result-body h1,.result-body h2,.result-body h3 {
  margin: 1em 0 0.4em;
  font-weight: 700;
}
.result-body h1 { font-size: 1.2em; }
.result-body h2 { font-size: 1.1em; }
.result-body h3 { font-size: 1em; }
.result-body p  { margin: 0.5em 0; }
.result-body ul,.result-body ol { padding-left: 1.4em; margin: 0.5em 0; }
.result-body li { margin: 0.25em 0; }
.result-body strong { font-weight: 700; }
.result-body em { font-style: italic; }
.result-body code {
  background: var(--bg);
  border-radius: 3px;
  padding: 1px 5px;
  font-size: 0.9em;
  font-family: monospace;
}
.result-body pre {
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  overflow-x: auto;
  margin: 0.6em 0;
}
.result-body pre code { background: none; padding: 0; }
.result-body blockquote {
  border-left: 3px solid var(--border);
  padding-left: 12px;
  color: var(--text-muted);
  margin: 0.5em 0;
}
.result-body hr { border: none; border-top: 1px solid var(--border); margin: 1em 0; }

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   History panel
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.history-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.history-card {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.history-card:hover {
  border-color: var(--accent);
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.history-card.selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

.history-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.history-card-type {
  font-size: var(--type-label);
  font-weight: 700;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: 4px;
  padding: 2px 7px;
}

.history-card-date {
  font-size: var(--type-meta);
  color: var(--text-muted);
}

.history-card-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--label);
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.history-card-preview {
  font-size: 12.5px;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.history-card-actions {
  display: flex;
  gap: 6px;
  margin-top: 10px;
}

.history-empty {
  text-align: center;
  padding: 60px 0;
  color: var(--text-muted);
  font-size: 14px;
}

.history-detail {
  display: none;
}
.history-detail.open {
  display: block;
}
.history-back {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  margin-bottom: 20px;
  background: none;
  border: none;
  padding: 0;
}
.history-back:hover { color: var(--text); }

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   시험지 설정 모달
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.exam-config-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 1000;
  display: flex;
  align-items: stretch;
  justify-content: center;
  padding: 20px;
}

.exam-config-inner {
  background: var(--bg);
  border-radius: var(--radius);
  display: flex;
  width: 100%;
  max-width: 1100px;
  max-height: 100%;
  overflow: hidden;
  box-shadow: 0 8px 40px rgba(0,0,0,0.3);
}

.exam-config-sidebar {
  width: 210px;
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.exam-config-sidebar-hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.ecm-label {
  display: block;
  font-size: var(--type-meta);
  color: var(--text-muted);
  font-weight: 600;
  margin-bottom: 5px;
}

.ecm-field {
  margin-bottom: 14px;
}

.exam-config-preview-wrap {
  flex: 1;
  overflow-y: auto;
  padding: 20px 28px;
  background: #d8d8d8;
}

/* A4 비율 흰 종이 */
.exam-preview-a4 {
  background: #fff;
  border-radius: 2px;
  box-shadow: 0 2px 16px rgba(0,0,0,0.18);
  padding: 18mm 15mm;
  min-height: 260mm;
  position: relative;
  overflow: hidden;
  color: #000;
}

.exam-preview-header {
  text-align: center;
  border-bottom: 2px solid #333;
  margin-bottom: 10mm;
  padding-bottom: 7px;
}

.exam-preview-title {
  font-size: 20px;
  font-weight: 700;
  margin-bottom: 8px;
  color: #000;
}

.exam-preview-meta {
  display: flex;
  gap: 24px;
  justify-content: center;
  font-size: 12px;
  color: #333;
}

.exam-preview-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 14px;
}

.exam-preview-col {
  padding-right: 7px;
  border-right: 1px solid #ddd;
}

.exam-preview-col:last-child {
  border-right: none;
  padding-right: 0;
  padding-left: 7px;
}

.exam-problem-item {
  margin-bottom: 14px;
  font-size: 12.5px;
  line-height: 1.75;
  color: #000;
}

.exam-problem-no {
  font-weight: 700;
  font-size: 13px;
  margin-bottom: 3px;
  color: #000;
}

/* 워터마크 오버레이 */
.exam-watermark {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-repeat: repeat;
  z-index: 10;
}

/* 히스토리 서브탭 */
.hist-tabs {
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-card);
  margin-bottom: 20px;
}

.hist-tab {
  min-height: var(--control-standard);
  padding: 9px 18px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.hist-tab:hover { color: var(--text); }
.hist-tab.active { background: var(--surface); color: var(--ink); border-color: var(--control-border); box-shadow: var(--shadow-control); font-weight: 700; }

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Export dropdown
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.export-wrap {
  position: relative;
  display: inline-flex;
}

.export-trigger {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

/* chevron SVG is injected directly into .export-trigger button in app.js */

.export-menu {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 180px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 16px rgba(0,0,0,0.1);
  z-index: 30;
  overflow: hidden;
  padding: 4px; /* 항목 호버 배경이 메뉴 모서리에 각지게 닿지 않게 */
}

.export-menu.open { display: block; }

.export-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 10px 14px;
  background: none;
  border: none;
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  border-radius: 8px;
  transition: background 0.12s;
}

.export-item:hover { background: var(--bg); }

.export-item.danger { color: var(--danger); }

.export-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 4px 0;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   ===== 공유 컴포넌트 (재디자인) =====
   목업 docs/superpowers/specs/2026-06-30-ui-redesign-mockup.html 의
   <style> 컴포넌트 규칙을 이식. 치환/충돌 해소:
   · 경고색 var(--warn) → var(--warn-2) (기존 --warn 의미 보존)
   · .btn 베이스 미이식(기존 유지) — 표준 .btn-primary/.btn-sm 사용(구 .btn.pri/.btn.sm 별칭 제거됨)
   · .field 베이스 미이식(기존 재사용) — .field-l 만 추가
   · .dot 은 기존 22px 난이도 점과 충돌 → .tbl/.legend 스코프로 한정
   · .cls-card/.cls-title/.cls-code 는 기존 LMS UI와 충돌 → [data-rd] 스코프
   · 모바일 @media / [data-view] 적응은 Task 3 으로 이연(베이스만 이식)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
/* nset/history/[data-rd] 패널: 2차 버튼(비 .btn-primary)은 흰 아웃라인 톤 */
#panel-nset .btn:not(.btn-primary):not(.dark),
#panel-history .btn:not(.btn-primary):not(.dark),
[data-rd] .btn:not(.btn-primary):not(.dark){background:var(--surface);border:1px solid var(--line);color:var(--ink)}
#panel-nset .btn:not(.btn-primary):not(.dark):hover,
#panel-history .btn:not(.btn-primary):not(.dark):hover,
[data-rd] .btn:not(.btn-primary):not(.dark):hover{background:var(--surface-2)}

.chip{border:1px solid var(--line);background:var(--surface);border-radius:99px;padding:7px 13px;font-size:12.5px;font-weight:600;color:var(--ink-2);cursor:pointer;display:inline-flex;gap:6px;align-items:center;white-space:nowrap}
.chip.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.tag{font-size:var(--type-label);font-weight:700;padding:3px 8px;border-radius:6px}
.tag.sub{background:var(--accent-soft);color:var(--accent)} .tag.lv{background:var(--warn-bg);color:var(--warn-2)}
.tag.ok{background:var(--good-bg);color:var(--good)} .tag.mut{background:var(--surface-2);color:var(--ink-2)}
.semantic-status{
  display:inline-flex;align-items:center;gap:6px;min-height:20px;
  box-sizing:border-box;padding:2px 7px;border:1px solid var(--control-border);
  border-radius:var(--radius-pill);background:transparent;color:var(--text-muted);
  font-size:var(--type-label);font-weight:700;line-height:1.2;white-space:normal;max-width:100%;overflow-wrap:anywhere
}
.semantic-status::before{
  content:"";width:6px;height:6px;flex:0 0 6px;border-radius:50%;background:currentColor
}
.semantic-status[data-tone="neutral"]{color:var(--text-muted);border-color:var(--control-border)}
.semantic-status[data-tone="success"]{color:var(--ok);border-color:var(--ok)}
.semantic-status[data-tone="warning"]{color:var(--warn);border-color:var(--warn)}
.semantic-status[data-tone="danger"]{color:var(--danger);border-color:var(--danger)}
.cls-paused-tag{margin-left:8px;vertical-align:2px}
.toolbar{display:flex;gap:10px;align-items:center;margin-bottom:18px;flex-wrap:wrap}
.search{flex:1;min-width:200px;display:flex;align-items:center;gap:9px;border:1px solid var(--line);background:var(--surface);border-radius:var(--r-sm);padding:9px 13px;color:var(--ink-4)}
.search input{border:0;outline:0;background:transparent;font:inherit;width:100%;color:var(--ink)}
.kbd{font-size:var(--type-label);border:1px solid var(--line);border-bottom-width:2px;border-radius:5px;padding:1px 6px;color:var(--ink-3);font-weight:600;background:var(--surface-2)}

.stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:22px}
/* .stat 정의는 여기 하나로 병합(과거 1422·1508 이중 정의 — 뒤 정의가 이기던 속성을 그대로 유지: 시각 결과 불변) */
.stat{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-card);padding:16px;box-shadow:none;transition:border-color .14s,transform .14s,box-shadow .14s}
.stat .k{font-size:var(--type-label);font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--k,var(--ink-2));margin-bottom:5px}
.stat .v{font-size:24px;font-weight:800;letter-spacing:-.03em;font-family:var(--font-num);font-variant-numeric:tabular-nums}
.stat .d{font-size:var(--type-meta);font-weight:700;margin-top:3px;color:var(--good);display:flex;align-items:center;gap:4px} .stat .d.dn{color:var(--bad)} .stat .d.neu{color:var(--ink-3)}
/* 클릭 가능한 KPI 타일(홈 등): 관련 화면 바로가기 */
.stat-go{cursor:pointer;box-shadow:var(--shadow-low)}
.stat-go:hover{transform:translateY(-1px);border-color:var(--control-border);box-shadow:var(--shadow-high)}
.stat-go:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}

.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}
.card{border:1px solid var(--line);background:var(--surface);border-radius:var(--card-radius);padding:16px 17px;box-shadow:var(--shadow);cursor:pointer;transition:.14s}
.card:hover{box-shadow:var(--shadow-lg);transform:translateY(-1px)}
.card .top{display:flex;align-items:center;gap:7px;margin-bottom:11px}
.card .no{margin-left:auto;font-size:12px;color:var(--ink-4);font-weight:700}
.card .q{font-size:13.5px;line-height:1.62;color:var(--ink-2);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;min-height:64px}
.card .foot{display:flex;align-items:center;gap:8px;margin-top:13px;padding-top:12px;border-top:1px solid var(--line-2);font-size:12px;color:var(--ink-3);flex-wrap:wrap;row-gap:6px}
.card .foot>*{white-space:nowrap}
.card .foot .ans{margin-left:auto;font-weight:800;color:var(--ink)}

.split{display:grid;grid-template-columns:340px 1fr;gap:20px;align-items:start}
.split>*{min-width:0}/* 그리드 아이템이 min-content 이하로 줄어들도록(모바일 1fr 오버플로 방지) */
.panel{border:1px solid var(--line);background:var(--surface);border-radius:var(--card-radius);box-shadow:var(--shadow)}
.panel-h{padding:14px 17px;border-bottom:1px solid var(--line-2);font-weight:700;display:flex;align-items:center;gap:8px}
.panel-b{padding:17px}
.field-l{font-size:var(--type-meta);font-weight:700;color:var(--ink-2);margin:14px 0 6px;display:block} .field-l:first-child{margin-top:0}
.seg{display:flex;gap:6px;flex-wrap:wrap}
.slider{height:6px;border-radius:99px;background:var(--surface-2);position:relative;margin:14px 4px}
.slider::before{content:"";position:absolute;left:0;top:0;bottom:0;width:62%;background:var(--accent);border-radius:99px}
.slider::after{content:"";position:absolute;left:62%;top:50%;width:16px;height:16px;border-radius:99px;background:#fff;border:2px solid var(--accent);transform:translate(-50%,-50%)}

.cls-cover{height:74px;background:linear-gradient(120deg,var(--accent),var(--accent-hover));position:relative}
[data-rd] .cls-card{border:1px solid var(--line);background:var(--surface);border-radius:var(--card-radius);overflow:hidden;box-shadow:var(--shadow);cursor:pointer;transition:.14s}
[data-rd] .cls-card:hover{box-shadow:var(--shadow-lg);transform:translateY(-1px)}
[data-rd] .cls-card:nth-child(2) .cls-cover{background:linear-gradient(120deg,var(--accent-hover),var(--nav2))}
[data-rd] .cls-card:nth-child(3) .cls-cover{background:linear-gradient(120deg,var(--accent),var(--nav2))}
[data-rd] .cls-code{position:absolute;right:12px;top:12px;background:var(--on-nav-a18);backdrop-filter:blur(6px);color:var(--sidebar-text);font-size:var(--type-label);font-weight:700;padding:4px 9px;border-radius:7px;letter-spacing:.08em;display:flex;align-items:center;gap:5px}
[data-rd] .cls-cover-icon{position:absolute;right:12px;top:12px;color:var(--sidebar-text);opacity:.9}
/* 강사 카드 커버 아이콘: 코드칩(우상단)과 안 겹치게 좌하단 + 조금 크게 */
[data-rd] .cls-cover-icon--bl{right:auto;top:auto;left:14px;bottom:10px;opacity:.85}
[data-rd] .cls-cover-icon--bl .ic{width:22px;height:22px}
[data-rd] .cls-code-copy{display:inline-flex;align-items:center;opacity:.8}
[data-rd] .cls-code-copy .ic{width:12px;height:12px}
.cls-body{padding:14px 16px 16px}
[data-rd] .cls-title{font-weight:800;font-size:15.5px;margin-bottom:3px}
.cls-meta{font-size:12.5px;color:var(--ink-3);display:flex;gap:14px;margin-top:10px}
.cls-meta span{display:inline-flex;align-items:center;gap:5px}
.prog{height:7px;border-radius:99px;background:var(--surface-2);margin-top:13px;overflow:hidden}
.prog i{display:block;height:100%;background:var(--accent);border-radius:99px}

.tbl-wrap{overflow-x:auto}
.tbl{width:100%;border:1px solid var(--line);border-radius:var(--card-radius);overflow:hidden;background:var(--surface);box-shadow:var(--shadow);border-collapse:collapse;min-width:560px}
.tbl th,.tbl td{text-align:left;padding:12px 16px;font-size:13px;border-bottom:1px solid var(--line-2)}
.tbl th{background:var(--surface-2);font-size:var(--type-label);font-weight:700;color:var(--ink-3);text-transform:uppercase;letter-spacing:.04em}
.tbl tr:last-child td{border-bottom:0}
.tbl td.num{font-variant-numeric:tabular-nums;font-weight:700}
.tbl .dot,.legend .dot{display:inline-block;width:7px;height:7px;border-radius:99px;margin-right:6px;vertical-align:1px}

.chart{border:1px solid var(--line);background:var(--surface);border-radius:var(--card-radius);padding:18px;box-shadow:var(--shadow);margin-bottom:18px}
.bars{display:flex;align-items:flex-end;gap:10px;height:160px;margin-top:14px;padding-top:10px}
.bars .b{flex:1;background:var(--data);border-radius:6px 6px 0 0;position:relative;min-width:0}
.bars .b span{position:absolute;top:-18px;left:0;right:0;text-align:center;font-size:var(--type-label);font-weight:700;color:var(--ink-3)}
.bars .b small{position:absolute;bottom:-20px;left:0;right:0;text-align:center;font-size:var(--type-label);color:var(--ink-4)}
.adm-bd-bar>i{display:block;height:100%;border-radius:99px;background:var(--data)}
.prog span:first-child{display:block;height:100%;background:var(--data);border-radius:99px}
/* 비용 통계(history.js) 보조 클래스 — 인라인 스타일 대체 */
.chart{padding-bottom:24px}
.chart-title{font-size:13px;font-weight:600}
.chart-max-label{display:block;font-size:var(--type-label);color:var(--ink-4);margin-bottom:2px}
.bars-grid{position:relative}
.bars-grid::before{content:'';position:absolute;left:0;right:0;top:50%;border-top:1px dashed var(--line);pointer-events:none;z-index:1}
.tc-3{color:var(--ink-3)}
.tc-date{color:var(--ink-4);font-size:12px}
.prov-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chart-no-margin{margin:0}
.inp-date{border:1px solid var(--border);border-radius:6px;padding:2px 6px;font-size:13px;color:var(--ink);background:var(--surface);cursor:pointer}
.banner.warn{padding:8px 12px;background:var(--warn-bg);color:var(--warn-2);border-radius:8px;font-size:13px;margin-bottom:12px}
.two{display:grid;grid-template-columns:1.6fr 1fr;gap:18px;align-items:start}
.page-h{display:flex;align-items:flex-end;gap:14px;margin-bottom:5px;flex-wrap:wrap}
.page-h .spacer{flex:1}
.page-sub{color:var(--ink-2);font-size:var(--type-meta);margin-bottom:22px}
/* 공용 로딩 라인: 맨 텍스트 대신 스피너+문구(홈·클래스 등) */
.load-line{display:flex;align-items:center;justify-content:center;gap:9px;color:var(--ink-3);font-size:13px;padding:26px 12px}
.load-line::before{content:"";width:16px;height:16px;flex:none;border:2px solid var(--surface-2);border-top-color:var(--accent);border-radius:50%;animation:mv-spin .7s linear infinite}
@keyframes mv-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.load-line::before{animation:none}}
/* 네이티브 체크박스·라디오 기본 액센트(미스타일 방지·브랜드 통일) */
input[type="checkbox"],input[type="radio"]{accent-color:var(--accent)}
.legend{display:flex;flex-direction:column;gap:11px}
.legend .row{display:flex;align-items:center;gap:9px;font-size:13px}
.legend .row .bar{flex:1;height:8px;border-radius:99px;background:var(--surface-2);overflow:hidden}
.legend .row .bar i{display:block;height:100%;border-radius:99px}
.legend .row b{margin-left:auto;font-variant-numeric:tabular-nums}

/* ━━━ 디자인 패스 ①: 시각 컴포넌트 ━━━ */
/* .stat(KPI 스트립)은 1421행대에 단일 정의로 병합됨(2026-07-08) */
/* 시각 카드(비-포인터) */
.vcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-card);box-shadow:none;padding:16px}
.vcard-go{cursor:pointer;box-shadow:var(--shadow-low);transition:transform .14s,border-color .14s,box-shadow .14s}
.vcard-go:hover{transform:translateY(-1px);border-color:var(--control-border);box-shadow:var(--shadow-high)}
.vcard .cap{display:block;font-size:12px;color:var(--ink-3);font-weight:700;margin-bottom:9px}
/* 도넛 */
.donut{width:var(--dsz,128px);height:var(--dsz,128px);border-radius:50%;margin:6px auto 4px}
.donut-legend{font-size:var(--type-label)}
.donut-legend div{display:flex;align-items:center;gap:6px;padding:2px 0;color:var(--ink)}
.donut-legend i{width:9px;height:9px;border-radius:2px;flex:0 0 auto}
/* 링 */
.ring{width:var(--rsz,120px);height:var(--rsz,120px);margin:6px auto 4px;position:relative}
.ring .lbl{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.ring .lbl b{font-size:24px;font-weight:800;letter-spacing:-.03em;font-variant-numeric:tabular-nums;color:var(--ink)}
.ring .lbl span{font-size:var(--type-label);color:var(--ink-3);text-transform:uppercase;letter-spacing:.05em;font-weight:700}
.ring circle.track{stroke:var(--surface-2)}
.ring circle.val{transition:stroke-dashoffset .9s ease}
/* 막대행 */
.barrow{display:flex;align-items:center;gap:9px;font-size:12px;margin:8px 0;color:var(--ink)}
.barrow .lb{width:auto;min-width:72px;flex:0 1 auto;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.barrow .track{flex:1;height:9px;background:var(--surface-2);border-radius:6px;overflow:hidden}
@media (max-width:640px){.barrow .lb{width:72px;min-width:0;flex:0 1 72px}}
.barrow .fill{display:block;height:100%;border-radius:6px;transition:width .7s ease}
.barrow .n{min-width:44px;flex:none;white-space:nowrap;text-align:right;font-weight:700;font-variant-numeric:tabular-nums}
/* 데이터 채움 헤어라인 — 채움색을 바꾸지 않고 경계만 세운다(--data-mark-edge). 도넛은 인접
   세그먼트끼리, 막대·범례 칩은 표면과의 경계가 대상이다. 값은 테마 토큰이 소유한다. */
.donut{box-shadow:inset 0 0 0 1px var(--data-mark-edge)}
.donut-legend i{box-shadow:inset 0 0 0 1px var(--data-mark-edge)}
.barrow .fill{box-shadow:inset 0 0 0 1px var(--data-mark-edge)}
/* 추이 */
.trend{display:flex;align-items:flex-end;gap:6px;height:130px;margin-top:6px;padding-top:8px}
.trend .col{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px}
.trend .bar{width:100%;background:var(--data);border-radius:5px 5px 0 0;transition:height .7s ease}
.trend .bar.hi{background:var(--data-strong)}
.trend small{font-size:var(--type-label);color:var(--ink-3)}
/* 토글 */
.switch{width:42px;height:24px;border-radius:var(--radius-pill);background:var(--accent);position:relative;display:inline-block;vertical-align:middle;cursor:pointer;flex:0 0 auto;transition:background .15s}
.switch.off{background:#cdd4e0}
.switch b{position:absolute;top:3px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.2);left:21px;transition:left .15s}
.switch.off b{left:3px}
.switch:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* 블랙: on(--accent 밝음)/off 구분 복원 — off 트랙 어둡게, on 노브(#fff→트랙 동화)를 어둡게 */
:root[data-theme="black"] .switch.off{background:#33333a}
:root[data-theme="black"] .switch:not(.off) b{background:var(--accent-ink)}
/* 세그먼트 컨트롤 */
.segmented{display:inline-flex;gap:2px;padding:3px;overflow-x:auto;-webkit-overflow-scrolling:touch;
  background:var(--surface-2);border:1px solid var(--control-border);
  border-radius:var(--radius-control);box-shadow:var(--shadow-control)}
.segmented button{min-height:var(--control-dense);padding:0 14px;border:1px solid transparent;
  border-radius:6px;background:transparent;color:var(--ink-2);font:inherit;font-size:var(--type-button);font-weight:600;
  cursor:pointer;user-select:none;white-space:nowrap}
.segmented button.on{background:var(--surface);color:var(--ink);border-color:var(--control-border);box-shadow:var(--shadow-control)}
.segmented button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
@media(max-width:768px){.segmented button{min-height:44px;display:inline-flex;align-items:center}}
/* 배지 상태색 보강 */
.tag.info{background:var(--accent-soft);color:var(--accent)}
.tag.bad{background:var(--bad-bg);color:var(--bad)}
/* 전역 포커스 링 */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* 화면 전환 문맥 포커스: 스크린리더 handoff는 유지하되 비인터랙티브 큰 사각 링은 숨김 */
.tool-panel:focus-visible,
[data-screen-title]:focus-visible{outline:none}
/* 모션 감소 존중 */
@media (prefers-reduced-motion: reduce){
  .stat,.card,.barrow .fill,.trend .bar,.ring circle.val,.switch,.switch b{transition:none!important}
  .draw-in{animation:none!important}
  .spin,.loading-dots span,.stream-cursor::after{animation:none!important}
  :where(#app-header,#tool-nav,.mob-tab,#panel-home,#panel-classes,#panel-asgn,#panel-admdb,.adm-wrap,.mv-map--semantic-six),
  :where(#app-header,#tool-nav,.mob-tab,#panel-home,#panel-classes,#panel-asgn,#panel-admdb,.adm-wrap,.mv-map--semantic-six) *,
  :where(#app-header,#tool-nav,.mob-tab,#panel-home,#panel-classes,#panel-asgn,#panel-admdb,.adm-wrap,.mv-map--semantic-six) *::before,
  :where(#app-header,#tool-nav,.mob-tab,#panel-home,#panel-classes,#panel-asgn,#panel-admdb,.adm-wrap,.mv-map--semantic-six) *::after{
    animation-duration:0s!important;animation-iteration-count:1!important;transition-duration:0s!important;scroll-behavior:auto!important
  }
}
/* 표 → 모바일 카드 변환 (opt-in: .tbl.tbl-cards, td[data-label] 필요) */
@media (max-width:640px){
  .tbl.tbl-cards{min-width:0;border:0;box-shadow:none;background:transparent}
  .tbl.tbl-cards thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  .tbl.tbl-cards tr{display:block;background:var(--surface);border-radius:var(--radius-card);box-shadow:var(--shadow-card);padding:6px 12px;margin-bottom:10px}
  .tbl.tbl-cards td{display:flex;justify-content:space-between;gap:14px;border:0;padding:8px 0;font-size:13px}
  .tbl.tbl-cards td::before{content:attr(data-label);color:var(--ink-3);font-weight:600;flex:0 0 auto}
  .tbl.tbl-cards td:last-child{border:0}
  /* P1-E: 셀이 라벨:값 1쌍을 전제하는데 계정 셀처럼 자식 3~4개가 붙는 경우, td가 flex row라 각 자식이
     개별 flex item으로 흩어져 부유한다 → 다중 자식을 .tbl-cell-stack 래퍼 하나로 묶어 값 쪽(우측)에 세로로 쌓는다 */
  .tbl.tbl-cards td>.tbl-cell-stack{display:flex;flex-direction:column;align-items:flex-end;gap:2px;min-width:0}
  .tbl.tbl-cards td>.tbl-cell-stack>*{max-width:100%}
}

/* 계정/보안 연결 provider UID — CSS 말줄임 */
.provid{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
/* 인쇄용 스타일 */
@media print {
  body > *:not(#print-root) { display: none !important; }
  #print-root {
    display: block !important;
    font-family: "Malgun Gothic", "Nanum Gothic", serif;
    font-size: 13pt;
    line-height: 1.9;
    padding: 20mm;
    color: #000;
  }
  #print-root h1,#print-root h2,#print-root h3 { margin: 1em 0 0.5em; }
  #print-root hr { border: none; border-top: 1px solid #ccc; margin: 1.5em 0; }
  #print-root table { border-collapse: collapse; width: 100%; }
  #print-root th,#print-root td { border: 1px solid #ccc; padding: 6px 10px; }
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   LaTeX 툴바
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.latex-toolbar {
  background: var(--surface-3);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  margin-bottom: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
}

.ltb-group {
  display: flex;
  align-items: center;
  gap: 3px;
}

.ltb-label {
  font-size: var(--type-label);
  color: var(--text-muted);
  font-weight: 600;
  margin-right: 2px;
  white-space: nowrap;
}

.ltb-btn {
  min-width: 28px;
  min-height: 36px;
  height: auto;
  padding: 0 5px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  transition: background 0.1s, border-color 0.1s;
  font-family: "Pretendard Variable", Pretendard, "Segoe UI", system-ui, sans-serif;
}

.ltb-btn:hover {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   그래프 모달
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.graph-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.3);
  z-index: 60;
}
.graph-overlay.open { display: block; }

.graph-modal {
  display: none;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(720px, 96vw);
  background: var(--surface);
  border-radius: var(--radius-overlay);
  box-shadow: var(--shadow-high);
  z-index: 70;
  flex-direction: column;
  overflow: hidden;
  max-height: 90vh;
}
.graph-modal.open { display: flex; }

.graph-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-3);
}

.graph-modal-title {
  font-size: 15px;
  font-weight: 700;
}

.graph-modal-body {
  padding: 18px;
  overflow-y: auto;
}

#graph-canvas {
  width: 100%;
  height: 320px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 14px;
  background: var(--bg);
  overflow: hidden;
}

.graph-controls {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.graph-controls .field {
  flex: 1;
}

.graph-expr-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
  min-height: 20px;
}

.graph-expr-tag{display:inline-flex;align-items:center;gap:7px;padding:4px 8px;
  border:1px solid var(--control-border);border-radius:var(--radius-control);
  background:var(--surface);box-shadow:var(--shadow-control);
  color:var(--ink);font-size:var(--type-meta);font-weight:600}
.graph-expr-tag::before{content:"";width:20px;border-top:3px solid var(--graph-color);border-radius:var(--radius-pill)}
.graph-expr-tag[data-line="dash"]::before{border-top-style:dashed}
.graph-expr-tag[data-line="dot"]::before{border-top-style:dotted}

.graph-expr-remove {
  background: none;
  border: none;
  color: inherit;
  opacity: 0.7;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
}
.graph-expr-remove:hover { opacity: 1; }

.graph-axis-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-muted);
}

.graph-axis-input {
  width: 64px;
  padding: 5px 8px;
  font-size: 13px;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   N제 생성기 탭
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.nset-panel {
  padding: 0 !important;
  max-width: none !important;
  height: calc(100vh - var(--header-h));
}

.nset-iframe {
  width: 100%;
  height: 100%;
  border: none;
  display: block;
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   보기 박스 (수능형 보기 태그 렌더링)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
.bogi-box {
  border: 1.5px solid var(--border, #d0d0d0);
  border-radius: 4px;
  padding: 10px 16px;
  margin: 8px 0 12px;
  background: var(--surface, #fff);
  font-size: 0.97em;
  line-height: 1.9;
}

/* ── 조건박스 (임포트된 HWP 조건박스 = blockquote 표기) ──
   hwpx_parser._format_box 가 조건박스(중첩 표·글상자)를 `> ` blockquote 로
   내리므로, 문제 렌더 컨텍스트에서는 인용 부호가 아니라 수능형 테두리 박스로
   그린다(박종원 2차 피드백: 조건 박스 미인식). AI 답변 인용에 쓰이는
   .result-body blockquote 스타일은 건드리지 않는다. */
.bk-imp-preview blockquote,
.bk-paper-stem blockquote,
.bk-card-content blockquote,
.bk-choices blockquote,
.bk-choicebody blockquote,
.bk-modal-content blockquote,
.bk-variant-solution blockquote,
.exam-q-stem blockquote,
.exam-choice blockquote,
.asgn-prob-content blockquote {
  border: 1.5px solid var(--border);
  border-radius: 4px;
  padding: 10px 16px;
  margin: 8px 0 12px;
  background: var(--surface);
  font-size: 0.97em;
  line-height: 1.9;
}
.bk-imp-preview blockquote p,
.bk-paper-stem blockquote p,
.bk-card-content blockquote p,
.bk-choices blockquote p,
.bk-choicebody blockquote p,
.bk-modal-content blockquote p,
.bk-variant-solution blockquote p,
.exam-q-stem blockquote p,
.exam-choice blockquote p,
.asgn-prob-content blockquote p { margin: 0.15em 0; }

/* ── 검증 배지 ── */
.verify-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 500;
  background: var(--bg);
  color: var(--text-muted);
}
.verify-badge.verify-pass    { background: var(--legacy-good-bg); color: var(--legacy-good); }
.verify-badge.verify-fail    { background: var(--legacy-bad-bg); color: var(--legacy-bad); }
.verify-badge.verify-unknown { background: var(--legacy-warn-bg); color: var(--legacy-warn-2); }

/* ── 사용량 카드 (설정 > API 키) ── */
.usage-cards { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
.usage-cards .usage-card { min-width: 140px; }

/* ── 문제 은행 레이아웃 ── */
.bank-layout {
  display: flex;
  height: 100%;
  gap: 0;
  overflow: hidden;
}
.bank-filters {
  width: 220px;
  min-width: 180px;
  padding: 16px 12px;
  border-right: 1px solid var(--border);
  overflow-y: auto;
  flex-shrink: 0;
  background: var(--bg);
}
.bank-main {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}
.filter-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.filter-group-label {
  font-size: var(--type-label);
  font-weight: 600;
  color: var(--text3);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin: 10px 0 5px;
}
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 4px;
}
#panel-bank .chip {
  padding: 3px 8px;
  font-size: 12px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: none;
  cursor: pointer;
  color: var(--text2);
  transition: background .15s, color .15s, border-color .15s;
}
#panel-bank .chip.active {
  background: var(--pri);
  color: var(--accent-ink);
  border-color: var(--pri);
}

/* ══════════════════════════════════════════════════════
   문제 은행 (panel-bank) — bank.html 스타일 이식
   ══════════════════════════════════════════════════════ */
/* 문제 은행은 전체 폭/높이 사용 (820px 제한 해제 — 오른쪽 빈 공간 활용) */
#panel-bank{padding:0 !important;max-width:none !important;height:calc(100vh - var(--header-h))}
.bk-layout{display:flex;height:100%;overflow:hidden}

/* 필터 사이드바 */
.bk-filter-panel{width:220px;flex-shrink:0;padding:18px 16px;border-right:1px solid var(--border);background:var(--surface-2);overflow-y:auto;display:flex;flex-direction:column;gap:18px}
.bk-filter-section{display:flex;flex-direction:column;gap:9px}
.bk-filter-label{font-size:var(--type-label);font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px}
.bk-filter-input{width:100%;min-height:var(--control-standard);padding:7px 10px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);box-shadow:var(--shadow-control);font-size:var(--type-body);color:var(--text);outline:none;transition:border-color .15s}
.bk-filter-input:focus{border-color:var(--accent)}
.bk-filter-input:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
.bk-chip-group{display:flex;flex-wrap:wrap;gap:5px}
.bk-chip{padding:4px 10px;border-radius:var(--radius-pill);border:1px solid var(--border);background:var(--surface);font-size:12px;font-family:inherit;line-height:1.3;cursor:pointer;transition:.2s;color:var(--text2);font-weight:500;user-select:none;-webkit-appearance:none;appearance:none;text-align:center}
.bk-chip:hover{border-color:var(--pri);color:var(--pri)}
.bk-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.bk-chip.active{background:var(--pri);color:var(--on-nav);border-color:var(--pri)}
/* 기본값('전체')은 '선택 없음'이므로 고스트로 — 실제 선택만 진한 네이비로 도드라지게 */
.bk-chip.active[data-v=""]{background:transparent;color:var(--accent);border-color:var(--accent);font-weight:700}
.bk-fav-chip.active{background:var(--fav);border-color:var(--fav)}
.bk-filter-reset{width:100%;padding:7px;border:1px solid var(--border);border-radius:var(--rs);background:transparent;font-size:12px;color:var(--text3);cursor:pointer;transition:.2s}
.bk-filter-reset:hover{border-color:var(--legacy-danger);color:var(--legacy-danger)}

/* 메인 영역 */
/* 통합 작업대: 은행 리스트는 시험지 한 단 폭으로 고정(빈 틈 제거), 오른쪽이 A4 무대 */
.bk-main-area{flex:0 0 auto;width:calc(var(--exam-col) + 48px);min-width:0;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px}
/* .toolbar 공유 컴포넌트 위에 bank-specific 오버라이드 */
.bk-toolbar{gap:10px;flex-shrink:0;margin-bottom:0}
/* 문항 수는 이제 알약이 아니라 목록 위 메타 텍스트다 — 검색이 첫 줄 주역이 되면서
   개수는 배경 정보로 내려왔다. 업로드 2종은 같은 줄 오른쪽에 아이콘 버튼으로 선다. */
.bk-listmeta{display:flex;align-items:center;gap:8px;min-width:0;margin:0 0 2px}
.bk-listmeta-gap{flex:1;min-width:0}
.bk-count-badge{font-size:var(--type-label);color:var(--text-muted);white-space:nowrap}
.bk-icon-action{display:inline-flex;align-items:center;justify-content:center;
  width:var(--control-standard);height:var(--control-standard);padding:0;
  background:var(--surface);color:var(--text-muted);border:0;cursor:pointer}
.bk-icon-action:hover{background:var(--surface-2);color:var(--text)}
.bk-icon-action svg{width:16px;height:16px}
.bk-sort-select{min-height:var(--control-standard);padding:6px 10px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);box-shadow:var(--shadow-control);font-size:var(--type-body);outline:none}
/* .btn.btn-primary.btn-sm 표준 클래스가 색/패딩 처리 — bank-specific: margin-left:auto 만 유지 */
.bk-exam-builder-btn{margin-left:auto;white-space:nowrap}
.bk-sel-cnt{background:var(--on-nav-a25);border-radius:10px;padding:1px 6px;font-size:var(--type-label)}
/* 블랙: --accent 밝은 면 위 흰 틴트 칩은 저대비 → 어두운 틴트로 보정 */
:root[data-theme="black"] .bk-sel-cnt{background:rgba(19,19,22,.12)}
/* 업로드+양식 클러스터: 테두리로 하나의 그룹임을 표시, 내부는 세로 구분선(.bk-tpl-btn border-left)만 */
.bk-upload-cluster{display:inline-flex;align-items:stretch;border:1px solid var(--border);
  border-radius:9px;overflow:hidden;box-shadow:var(--shadow)}
.bk-upload-cluster .btn{border:0;border-radius:0;box-shadow:none}
.bk-tpl-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  background:var(--surface);color:var(--text-muted);font-size:12.5px;font-weight:600;
  border:0;border-left:1px solid var(--border);cursor:pointer;white-space:nowrap}
.bk-tpl-btn:hover{background:var(--surface-2);color:var(--text)}
.bk-tpl-btn .ic,.bk-tpl-btn svg{width:16px;height:16px}

/* ── Bank Instrument command header ── */
.bk-command-header{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--s3);min-height:88px;padding:var(--s3) 0;border-bottom:1px solid var(--border);background:transparent;flex:none;min-width:0}
.bk-command-local{align-self:start;padding-top:3px;color:var(--text-muted);font-size:var(--type-label);font-weight:700;white-space:nowrap}
.bk-command-copy{display:flex;min-width:0;flex-direction:column;gap:3px}
.bk-command-copy #bk-screen-title{margin:0;font-size:var(--type-screen);line-height:1.2;color:var(--text)}
.bk-command-summary{margin:0;color:var(--text-muted);font-size:var(--type-body);line-height:1.45}
.bk-command-context{display:flex;align-items:center;gap:var(--s2);min-width:0;color:var(--text-muted);font-size:var(--type-meta)}
.bk-command-context>span+span{padding-left:var(--s2);border-left:1px solid var(--border)}
.bk-command-actions{display:flex;align-items:center;justify-content:flex-end;gap:var(--s2);min-width:0}
.bk-command-actions .btn{min-width:44px;min-height:44px}
html[data-shell-mode="desktop"] .bk-command-header,
html[data-shell-mode="tablet-landscape"] .bk-command-header{grid-template-columns:auto minmax(0,1fr) auto}
html[data-shell-mode="tablet-portrait"] .bk-command-header,
html[data-shell-mode="mobile-portrait"] .bk-command-header,
html[data-shell-mode="mobile-landscape"] .bk-command-header{grid-template-columns:auto minmax(0,1fr);grid-template-rows:auto auto;align-items:start}
html[data-shell-mode="tablet-portrait"] .bk-command-actions,
html[data-shell-mode="mobile-portrait"] .bk-command-actions,
html[data-shell-mode="mobile-landscape"] .bk-command-actions{grid-column:1/-1;grid-row:2;justify-self:stretch;justify-content:flex-start;flex-wrap:wrap;width:100%;margin-top:var(--s2)}
html[data-shell-mode="tablet-portrait"] .bk-command-actions .btn-primary,
html[data-shell-mode="mobile-portrait"] .bk-command-actions .btn-primary,
html[data-shell-mode="mobile-landscape"] .bk-command-actions .btn-primary{order:-1}
@media(forced-colors:active){.bk-command-header{border-bottom:1px solid CanvasText}.bk-command-actions .btn{border:1px solid ButtonText}}
@media(prefers-reduced-motion:reduce){.bk-command-actions .btn{transition:none}}

/* 문제 목록 — 카드 폭 = 시험지 한 단 폭(--exam-col), 가로로 깔리는 답안지 콘택트시트 */
.bk-problem-list{display:grid;grid-template-columns:repeat(auto-fill,var(--exam-col));gap:12px;justify-content:start;margin-top:16px}
@media(max-width:560px){.bk-problem-list{grid-template-columns:1fr}}
/* 시그니처: 은행 전역 숫자 tabular */
.bk-layout{font-variant-numeric:tabular-nums}
/* 페이지 버튼 (하단) */
.bk-pagination{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:6px;padding:18px 4px 8px}
.bk-pagination:empty{display:none}
.bk-page-btn{min-width:34px;height:34px;padding:0 9px;border:1px solid var(--border);background:var(--surface);color:var(--text2);border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;transition:.15s}
.bk-page-btn:hover:not(:disabled):not(.active){border-color:var(--accent);color:var(--accent)}
.bk-page-btn.active{background:var(--accent);border-color:var(--accent);color:var(--on-nav);cursor:default}
.bk-page-btn:disabled{opacity:.4;cursor:default}
.bk-page-ellipsis{padding:0 2px;color:var(--text-muted,#646d82);font-size:13px}
/* 범위 필터 한 줄(년도 부터~까지, 월 부터~까지) */
.bk-range-row{display:flex;align-items:center;gap:6px;min-width:0}
.bk-range-row .bk-filter-input{flex:1 1 0;min-width:0}
.bk-range-sep{flex:0 0 auto;color:var(--text-muted);font-size:var(--type-label)}
/* 필터 select (과목·대단원·소단원·년도·월) */
/* 상위를 안 고르면 하위 단원 셀렉트는 고를 것이 없다 — 잠긴 상태가 눈에 보여야 한다 */
select.bk-filter-input:disabled{cursor:default;opacity:.55;color:var(--text-muted)}
select.bk-filter-input{cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23646d82' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 10px center;padding-right:28px}
.bk-ps-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-card);padding:14px 16px;cursor:pointer;transition:.2s;position:relative}
.bk-ps-card:hover{border-color:var(--accent)}
.bk-ps-card:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* 미리보기 버튼: 데스크톱 최소 24×24 hit-area(WCAG 2.2 target-size). 카드 담기와 분리된
   data-action="preview" 위임은 그대로 — 시각 카피/키보드 포커스 불변, 세로 여백만 확보. */
.bk-preview-btn{cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;min-height:24px;padding:3px 9px}
@media(hover:hover){#panel-bank .bk-ps-card:hover .q{-webkit-line-clamp:unset}}
.bk-card-top{display:flex;align-items:flex-start;gap:8px;margin-bottom:8px}
.bk-card-badges{display:flex;flex-wrap:wrap;gap:4px;flex:1}
/* .bk-badge 베이스 → .tag 공유 컴포넌트로 대체됨 (subject→tag.sub / score→tag.lv / unit→tag.mut) */
/* 난이도는 의미색이 3단계(하 녹/중 호박/상 적) → 공유 .tag 매핑 불가, bank-specific 유지 */
.bk-badge{padding:3px 8px;border-radius:4px;font-size:12px;font-weight:600;white-space:nowrap;line-height:1.45}
.bk-layout .tag.lv{background:var(--legacy-warn-bg);color:var(--legacy-warn-2)}
.bk-badge-diff-하{background:var(--legacy-good-bg);color:var(--legacy-good)}
.bk-badge-diff-중{background:var(--legacy-warn-bg);color:var(--legacy-warn-2)}
.bk-badge-diff-상{background:var(--legacy-bad-bg);color:var(--legacy-bad)}
/* 정답 배지 */
.bk-badge-ans{display:inline-flex;align-items:center;gap:5px;background:var(--ink-deep);color:var(--accent-ink);padding:3px 9px}
/* .bk-ans-label / .bk-ans-num / .bk-card-actions — 고아 삭제 (bank.js 카드액션 → 상세패널 이전) */
.bk-icon-btn{width:28px;height:28px;border:none;background:transparent;cursor:pointer;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:14px;transition:.2s;color:var(--text3)}
.bk-icon-btn:hover{background:rgba(0,0,0,.06);color:var(--text)}
.bk-icon-btn.fav-active{color:var(--fav)}
.bk-icon-btn.sel-active{color:var(--pri)}
/* 카드 즐겨찾기 버튼: fine-pointer=hover 밀도, touch=항상, 키보드=자체 focus에서 항상 */
.bk-card-fav-btn{position:absolute;top:8px;right:8px;opacity:0;transition:opacity .15s}
.bk-ps-card:hover .bk-card-fav-btn,.bk-ps-card:focus-within .bk-card-fav-btn,.bk-card-fav-btn:focus-visible{opacity:1}
html[data-input="touch"] #panel-bank .bk-card-fav-btn{opacity:1}
/* 모바일 필터 버튼 활성 필터 수 뱃지 */
.bk-filter-badge{display:inline-flex;align-items:center;justify-content:center;background:var(--pri);color:var(--accent-ink);border-radius:10px;font-size:var(--type-label);font-weight:700;min-width:16px;height:16px;padding:0 4px;margin-left:4px;line-height:1}
/* 기출 검색 카드 본문 (검색탭 특화 크기) */
.bk-search-content{font-size:13px;margin-top:8px}
/* 풀이 토글 버튼: 데스크톱 최소 24×24 hit-area(검색 상세 카드 내 자체 리스너 유지). */
.bk-sol-toggle{margin-left:auto;background:none;border:none;cursor:pointer;font-size:12px;color:var(--pri);display:inline-flex;align-items:center;gap:4px;padding:4px 8px;min-height:24px}
/* 풀이 본문 (collapsed by default, shown with JS) */
.bk-sol-body{margin-top:8px;font-size:12px;color:var(--text2);line-height:1.6;border-top:1px solid var(--border);padding-top:8px}
/* 변환 문항 레이블 */
.bk-variant-lbl{font-size:var(--type-label);font-weight:700;color:var(--ink-2);margin-bottom:6px}
/* 카드 본문: 짤림 없이 전부 표시 + 수식 가로 오버플로 방지 */
.bk-card-content{font-size:14px;color:var(--text2);line-height:1.65;overflow-wrap:anywhere}
.bk-card-content p{margin:.3em 0}
.bk-card-content .katex-display{margin:.4em 0;overflow-x:auto;overflow-y:hidden}
.bk-card-content img{max-width:100%;height:auto}
/* .card .foot 공유 규칙이 display/flex/border-top 처리 — bank-specific 색 오버라이드만 */
.bk-card-footer{color:var(--ink-2)}
.bk-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;color:var(--ink-2)}
.bk-empty-icon{width:48px;height:48px;opacity:.3;display:flex;align-items:center;justify-content:center}
.bk-loading{text-align:center;padding:40px;color:var(--ink-2)}

/* .bk-modal-backdrop / .bk-modal / .bk-modal-close / .bk-modal-body — 고아 삭제 (슬라이드 상세패널로 대체) */
.bk-modal-section{margin-bottom:20px}
.bk-modal-section-title{font-size:12px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;padding-bottom:6px;border-bottom:1px solid var(--border)}
.bk-modal-content{font-size:14px;line-height:1.7;color:var(--text)}
.bk-variant-item{background:var(--surface-3);border-radius:var(--rs);padding:12px;margin-bottom:8px}
.bk-variant-answer{display:inline-flex;align-items:center;gap:6px;background:var(--ink-deep);color:var(--accent-ink);padding:3px 10px;border-radius:4px;font-size:12px;margin-top:8px}
.bk-variant-solution{color:var(--text2);font-size:13px;margin-top:8px;padding-top:8px;border-top:1px solid var(--border)}

/* ── 문제 상세 페이지 (전체 화면 전환 + 브레드크럼) ── */
/* 패널은 메인 콘텐츠 배경(연회색)과 동일 → 흰 시험지가 카드처럼 떠 보이게 */
/* 카드 클릭 시 우측에서 슬라이드되는 전체 페이지. 브레드크럼/X/뒤로가기로 목록 복귀 */
.bk-detail{position:fixed;top:0;right:0;height:100vh;width:100%;display:flex;flex-direction:column;background:var(--bg);z-index:220;overflow-y:auto;transform:translateX(100%);visibility:hidden;transition:transform .25s cubic-bezier(.4,0,.2,1)}
.bk-detail.open{transform:translateX(0);visibility:visible}
.bk-detail-backdrop{display:none;position:fixed;inset:0;background:rgba(26,32,53,.32);z-index:215}
.bk-detail-backdrop.open{display:block}
/* 브레드크럼(왼쪽 위 접속 경로): 앞 단계 클릭 = 그 화면으로 복귀 */
.bk-crumbs{display:flex;gap:7px;align-items:center;flex-wrap:wrap;font-size:12.5px;color:var(--text-muted);
  padding:12px 18px 0;background:var(--surface)}
.bk-crumbs button{background:none;border:0;padding:0;font:inherit;color:var(--text-muted);cursor:pointer}
.bk-crumbs button:hover{color:var(--accent);text-decoration:underline}
.bk-crumbs .cur{color:var(--text);font-weight:600;max-width:min(420px,60vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 본문(종이·부가정보)은 페이지 중앙 칼럼으로 */
#bk-detail-paper,#bk-detail-extra{width:100%;max-width:900px;margin-left:auto;margin-right:auto}
/* 정보 그리드(출처·형태·단원·태그·메모·등록일) */
.bk-info-grid{display:grid;grid-template-columns:92px 1fr;gap:7px 14px;font-size:13px;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius-sm);padding:14px 16px}
.bk-info-grid .k{color:var(--text-muted);font-weight:600}
.bk-info-grid .v{color:var(--text);min-width:0;overflow-wrap:anywhere}
.bk-info-tags{display:flex;gap:5px;flex-wrap:wrap}
/* 헤더: 메인 #app-header와 동일한 흰 바 */
.bk-detail-head{position:sticky;top:0;display:flex;align-items:center;gap:8px;padding:12px 16px;background:var(--surface);border-bottom:1px solid var(--border);z-index:3}
.bk-detail-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex:1}
/* 추가 버튼: 메인 .btn-primary와 동일한 솔리드 네이비 */
.bk-detail-add{padding:7px 14px;background:var(--accent);color:var(--accent-ink);border:1.5px solid var(--accent);border-radius:var(--radius-sm);font-size:12.5px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s;white-space:nowrap}
.bk-detail-add:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.bk-detail-add.added{background:var(--legacy-ok);border-color:var(--legacy-ok)}
/* 변형 뽑기: 보조 아웃라인 (주 CTA '시험지에 추가'와 구분) */
.bk-detail-variant{background:transparent;color:var(--accent);border-color:var(--border)}
.bk-detail-variant:hover{background:var(--bg);border-color:var(--accent)}
.bk-detail-variant:disabled{opacity:.55;cursor:not-allowed}
/* 닫기: 중립 아이콘 버튼 */
.bk-detail-close{width:30px;height:30px;flex-shrink:0;border:none;background:transparent;color:var(--text-muted);border-radius:var(--radius-sm);cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;transition:.15s}
.bk-detail-close:hover{background:rgba(0,0,0,.05);color:var(--text)}
/* 시험지 종이: 연회색 패널 위에 떠 있는 흰 카드 */
.bk-paper{margin:18px;padding:28px 30px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:0 1px 3px rgba(26,32,53,.06),0 8px 24px rgba(26,32,53,.05);font-family:"Malgun Gothic","Nanum Gothic",serif;color:var(--text);font-size:15px;line-height:1.9}
.bk-paper-stem{color:inherit}
.bk-paper-stem p{margin:.5em 0}
.bk-figure{display:flex;justify-content:center;margin:16px 0}
.bk-figure img{max-width:100%;max-height:360px;object-fit:contain;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;padding:6px}
.bk-figure.broken{display:none}
/* figures 갤러리 (분해 그림: 메인 + 보기 + 선지 ①~⑤) */
.bk-figgal{margin:16px 0}
.bk-figmain{display:flex;justify-content:center;flex-wrap:wrap;gap:12px;margin:8px 0}
.bk-figmain .bk-figcell img{max-width:100%;max-height:340px}
.bk-figchoices{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;margin-top:12px;
  padding-top:12px;border-top:1px dashed var(--border)}
.bk-figcell{display:flex;flex-direction:column;align-items:center;gap:4px}
.bk-figcell img{max-width:100%;max-height:200px;object-fit:contain;border:1px solid var(--border);border-radius:4px;background:#fff;padding:4px;display:block}
.bk-figcell.broken{display:none}
.bk-figlbl{font-size:14px;font-weight:700;color:var(--text)}
.bk-choices{margin-top:8px;color:inherit}
.bk-choices p{margin:.35em 0}
/* 선지 배열(임포트 문항)의 ①~⑤ 마커 렌더 — 브라우저 기본 1.2.3. 목록 대신 시험지 표기 */
.bk-choicelist{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:2px}
.bk-choicelist li{display:flex;align-items:baseline;gap:6px}
.bk-choicemark{flex:0 0 auto;font-weight:700}
.bk-choicebody{flex:1;min-width:0}
.bk-choicebody p{margin:.2em 0}
/* 카드용 선지 — 시험지 조판처럼 가로 흐름으로 감싸 카드 높이를 아낀다(전 플랫폼 공통, 좁은 폭은 wrap) */
.bk-card-choices{flex-direction:row;flex-wrap:wrap;gap:2px 14px;margin-top:6px;font-size:12.5px;color:var(--ink-2)}
.bk-card-choices li{flex:0 1 auto}
.bk-card-choices .bk-choicebody{flex:0 1 auto}
/* 상세·시험지 미리보기의 배열 선지 — 실물 수능처럼 ①~⑤ 를 한 줄로 흘리고, 길어서 한 줄에
   못 담기는 선지만 다음 줄로 내린다(li 단위 wrap). 본문 인라인 선지는 마크다운 그대로라
   .bk-choices 단독(div)이고 이 규칙(.bk-choicelist 동반)에 걸리지 않는다. */
.bk-choicelist.bk-choices{flex-direction:row;flex-wrap:wrap;gap:4px 22px}
.bk-choicelist.bk-choices li{flex:0 1 auto}
.bk-choicelist.bk-choices .bk-choicebody{flex:0 1 auto}
/* 같은 소단원 유사 문항(B③) — 카드 시각 문법(.card.bk-ps-card)과 본문 클램프(.q)를
   그대로 쓰고, 카드를 button 으로 만들면서 생기는 UA 기본값만 지운다. 좁은 폭에서는
   한 줄로 접혀 모바일·패드도 같은 마크업 그대로 쓴다. */
.bk-related-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:10px}
.bk-related-card{width:100%;text-align:left;font:inherit;color:inherit}
.bk-related-meta{margin-top:8px;font-size:var(--type-label);color:var(--ink-2)}
/* 시험지 아래 메타(정답/풀이/변환): 종이 카드와 같은 가로 인셋으로 배치 */
.bk-detail-extra{padding:2px 18px 24px}
.bk-detail-extra .bk-modal-section{margin-top:18px}
.bk-detail-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:var(--text3);padding:40px;text-align:center;line-height:1.6}
.bk-detail-empty .ic{font-size:44px;opacity:.3}
/* 현재 보고있는 카드 하이라이트 */
.bk-ps-card.bk-active{border-color:var(--accent);box-shadow:0 0 0 2px var(--active-halo)}
/* 변형 계보(마이그 275): 파생이 많은 원본은 좌측 안쪽 선 한 줄로만 구분한다(배지·이모지 없음).
   inset 이라 카드 크기가 변하지 않고, '파생 N개' 버튼이 같은 정보를 텍스트로도 준다. */
.bk-ps-card.bk-lineage-hot{box-shadow:inset 3px 0 0 var(--accent-soft)}
/* 계보 좁히기 안내(툴바). ⚠️ display 를 클래스에서 선언하므로 UA 의 [hidden]{display:none}
   이 진다 — 숨김 규칙을 함께 둔다(app.css 5338 과 같은 함정). */
.bk-lineage-filter{display:inline-flex;align-items:center;gap:6px;font-size:var(--type-label);color:var(--ink-2)}
.bk-lineage-filter[hidden]{display:none}
/* 자연어 출제(문항 검색) 진입 줄 + 해석 줄. ⚠️ 클래스에서 display 를 선언하므로
   UA 의 [hidden]{display:none} 이 진다 — 숨김 규칙을 함께 둔다(위 계보 안내와 같은 함정). */
.bk-nl{display:flex;align-items:center;gap:8px;margin:0 0 10px}
.bk-nl-input{flex:1;min-width:0}
.bk-nl-status{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 10px;font-size:var(--type-label);color:var(--ink-2)}
.bk-nl-status[hidden]{display:none}
.bk-nl-extra{display:inline-flex;flex-wrap:wrap;gap:6px}

/* ── 목록 정렬 줄 ──────────────────────────────────────────────────────────
   버튼 하나가 방향 두 개를 맡는다. 활성은 늘 한 개이고, 방향은 버튼에 붙은 두
   캐럿 중 진한 쪽으로 읽는다(꺼진 버튼은 둘 다 흐리다 = 아직 아무 방향도 아니다).
   좁은 폭에서는 줄바꿈으로 접힌다 — 가로로 넘쳐 페이지가 옆으로 밀리면 안 된다. */
.bk-sortbar{display:flex;align-items:baseline;gap:10px;min-width:0;margin:0 0 2px}
.bk-sortbar-label{flex:none;font-size:var(--type-label);font-weight:700;color:var(--text3);
  text-transform:uppercase;letter-spacing:.5px}
.bk-sortbar-btns{display:flex;flex-wrap:wrap;gap:6px;min-width:0}
.bk-sort-btn{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;
  border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);
  color:var(--text2);font-family:inherit;font-size:12.5px;font-weight:600;line-height:1.3;
  cursor:pointer;white-space:nowrap;-webkit-appearance:none;appearance:none;
  transition:border-color .15s,color .15s,background .15s}
.bk-sort-btn[hidden]{display:none}
.bk-sort-btn:hover{border-color:var(--pri);color:var(--pri)}
.bk-sort-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.bk-sort-btn.active{background:var(--pri);border-color:var(--pri);color:var(--on-nav)}
/* 캐럿은 지시등이지 두 번째 버튼이 아니다 — 클릭 대상은 언제나 버튼 전체다
   (aria-hidden 인 장식이 제 힛박스를 갖지 않게 한다). */
.bk-sort-arrows{display:inline-flex;flex-direction:column;justify-content:center;gap:2px;flex:none;
  pointer-events:none}
.bk-sort-caret{display:block;width:9px;height:6px;opacity:.32}
/* 켜진 버튼에서만 지금 방향의 캐럿이 또렷해진다 */
.bk-sort-btn.active[data-dir="asc"] .bk-sort-caret.up,
.bk-sort-btn.active[data-dir="desc"] .bk-sort-caret.down{opacity:1}
.bk-prob-no{font-weight:800;margin-right:4px}
@media(max-width:560px){.bk-detail{width:100%}}  /* fixed 요소의 100%=뷰포트폭. 100vw는 스크롤바 유무와 무관하게 계산돼
                                                      세로 스크롤바가 있는 환경에서 그만큼 우측 초과(가로 오버플로) 가능 */
/* ── 모바일 폴리시 (2026-06-30) ── */
@media(max-width:768px){
  /* 은행 상세 헤더: 배지 줄 전체폭 + 액션 버튼 다음 줄로 */
  .bk-detail-head{flex-wrap:wrap}
  .bk-detail-meta{flex-basis:100%}
  /* 은행 툴바: 가로 스크롤 대신 줄바꿈(필터/개수/정렬/시험지구성 모두 보이게) — 전역 .toolbar nowrap(2376행) 이기게 #id 스코프 */
  #panel-bank .bk-toolbar{flex-wrap:wrap;overflow-x:visible}
  /* 비용통계 막대 값 라벨: 모바일에선 겹쳐서 숨김(막대+날짜축만) */
  .bars .b span{display:none}
}

/* .bk-exam-panel / header / body / footer / item / no / content / rm — 고아 삭제 (우측 빌더 패널로 대체) */
/* bk-btn-primary removed — replaced by .btn.btn-primary (bank.js line 207) */

/* ── 우측 시험지 빌더 (상시 조립 작업대) ── */
.bk-builder{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;border-left:1px solid var(--border);background:var(--surface);overflow:hidden}
.bk-builder-head{display:flex;align-items:center;gap:8px;padding:12px 16px;border-bottom:1px solid var(--border);flex:none;position:relative;z-index:2;background:var(--surface)}
.bk-builder-scroll{display:flex;flex:1 1 auto;min-width:0;min-height:44px;flex-direction:column;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}
.bk-builder-scroll:focus{outline:none}
.bk-builder-scroll>*{flex:0 0 auto;min-width:0}
.bk-builder-title{flex:1;min-width:0;min-height:var(--control-dense);padding:7px 10px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);box-shadow:var(--shadow-control);font-size:var(--type-button);color:var(--text);outline:none;transition:border-color .15s}
.bk-builder-title:focus{border-color:var(--accent)}
.bk-builder-title:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
.bk-builder-title::placeholder{color:var(--text-muted)}
/* 빌더 패널 입력칸(.bk-input) — 필터 칼럼의 .bk-filter-input 과 같은 컨트롤 토큰 체계.
   .sm 은 아코디언 안에 여러 칸이 붙는 자리를 위한 컴팩트 변형(높이·여백만 줄이고 토큰은 유지). */
.bk-input{width:100%;min-height:var(--control-standard);padding:7px 10px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);box-shadow:var(--shadow-control);font-size:var(--type-body);color:var(--text);outline:none;transition:border-color .15s}
.bk-input:focus{border-color:var(--accent)}
.bk-input:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
.bk-input::placeholder{color:var(--text-muted)}
.bk-input:disabled{cursor:default;opacity:.55;color:var(--text-muted)}
.bk-input.sm{min-height:var(--control-dense);padding:6px 9px;font-size:var(--type-button)}
select.bk-input{cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23646d82' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 10px center;padding-right:28px}
select.bk-input.sm{background-position:right 8px center;padding-right:24px}
.bk-builder-count{font-size:12px;color:var(--text-muted);white-space:nowrap}
.bk-builder-count b{color:var(--text);font-size:15px}
#bk-builder-close{display:none}
/* 담긴 목록 접기 토글 → A4 미리보기 세로공간 확보 */
.bk-build-collapse{display:flex;align-items:center;justify-content:space-between;width:100%;padding:9px 16px;border:none;border-bottom:1px solid var(--border);background:var(--surface);cursor:pointer;font-size:var(--type-label);font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em}
.bk-build-collapse:hover{color:var(--text)}
.bk-build-collapse b{color:var(--text);font-variant-numeric:tabular-nums}
.bk-build-collapse .ic{transition:transform .15s}
.bk-builder.build-collapsed .bk-build-collapse .ic{transform:rotate(-90deg)}
.bk-builder.build-collapsed #bk-build-list{display:none}
/* 분포 게이지 */
.bk-gauge{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;flex-direction:column;gap:9px}
.bk-gauge:empty{display:none}
.bk-gauge-row{display:flex;align-items:center;gap:8px}
.bk-gauge-label{font-size:var(--type-label);font-weight:700;color:var(--text-muted);width:36px;flex-shrink:0}
.bk-gauge-bar{flex:1;display:flex;height:8px;border-radius:6px;overflow:hidden;background:var(--surface-2)}
.bk-gauge-seg{height:100%}
.bk-gauge-seg.d-하{background:var(--legacy-good)}
.bk-gauge-seg.d-중{background:var(--legacy-warn)}
.bk-gauge-seg.d-상{background:var(--legacy-danger)}
.bk-gauge-chips{display:flex;flex-wrap:wrap;gap:4px}
.bk-gauge-chip{font-size:var(--type-label);padding:2px 8px;border-radius:var(--radius-pill);background:var(--surface-2);color:var(--text);font-weight:600}
/* 수능형 30문항 조립 보드 — 규격(문항 수·유형 구간·배점)은 서버 registry 가 준다.
   게이지와 같은 활자·칩 언어를 쓰고, 좌측 강조 바나 단계 카드 문법은 쓰지 않는다.
   상태는 색이 아니라 슬롯 안의 짧은 글자(유형·배점·정답)로 먼저 말한다. */
.bk-csat-board{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;flex-direction:column;gap:10px}
.bk-csat-board:empty{display:none}
.bk-board-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;flex-wrap:wrap}
.bk-board-title{margin:0;font-size:var(--type-meta);font-weight:700;color:var(--text)}
.bk-board-fixed,.bk-board-sum{display:flex;flex-wrap:wrap;gap:4px}
.bk-board-chip{font-size:var(--type-label);padding:2px 8px;border-radius:var(--radius-pill);background:var(--surface-2);color:var(--text);font-weight:600}
.bk-board-chip.is-fixed{background:transparent;border:1px solid var(--border);color:var(--text-muted);font-weight:600}
.bk-board-chip.is-warn{background:var(--legacy-warn-bg);color:var(--legacy-warn-2)}
.bk-board-chip.is-bad{background:var(--legacy-bad-bg);color:var(--legacy-bad)}
.bk-board-sec{display:flex;flex-direction:column;gap:6px}
.bk-board-sec-h{margin:0;font-size:var(--type-label);font-weight:700;color:var(--text-muted);display:flex;gap:6px;align-items:baseline}
.bk-board-sec-range{font-weight:500;color:var(--ink-4)}
.bk-board-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:4px}
.bk-slot{border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);
  padding:5px 4px 4px;display:flex;flex-direction:column;align-items:center;gap:1px;min-height:44px;text-align:center}
.bk-slot-no{font-family:var(--font-num);font-size:var(--type-meta);font-weight:700;color:var(--text);line-height:1.1}
.bk-slot-meta{font-size:12px;color:var(--text-muted);line-height:1.2;white-space:nowrap}
.bk-slot-flag{font-size:12px;font-weight:700;line-height:1.2;color:var(--legacy-warn-2)}
.bk-slot.is-empty{border-style:dashed;background:transparent}
.bk-slot.is-empty .bk-slot-no{color:var(--ink-4)}
.bk-slot.is-filled{background:var(--surface-2)}
.bk-slot.is-warn{border-color:var(--legacy-warn-2)}
.bk-slot.is-bad{border-color:var(--legacy-bad)}
.bk-slot.is-bad .bk-slot-flag{color:var(--legacy-bad)}
.bk-board-msgs{margin:0;padding:0 0 0 16px;font-size:var(--type-label);color:var(--legacy-bad);line-height:1.6}
.bk-board-note{margin:0;font-size:var(--type-label);color:var(--text-muted);line-height:1.5}
@media (max-width:640px){
  .bk-csat-board{padding:10px 12px}
  .bk-board-grid{grid-template-columns:repeat(auto-fill,minmax(56px,1fr))}
  .bk-slot{min-height:40px;padding:4px 2px 3px}
}
/* 담긴 문제 리스트 */
.bk-build-list{max-height:220px;overflow-y:auto;padding:10px 12px;display:flex;flex-direction:column;gap:6px}
.bk-build-empty{margin:auto;text-align:center;color:var(--ink-2);font-size:13px;line-height:1.8;padding:26px 18px;border:1.5px dashed var(--border);border-radius:var(--radius)}
.bk-build-item{border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);transition:border-color .15s,box-shadow .15s,opacity .15s}
.bk-build-item.dragging{opacity:.45}
.bk-build-item.drag-over{border-color:var(--accent);box-shadow:0 0 0 2px var(--active-halo)}
.bk-build-row{display:flex;align-items:center;gap:8px;padding:8px 10px}
.bk-build-handle{cursor:grab;color:var(--text-muted);font-size:14px;flex-shrink:0;user-select:none}
.bk-build-no{width:22px;height:22px;background:var(--accent);color:var(--accent-ink);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:var(--type-label);font-weight:700;flex-shrink:0}
.bk-build-text{flex:1;min-width:0;font-size:12.5px;color:var(--text2);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.bk-build-toggle,.bk-build-rm{border:none;background:transparent;cursor:pointer;color:var(--text-muted);flex-shrink:0;padding:2px 5px}
.bk-build-toggle{font-size:12px}
.bk-build-rm{font-size:15px}
.bk-build-rm:hover{color:var(--legacy-danger)}
.bk-build-preview{display:none;padding:0 12px 12px;font-size:12.5px;color:var(--text);line-height:1.7}
.bk-build-preview.open{display:block;padding-top:10px;border-top:1px solid var(--border)}
.bk-build-preview img{max-width:100%;max-height:200px;object-fit:contain;display:block;margin:8px auto;border:1px solid var(--border);border-radius:var(--radius-sm)}
.bk-builder-foot{padding:12px 16px;border-top:1px solid var(--border);overflow-wrap:anywhere}
.bk-builder-foot .btn-primary{width:100%}
.bk-builder-foot #bk-hwp-btn{display:flex;width:100%;max-width:100%;min-width:0;white-space:normal;overflow-wrap:anywhere}
.bk-endnote-opt{display:flex;align-items:center;gap:6px;margin-bottom:8px;font-size:12.5px;color:var(--ink-2);cursor:pointer;user-select:none}
.bk-endnote-opt input{accent-color:var(--accent);cursor:pointer}

/* ── 시험지 설정 접이식 3구역(조판 / 시험지 문구 / 출력물) ──
   예전 fieldset 3개에 박혀 있던 인라인 style 속성을 전부 여기로 옮겼다. 접힌 헤더의
   요약 줄은 한 줄로 잘라 말줄임한다(두 줄로 접히면 헤더가 목록처럼 보인다). */
.bk-acc{border:1px solid var(--border);border-radius:var(--radius-card);overflow:hidden;margin:0 0 10px}
.bk-acc-sec+.bk-acc-sec{border-top:1px solid var(--border)}
.bk-acc-h{margin:0;font-size:inherit;font-weight:inherit}
.bk-acc-head{display:flex;align-items:center;gap:10px;width:100%;min-height:var(--control-standard);
  padding:8px 12px;border:0;background:var(--surface);color:var(--text);font:inherit;text-align:left;cursor:pointer}
.bk-acc-head:hover{background:var(--surface-2)}
.bk-acc-t{flex:none;font-size:var(--type-label);font-weight:700}
.bk-acc-sum{flex:1;min-width:0;font-size:var(--type-label);color:var(--ink-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bk-acc-car{flex:none;display:inline-flex;align-items:center;color:var(--ink-3);
  transform:rotate(-90deg);transition:transform .15s}
.bk-acc-head[aria-expanded="true"] .bk-acc-car{transform:none}
.bk-acc-body{padding:10px 12px 14px;background:var(--surface-2)}
.bk-acc-body[hidden]{display:none}
.bk-acc-field{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--ink-2);margin:0 0 8px}
.bk-acc-field select{width:100%;min-width:0}
.bk-output-variants label{display:flex;align-items:center;gap:6px;margin:0 0 6px;
  font-size:12.5px;color:var(--ink-2);cursor:pointer}
.bk-output-variants label input{accent-color:var(--accent);cursor:pointer}
@media (prefers-reduced-motion:reduce){.bk-acc-car{transition:none}}
.bk-examtype{display:flex;gap:14px;margin-bottom:8px;font-size:12.5px;color:var(--ink-2)}
.bk-examtype label{display:flex;align-items:center;gap:5px;cursor:pointer;user-select:none}
.bk-examtype input{accent-color:var(--accent);cursor:pointer}
/* 페이지당 문제 수(스테퍼)·여백(라디오) */
.bk-layout-opts{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;margin-bottom:8px;font-size:12.5px;color:var(--ink-2)}
.bk-opt-lbl{color:var(--ink-2)}
.bk-perpage{display:flex;align-items:center;gap:6px}
.bk-perpage b{min-width:14px;text-align:center;font-weight:700;color:var(--ink)}
.bk-step{width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--ink);font-size:15px;line-height:1;cursor:pointer;padding:0}
.bk-step:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
.bk-step:disabled{opacity:.4;cursor:not-allowed}
/* 문항 간격 슬라이더 — 스테퍼·라디오와 같은 한 줄 옵션 문법을 쓴다.
   손가락으로도 끌 수 있어야 하므로(패드·모바일) 트랙과 손잡이를 직접 그린다:
   기본 크롬 손잡이는 굵은 손가락에 비해 작고 터치 판정도 좁다. */
.bk-gap-opt{display:flex;align-items:center;gap:8px;min-width:210px;flex:1 1 210px}
.bk-range{flex:1 1 auto;min-width:96px;height:22px;margin:0;padding:0;background:none;
  accent-color:var(--accent);cursor:pointer;-webkit-appearance:none;appearance:none;touch-action:pan-y}
.bk-range::-webkit-slider-runnable-track{height:4px;border-radius:999px;background:var(--border)}
.bk-range::-moz-range-track{height:4px;border-radius:999px;background:var(--border)}
.bk-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;
  margin-top:-6px;border-radius:50%;background:var(--accent);border:2px solid var(--surface);
  box-shadow:0 1px 3px rgba(20,28,48,.28)}
.bk-range::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--accent);
  border:2px solid var(--surface);box-shadow:0 1px 3px rgba(20,28,48,.28)}
.bk-range:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:999px}
.bk-range:disabled{opacity:.4;cursor:not-allowed}
.bk-gap-val{min-width:52px;font-weight:700;color:var(--ink);white-space:nowrap}
.bk-gap-note{margin:0 0 8px;font-size:12px;line-height:1.5;color:var(--ink-3)}
/* 굵은 포인터(패드·모바일)에서는 손잡이와 트랙을 키워 끌기 쉽게. */
@media(pointer:coarse){
  .bk-range{height:28px}
  .bk-range::-webkit-slider-runnable-track{height:6px}
  .bk-range::-moz-range-track{height:6px}
  .bk-range::-webkit-slider-thumb{width:22px;height:22px;margin-top:-8px}
  .bk-range::-moz-range-thumb{width:22px;height:22px}
}
.bk-margin-opt{display:flex;align-items:center;gap:10px}
.bk-margin-opt label{display:flex;align-items:center;gap:5px;cursor:pointer;user-select:none}
.bk-margin-opt input{accent-color:var(--accent);cursor:pointer}
.bk-margin-opt label:has(input:disabled){opacity:.45;cursor:not-allowed}
.bk-margin-opt input:disabled{cursor:not-allowed}
/* 시험지 미리보기 */
.bk-preview-wrap{border-top:1px solid var(--border);padding:20px;overflow-x:auto;overflow-y:visible;min-height:0;background:var(--bg)}
.bk-preview-label{font-size:var(--type-label);font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;margin-bottom:10px}
/* 미리보기 접기/펼치기(라벨 옆 토글) — 접으면 좌측 목록·검수가 남는 폭을 전부 쓴다 */
.bk-preview-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
.bk-preview-head .bk-preview-label{margin-bottom:0}
.bk-preview-toggle{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:4px 9px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);color:var(--text-muted);font-size:var(--type-label);font-weight:600;cursor:pointer;transition:color .15s,border-color .15s}
.bk-preview-toggle:hover{color:var(--text);border-color:var(--accent)}
.bk-preview-toggle .ic{transition:transform .15s}
.preview-collapsed .bk-preview-toggle .ic{transform:rotate(-90deg)}
.preview-collapsed #bk-preview-paper{display:none}
.preview-collapsed .bk-preview-wrap{overflow:visible}
.preview-collapsed .bk-preview-head{margin-bottom:0}
/* 미주 ON 이면 미리보기(순수 학생지)와 내려받는 학생지가 갈린다. 경고가 아니라
   사실 안내라 빨강 대신 톤을 낮추고, 접힌 상태에선 머리말만 남긴다. */
/* 안내는 콜아웃 박스가 아니라 캡션이다 — 배경·테두리·좌측 강조 바를 걷어냈다. */
/* 미리보기·다운로드 차이 캡션 — '접기' 줄에 인라인 한 줄. 좁으면 말줄임(전체 문장은 title) */
.bk-preview-variant-note{margin:0;flex:1 1 auto;min-width:0;text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text-muted);font-size:var(--type-label);line-height:1.5}
.preview-collapsed .bk-preview-variant-note{display:none!important}
/* 데스크톱(빌더 상시 표시)에서만 좌우 폭을 재배분한다 — ≤1280px 은 빌더가 고정 드로어라
   폭 규칙을 건드리면 드로어가 찌그러진다(접힘은 그 폭 안에서 미리보기만 숨김). */
@media(min-width:1281px){
  .bk-layout.preview-collapsed .bk-main-area{flex:1 1 auto;width:auto}
  .bk-layout.preview-collapsed .bk-builder{flex:0 0 auto;width:320px}
}
/* 실제 A4 페이지네이션: 페이지별 2단(한 단=exam-col) 시트를 세로로 스택 */
.bk-preview-paper{display:flex;flex-direction:column;align-items:center;gap:22px;background:none;border:none;box-shadow:none;padding:0;width:auto;max-width:none}
.bk-pv-empty{color:var(--ink-2);font-size:12px;text-align:center;padding:24px 0}
/* 빈 미리보기: ~500px 공백 대신 고스트 A4 시트로 출력 형식 예고 */
.bk-pv-ghost{width:min(440px,88%);aspect-ratio:1/1.414;margin:6px auto;border:2px dashed var(--border-dash);border-radius:4px;background:var(--surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:11px;text-align:center;padding:26px}
.bk-pv-ghost svg{width:40px;height:40px;color:var(--ink-4)}
.bk-pv-ghost span{font-size:13px;font-weight:600;color:var(--ink-2)}
.bk-pv-ghost small{font-size:var(--type-meta);color:var(--ink-3);max-width:260px;line-height:1.5}
.bk-pv-measure{position:absolute;left:-9999px;top:0;width:var(--exam-col);visibility:hidden}
/* 세로 flex — 본문 2단이 머리글 아래 남은 높이를 전부 가져가야 중앙 구분선이
   실물처럼 본문 영역 전 높이로 선다. 블록 흐름이던 동안에는 .bk-pv-cols 높이가
   담긴 내용만큼이라, 문항이 적은 쪽에서 선이 중간에 끊겼다(지석 실물 신고). */
.bk-pv-page{position:relative;background:#fff;border:1px solid var(--border);border-radius:2px;box-shadow:0 2px 24px rgba(20,28,48,.16);width:calc(var(--exam-col)*2 + 28px + 64px);padding:32px;min-height:calc((var(--exam-col)*2 + 28px + 64px) * 1.414);display:flex;flex-direction:column}
.bk-pv-page::before{content:"FULLDA";position:absolute;top:46%;left:50%;transform:translate(-50%,-50%) rotate(-20deg);font-size:64px;font-weight:800;color:rgba(30,38,56,.045);pointer-events:none;z-index:0}
.bk-pv-cols{display:grid;grid-template-columns:var(--exam-col) var(--exam-col);gap:0 28px;position:relative;z-index:1;flex:1 1 auto;min-height:0}
.bk-pv-cols::before{content:"";position:absolute;top:0;bottom:0;left:50%;width:1px;background:var(--border);transform:translateX(-50%)}
.bk-pv-col{width:var(--exam-col)}
/* ── 빠른 미리보기(비 strict)의 수능 스킨 ──
   머리글·꼬리글 요소는 strict 경로(.exam-page-skinned)가 쓰는 .exam-skin-* 클래스를
   **그대로** 쓴다. 활자·괘선·크기·모서리 규칙을 여기서 다시 쓰지 않으므로 두 지면이
   갈릴 수 없다. 이 블록은 두 지면의 상자 모델 차이(그리드 대 블록, mm 여백 대 px
   여백, 워터마크 위 겹침)만 메운다. */
.bk-pv-skinned{font-family:"Noto Serif KR","Nanum Myeongjo",Batang,"Apple SD Gothic Neo",serif}
.bk-pv-skinned .bk-paper{font-family:inherit}
/* .exam-skin-head 의 grid-column 은 블록 부모에서 무시되고 폭은 그대로 100% 가 된다.
   워터마크(::before, z-index:0) 위로 올리는 지정만 더한다. */
.bk-pv-skinned .exam-skin-head,.bk-pv-skinned .exam-skin-foot{z-index:1}
/* 꼬리글 좌우는 strict 의 12mm 고정이 아니라 이 지면이 실제로 쓰는 여백에 맞춘다
   (여백 선택이 좁게·보통·넓게로 바뀌므로 JS 가 --bk-pv-pad 로 알려 준다). */
.bk-pv-skinned .exam-skin-foot{left:var(--bk-pv-pad,32px);right:var(--bk-pv-pad,32px);bottom:12px}
/* 미리보기 문제: 카드 크롬 제거 → 연속 시험지(인쇄 미감 serif 유지) */
/* 문항 사이 여백은 '본문 몇 줄'로만 정한다(--exam-gap-lines, 기본 1줄 = 실물).
   HWPX 조판도 같은 줄 배수를 쓰므로(exam_gap.py) 화면과 받은 파일이 갈리지
   않는다. 예전 고정 16px 은 한 줄(13px x 1.7 = 22.1px)보다 좁아 문항이
   다닥다닥 붙어 보였다. */
.bk-pv-col .bk-paper,.bk-pv-measure .bk-paper{margin:0 0 calc(var(--exam-gap-lines,1) * 1em * 1.7);padding:0;background:none;border:none;box-shadow:none;border-radius:0;font-size:13px;line-height:1.7}
/* 문항 아래 풀이 공간(줄 수 비례). greedy 미리보기(.bk-paper)와 서버 플랜
   렌더(.exam-q) 두 경로가 같이 쓴다. 높이는 JS 가 em 으로 넣어 축소 배율에
   비례하고, 여기서는 '여기에 쓴다'를 알리는 점선 경계만 준다. */
.bk-answerspace{margin-top:6px;border-top:1px dashed var(--border)}
/* 내신형 섹션 머리말(객관식/서술형) */
.bk-pv-col .bk-pv-section,.bk-pv-measure .bk-pv-section{display:flex;align-items:baseline;justify-content:space-between;gap:8px;border-bottom:1.5px solid var(--text);padding-bottom:4px;margin:2px 0 10px}
/* 시험지 미리보기 계보 라벨(원본/변형). 절대배치 = 페이지 배분 실측 높이에 영향 없음.
   배경은 .bk-pv-page 와 같은 흰 종이색이라 본문 위에 겹쳐도 읽힌다. */
.bk-pv-col .bk-paper,.bk-pv-measure .bk-paper{position:relative}
.bk-pv-lineage{position:absolute;top:0;right:0;pointer-events:none;background:#fff;padding:0 2px;font-size:var(--type-label);color:var(--text-muted)}
.bk-pv-section-t{font-weight:800;font-size:13.5px;color:var(--text)}
.bk-pv-section-c{font-size:var(--type-label);color:var(--text-muted);font-variant-numeric:tabular-nums}
/* 정답 토글 */
/* 정답 토글: 데스크톱 최소 24×24 hit-area(카드 담기와 분리된 toggle-ans 위임 유지). */
.bk-ans-toggle{background:none;border:none;cursor:pointer;font-size:var(--type-label);color:var(--ink-2);padding:4px 8px;border-radius:3px;display:inline-flex;align-items:center;gap:4px;min-height:24px}
.bk-ans-toggle:hover{color:var(--accent)}
.bk-ans-toggle .ic{transform:rotate(-90deg);transition:transform .18s}
.bk-ans-toggle.open .ic{transform:rotate(0deg)}
.bk-card-answer{font-family:monospace;font-size:12px;color:var(--text2);padding:4px 16px 6px;border-top:1px solid var(--border)}
/* 시험지 구성은 command header가 sole visible primary owner다. */
#bk-view-bank #bk-exam-builder-btn{display:none}
.bk-command-actions #bk-exam-builder-btn{display:inline-flex}
@media(max-width:1280px){
  /* 좁은 화면: 은행 리스트 풀폭 복귀, 빌더는 슬라이드인 + A4 1단 컴팩트 */
  .bk-main-area{flex:1 1 auto;width:auto}
  .bk-builder{position:fixed;top:0;right:0;height:100vh;max-height:100vh;width:min(440px,94vw);z-index:200;transform:translateX(100%);transition:transform .25s cubic-bezier(.4,0,.2,1);box-shadow:-12px 0 40px rgba(26,32,53,.18)}
  .bk-builder.open{transform:translateX(0)}
  .bk-preview-wrap{padding:12px}
  #bk-builder-close{display:flex}
  .bk-command-actions #bk-exam-builder-btn{display:inline-flex}
  /* 좁은 슬라이드인: 페이지를 축소(2단 유지) — 1단 재배치 금지(V8 §4.4).
     zoom 은 레이아웃 박스까지 축소해 가로 오버플로/음수마진 보정이 불필요(Chromium 지원). */
  .bk-pv-page{zoom:.55}
}

/* 모바일 필터 토글 + 오버레이 백드롭 (데스크톱 기본 숨김) */
.bk-filter-toggle{display:none;align-items:center;gap:6px;padding:7px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);font-size:13px;font-weight:600;color:var(--text);cursor:pointer}
.bk-overlay-backdrop{display:none;position:fixed;inset:0;background:rgba(26,32,53,.32);z-index:225}
.bk-overlay-backdrop.open{display:block}

/* ── 모바일(≤768px): 필터 드로어 + 44px 터치 타깃 + 본문 확대 ── */
@media(max-width:768px){
  .bk-filter-panel{position:fixed;left:0;top:0;height:100vh;width:min(290px,86vw);z-index:230;transform:translateX(-100%);transition:transform .25s cubic-bezier(.4,0,.2,1);box-shadow:12px 0 40px rgba(26,32,53,.18)}
  .bk-filter-panel.open{transform:none}
  .bk-filter-toggle{display:inline-flex}
  .bk-chip{padding:10px 14px;min-height:44px;display:inline-flex;align-items:center}
  .bk-icon-btn{width:44px;height:44px}
  .bk-card-fav-btn{opacity:1}
  .bk-tab{padding:13px 14px}
  .bk-filter-input,.bk-sort-select,.bk-search-bar input,.bk-search-bar select{min-height:44px;font-size:15px}
  /* 빌더 입력칸도 같은 44px 터치 타깃. .sm 컴팩트 변형까지 함께 올린다(선택자 특이도 동률 → 뒤에 오는 이 규칙이 이긴다). */
  .bk-input,.bk-input.sm,.bk-builder-title{min-height:var(--control-touch);font-size:var(--type-body)}
  /* 정렬 버튼도 44px 터치 타깃. 줄은 라벨을 위로 올려 버튼이 폭을 다 쓰게 한다. */
  .bk-sortbar{flex-direction:column;align-items:stretch;gap:6px}
  .bk-sort-btn{min-height:44px;padding:8px 12px;font-size:13px}
  .bk-card-content{font-size:15px}
  .bk-detail-close{width:44px;height:44px}
  .bk-detail-add{min-height:42px}
  .bk-build-rm,.bk-build-toggle{min-width:38px;min-height:38px}
  /* 카드/상세 텍스트 토글도 44px 터치 정책 유지(데스크톱 24px → 모바일 44px) */
  .bk-preview-btn,.bk-ans-toggle,.bk-sol-toggle{min-height:44px}
  .bk-main-area{padding:12px}
}

/* 문제 은행 탭 */
.bk-tabs{display:flex;flex:none;gap:4px;margin-bottom:12px;border-bottom:1px solid var(--border);padding-bottom:0;position:relative;z-index:2}
.bk-tab{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border:none;background:none;cursor:pointer;font-size:13px;font-weight:600;color:var(--text3);border-bottom:2px solid transparent;margin-bottom:-1px;transition:.2s;position:relative;z-index:2}
.bk-tab:hover{color:var(--text)}
.bk-tab.active{color:var(--pri);border-bottom-color:var(--pri)}
/* Compact modes own their local tabs: the target row stays scrollable rather than widening the document. */
html[data-shell-mode="tablet-portrait"] #panel-bank,
html[data-shell-mode="mobile-portrait"] #panel-bank,
html[data-shell-mode="mobile-landscape"] #panel-bank,
html[data-shell-mode="tablet-portrait"] .bk-layout,
html[data-shell-mode="mobile-portrait"] .bk-layout,
html[data-shell-mode="mobile-landscape"] .bk-layout,
html[data-shell-mode="tablet-portrait"] .bk-main-area,
html[data-shell-mode="mobile-portrait"] .bk-main-area,
html[data-shell-mode="mobile-landscape"] .bk-main-area{box-sizing:border-box;min-width:0;max-width:100%;overflow-x:hidden}
html[data-shell-mode="tablet-portrait"] #panel-bank,
html[data-shell-mode="mobile-portrait"] #panel-bank,
html[data-shell-mode="mobile-landscape"] #panel-bank,
html[data-shell-mode="tablet-portrait"] .bk-layout,
html[data-shell-mode="mobile-portrait"] .bk-layout,
html[data-shell-mode="mobile-landscape"] .bk-layout{width:100%}
html[data-shell-mode="tablet-portrait"] .bk-main-area,
html[data-shell-mode="mobile-portrait"] .bk-main-area,
html[data-shell-mode="mobile-landscape"] .bk-main-area{width:100%;flex:1 1 100%;flex-basis:100%}
html[data-shell-mode="tablet-portrait"] .bk-tabs,
html[data-shell-mode="mobile-portrait"] .bk-tabs,
html[data-shell-mode="mobile-landscape"] .bk-tabs{display:flex;min-width:0;max-width:100%;height:45px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;-webkit-overflow-scrolling:touch;position:relative;z-index:3}
html[data-shell-mode="tablet-portrait"] .bk-tab,
html[data-shell-mode="mobile-portrait"] .bk-tab,
html[data-shell-mode="mobile-landscape"] .bk-tab{display:inline-flex !important;flex:none;min-width:44px;min-height:44px;padding:10px 14px;pointer-events:auto !important}
/* 좁은 폭에서도 업로드 2종은 아이콘 한 쌍이다 — 폭을 다 먹던 옛 전폭 그리드 대신
   44px 터치 타깃만 보장한다(이름은 툴팁·aria-label 이 든다). */
html[data-shell-mode="tablet-portrait"] .bk-upload-cluster,
html[data-shell-mode="mobile-portrait"] .bk-upload-cluster,
html[data-shell-mode="mobile-landscape"] .bk-upload-cluster{max-width:100%;min-width:0;overflow:visible}
html[data-shell-mode="tablet-portrait"] .bk-icon-action,
html[data-shell-mode="mobile-portrait"] .bk-icon-action,
html[data-shell-mode="mobile-landscape"] .bk-icon-action,
html[data-shell-mode="tablet-portrait"] .bk-tpl-btn,
html[data-shell-mode="mobile-portrait"] .bk-tpl-btn,
html[data-shell-mode="mobile-landscape"] .bk-tpl-btn{min-width:44px;min-height:44px;justify-content:center;white-space:normal;overflow-wrap:anywhere}
html[data-shell-mode="tablet-portrait"] .bk-search-bar,
html[data-shell-mode="mobile-portrait"] .bk-search-bar,
html[data-shell-mode="mobile-landscape"] .bk-search-bar{min-width:0;flex-wrap:wrap}
html[data-shell-mode="tablet-portrait"] .bk-search-bar input,
html[data-shell-mode="tablet-portrait"] .bk-search-bar select,
html[data-shell-mode="mobile-portrait"] .bk-search-bar input,
html[data-shell-mode="mobile-portrait"] .bk-search-bar select,
html[data-shell-mode="mobile-landscape"] .bk-search-bar input,
html[data-shell-mode="mobile-landscape"] .bk-search-bar select{flex:1 1 100%;min-width:0}
/* Touch input semantics own target size independently of width-derived shell mode.
   Mobile shells retain the same contract even on hybrid/unknown pointer devices. */
html[data-input="touch"] #panel-bank button:not(:disabled),
html[data-input="touch"] #panel-bank input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(:disabled),
html[data-input="touch"] #panel-bank select:not(:disabled),
html[data-input="touch"] #panel-bank textarea:not(:disabled),
html[data-input="touch"] #panel-bank a[href],
html[data-input="touch"] #panel-bank [role="button"]:not([aria-disabled="true"]),
html[data-input="touch"] #panel-bank [tabindex]:not([tabindex="-1"]):not([aria-disabled="true"]),
html[data-shell-mode="tablet-portrait"] #panel-bank button:not(:disabled),
html[data-shell-mode="tablet-portrait"] #panel-bank input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(:disabled),
html[data-shell-mode="tablet-portrait"] #panel-bank select:not(:disabled),
html[data-shell-mode="tablet-portrait"] #panel-bank textarea:not(:disabled),
html[data-shell-mode="tablet-portrait"] #panel-bank a[href],
html[data-shell-mode="tablet-portrait"] #panel-bank [role="button"]:not([aria-disabled="true"]),
html[data-shell-mode="tablet-portrait"] #panel-bank [tabindex]:not([tabindex="-1"]):not([aria-disabled="true"]),
html[data-shell-mode="mobile-portrait"] #panel-bank button:not(:disabled),
html[data-shell-mode="mobile-portrait"] #panel-bank input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(:disabled),
html[data-shell-mode="mobile-portrait"] #panel-bank select:not(:disabled),
html[data-shell-mode="mobile-portrait"] #panel-bank textarea:not(:disabled),
html[data-shell-mode="mobile-portrait"] #panel-bank a[href],
html[data-shell-mode="mobile-portrait"] #panel-bank [role="button"]:not([aria-disabled="true"]),
html[data-shell-mode="mobile-portrait"] #panel-bank [tabindex]:not([tabindex="-1"]):not([aria-disabled="true"]),
html[data-shell-mode="mobile-landscape"] #panel-bank button:not(:disabled),
html[data-shell-mode="mobile-landscape"] #panel-bank input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not(:disabled),
html[data-shell-mode="mobile-landscape"] #panel-bank select:not(:disabled),
html[data-shell-mode="mobile-landscape"] #panel-bank textarea:not(:disabled),
html[data-shell-mode="mobile-landscape"] #panel-bank a[href],
html[data-shell-mode="mobile-landscape"] #panel-bank [role="button"]:not([aria-disabled="true"]),
html[data-shell-mode="mobile-landscape"] #panel-bank [tabindex]:not([tabindex="-1"]):not([aria-disabled="true"]){box-sizing:border-box;min-width:45px;min-height:45px}
html[data-input="touch"] #panel-bank label:has(>input[type="checkbox"]:not(:disabled)),
html[data-input="touch"] #panel-bank label:has(>input[type="radio"]:not(:disabled)),
html[data-shell-mode="tablet-portrait"] #panel-bank label:has(>input[type="checkbox"]:not(:disabled)),
html[data-shell-mode="tablet-portrait"] #panel-bank label:has(>input[type="radio"]:not(:disabled)),
html[data-shell-mode="mobile-portrait"] #panel-bank label:has(>input[type="checkbox"]:not(:disabled)),
html[data-shell-mode="mobile-portrait"] #panel-bank label:has(>input[type="radio"]:not(:disabled)),
html[data-shell-mode="mobile-landscape"] #panel-bank label:has(>input[type="checkbox"]:not(:disabled)),
html[data-shell-mode="mobile-landscape"] #panel-bank label:has(>input[type="radio"]:not(:disabled)){box-sizing:border-box;display:inline-flex;align-items:center;min-width:45px;min-height:45px}

/* 문제은행: HWPX 임포트 검수 */
#bk-view-review,.bk-imp-summary,.bk-imp-fail,.bk-imp-card,.bk-imp-form,.bk-imp-form>label{box-sizing:border-box;min-width:0;max-width:100%}
.bk-imp-summary{display:flex;align-items:center;gap:10px;padding:12px 16px;margin-bottom:12px;overflow-wrap:anywhere}
.bk-imp-summary .btn{margin-left:auto}
.bk-imp-warn-txt{color:var(--legacy-warn-2);font-weight:600}
/* 파싱 실패 = 오류다. 좌측 강조 바 대신 danger 계열 배경·글자색으로 읽히게 한다
   (이 화면은 legacy 색 경로 — a_plus 색 인벤토리가 토큰을 고정한다). */
.bk-imp-fail{background:var(--legacy-bad-bg);color:var(--legacy-bad);border-radius:var(--radius-sm);padding:10px 14px;margin-bottom:8px;font-size:13px;overflow-wrap:anywhere}
.bk-imp-card{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,280px);gap:16px;padding:16px;margin-bottom:12px}
.bk-imp-card .bk-imp-preview{min-width:0;max-width:100%;overflow-x:auto;overflow-wrap:anywhere}
.bk-imp-warn{background:var(--legacy-warn-bg);border-radius:3px}
.bk-imp-form{display:flex;flex-direction:column;gap:8px}
.bk-imp-form .field,.bk-imp-form .segmented,.bk-imp-form>.btn{box-sizing:border-box;min-width:0;max-width:100%}
.bk-imp-lbl{font-size:12px;font-weight:600;color:var(--text3);display:block;margin-bottom:2px;overflow-wrap:anywhere}
/* 검수 카드 선지: ①~⑤ 마커를 직접 렌더(list-style 제거) */
.bk-imp-choices{list-style:none;margin:6px 0 0;padding-left:0;font-size:14px;display:flex;flex-direction:column;gap:2px}
.bk-imp-choices li{display:flex;align-items:baseline;gap:6px}
.bk-imp-choices .bk-choicebody p{margin:.2em 0}
/* 검수 카드 그림 + 너비 슬라이더(25~100%) */
.bk-imp-figcell{margin-top:8px}
.bk-imp-figsize{display:flex;align-items:center;gap:8px;margin-top:4px;font-size:12px;color:var(--text3)}
.bk-imp-figsize input[type=range]{flex:1;min-width:90px;max-width:220px;accent-color:var(--accent);cursor:pointer}
.bk-imp-figsize-val{color:var(--text2);font-variant-numeric:tabular-nums;min-width:38px;text-align:right}
@media (max-width:900px){.bk-imp-card{grid-template-columns:minmax(0,1fr)}}
/* 모바일: 슬라이더 손가락 조작 여유 + 접기 버튼 44px 터치 타깃 */
@media (max-width:768px){
  .bk-imp-figsize input[type=range]{height:32px;max-width:none}
  .bk-preview-toggle{min-height:44px;padding:6px 12px}
}

/* ── SVG 아이콘 정렬/동작 (.ic.sm 공유 클래스 사용) ── */
/* .bk-ic 제거 — tools/bank.js가 .ic.sm 사용으로 이전됨 */
.bk-build-toggle .ic{transition:transform .15s}
.bk-build-toggle.open .ic{transform:rotate(180deg)}
.bk-empty-icon .ic{opacity:.4}
.bk-filter-reset,.bk-detail-add,.bk-builder-foot .btn-primary{display:inline-flex;align-items:center;justify-content:center;gap:6px}

/* 기출 검색 바 */
.bk-search-bar{display:flex;gap:8px;margin-bottom:12px;align-items:center}

/* ── 제공사별 설정 패널 ── */
/* ── 통합 API 키 입력 ── */
.unikey-box {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 14px 16px;
  margin-bottom: 14px;
}
.unikey-box .field { margin-top: 4px; }
.unikey-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  margin: 8px 0 0;
  min-height: 16px;
}
.unikey-status.ok  { color: var(--legacy-good); font-weight: 600; }
.unikey-status.err { color: var(--legacy-bad); }
.unikey-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.unikey-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 6px 3px 10px;
  border-radius: var(--radius-pill);
}
.unikey-chip button {
  border: none;
  background: rgba(0,0,0,.08);
  color: inherit;
  font-size: 13px;
  line-height: 1;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
}
.unikey-chip button:hover { background: rgba(0,0,0,.18); }
.prov-advanced { margin-bottom: 12px; }
.prov-advanced > summary {
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
  padding: 6px 0;
  list-style: revert;
  user-select: none;
}
.prov-advanced > summary:hover { color: var(--pri); }
.prov-advanced[open] > summary { margin-bottom: 10px; }

.prov-section {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 14px 16px;
  margin-bottom: 12px;
  transition: border-color .2s;
}
.prov-section.prov-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(30,38,56,.1);
}
.prov-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.prov-badge {
  font-size: 12px;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
}
.prov-claude,.prov-gpt,.prov-gemini{
  background:var(--surface-2);color:var(--ink-2);border:1px solid var(--line)
}
.prov-active-badge {
  font-size: var(--type-label);
  color: var(--pri);
  font-weight: 600;
}
.model-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.model-row .settings-key-label {
  width: 64px;
  flex-shrink: 0;
  font-size: var(--type-label);
}
.model-row .model-select {
  flex: 1;
  min-height: var(--control-standard);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-control);
  background: var(--surface);
  box-shadow: var(--shadow-control);
  font-size: 12px;
  padding: 5px 8px;
}
/* ── 모델 품질바 (settings API 키 섹션) ── */
.qbar{display:inline-flex;gap:2px;vertical-align:middle;flex-shrink:0;margin-left:4px}
.qbar i{width:5px;height:12px;border-radius:1px;background:var(--surface-2);font-style:normal}
.qbar i.on{background:var(--legacy-qbar)}
/* vcard 안 unikey-box: 점선 테두리로 mockup 정렬 */
.apikey-card .unikey-box{border-style:dashed}

/* ━━━ 로그인 / 사용자 ━━━ */
.user-chip{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--text);background:var(--bg);border:1px solid var(--border);border-radius:999px;padding:4px 10px 4px 4px;min-width:0}
/* .user-chip b(사용자명)는 이미 max-width:96px+ellipsis지만, flex 아이템 자체의 min-width:auto
   floor(연쇄) 때문에 헤더 오버플로에 마지막으로 기여하던 지점 — 위 min-width:0으로 해제 */
.user-chip b{font-weight:700;white-space:nowrap;max-width:96px;overflow:hidden;text-overflow:ellipsis;display:inline-block;vertical-align:middle}
.user-avatar{width:26px;height:26px;border-radius:50%;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  background:var(--accent);color:var(--accent-ink);font-size:12px;font-weight:700;overflow:hidden;text-transform:uppercase}
.user-avatar img{width:100%;height:100%;object-fit:cover;display:block}
.user-logout{border:0;background:transparent;color:var(--ink-2);cursor:pointer;font-size:12px;padding:0 0 0 6px;border-left:1px solid var(--border);margin-left:2px;white-space:nowrap;display:inline-flex;align-items:center;gap:4px;text-decoration:none}
.user-logout .ic.sm{width:15px;height:15px;flex:none}
.user-logout:hover{color:var(--danger)}
.mv-annc-empty{padding:22px 8px;text-align:center;color:var(--text-muted);font-size:13.5px}

.auth-screen{position:fixed;inset:0;z-index:var(--z-auth);display:flex;align-items:center;justify-content:center;background:var(--bg);padding:20px}
.auth-card{width:100%;max-width:360px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);padding:32px 28px;box-shadow:0 18px 50px rgba(30,38,56,.12)}
.auth-brand{font-size:22px;font-weight:800;color:var(--text);letter-spacing:-.02em;margin-bottom:6px}
.auth-tagline{font-size:15px;font-weight:600;color:var(--text);letter-spacing:-.01em;margin:0 0 4px}
.auth-sub{font-size:13px;color:#5f6980;line-height:1.6;margin-bottom:22px;word-break:keep-all}  /* 흰 카드 위 대비 AA(5.5:1) */
.auth-label{display:block;font-size:12px;font-weight:600;color:var(--label);margin:12px 0 5px}
.auth-input{width:100%;height:auto;min-height:var(--control-touch);padding:0 12px;border:1px solid var(--control-border);border-radius:var(--radius-control);font-size:var(--type-body);color:var(--text);background:var(--surface);box-shadow:var(--shadow-control);outline:none}
.auth-input:focus-visible{border-color:var(--accent);outline:2px solid var(--accent);outline-offset:1px}
.auth-input:focus{border-color:var(--accent)}
/* 생년월일 년/월/일 분리 select — 캘린더(date picker) 대체 */
.birth-row{display:flex;gap:8px}
.birth-row select{flex:1;min-width:0;padding-left:10px;padding-right:6px}
/* 생년월일 커스텀 스크롤 드롭다운 (데스크탑 전용 — birth-select.js가 씌움). 모바일은 네이티브 유지. */
.mv-bsel{position:relative;flex:1;min-width:0}
.mv-bsel > select{position:absolute;width:1px;height:1px;margin:-1px;padding:0;opacity:0;pointer-events:none;overflow:hidden}
.mv-bsel-btn{display:flex;align-items:center;text-align:left;cursor:pointer;font-family:inherit;
  -webkit-appearance:none;appearance:none;padding-right:30px;position:relative}
.mv-bsel-btn.is-placeholder{color:var(--text-muted)}
.mv-bsel-btn::after{content:"";position:absolute;right:12px;top:50%;width:7px;height:7px;
  border-right:1.5px solid var(--text-muted);border-bottom:1.5px solid var(--text-muted);
  transform:translateY(-70%) rotate(45deg);pointer-events:none;transition:transform .15s}
.mv-bsel.is-open .mv-bsel-btn::after{transform:translateY(-20%) rotate(225deg)}
.mv-bsel-panel{display:none;position:absolute;z-index:60;top:calc(100% + 4px);left:0;right:0;
  max-height:240px;overflow-y:auto;background:var(--surface);border:1.5px solid var(--border);
  border-radius:var(--radius-sm);box-shadow:var(--shadow-lg);padding:4px}
.mv-bsel.is-open .mv-bsel-panel{display:block}
.mv-bsel-opt{padding:8px 10px;border-radius:var(--radius-sm);font-size:14px;color:var(--text);cursor:pointer;white-space:nowrap}
.mv-bsel-opt:hover{background:rgba(30,38,56,.06)}
.mv-bsel-opt.is-sel{background:var(--accent);color:var(--accent-ink)}
.mv-bsel-opt.is-sel:hover{background:var(--accent)}
.auth-error{margin-top:12px;font-size:12.5px;color:var(--danger);background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.25);border-radius:var(--radius-sm);padding:8px 10px}
.auth-submit{width:100%;height:auto;min-height:var(--control-touch);margin-top:18px;font-size:14px;font-weight:700}
.auth-switch{margin-top:16px;text-align:center;font-size:13px;color:var(--text-muted)}
.auth-switch-btn{border:0;background:transparent;color:var(--accent);font-weight:700;cursor:pointer;font-size:13px}
.auth-switch-btn:hover{text-decoration:underline}

/* 소셜 로그인 (OAuth) 버튼 — index.html / lms/login.html 공통 */
.auth-oauth-sep{display:flex;align-items:center;gap:.6rem;margin:18px 0 12px;color:var(--text-muted);font-size:12px}
.auth-oauth-sep::before,.auth-oauth-sep::after{content:"";flex:1;height:1px;background:var(--border)}
.auth-oauth-wrap{display:flex;flex-direction:column;gap:9px}
.auth-oauth-btn{display:flex;align-items:center;justify-content:center;gap:9px;height:auto;min-height:var(--control-touch);padding-block:10px;border-radius:var(--radius-sm);text-decoration:none;font-weight:700;font-size:14px;transition:filter .15s;border:1px solid transparent}
.auth-oauth-btn:hover{filter:brightness(.96)}
.auth-oauth-btn svg{width:18px;height:18px;flex:none}
.auth-oauth-kakao{background:#fee500;color:#191919}
.auth-oauth-google{background:#fff;color:#3c4043;border-color:#dadce0}
.auth-oauth-hint{font-size:var(--type-meta);color:var(--ink-2);text-align:center;margin-top:9px}
.auth-legal-foot{font-size:12px;text-align:center;margin-top:14px}
.auth-legal-foot a{color:var(--ink-2);text-decoration:none}
.auth-legal-foot a:hover{text-decoration:underline}

/* 계정 / 프로필 설정 */
.profile-box{margin-top:18px;padding-top:16px;border-top:1px solid var(--border)}
.profile-h{font-size:14px;font-weight:800;color:var(--text);margin:0 0 12px}
.profile-top{display:flex;align-items:center;gap:14px;margin-bottom:12px}
.profile-avatar{width:64px;height:64px;border-radius:50%;background:var(--accent);color:var(--accent-ink);display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:800;overflow:hidden;flex:none}
.profile-avatar img{width:100%;height:100%;object-fit:cover}
.profile-top-r{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.profile-meta{font-size:12.5px;color:var(--text-muted);margin:10px 0 14px;line-height:1.7}
.profile-meta b{color:var(--text);font-weight:600}
.profile-msg{font-size:12.5px;margin-left:10px}
.profile-msg.ok{color:var(--good)}
.profile-msg.err{color:var(--bad)}
#settings-profile .field{margin-top:6px}

/* 개인정보 동의 (회원가입) */
.auth-consent{margin-top:14px}
.auth-notice{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px 12px;font-size:var(--type-meta);color:var(--text-muted);line-height:1.55}
.auth-notice b{color:var(--text)}
.auth-notice ul{margin:6px 0 0;padding-left:16px}
.auth-notice li{margin:2px 0}
.auth-check{display:flex;align-items:flex-start;gap:7px;margin-top:10px;font-size:12.5px;color:var(--text);cursor:pointer;line-height:1.4}
.auth-check input{margin-top:2px;width:15px;height:15px;flex:0 0 auto;accent-color:var(--accent)}
.auth-remember{display:flex;gap:16px;margin-top:12px}
.auth-remember .auth-check{margin-top:0;font-size:12px;color:var(--ink-2)}
.auth-age{display:flex;gap:16px;margin-top:10px}
.auth-age .auth-check{margin-top:0}
.auth-guardian{margin-top:10px;padding-top:10px;border-top:1px dashed var(--border)}
.auth-guardian .auth-input{margin-top:8px}
.auth-foot{margin-top:14px;text-align:center;font-size:var(--type-label);color:var(--text-muted)}
.auth-foot a{color:var(--text-muted);text-decoration:underline;cursor:pointer}

/* 설정: 위험 영역(회원 탈퇴) */
.settings-danger{margin-top:20px;padding-top:16px;border-top:1px solid var(--border)}
.settings-danger .btn-danger{background:transparent;color:var(--danger);border:1px solid var(--bad-line)}
.settings-danger .btn-danger:hover{background:var(--bad-bg)}
.settings-danger p{font-size:var(--type-meta);color:var(--text-muted);margin-top:8px;line-height:1.5}

/* ── LMS 클래스 패널 (Phase B → 재디자인) ── */
/* .cls-card/.cls-title/.cls-code 는 [data-rd] 스코프로 이동(app.css ~1289) */
.cls-h2{font-size:14px;margin:22px 0 12px;color:var(--text);padding-bottom:8px;border-bottom:1px solid var(--line-2)}
.cls-box{border:1px solid var(--border);border-radius:var(--radius,14px);padding:16px 18px;background:var(--surface)}
/* 클래스 시험 해설의 markdown 그림만 카드 폭에 맞춘다. 문제지 카드의 다른 그림에는 적용하지 않는다. */
.cls-solution-markdown img{max-width:100%;height:auto;display:block;margin:8px 0}
.cls-box .cls-h2{margin-top:0}
/* 섹션 카드 수직 리듬 — 탭 패널(강사)·상세 직속(학생)에서 .cls-box끼리 마진 0으로 맞닿아 쌓이던 밀집 해소 */
.cls-tab-panel > .cls-box + .cls-box{margin-top:18px}
#cls-detail > .cls-box{margin-top:18px}
/* 인라인 폼 공용 디스클로저 (CL-5) */
.disc-toggle{margin:10px 0 2px}
.disc-body{margin-top:10px;padding:14px;border-top:1px solid var(--line);background:var(--surface-2,var(--surface));border-radius:0 0 10px 10px}
.form-stack{display:flex;flex-direction:column;gap:10px}
.form-field{margin-bottom:0}
.form-label{display:block;font-size:12.5px;color:var(--ink-2);margin-bottom:4px}
.form-acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:2px}
.form-acts .btn{min-height:44px}
.cls-code-input{flex:1;text-transform:uppercase;letter-spacing:.12em;font-variant-numeric:tabular-nums}
.cls-msg{font-size:12.5px;margin:6px 0 12px;min-height:16px;line-height:1.55;color:var(--text-muted)}
.cls-msg.ok{color:var(--good);font-weight:600}
.cls-msg.err{color:var(--bad)}
.cls-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}
.cls-empty{font-size:13px;color:var(--ink-2);padding:10px 2px}
/* 빈 섹션 병합: 데이터 없는 섹션 박스는 숨기고, 전부 비면 병합 카드 1개만 노출 */
.cls-box-empty{display:none}
.cls-empty-merged{display:flex;flex-direction:column;align-items:center;text-align:center;gap:10px;padding:34px 20px}
.cls-empty-merged-ic{color:var(--ink-4)}
.cls-empty-merged-ic svg{width:40px;height:40px}
.cls-empty-merged-txt{margin:0;font-size:14px;color:var(--ink-2);line-height:1.5}
/* 빈 상태 온보딩 카드(강사 첫 랜딩·학생 미입장): dashed 카드 + 라인 SVG + CTA */
.cls-empty-card{grid-column:1/-1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:12px;
  border:1.5px dashed var(--border-dash);border-radius:var(--radius-lg);padding:34px 20px;background:var(--surface)}
.cls-empty-card .ic{width:38px;height:38px;color:var(--ink-4)}
.cls-empty-title{margin:0;font-size:14px;color:var(--ink-2);max-width:340px;line-height:1.5}
.cls-desc{font-size:12.5px;color:var(--text-muted);margin-top:2px}
.cls-actions{display:flex;gap:8px;margin-top:0}
.cls-mini{font-size:12px;padding:4px 10px;border-radius:8px;border:1px solid var(--border);background:transparent;color:var(--text);cursor:pointer}
.cls-mini:hover{border-color:var(--accent)}
/* 강사 상세 4탭 (CL-6) */
.cls-tabs { display: flex; gap: 2px; padding: 3px; background: var(--surface-2); border: 1px solid var(--control-border); border-radius: var(--radius-card); margin: 4px 0 16px; }
.cls-tab { appearance: none; min-height: var(--control-standard); padding: 10px 14px; background: transparent;
  border: 1px solid transparent; border-radius: var(--radius-control); font-size: 14px; color: var(--ink-2); cursor: pointer; }
.cls-tab.active { background: var(--surface); color: var(--ink); border-color: var(--control-border); box-shadow: var(--shadow-control); font-weight: 700; }
@media (max-width: 900px) {
  /* 5탭(수행평가 포함)이 균등분할로 안 들어가 줄바꿈되던 것 → 탭바 내부 가로 스크롤 */
  /* 스크롤이 된다는 사실을 가장자리 그늘로 알린다. 탭이 열둘이 된 뒤(출석 추가)
     768 에서 설정·수행평가가 화면 밖에 앉는데, 표시가 없으면 그 탭이 없는 것처럼
     보인다. background-attachment 를 섞어 쓰는 고전 기법이라 스크립트가 필요 없고,
     양 끝에 닿으면 그늘이 저절로 사라진다. */
  .cls-tabs { gap: 0; overflow-x: auto; -webkit-overflow-scrolling: touch;
    background-image:
      linear-gradient(to right, var(--surface-2), transparent 24px),
      linear-gradient(to left, var(--surface-2), transparent 24px),
      linear-gradient(to right, var(--border), transparent 12px),
      linear-gradient(to left, var(--border), transparent 12px);
    background-repeat: no-repeat;
    background-size: 32px 100%, 32px 100%, 12px 100%, 12px 100%;
    background-position: left center, right center, left center, right center;
    background-attachment: local, local, scroll, scroll; }
  .cls-tab { flex: 0 0 auto; white-space: nowrap; padding: 10px 12px; min-height: var(--control-touch); }
}
/* ── LMS 클래스 상세·플레이어·대시보드 (Phase C+D) ── */
.cls-mini.cls-primary{color:var(--accent);border-color:var(--accent)}
.cls-detail-head{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.cls-detail-title{font-size:19px;margin:0}
.cls-lec-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,420px),1fr));gap:12px;margin-top:10px}
.cls-lec-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  border:1px solid var(--border);border-radius:10px;padding:15px 16px;background:var(--surface)}
.cls-lec-main{display:flex;align-items:center;gap:10px;min-width:0}
/* 번호 폭이 내용대로라 행마다 제목 시작점이 지그재그였음 → 고정 최소폭+우측정렬 */
.cls-lec-no{color:var(--text-muted);font-size:13px;flex:0 0 auto;
  min-width:24px;text-align:right;font-variant-numeric:tabular-nums}
.cls-lec-title{font-weight:600;font-size:14px}
.cls-lec-unit{font-size:12px;color:var(--text-muted);margin-top:4px}
.cls-lec-acts{display:flex;gap:5px;flex:0 0 auto}
.cls-lec-badge{font-size:12px;color:var(--text-muted);flex:0 0 auto}
.cls-lec-badge.done{color:var(--good);font-weight:700}
.cls-lec-badge.part{color:var(--warn-2);font-weight:600}
.cls-dash{margin-top:10px;overflow-x:auto}
.cls-dash-table{border-collapse:collapse;font-size:12.5px;min-width:100%}
.cls-dash-table th,.cls-dash-table td{border:1px solid var(--border);padding:6px 9px;text-align:center;white-space:nowrap}
.cls-dash-table th{background:var(--surface-2);font-weight:600}
.cls-dash-name{text-align:left!important;font-weight:600}
.cls-cell-done{color:var(--good);font-weight:700}
.cls-cell-part{color:var(--warn-2)}
.cls-cell-done .ic,.cls-cell-part .ic{width:13px;height:13px;vertical-align:-2px}
/* 인라인 상태 마크(채점 결과·극복 표시 ✓/✗ → 라인 SVG) */
.mk{display:inline-flex;vertical-align:-2px}
.mk .ic{width:14px;height:14px}
.lec-thumb{width:80px;height:45px;object-fit:cover;border-radius:4px;flex-shrink:0}
.cls-cell-none{color:var(--border)}
.cls-player-ov{position:fixed;inset:0;background:rgba(0,0,0,.72);z-index:var(--z-player);display:flex;align-items:center;justify-content:center;padding:20px}
.cls-player-box{background:#000;border-radius:12px;overflow:hidden;width:min(960px,100%);max-height:92vh;display:flex;flex-direction:column}
.cls-player-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 14px;background:#111}
.cls-player-title{color:#fff;font-size:14px;font-weight:600}
/* 플레이어 머리의 질문하기. 제목은 왼쪽, 질문하기와 닫기는 오른쪽에 붙는다. */
.cls-player-ask{margin-left:auto;background:transparent;border:1px solid rgba(255,255,255,.4);border-radius:var(--radius-pill);color:#fff;font-size:12.5px;line-height:1;padding:6px 10px;cursor:pointer;white-space:nowrap}
.cls-player-ask:hover{background:rgba(255,255,255,.12)}
.cls-player-close{position:relative;background:transparent;border:0;color:#fff;font-size:18px;cursor:pointer;line-height:1;padding:2px 6px;display:inline-flex;align-items:center;justify-content:center}
/* 터치 히트존 44px — 시각 크기는 유지하고 투명 오버레이만 확장(클릭은 버튼으로 귀속) */
.cls-player-close::after{content:'';position:absolute;left:50%;top:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
/* 16:9 비율 박스 — padding-top 방식. aspect-ratio는 flex 컨테이너 안에서(특히
   데스크탑 목차 레이아웃의 flex:1 mount) 초기 높이를 0으로 계산해 '영상이 안 뜨고
   줌해야 보이는' 버그를 유발하므로 쓰지 않는다. */
.cls-player-mount{position:relative;width:100%;background:#000;overflow:hidden}
.cls-player-mount::before{content:"";display:block;padding-top:56.25%}
/* iframe 상하 크롭: 유튜브는 16:9 영상을 세로로 큰 iframe에 레터박스로 그리고 제목(상단)·로고(하단)는
   iframe 가장자리에 붙인다 → 가장자리 90px씩을 mount 밖으로 밀어 마크만 잘라낸다(영상 픽셀 손실 0). */
.cls-player-mount iframe{position:absolute;left:0;top:-90px;width:100%;height:calc(100% + 180px);border:0}
.cls-pc-catch{position:absolute;inset:0;z-index:1;cursor:pointer}
/* 베일: 시작 전/종료/큐 화면의 유튜브 마크·관련영상 벽을 불투명하게 덮는다(full).
   일시정지는 원인 무관 clear(투명, 정지 프레임 그대로) — 블러는 전면 폐기(지석 2026-08-09). */
.cls-pc-veil{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;background:rgba(8,12,22,.97);cursor:pointer;opacity:0;visibility:hidden;transition:opacity .4s,visibility 0s .4s}
.cls-pc-veil.on{opacity:1;visibility:visible;transition:opacity .15s,visibility 0s}
/* 로딩 커버: iframe 로드~onReady 사이 유튜브 첫 화면 차단(불투명 — 뒤에 보여줄 게 없음) */
.cls-pc-preveil{position:absolute;inset:0;z-index:1;background:#0b0e15}
.cls-pc-veil .ic{width:64px;height:64px;color:#fff;opacity:.85;filter:drop-shadow(0 2px 10px rgba(0,0,0,.5))}
/* 일시정지 필기 모드: clear=정지 프레임 그대로(무표시). 딤(reveal) 단계도 블러도 폐기(유튜브 패리티, 지석 2026-08-09) — 정지 중 표시는 컨트롤 바가 전담 */
.cls-pc-veil.on.cls-pc-veil-clear{transition:opacity .15s,visibility 0s;background:transparent}
.cls-pc-veil.on.cls-pc-veil-clear .ic{opacity:0}
/* 컨트롤 크롬: 딱딱한 검정 띠 대신 네이비 잉크 그라디언트 페이드(영상 하단에 자연스럽게 녹음). */
.cls-pc{position:absolute;left:0;right:0;bottom:0;z-index:2;padding:26px 14px 12px;display:flex;flex-direction:column;gap:9px;background:linear-gradient(to top,rgba(9,12,20,.92) 0%,rgba(9,12,20,.52) 58%,rgba(9,12,20,0) 100%);transition:opacity .25s;opacity:1}
.cls-wm{position:absolute;z-index:1;color:#fff;opacity:.13;font-size:13px;letter-spacing:.4px;white-space:nowrap;pointer-events:none;user-select:none;text-shadow:0 0 2px rgba(0,0,0,.6);transition:left 1.2s ease,top 1.2s ease}
/* 강사 브랜딩 마크: 우상단 고정·또렷. 추적용 학생 워터마크(.cls-wm)와 별개, 정지 베일(z1) 위에도 보이게 z2 */
.cls-brandmark{position:absolute;top:10px;right:12px;z-index:2;color:#fff;opacity:.55;font-size:13px;font-weight:600;letter-spacing:.06em;pointer-events:none;user-select:none;text-shadow:0 1px 3px rgba(0,0,0,.5)}
/* 자료 뷰어(흰 문서) 변형: 잉크색 저투명 대각선 — 흰 글자+그림자는 밝은 PDF 위에서 얼룩처럼 보임(유출 억지 기능은 유지) */
.cls-wm-doc{color:#1f2637;opacity:.11;text-shadow:none;font-size:17px;font-weight:700;letter-spacing:.22em;transform:translate(-50%,-50%) rotate(-22deg)}
.cls-pc.cls-pc-hidden{opacity:0;pointer-events:none}
.cls-pc-nocursor{cursor:none}
.cls-pc-seek{position:relative;height:6px;background:rgba(255,255,255,.22);border-radius:99px;cursor:pointer;transition:height .12s}
.cls-pc-seek:hover,.cls-pc-seek.cls-pc-seek-preview{height:8px}
/* 시크바는 얇은 시각 높이 유지 + 투명 세로 히트존(≈24px). 위로 확장해 아래 컨트롤 행과 겹치지 않게(가로 폭 불변 → seekToClientX의 rect.width/left 계산 영향 없음) */
.cls-pc-seek::before{content:'';position:absolute;left:0;right:0;top:-13px;bottom:-6px}
.cls-pc-seek-fill{position:absolute;left:0;top:0;bottom:0;width:0;background:#fff;border-radius:99px}
/* 핸들: 평소 작은 점, hover/프리뷰 시 풀사이즈(유튜브식). 터치는 hover 없어 작은 점 상시 — 위치 파악엔 충분 */
.cls-pc-seek-handle{position:absolute;top:50%;left:0;width:13px;height:13px;margin-left:-6.5px;border-radius:50%;background:#fff;transform:translateY(-50%) scale(.5);transition:transform .12s;box-shadow:0 1px 4px rgba(0,0,0,.55)}
.cls-pc-seek:hover .cls-pc-seek-handle,.cls-pc-seek.cls-pc-seek-preview .cls-pc-seek-handle{transform:translateY(-50%) scale(1)}
/* hover 시간 프리뷰 툴팁 — 시크바 위에 커서 시각의 재생시간 표시 */
.cls-pc-seek-tip{position:absolute;bottom:calc(100% + 9px);left:0;transform:translateX(-50%);background:rgba(9,12,20,.96);color:#fff;font-size:var(--type-label);font-variant-numeric:tabular-nums;padding:3px 7px;border-radius:6px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;box-shadow:0 2px 8px rgba(0,0,0,.4)}
.cls-pc-seek.cls-pc-seek-preview .cls-pc-seek-tip{opacity:1}
.cls-pc-row{display:flex;align-items:center;gap:10px}
.cls-pc-spacer{flex:1}
.cls-pc-right{display:flex;align-items:center;gap:10px}
.cls-pc-btn{position:relative;background:transparent;border:0;color:#fff;font-size:15px;line-height:1;cursor:pointer;padding:4px 6px;transition:transform .12s,opacity .12s}
.cls-pc-btn:hover{transform:scale(1.12)}
.cls-pc-btn svg{display:block}
/* 터치 히트존 44px — 아이콘 시각 크기 유지, 투명 오버레이만 확장 */
.cls-pc-btn::after{content:'';position:absolute;left:50%;top:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
/* 재생/일시정지 = 주 액션. 채움 아이콘(.ic fill:none 되돌림) + 다른 버튼보다 크게 강조 */
.cls-pc-play .ic{fill:currentColor;stroke:none;width:23px;height:23px}
/* 중앙 재생/정지 버튼: 터치 전용(유튜브 모바일 패리티). 컨트롤 바와 생명주기 동일 — 바가 숨으면 함께
   사라진다(형제 선택자는 DOM 순서상 불가해 JS가 cls-pc-hidden을 함께 토글). .cls-pc-btn 뒤에 두어야
   position·padding·transition이 덮이지 않는다(같은 명시도는 뒤가 이긴다). */
.cls-pc-big{display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2;width:64px;height:64px;border-radius:50%;background:rgba(8,12,22,.55);align-items:center;justify-content:center;padding:0;transition:opacity .25s}
/* 바 재생버튼과 동일한 채움 아이콘(.ic 기본은 선 아이콘 — 주 액션은 채움으로 통일) */
.cls-pc-big svg,.cls-pc-big .ic{width:32px;height:32px;fill:currentColor;stroke:none}
/* iOS는 탭에도 :hover가 붙는다 — .cls-pc-btn:hover의 scale이 중앙 정렬 transform을 지우지 않게 고정 */
.cls-pc-big:hover{transform:translate(-50%,-50%)}
.cls-pc-big.cls-pc-hidden{opacity:0;pointer-events:none}
@media (hover:none){.cls-pc-big{display:flex}}
/* 중앙 버튼은 재생 중에만: 정지·종료·버퍼링에선 유튜브 자체 중앙 UI가 유일한 아이콘이 되게 숨긴다 */
.cls-pc-big.cls-pc-big-idle{display:none}
/* 더블탭 스킵 피드백: 해당 구간에 원형 리플 + 초 표시(400ms 후 자동 제거) */
.cls-pc-ripple{position:absolute;top:50%;transform:translateY(-50%);z-index:2;width:120px;height:120px;border-radius:50%;background:rgba(255,255,255,.16);color:#fff;font-size:14px;font-weight:600;display:flex;align-items:center;justify-content:center;pointer-events:none;animation:cls-pc-ripple-fade .4s ease-out forwards}
.cls-pc-ripple-l{left:6%}
.cls-pc-ripple-r{right:6%}
@keyframes cls-pc-ripple-fade{from{opacity:1;transform:translateY(-50%) scale(.7)}to{opacity:0;transform:translateY(-50%) scale(1.15)}}
/* 프레임 이동 버튼: 터치 전용(키보드가 없는 기기의 ,/. 대체 수단) + 정지 상태에서만 노출.
   데스크톱은 유튜브 데스크톱과 동일하게 미표시 — ,/. 단축키가 같은 일을 한다(스펙 F). */
.cls-pc-frame{display:none}
@media (hover:none){.cls-pc-paused .cls-pc-frame{display:inline-flex}}
.cls-pc-time{color:#fff;font-size:12px;font-variant-numeric:tabular-nums;white-space:nowrap}
/* 배속: 볼륨 왼쪽에 칩 5개(1x~2x) 상시 노출 — 활성 칩=흰 채움(다크 팔레트) */
.cls-pc-speeds{display:flex;align-items:center;gap:3px;flex-wrap:wrap}
.cls-pc-chip{position:relative;background:rgba(255,255,255,.14);border:0;color:#fff;font-size:var(--type-label);min-width:34px;padding:3px 6px;border-radius:5px;cursor:pointer;transition:background .12s}
.cls-pc-chip:hover{background:rgba(255,255,255,.28)}
.cls-pc-chip.on{background:#fff;color:#000;font-weight:700}
@media (prefers-reduced-motion:reduce){
  .cls-pc-seek,.cls-pc-seek-handle,.cls-pc-seek-tip,.cls-pc-btn,.cls-pc-chip{transition:none}
  /* 리플은 transition 이 아니라 animation 이라 위 규칙이 못 잡는다. JS 가 400ms 뒤 제거하므로
     꺼도 잔상이 남지 않고, 스킵량("+5초") 표시는 그대로 전달된다. */
  .cls-pc-ripple{animation:none}
}
/* 투명 히트존: 세로만 44px로 확장(가로는 칩폭 유지 → 인접 칩과 겹치지 않음) */
.cls-pc-chip::after{content:'';position:absolute;left:0;right:0;top:50%;height:44px;transform:translateY(-50%)}
.cls-pc-vol{position:relative;display:flex;align-items:center}
/* 세로 볼륨 팝업: 버튼 위로 뜨는 absolute 박스 안에 슬라이더를 -90도 회전해 세로로.
   흐름에서 빠져 컨트롤 행 폭을 먹지 않음 → 모바일에서 바가 아래로 늘어나지 않음. */
.cls-pc-vol-pop{position:absolute;left:50%;bottom:100%;transform:translateX(-50%);margin-bottom:8px;width:34px;height:108px;background:rgba(20,20,20,.92);border-radius:8px;opacity:0;pointer-events:none;transition:opacity .15s}
/* 노출은 데스크톱 hover 한정(지석 2026-08-03): 터치는 아이콘 탭이 음소거 토글이라 슬라이더를 열
   경로가 없는데, hover 가드가 없으면 모바일의 sticky :hover가 탭 후에 팝업을 띄워 되살아난다. */
@media (hover:hover){.cls-pc-vol:hover .cls-pc-vol-pop{opacity:1;pointer-events:auto}}
/* 버튼↔팝업 사이 8px 틈을 투명 브리지로 메워 마우스를 슬라이더로 옮길 때 hover가 끊겨 사라지지 않게 */
.cls-pc-vol-pop::after{content:'';position:absolute;top:100%;left:0;right:0;height:10px}
/* 슬라이더(90px)를 팝업 중앙에 절대배치 후 회전 — grid place-items로는 회전된 range가 ~28px 우측으로 어긋나 박스 밖 seam으로 삐져나왔음 */
.cls-pc-vol-slider{position:absolute;left:50%;top:50%;width:90px;transform:translate(-50%,-50%) rotate(-90deg);accent-color:#fff;cursor:pointer}
/* 배속: 협폭(≤900px)=단일 버튼+세로 팝업, 광폭=기존 칩(아래 미디어쿼리가 전환. DOM은 둘 다 상주) */
.cls-pc-spd{position:relative;display:none;align-items:center}
/* 버튼은 칩과 같은 시각 크기로 작게, 탭 영역은 ::after 44px로 유지(.cls-player-close와 동일 패턴) */
.cls-pc-spd-btn{position:relative;background:rgba(255,255,255,.16);border:0;color:#fff;font-size:var(--type-label);font-weight:700;min-width:36px;padding:3px 8px;border-radius:6px;cursor:pointer}
.cls-pc-spd-btn::after{content:'';position:absolute;left:50%;top:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
.cls-pc-spd-pop{position:absolute;right:0;bottom:100%;margin-bottom:8px;background:rgba(20,20,20,.92);border-radius:8px;padding:5px;display:flex;flex-direction:column;gap:2px;min-width:74px;max-height:200px;overflow-y:auto;opacity:0;pointer-events:none;transition:opacity .15s}
.cls-pc-spd.cls-pc-spd-open .cls-pc-spd-pop{opacity:1;pointer-events:auto}
.cls-pc-spd-item{background:none;border:0;color:#fff;font-size:13.5px;padding:9px 12px;border-radius:7px;cursor:pointer;min-height:40px}
.cls-pc-spd-item.on{background:#fff;color:#10131b;font-weight:700}
@media(max-width:900px){.cls-pc-spd{display:flex}.cls-pc-speeds{display:none}}
@media (max-width:560px){
  .cls-pc{padding:4px 8px 8px;gap:5px}
  .cls-pc-row{gap:6px;flex-wrap:wrap}
  .cls-pc-time{font-size:var(--type-label)}
  .cls-pc-chip{min-width:30px;font-size:var(--type-label);padding:2px 5px}
  /* row wrap이 밀도를 흡수하므로 스크롤 컨테이너를 만들지 않는다(44px 히트존 클리핑 방지) */
  .cls-pc-speeds{flex:1 1 auto;flex-wrap:wrap}
}

/* ── 수행평가 도우미 강사 열람(as-t-*) ── */
.as-t-list{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}
.as-t-view{display:flex;flex-direction:column;gap:10px;margin-top:12px}
.as-t-msg{border-radius:var(--radius,14px);padding:10px 14px}
.as-t-msg strong{display:block;font-size:12px;color:var(--ink-2);margin-bottom:4px}
.as-t-msg.user{background:var(--surface-2)}
.as-t-msg.assistant{background:var(--surface);border:1px solid var(--line)}

/* ── 토스트 알림 + 초대/카톡 ── */
#toast-host{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:var(--z-toast);display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{background:#222;color:#fff;font-size:13px;padding:10px 16px;border-radius:10px;box-shadow:0 4px 16px rgba(0,0,0,.3);opacity:0;transform:translateY(10px);transition:opacity .25s,transform .25s;max-width:90vw;text-align:center}
.toast.show{opacity:1;transform:translateY(0)}
.toast.err{background:#b3261e}
/* 카톡 공유 심볼: 브랜드 노랑을 말풍선 심볼 면적으로만 한정(셸은 .btn.btn-outline.btn-sm). */
.ic-kakao{flex:0 0 auto}
/* ⋯ 오버플로 메뉴 (D): 파괴·저빈도 동작 수납 */
.ovf-wrap{position:relative;display:inline-flex}
.ovf-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;padding:4px 8px}
.ovf-btn .ic{width:16px;height:16px}
/* 아이콘 버튼(24×32) → 44px+ 투명 히트존 (Task 12 .diff-dots .dot::after 패턴) */
.ovf-btn::after{content:"";position:absolute;inset:-10px}
.ovf-menu{position:absolute;right:0;top:calc(100% + 4px);z-index:60;min-width:120px;
  background:var(--surface);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shadow-lg);padding:4px}
/* 위로 펼침(액션바 ⋯): 아래 탭바 라벨을 덮지 않도록 제목줄 우측 여백으로 개방 (N-1) */
.ovf-menu-up{top:auto;bottom:calc(100% + 4px)}
.ovf-item{display:block;width:100%;text-align:left;padding:10px 12px;min-height:44px;
  border:none;background:none;color:var(--text);font-size:13.5px;border-radius:6px;cursor:pointer}
.ovf-item:hover{background:var(--surface-2)}
.ovf-item.danger{color:var(--danger)}
.ovf-item:disabled{opacity:.5;cursor:default}

/* 플레이어 오류 폴백 */
.cls-player-err{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;height:100%;color:#fff;text-align:center;padding:24px}
.cls-player-err p{font-size:14px;margin:0;line-height:1.6}

/* ━━ 인강 학생 강의 목록 (재설계) ━━ */
.lec-summary{background:var(--accent);color:var(--accent-ink);border-radius:var(--radius-lg);padding:20px 22px;margin-bottom:18px}
.lec-summary-top{display:flex;align-items:baseline;gap:14px}
.lec-summary-stat{font-size:40px;font-weight:800;line-height:1;letter-spacing:-.02em}
.lec-summary-meta{display:flex;flex-direction:column;gap:2px}
.lec-summary-label{font-size:13px;color:rgba(255,255,255,.7)}
.lec-summary-pct{font-size:14px;font-weight:600}
.lec-bar{height:6px;background:var(--border);border-radius:99px;overflow:hidden}
.lec-bar-lg{height:8px;background:rgba(255,255,255,.18);margin-top:16px}
.lec-bar-fill{height:100%;border-radius:99px;transition:width .4s ease}
/* 블랙: .lec-summary(bg accent)가 밝은 면으로 반전 → 자식 rgba 흰 글자/트랙을
   accent-ink(#131316)의 rgb=19,19,22 로 알파 보존 오버라이드 */
:root[data-theme="black"] .lec-summary-label{color:rgba(19,19,22,.7)}
:root[data-theme="black"] .lec-bar-lg{background:rgba(19,19,22,.18)}
.lec-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,420px),1fr));gap:10px;margin-top:10px}
.lec-row{display:flex;align-items:center;gap:14px;min-width:0;background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:14px 16px;cursor:pointer;transition:border-color .15s,box-shadow .15s,transform .1s}
.lec-row:hover{border-color:var(--accent);box-shadow:var(--shadow-low);transform:translateY(-1px)}
.lec-idx{flex:0 0 auto;width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;border:1.5px solid var(--border);color:var(--text-muted);background:var(--bg)}
.lec-idx.active{border-color:var(--accent);color:var(--accent)}
.lec-idx.done{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-size:16px}
.lec-body{flex:1;min-width:0}
.lec-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.lec-title{font-weight:700;font-size:14.5px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lec-status{flex:0 0 auto;font-size:12px;font-weight:600;color:var(--text-muted)}
.lec-status.done{color:var(--ok)}
.lec-status.part{color:var(--warn)}
.lec-barwrap{display:flex;align-items:center;gap:10px;margin-top:9px}
.lec-barwrap .lec-bar{flex:1}
.lec-pct{flex:0 0 auto;font-size:var(--type-label);font-weight:700;color:var(--text-muted);font-variant-numeric:tabular-nums;width:34px;text-align:right}
.lec-play{flex:0 0 auto;width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--text-muted);background:var(--bg);transition:background .15s,color .15s}
.lec-play svg{width:18px;height:18px;margin-left:1px}
.lec-row:hover .lec-play{background:var(--accent);color:var(--accent-ink)}
/* 학생 강의: 좌 목록 ↔ 우 상세 2열 */
.lec-split{display:grid;grid-template-columns:1fr 320px;gap:18px;align-items:start;margin-top:6px}
/* grid-row:1 필수 — DOM은 .lec-right가 먼저라, 행 미지정 시 sparse 자동 배치 커서가 col2를 지난 뒤여서 .lec-left(col1)가 2행으로 밀려 좌상단이 비는 버그 */
.lec-left{grid-column:1;grid-row:1;min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);padding:16px 18px}
/* 좌측 강의 목록을 카드로 → 우측 요약 카드와 상단 정렬(위 정렬) */
.lec-left .cls-h2{margin-top:0}
/* DOM 순서=히어로(.lec-right) 먼저 → SR/Tab 위계 정상. 데스크탑 2열 시각 배치는 grid-column/grid-row 명시로 좌·우 고정 */
.lec-right{grid-column:2;grid-row:1;position:sticky;top:8px;display:flex;flex-direction:column;gap:14px}
.lec-list-1col{grid-template-columns:1fr}
.lec-row{cursor:pointer}
.lec-row-sel{border-color:var(--selection-outline);background:var(--surface)}
.lec-detail-card{border:1px solid var(--border);border-radius:var(--radius-lg);padding:18px;background:var(--surface)}
.lec-dc-no{font-size:12px;font-weight:700;color:var(--text-muted);font-variant-numeric:tabular-nums}
.lec-dc-title{font-size:16px;font-weight:700;margin:4px 0 2px;color:var(--text);line-height:1.4}
.lec-dc-unit{font-size:12.5px;color:var(--text-muted);margin-bottom:12px}
.lec-dc-status{font-size:12.5px;font-weight:600;color:var(--text-muted);margin-top:8px}
.lec-dc-status.done{color:var(--ok)}
.lec-dc-status.part{color:var(--warn)}
.lec-dc-play{width:100%;margin-top:14px;justify-content:center}
.lec-sec-head{margin:14px 2px 2px;font-size:12.5px;font-weight:700;color:var(--text-muted);letter-spacing:.02em}
.lec-list .lec-sec-head:first-child{margin-top:2px}
.lec-meta{font-size:12px;color:var(--text-muted);margin-top:3px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 모바일: 단일 컬럼 → grid-column 해제 시 DOM 순서(히어로 먼저)가 자연 흐름으로 노출(정보 위계) */
@media(max-width:900px){.lec-split{grid-template-columns:1fr}.lec-left,.lec-right{grid-column:auto;grid-row:auto}.lec-right{position:static}}
/* 모바일 강의 행: 썸네일·인덱스·재생버튼(고정폭)+gap이 좁은 화면에서 .lec-body를
   거의 다 잠식해 .lec-meta(강의시간·최종학습일·교재)가 몇 px만 남아 잘리던 문제.
   장식 요소(썸네일) 폭을 줄이고 메타는 줄바꿈 허용으로 전환해 항상 전체 텍스트가 보이게 함. */
@media(max-width:600px){
  .lec-row{gap:8px;padding:10px 12px}
  .lec-row .lec-thumb{display:none}
  .lec-idx{width:30px;height:30px;font-size:var(--type-label)}
  .lec-play{width:32px;height:32px}
  .lec-meta{white-space:normal;overflow:visible;text-overflow:clip}
}

/* ── 목차 편집기 모달 오버레이 + 헤더 ── */
.lec-modal-ov{position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:calc(var(--z-overlay) - 1);overflow:auto}
.lec-modal-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 16px;border-bottom:1px solid var(--border);flex:0 0 auto;background:var(--surface)}
.lec-modal-x{background:transparent;border:0;cursor:pointer;color:var(--text-muted);width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:6px;padding:0}
.lec-modal-x:hover{background:var(--bg);color:var(--text)}
.lec-modal-x svg{width:16px;height:16px}

/* ── 목차 편집기 내부 레이아웃 ── */
.chap-editor{position:fixed;inset:0;margin:auto;width:min(960px,94vw);height:min(640px,92vh);background:var(--surface);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);z-index:var(--z-overlay);display:flex;flex-direction:column;overflow:hidden}
.chap-split{display:grid;grid-template-columns:1fr 360px;gap:0;flex:1;min-height:0}
.chap-left{background:#000;display:flex;align-items:center;justify-content:center}
.chap-left>div,.chap-left iframe{width:100%;aspect-ratio:16/9}
.chap-right{display:flex;flex-direction:column;gap:10px;padding:14px;overflow-y:auto;border-left:1px solid var(--border)}
.chap-tools{display:flex;flex-direction:column;gap:8px}
.chap-manual{display:flex;gap:6px}
.chap-tin{width:80px;flex:0 0 auto;padding:6px 8px;border:1px solid var(--border);border-radius:8px;font-variant-numeric:tabular-nums}
.chap-ttlin{flex:1;min-width:0;padding:6px 8px;border:1px solid var(--border);border-radius:8px}
.chap-bulk{width:100%;min-height:56px;resize:vertical;padding:8px;border:1px solid var(--border);border-radius:8px;font-size:13px}
.chap-ai-note{font-size:12.5px;color:var(--ink-2);margin:6px 0 2px}
.chap-list{display:flex;flex-direction:column;gap:6px;flex:1;min-height:0}
.chap-row{display:flex;gap:6px;align-items:center}
.chap-del{position:relative;flex:0 0 auto;width:28px;height:28px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text-muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
/* 터치 히트존 44px — 삭제 버튼 시각 크기(28px) 유지 */
.chap-del::after{content:'';position:absolute;left:50%;top:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
.chap-empty{color:var(--text-muted);font-size:13px;text-align:center;padding:20px}
.chap-save{margin-top:auto}
@media(max-width:768px){.chap-editor{width:auto;height:100vh;border-radius:0}.chap-split{grid-template-columns:1fr;grid-template-rows:auto 1fr}.chap-right{border-left:none;border-top:1px solid var(--border)}}
/* width:100vw 대신 auto — inset:0(위 기본 규칙)만으로 fixed 요소가 뷰포트 폭에 스트레치되며,
   100vw는 스크롤바 유무와 무관해 세로 스크롤바가 있으면 그만큼 우측으로 넘친다(가로 오버플로) */

/* ── 강의 수정 모달(lec-modal-ov 셸의 축소판, S-1) ── */
.lec-edit-box{position:fixed;inset:0;margin:auto;width:min(440px,94vw);height:max-content;max-height:92vh;background:var(--surface);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);z-index:var(--z-overlay);display:flex;flex-direction:column;overflow:hidden}
.lec-edit-body{padding:16px;overflow-y:auto}

/* --- 학생 도구 권한 스위치 --- */
.perm-row{display:flex;align-items:center;justify-content:space-between;padding:15px 2px;border-top:1px solid var(--border);font-size:14px;color:var(--text)}
.perm-row.locked{opacity:.6}
.perm-sw{
  width:42px;height:24px;box-sizing:border-box;
  -webkit-appearance:none;appearance:none;
  background:var(--border-dash);border:1px solid var(--control-border);
  border-radius:var(--radius-pill);position:relative;cursor:pointer;transition:.15s;flex:none
}
.perm-sw:checked{background:var(--accent);border-color:var(--accent)}
.perm-sw::after{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:var(--surface);box-shadow:var(--shadow-control);transition:.15s}
.perm-sw:checked::after{left:21px}

/* ── 클래스 상세: 요약 타일 (학생·강의·평균진도·입장코드) ── */
.cls-summary{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:2px 0 4px}
@media (max-width:560px){.cls-summary{grid-template-columns:repeat(2,1fr)}}
.cls-tile{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:12px 13px;display:flex;flex-direction:column;gap:3px}
.cls-tile-top{display:flex;align-items:center;gap:6px;color:var(--text-muted)}
.cls-tile-top .ic{width:15px;height:15px;flex:none}
.cls-tile-lbl{font-size:var(--type-meta);font-weight:600}
.cls-tile-val{font-family:var(--display);font-size:22px;font-weight:800;letter-spacing:-.01em;
  line-height:1.15;font-variant-numeric:tabular-nums;color:var(--text);word-break:keep-all;overflow-wrap:anywhere}
.cls-tile-val small{font-size:13px;font-weight:600;color:var(--text-muted)}
.cls-tile-strip{height:5px;border-radius:999px;background:var(--line-2);overflow:hidden;margin-top:5px}
.cls-tile-strip>i{display:block;height:100%;border-radius:999px;transition:width .3s}
.cls-tile-btn{cursor:pointer;transition:border-color .15s,background .15s}
.cls-tile-btn:hover{border-color:var(--accent)}
.cls-tile-btn:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}

/* ── 클래스 설정 탭: 권한 그룹 카드 ── */
.cls-scard{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow-card);overflow:hidden;margin-top:16px}
.cls-scard-h{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line-2)}
.cls-scard-badge{width:32px;height:32px;border-radius:8px;background:var(--accent-soft);color:var(--accent);
  display:grid;place-items:center;flex:none}
.cls-scard-badge .ic{width:19px;height:19px}
.cls-scard-htx{min-width:0}
.cls-scard-htx h3{font-family:var(--display);font-size:15px;font-weight:800;margin:0;color:var(--text)}
.cls-scard-htx p{font-size:12px;color:var(--text-muted);margin:2px 0 0}
.cls-scard-body{padding:4px 16px 14px}
.cls-scard-body>.cls-msg{margin:6px 0 0}
/* 클래스 삭제 카드 — 되돌릴 수 없는 동작이라 danger 토큰을 쓰되 강조 바는 두지 않는다 */
.cls-scard-danger{border-color:var(--bad-line)}
.cls-scard-badge-danger{background:var(--bad-bg);color:var(--danger)}
.cls-del-warn{font-size:12.5px;line-height:1.6;color:var(--text-muted);margin:10px 0 12px}
.cls-del-openwrap{display:flex}
.cls-del-openwrap[hidden]{display:none}
.cls-del-open{min-height:40px}
.cls-del-confirm{margin-top:2px;padding-top:12px;border-top:1px solid var(--line-2)}
.cls-del-confirm[hidden]{display:none}
.cls-del-guide{font-size:12.5px;color:var(--text);margin:0 0 8px;line-height:1.6}
.cls-del-name{font-weight:700;font-size:13px;color:var(--text);margin:0 0 8px;padding:8px 10px;
  border-radius:8px;background:var(--surface-2,var(--surface));border:1px solid var(--line-2);
  overflow-wrap:anywhere;word-break:break-word}
.cls-del-input{width:100%;box-sizing:border-box}
.cls-del-confirm .form-acts{margin-top:10px}
@media (max-width:520px){
  .cls-del-openwrap .btn,
  .cls-del-confirm .form-acts .btn{flex:1 1 auto;min-width:0}
}
.perm-grp{font-size:var(--type-label);font-weight:700;letter-spacing:.05em;color:var(--ink-4);margin:0 0 2px;
  padding-top:12px;margin-top:10px;border-top:1px solid var(--line-2)}
.perm-grp:first-child{border-top:none;padding-top:6px;margin-top:2px}
.perm-row2{display:flex;align-items:center;gap:12px;padding:11px 8px;margin:0;cursor:pointer;border-radius:10px}
.perm-row2+.perm-row2{border-top:1px solid var(--line-2)}
.perm-row2.locked{opacity:.72;cursor:default}
.perm-row2-col{flex-direction:column;align-items:stretch;gap:10px;cursor:default}
.perm-row2-main{display:flex;align-items:center;gap:12px}
.perm-ico{width:34px;height:34px;border-radius:8px;background:var(--surface-3);border:1px solid var(--line-2);
  color:var(--ink-2);display:grid;place-items:center;flex:none}
.perm-ico .ic{width:17px;height:17px}
.perm-tx{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.perm-tx b{font-size:13.5px;font-weight:600;color:var(--text)}
.perm-tx i{font-size:var(--type-meta);font-style:normal;color:var(--text-muted);line-height:1.4;margin-top:1px}
.perm-lockpill{font-size:var(--type-label);font-weight:700;color:var(--ink-2);background:var(--surface-3);
  border:1px solid var(--border);border-radius:999px;padding:4px 9px;display:inline-flex;gap:4px;
  align-items:center;flex:none;white-space:nowrap}
.perm-lockpill .ic.sm{width:12px;height:12px}
.perm-row2-col .perm-seg{align-self:flex-start;margin-left:46px}
@media (max-width:560px){.perm-row2-col .perm-seg{margin-left:0}}

/* ── 과제 (S4 Assignment UI) ── */
.asgn-viewbar{display:flex;gap:6px;margin-bottom:8px}
.asgn-viewbar .cls-mini.on{background:var(--accent);color:var(--accent-ink)}
.asgn-list,.practice-list{display:flex;flex-direction:column;gap:10px;margin-top:14px}
.asgn-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;width:100%;
  border:1px solid var(--border);border-radius:10px;padding:13px 16px;background:var(--surface);
  color:inherit;font:inherit;text-align:left}
.asgn-row-clickable{cursor:pointer;transition:border-color .15s,background .15s}
.asgn-row.is-expanded{border-color:var(--selection-outline);border-radius:var(--radius-card) var(--radius-card) 0 0}
.asgn-row.is-expanded + .asgn-dash,
.asgn-row.is-expanded + .asgn-solve{border-top:0;border-radius:0 0 var(--radius-card) var(--radius-card)}
.asgn-row-clickable:hover{border-color:var(--accent);background:var(--accent-tint)}
.asgn-info{flex:1;min-width:0}
.asgn-title{font-weight:600;font-size:14px;color:var(--text)}
.asgn-meta{font-size:12px;color:var(--text-muted);margin-top:4px}
.asgn-kind,.acal-kind{display:inline-flex;align-items:center;gap:4px;flex:none;color:var(--text-muted);font-size:var(--type-label);font-weight:700;white-space:nowrap}
.assignment-kind-line,.practice-kind-line{display:inline-block;width:12px;height:0;border-top:2px solid currentColor;flex:none}
.practice-kind-line{border-top-style:dashed}
.asgn-row-state{display:flex;flex:0 0 auto;flex-direction:column;align-items:flex-end;gap:5px;min-width:112px}
.asgn-data-metric{display:inline-flex;flex-direction:column;gap:3px;min-width:96px;max-width:160px}
.asgn-data-value{color:var(--text);font-size:var(--type-meta);font-weight:600;font-variant-numeric:tabular-nums;text-align:right}
.asgn-data-track{display:block;width:100%;height:4px;border-radius:999px;background:var(--surface-2);overflow:hidden}
.asgn-progress-fill,.asgn-score-bar,.asgn-correctness-bar{display:block;height:100%;border-radius:inherit;background:var(--data)}
.asgn-scheduled-meta,.acal-scheduled-meta{color:var(--text-muted)}
/* 수정 모달: 제출물 있는 과제의 문제·배점 잠금 안내 */
.asgn-edit-lock{margin:2px 0 4px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--bg);color:var(--text-muted);font-size:13px}
/* 숨긴 과제 목록 */
.asgn-archived-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.asgn-archived-list .asgn-del{color:var(--danger);border-color:var(--danger)}

/* 마감 임박 요약 스트립(우측 컬럼 맨아래·모바일에서 히어로 근처)
   조용한 카드 1장: 위험색은 D-day 칩에만(면적 최소), 지시문 카피 없음 */
.lec-due-strip{display:flex;flex-direction:column;gap:8px}
.lec-due-item{display:flex;align-items:center;gap:10px;width:100%;text-align:left;min-height:44px;
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:10px 12px;
  background:var(--surface);font-size:13.5px;cursor:pointer;
  transition:border-color .15s, background .15s}
.lec-due-item:hover{border-color:var(--accent);background:var(--surface-2,var(--surface))}
.lec-due-item .ic{flex:0 0 auto;color:var(--ink-2)}
.lec-due-text{min-width:0;flex:1;color:var(--text);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lec-due-dday{flex:0 0 auto}
@media (min-width: 901px){.lec-due-strip{display:none}}
/* Dashboard panel */
.asgn-dash{border:1px solid var(--border);border-top:none;border-radius:0 0 10px 10px;
  padding:14px 16px;background:var(--bg);display:flex;flex-direction:column;gap:10px}
.asgn-dash-stat{font-size:13.5px;font-weight:600;color:var(--text)}
.asgn-dash-pp{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
.asgn-pp-chip{font-size:12px;padding:4px 10px;border:1px solid var(--border);border-radius:var(--radius-pill);
  background:var(--surface);color:var(--ink-2)}
/* Solve panel */
.asgn-solve{border:1px solid var(--border);border-top:none;border-radius:0 0 10px 10px;
  padding:16px 16px;background:var(--bg);display:flex;flex-direction:column;gap:14px}
.asgn-prob{display:flex;flex-direction:column;gap:6px;padding-bottom:12px;border-bottom:1px solid var(--border)}
.asgn-prob:last-of-type{border-bottom:none}
.asgn-prob-no{font-size:12px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em}
.asgn-prob-content{font-size:14px;line-height:1.7;color:var(--text)}
/* 문항 이미지: 세로 클램프 + 클릭 확대(라이트박스) */
.asgn-prob img{max-height:360px;width:auto;max-width:100%;cursor:zoom-in}
.img-lightbox{position:fixed;inset:0;z-index:var(--z-lightbox);background:rgba(0,0,0,.82);
  display:flex;align-items:center;justify-content:center;cursor:zoom-out;padding:16px}
.img-lightbox img{max-width:94vw;max-height:92vh;object-fit:contain}

/* ── LMS ④: 연습 채점 결과 · 풀이 · 오답 노트 ── */
.asgn-prob-ans{font-size:13px;font-weight:700;color:var(--text)}
.asgn-prob-sol{font-size:13px;line-height:1.7;color:var(--ink-2);background:var(--surface-2);
  border-radius:8px;padding:8px 10px}
/* 해설을 마크다운으로 렌더하면서 공식 해설 그림이 카드 안에 들어온다.
   PC·모바일·패드 공통으로 카드 폭을 넘지 않게 묶는다. */
.asgn-prob-sol img{max-width:100%;height:auto;display:block;margin:6px 0}
.asgn-prob-sol p{margin:0 0 6px}
.asgn-prob-sol p:last-child{margin-bottom:0}
.wn-row{display:flex;align-items:center;gap:10px;padding:9px 4px;border-bottom:1px solid var(--line)}
.wn-row:last-child{border-bottom:none}
.wn-badge{font-size:var(--type-label);font-weight:700;padding:2px 8px;border-radius:var(--radius-pill);white-space:nowrap;flex-shrink:0}
.wn-prac{background:var(--good-bg);color:var(--good)}
.wn-asgn{background:var(--surface-2);color:var(--ink-2)}
.wn-preview{flex:1;min-width:0;font-size:13px;color:var(--ink-2);display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}
.wn-stat{font-size:12px;font-weight:700;color:var(--bad);white-space:nowrap;flex-shrink:0}
.wn-stat.ok{color:var(--good)}
.wn-over .wn-preview{text-decoration:line-through;color:var(--ink-3)}
/* 오답 미리보기는 눌러서 상세를 여는 버튼이다 — 버튼 기본 꾸밈은 지우고 본문처럼 보이게.
   수식(KaTeX)이 들어가므로 2줄까지 보여 준다(1줄이면 수식 한 덩이에 다 먹힌다). */
.wn-preview-btn{-webkit-line-clamp:2;background:none;border:none;padding:0;margin:0;text-align:left;
  font:inherit;font-size:13px;color:var(--ink-2);cursor:pointer}
.wn-preview-btn:hover{color:var(--text);text-decoration:underline}
.wn-preview-btn .katex{font-size:1em}
.wn-detail{max-width:min(680px,94vw)}
.wn-detail-content{font-size:14px;line-height:1.75;color:var(--text);white-space:pre-wrap;word-break:keep-all}
.wn-detail-choice{display:flex;gap:8px;align-items:flex-start;margin-top:6px;font-size:13.5px;color:var(--ink-2)}
.wn-detail-no{flex:none;font-weight:700;color:var(--ink-3)}
/* 오답 원본 재시험지 — 강사 학생상세의 오답 선택 목록(.wn-row 관례 재사용) */
.tsm-wn-row{cursor:pointer;min-height:44px}
.tsm-wn-row:has(input:disabled){cursor:default;opacity:.55}
.tsm-wn-row input{accent-color:var(--accent);flex-shrink:0}
.tsm-wn-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.tsm-wn-why{font-size:var(--type-label);color:var(--ink-3);flex-shrink:0}
.tsm-wn-count{font-size:var(--type-meta);color:var(--ink-3);margin-left:auto}

/* ── LMS ③ 자료실(파일 목록 + 전면 뷰어) ── */
.file-list{margin-top:10px;display:flex;flex-direction:column}
.file-row{display:flex;align-items:center;gap:10px;padding:13px 4px;border-bottom:1px solid var(--line)}
.file-row:last-child{border-bottom:none}
.file-row-clickable{cursor:pointer;border-radius:8px;padding:13px 10px}
.file-row-clickable:hover{background:var(--surface-2)}
.file-info{flex:1;min-width:0}
.file-info-open{padding:0;border:0;background:transparent;text-align:left;font:inherit;color:inherit;cursor:pointer}
.file-info-open:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:4px}
.file-title{font-size:14px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-meta{font-size:12px;color:var(--ink-2);margin-top:4px}
.file-toggles{display:flex;align-items:center;flex-wrap:wrap;justify-content:flex-end;gap:6px 12px}
.file-dl{font-size:12px;color:var(--ink-2);display:inline-flex;align-items:center;gap:4px;white-space:nowrap;cursor:pointer}
.file-dl input:disabled{cursor:wait}
.file-open{font-size:12px;font-weight:700;color:var(--accent);white-space:nowrap}
@media(max-width:560px){
  .file-row-teacher{flex-wrap:wrap;align-items:center}
  .file-row-teacher .file-info{flex:1 1 120px;min-width:44px;min-height:44px;display:flex;flex-direction:column;justify-content:center}
  .file-row-teacher .file-open{order:2}
  .file-row-teacher>.ovf-wrap{order:3}
  .file-row-teacher .file-toggles{order:4;flex:1 0 100%;justify-content:flex-start}
}
.file-viewer-ov{position:fixed;inset:0;z-index:var(--z-viewer);background:rgba(16,22,38,.97);display:flex;flex-direction:column;padding:16px}
.file-viewer-bar{display:flex;align-items:center;gap:10px;padding:6px 4px 12px}
.file-viewer-title{flex:1;min-width:0;color:#fff;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-viewer-stage{position:relative;flex:1;min-height:0;background:var(--surface);border-radius:10px;overflow:hidden;display:flex;align-items:center;justify-content:center}
.file-viewer-frame{width:100%;height:100%;border:0}
.file-viewer-img{max-width:100%;max-height:100%;object-fit:contain}

/* ── UI Modal (네이티브 confirm/prompt 대체) ── */
.ui-modal-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
  padding:16px;z-index:9999;background:rgba(0,0,0,.45)}
.ui-modal{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  max-width:420px;width:100%;padding:24px;display:flex;flex-direction:column;gap:16px;
  box-shadow:0 8px 32px rgba(0,0,0,.18)}
.ui-modal-msg{font-size:15px;color:var(--text);line-height:1.6;white-space:pre-wrap;margin:0}
.ui-modal-label{font-size:13px;font-weight:600;color:var(--label);margin:0}
.ui-modal-actions{display:flex;gap:8px;justify-content:flex-end}

/* ── 과제 문제 은행 Picker ── */
/* 선택 컨트롤 행 */
.asgn-pick-row{display:flex;align-items:center;gap:10px;margin-top:12px}
.asgn-pick-btn{font-size:13px;padding:6px 14px}
.asgn-pick-count{font-size:12px;font-weight:600;color:var(--text-muted)}
/* 선택된 문제 칩 목록 */
.asgn-pick-chips{display:flex;flex-direction:column;gap:4px;margin-top:6px}
.asgn-pick-chip{display:flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg);font-size:12.5px}
.asgn-pick-chip-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.asgn-pick-chip-rm{flex:0 0 auto;background:none;border:none;cursor:pointer;font-size:13px;color:var(--text-muted);padding:0 2px;line-height:1}
.asgn-pick-chip-rm:hover{color:var(--danger)}
/* 피커 모달 오버라이드 */
.asgn-pick-overlay{z-index:var(--z-picker)}
.asgn-pick-modal{max-width:560px;width:100%;padding:0;gap:0;max-height:80vh;display:flex;flex-direction:column;overflow:hidden}
.asgn-pick-header{padding:18px 20px 0;flex:0 0 auto;display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.asgn-pick-title{font-size:16px;font-weight:700;color:var(--text);margin:0}
.asgn-pick-x{position:relative;flex:0 0 auto;margin:-6px -6px 0 0;padding:6px;background:none;border:0;color:var(--text-muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-sm)}
.asgn-pick-x:hover{color:var(--text)}
.asgn-pick-x::after{content:'';position:absolute;left:50%;top:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
.asgn-pick-search{margin:12px 20px 0;width:calc(100% - 40px);display:block;flex:0 0 auto}
.asgn-pick-filters{display:flex;gap:8px;margin:10px 20px 0;flex:0 0 auto}
.asgn-pick-filter-sel{flex:1;min-width:0;min-height:44px}
/* 스크롤 목록 */
.asgn-pick-list{flex:1 1 auto;overflow-y:auto;padding:8px 20px;display:flex;flex-direction:column;gap:2px;min-height:120px}
.asgn-pick-item{display:flex;align-items:flex-start;gap:10px;padding:9px 6px;border-radius:var(--radius-sm);cursor:pointer;transition:background .12s}
.asgn-pick-item:hover{background:var(--accent-tint)}
.asgn-pick-cb{flex:0 0 auto;margin-top:3px;accent-color:var(--accent);width:15px;height:15px;cursor:pointer}
.asgn-pick-item-info{flex:1;min-width:0}
.asgn-pick-badges{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:3px}
.asgn-pick-badge{font-size:var(--type-label);font-weight:600;padding:2px 7px;border-radius:var(--radius-pill);border:1px solid var(--border)}
.asgn-pick-badge-subj{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.asgn-pick-badge-diff{background:var(--bg);color:var(--text-muted);border-color:var(--border-dash)}
.asgn-pick-badge-score{background:var(--surface);color:var(--text);border-color:var(--control-border);font-variant-numeric:tabular-nums}
/* 객관식/주관식 — 임포트 객관식은 본문에 선지가 없어 미리보기로 구분 불가 */
.asgn-pick-badge-form{background:var(--surface-2);color:var(--ink-2);border-color:var(--border)}
.asgn-pick-preview{font-size:12.5px;color:var(--ink-2);line-height:1.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.asgn-pick-spinner{font-size:13px;color:var(--text-muted);padding:12px 0;text-align:center}
.asgn-pick-more{width:100%;margin-top:6px;font-size:13px;color:var(--text-muted);background:none;border:1px dashed var(--border-dash);border-radius:var(--radius-sm)}
.asgn-pick-more:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-tint)}
/* 푸터 */
.asgn-pick-footer{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;padding:12px 20px;border-top:1px solid var(--border);gap:10px}
.asgn-pick-sel-count{font-size:13px;font-weight:600;color:var(--text-muted)}
.asgn-pick-footer-acts{display:flex;gap:8px}
@media (pointer:coarse){
  .asgn-row .cls-mini,
  .asgn-pick-item,
  .asgn-pick-modal input:not([type="checkbox"]),
  .asgn-pick-modal select,
  .asgn-pick-modal button{min-width:44px;min-height:44px}
  .asgn-pick-item{display:flex;align-items:center}
  .asgn-pick-item input[type="checkbox"]{inline-size:20px;block-size:20px;flex:none}
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   공통 유틸 (Task 1 — 모든 패널이 소비)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
/* 토스트 */
.mv-toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,8px);background:var(--accent);color:var(--accent-ink);font-weight:600;font-size:13px;padding:10px 16px;border-radius:10px;box-shadow:var(--shadow-lg);z-index:var(--z-overlay);opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;max-width:90vw}
.mv-toast.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.mv-toast.err{background:var(--bad)}
/* 인라인 필드 에러 */
.field-err{color:var(--bad);font-size:12px;margin-top:4px}
/* 선택 카드 */
.segmented button[aria-checked="true"],
.segmented button[aria-pressed="true"],
[role="tab"][aria-selected="true"],
[aria-expanded="true"].is-expanded,
.lec-row-sel{
  border-color:var(--selection-outline)
}
.card.selected{
  border-color:var(--selection-outline);
  box-shadow:0 0 0 2px var(--selection-outline) inset
}
.card.bk-ps-card.selected{
  border-color:var(--accent);
  box-shadow:0 0 0 2px var(--accent) inset
}
.card-check{position:absolute;top:10px;right:10px;width:20px;height:20px;border-radius:99px;background:var(--accent);color:var(--accent-ink);display:grid;place-items:center}
.card{position:relative}
/* 포커스 접근성 */
.btn:focus-visible,
select:focus-visible,
.field:focus-visible,
[role="button"]:focus-visible,
.segmented button:focus-visible,
.perm-sw:focus-visible,
.home-dashboard-action:focus-visible,
.home-dashboard-class:focus-visible,
.home-dashboard-tool:focus-visible,
.mob-tab-item:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)
}
.card.bk-ps-card.selected:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px var(--accent) inset,0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)
}

#sidebar a:focus-visible,
.shell-rail-group:focus-visible,
.shell-hub-link:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px var(--sidebar-bg),0 0 0 4px var(--focus-on-shell)
}

:root[data-sb="white"] #sidebar a:focus-visible,
:root[data-sb="white"] .shell-rail-group:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)
}
[role="button"]{cursor:pointer}
@media (forced-colors: active){
  :where(#app-header,#tool-nav,.mob-tab,#panel-home,#panel-classes,#panel-asgn,#panel-admdb,.adm-wrap,.mv-map--semantic-six) :where(button,a[href],input,select,textarea,[role="button"],[role="tab"],[tabindex]):focus-visible{
    outline:2px solid Highlight !important;
    outline-offset:2px;
    box-shadow:none !important;
  }
}
/* 빈/로딩 공통 */
.empty-msg{text-align:center;color:var(--ink-2);font-size:13px;padding:28px 12px;display:flex;flex-direction:column;align-items:center;gap:8px}
.empty-msg .ic{width:34px;height:34px;color:var(--ink-4)}

/* ── 시험지 자료 (handouts) ── */
.handout-list{display:flex;flex-direction:column;gap:10px;margin-top:14px}
.handout-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:13px 16px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}
.handout-info{flex:1;min-width:0}
.handout-title{font-weight:600;font-size:14px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.handout-meta{font-size:12px;color:var(--text-muted);margin-top:2px}
.handout-acts{flex:0 0 auto;display:flex;gap:6px}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   Task 3: 모바일 시스템 + 사이드바 2종
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */

/* 설정 패널 — 사이드바 스타일 토글 */
.sb-toggle-section{margin-top:18px;padding-top:14px;border-top:1px solid var(--border)}
.sb-toggle-row{display:flex;align-items:center;gap:16px;margin-top:8px}
.sb-toggle-row label{display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:600;color:var(--ink-2);cursor:pointer}

/* ── 하단 모바일 내비게이션 + 허브 시트 (역할 셸) ── */
:root{--shell-bottom-nav-h:64px;--z-shell-hub:calc(var(--z-overlay) + 10)}
.mob-tab{display:none}
.mob-tab-item{appearance:none;border:0;background:transparent;color:var(--ink-2);text-decoration:none;font-size:var(--type-label);font-weight:600;min-width:44px;min-height:44px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding:4px}
.mob-tab-item[aria-current="page"]{color:var(--accent);font-weight:700;box-shadow:inset 0 2px 0 var(--selection-outline)}
.mob-tab-item[data-current-category="true"]{color:var(--accent);font-weight:700;box-shadow:inset 0 2px 0 var(--selection-outline)}
.mob-tab-item[aria-current="page"]:focus-visible,
.mob-tab-item[data-current-category="true"]:focus-visible{box-shadow:inset 0 2px 0 var(--selection-outline),0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)}
.mob-tab-item .ic{width:21px;height:21px}
#shell-hub-layer{display:none;position:fixed;inset:0;z-index:var(--z-shell-hub)}
#shell-hub-layer.open{display:block}
/* 하단탭 노출(display:grid)·본문 하단 여백은 세로 모드 data-shell-mode 선택자(상단 6단계 셸 블록)가 단일 관리한다. */
.shell-hub-backdrop{position:absolute;inset:0;background:var(--overlay)}
.shell-hub-sheet{position:absolute;left:0;right:0;bottom:0;max-height:min(70dvh,560px);overflow:auto;background:var(--surface);border-radius:var(--radius-overlay) var(--radius-overlay) 0 0;padding:16px 16px calc(16px + env(safe-area-inset-bottom));box-shadow:var(--shadow-high)}
.shell-hub-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.shell-hub-head h2{font-size:var(--type-section)}
.shell-hub-close{width:44px;height:44px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);color:var(--ink);font-size:22px}
.shell-hub-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.shell-hub-link{min-height:52px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);color:var(--ink);text-decoration:none;display:flex;align-items:center;gap:9px;padding:10px 12px;box-shadow:var(--shadow-control)}
.shell-hub-link[aria-current="page"]{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}
/* 같은 덮어쓰기 패턴(.shell-hub-link:focus-visible 과 특정도 동률·소스 후순위) — 현재 위치 바 위에 셸 링을 유지. */
.shell-hub-link[aria-current="page"]:focus-visible{
  outline:none;
  box-shadow:inset 3px 0 0 var(--accent),0 0 0 2px var(--sidebar-bg),0 0 0 4px var(--focus-on-shell)}
@media(prefers-reduced-motion:reduce){.shell-hub-sheet{transition:none}}

/* N제 생성기 고정 생성 버튼(모바일) — 기본 숨김 */
.nset-gen-sticky{display:none}

/* ── 모바일 전용 규칙 ── */
@media(max-width:768px){
  /* 헤더 — 좁은 폭에서 로고와 우측 아이콘이 겹치지 않도록 우측을 최대한 컴팩트하게.
     엔진뱃지·설정텍스트·사용자명 숨기고, 관리자/로그아웃은 아이콘만(텍스트 숨김). */
  .engine-badge{display:none}
  .hdr-set-txt{display:none}
  #user-name{display:none}          /* 아바타가 신원 표시 — 이름 텍스트는 숨겨 폭 확보 */
  .hdr-uc-txt{display:none}         /* 관리자·로그아웃은 아이콘만 */
  .user-chip{padding:4px 6px 4px 4px;gap:4px}
  #app-header{padding:0 12px}      /* 모바일 좌우 여백 축소 — 로고·아이콘 겹침 방지 */
  #header-right{gap:4px}
  #header-right .btn.btn-sm{padding:6px 8px}   /* 종·설정 아이콘 버튼 컴팩트화(폭 확보) */

  /* 하단 내비게이션 클리어런스·탭바 스타일은 위 역할 셸 블록(--shell-bottom-nav-h)에서 단일 관리 */

  /* 컴포넌트 반응형 (목업 [data-view="mobile"] 이식) — h1/h2.disp 는 타입 토큰(data-font 모바일 오버라이드)으로 스케일 */
  .page-h{flex-wrap:wrap;gap:9px;margin-bottom:4px}
  .page-h h1{width:100%}
  .page-h .spacer{display:none}
  .page-h .btn{flex:1 1 0;justify-content:center;min-height:44px}
  .page-h .tag{order:-1}
  .page-sub{font-size:var(--type-meta);margin-bottom:16px}
  .stat{padding:13px 14px}
  .stat .v{font-size:21px}
  .toolbar{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:3px}
  .toolbar .chip{flex:0 0 auto}
  .search{order:-1;flex:1 1 100%}
  .stat-row{grid-template-columns:repeat(2,1fr);gap:10px}
  .grid{grid-template-columns:1fr}
  .two{grid-template-columns:1fr}
  .split{grid-template-columns:1fr}
  /* .tbl-wrap{overflow-x:auto} + .tbl{min-width:560px} → 전역으로 이동 (데스크탑 좁은 창도 스크롤) */
  /* 카드 푸터 버튼 터치타깃 */
  .card .foot .btn.btn-sm{min-height:44px}

  /* N제 생성기 반응형 */
  .nset-gen-inline{display:none}
  .nset-gen-sticky{
    display:flex;
    position:fixed;
    left:0;right:0;bottom:62px;
    padding:10px 16px;
    background:linear-gradient(180deg,rgba(255,255,255,0),#fff 28%);
    z-index:6
  }
  /* 블랙: 흰 페이드가 다크 배경 위 흰 띠로 보임 → --bg(#09090b)로 페이드 (모바일 전용 스티키) */
  :root[data-theme="black"] .nset-gen-sticky{background:linear-gradient(180deg,rgba(9,9,11,0),var(--bg) 28%)}
  .nset-gen-sticky .btn{flex:1;justify-content:center;padding:13px;box-shadow:var(--shadow-lg)}

  /* 난이도 선택 — 1줄 수평 스크롤 */
  /* 난이도: [최하 ●●● 최상]은 한 줄(가운데 정렬), 선택 라벨(.diff-label width:100%)은 제 줄.
     좁은 폭(≈272)에 9점+양끝 라벨이 다 들어가게 점 16px·간격 축소 */
  .diff-wrap{flex-wrap:wrap;gap:8px;padding:12px 10px;justify-content:center}
  .diff-dots{gap:5px;flex:0 0 auto;flex-wrap:nowrap;min-width:0}
  .diff-dots .dot{width:16px;height:16px;flex:0 0 auto}
  .diff-label{order:3;flex-basis:100%}
}

/* ── 학생 플레이어 목차 패널 ── */
.cls-player-body{display:flex;flex-direction:column}
.lec-chap-panel{display:flex;flex-direction:column;gap:2px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);padding:10px;overflow-y:auto;max-height:100%}
.lec-chap-head{font-weight:700;font-size:13px;color:var(--text);padding:4px 6px 8px}
.lec-chap-empty{color:var(--text-muted);font-size:13px;line-height:1.5;padding:12px 8px}
.lec-chap-row{display:flex;gap:8px;align-items:center;min-height:44px;width:100%;text-align:left;padding:8px 8px;background:none;border:none;border-radius:8px;cursor:pointer;color:var(--text)}
.lec-chap-row:hover{background:var(--bg)}
.lec-chap-row.on{background:var(--accent);color:var(--accent-ink)}
.lec-chap-t{flex:0 0 auto;font-variant-numeric:tabular-nums;font-size:12px;color:var(--ink-2)}
.lec-chap-row.on .lec-chap-t{color:rgba(255,255,255,.85)}
/* 블랙: .lec-chap-row.on(bg accent) 반전 → 자식 rgba 흰 글자 알파 보존 오버라이드(아래 .lec-side-st 동일) */
:root[data-theme="black"] .lec-chap-row.on .lec-chap-t{color:rgba(19,19,22,.85)}
.lec-chap-title{flex:1;min-width:0;font-size:13.5px}
.lec-side-tabs{display:flex;gap:4px;margin:0 0 8px}
.lec-side-tab{flex:1;display:flex;align-items:center;justify-content:center;min-height:44px;padding:7px 0;border:1px solid var(--border);background:var(--bg);border-radius:8px;font-size:13px;font-weight:600;color:var(--text-muted);cursor:pointer}
.lec-side-tab.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.lec-side-pane{display:flex;flex-direction:column;gap:2px;overflow-y:auto;min-height:0}
.lec-side-prog{padding:4px 6px 10px}
.lec-side-prog-label{font-size:12.5px;font-weight:700;color:var(--text);margin-bottom:6px}
.lec-side-st{flex:0 0 auto;font-size:var(--type-label);font-weight:700;color:var(--legacy-ok)}
.lec-chap-row.on .lec-side-st{color:rgba(255,255,255,.9)}
:root[data-theme="black"] .lec-chap-row.on .lec-side-st{color:rgba(19,19,22,.9)}
.lec-chap-toggle{display:none;align-items:center;gap:6px;padding:8px 12px;border:1px solid var(--border);border-radius:8px;background:var(--surface);cursor:pointer;font-size:13px;font-weight:600;color:var(--text)}
@media(min-width:901px){
  .lec-chap-toggle{display:none!important}
  .cls-player-body{flex-direction:row;flex:1;min-height:0;overflow:hidden}
  .cls-player-mount{width:auto;flex:1;min-width:0}
  .lec-chap-panel{width:240px;flex:0 0 240px;border-radius:0;border-top:none;border-bottom:none;border-right:none;border-left:1px solid var(--border)}
}
@media(max-width:900px){
  .lec-chap-panel{display:none;border-radius:0;border-left:none;border-right:none;border-top:1px solid var(--border);max-height:min(280px,40vh)}
  .lec-chap-panel.open{display:flex}
  .lec-chap-toggle{display:flex;margin:6px 10px}
}
/* 모바일 풀스크린 시트: 플레이어 모달이 화면 전체 — 영상 풀폭, 목차 패널이 잔여 높이(기본 펼침, 내부 스크롤) */
@media(max-width:900px){
  .cls-player-ov{padding:0;align-items:stretch;justify-content:stretch}
  .cls-player-box{width:100%;max-height:none;border-radius:0;flex:1}
  .cls-player-head{padding-top:calc(10px + env(safe-area-inset-top))}
  .cls-player-body{flex:1;min-height:0;overflow:hidden}
  .cls-player-mount{flex:0 0 auto}   /* 세로 flex에서 영상(16:9)이 패널에 밀려 압축되지 않게 고정 */
  .lec-chap-panel{max-height:none;flex:1;min-height:0;padding-bottom:calc(10px + env(safe-area-inset-bottom))}
}

/* ── 홈 대시보드 ── */
.home-wrap{display:flex;flex-direction:column;gap:20px}
.home-hero{display:flex;gap:18px;align-items:center;justify-content:space-between;
  background:linear-gradient(135deg,var(--nav,#1e2747),var(--nav2,#2f3d6b));
  color:var(--on-nav);border-radius:var(--radius-lg,16px);padding:22px 24px;box-shadow:var(--shadow-card,0 6px 20px -8px rgba(26,32,53,.25))}
.home-hero-txt{min-width:0}
.home-hello{font-family:var(--display);font-size:22px;font-weight:700;margin:0 0 4px;letter-spacing:-.02em}
.home-sub{margin:0;font-size:13px;opacity:.82}
.home-resume{flex:0 0 auto;max-width:300px;text-align:left;background:var(--on-nav-a12);
  border:1px solid var(--on-nav-a18);border-radius:12px;padding:12px 14px;color:var(--on-nav);cursor:pointer;transition:.14s}
.home-resume:hover{background:var(--on-nav-a20)}
.home-resume-cap{font-size:var(--type-label);font-weight:700;text-transform:uppercase;letter-spacing:.06em;opacity:.75}
.home-resume-title{font-size:14px;font-weight:700;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-resume-sub{font-size:12px;opacity:.78;margin-top:2px}
.home-resume-track{height:6px;background:var(--on-nav-a25);border-radius:6px;margin-top:9px;overflow:hidden}
.home-resume-fill{height:100%;background:var(--on-nav);border-radius:6px}
.home-kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.home-grid{display:grid;grid-template-columns:1.55fr 1fr;gap:20px;align-items:start}
.home-grid>.home-col{min-width:0;display:flex;flex-direction:column;gap:20px}
.home-card{display:flex;flex-direction:column}
.home-empty{font-size:13px;color:var(--ink-2);padding:8px 2px}
/* '과제' 탭: 홈 카드 컴포넌트 재사용, 단일 칼럼 */
#asgn-tab-body{max-width:860px;display:flex;flex-direction:column;gap:18px}
.home-row{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:none;border:0;
  border-top:1px solid var(--line-2);padding:11px 8px;cursor:pointer;color:inherit;min-height:44px;border-radius:10px}
.home-row:first-of-type{border-top:0}
.home-row:hover{background:var(--surface-2)}
.home-row-tx{min-width:0;flex:1}
.home-row-title{font-size:13.5px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-row-sub{font-size:12px;color:var(--ink-3);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-cta{margin-top:12px;align-self:flex-start}
/* 빠른 도구/바로가기 = 반응형 타일 그리드 (폭에 맞춰 열 수 자동) */
.home-quick-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-top:4px}  /* 4개=2×2, 2개=1행 (균형 배치) */
.home-quick{display:flex;flex-direction:column;align-items:flex-start;gap:9px;text-align:left;
  background:var(--surface-3);border:1px solid var(--line-2);border-radius:10px;
  padding:14px 13px;cursor:pointer;color:var(--ink);font-size:13.5px;font-weight:600;min-height:44px;
  transition:border-color .15s,background .15s,color .15s}
.home-quick:hover{border-color:var(--accent);background:var(--surface);color:var(--accent)}
.home-quick:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.home-quick .home-ic svg{width:20px;height:20px;display:block}
.home-ic{display:inline-flex;color:var(--accent)}
.home-quick:hover .home-ic{color:var(--accent)}

/* ── 반응형 버튼 행: 좁은 폭·긴 라벨에서 버튼이 넘치지 않게 줄바꿈(다중버튼 액션바·헤더 전반) ── */
.result-header,.result-actions,.history-card-header,.history-card-actions,
.ui-modal-actions,.asgn-pick-footer-acts,.handout-acts,.tsm-note-actions,
.asgn-omr-actions,.graph-controls,.graph-modal-header,.asgn-pts-bar,
.file-viewer-bar,.filter-header,.section-header,.settings-header,
.bk-detail-head,.bk-builder-head,.prov-header,.lec-head,.cls-lec-acts,
.subj-footer{flex-wrap:wrap}
/* 제목+액션 헤더: 줄바꿈 시 붙지 않게 최소 간격(space-between이라 넓은 화면엔 무영향) */
.result-header,.history-card-header,.graph-modal-header,.filter-header,
.section-header,.settings-header,.bk-detail-head,.bk-builder-head,
.prov-header,.lec-head{gap:8px 10px}

/* ── 커서 호버 반응: 탭·설정행이 커서를 올리면 시각적으로 반응 ── */
.cls-tab,.subj-tab,.hist-tab{transition:color .12s,background .12s}
@media (max-width:900px){.subj-tab,.hist-tab{min-height:var(--control-touch)}}   /* 모바일·태블릿 hit area 44px (cls-tab는 자체 900px 블록에서 처리) */
.cls-tab:hover:not(.active){color:var(--text);background:var(--accent-tint)}
.subj-tab:hover:not(.active),.hist-tab:hover:not(.active){color:var(--text)}
.lec-side-tab{transition:border-color .12s,color .12s,background .12s}
.lec-side-tab:hover:not(.on){border-color:var(--accent);color:var(--accent)}
.perm-row2:not(.locked):not(.perm-row2-col){transition:background .12s}
.perm-row2:not(.locked):not(.perm-row2-col):hover{background:var(--accent-tint)}

/* 버튼 모션은 위 .btn 블록(Buttons 섹션)이 단일 출처 — 여기 중복 정의 제거(Task 3) */

/* ── 화면 전반 호버 통일: 클릭 카드·행에 그림자(+살짝 뜸) ──
   홈 KPI/클래스 카드가 쓰는 --shadow-lg 재사용. 색/테두리 기존 호버는 유지하고
   그 위에 뜸+그림자만 얹음. 테이블 <tr>(tsm-row/asgn-dash-row)·메뉴(ovf-item)·
   비클릭 설정카드는 대상 아님(각각 transform 불가/오인 방지). */
@media (hover:hover){
  /* 카드/타일: 뜸(-1px) + 큰 그림자 (홈 카드와 통일) */
  .bk-ps-card,.history-card,.home-quick{transition:transform .14s,box-shadow .14s,border-color .14s,background .14s,color .14s}
  .bk-ps-card:hover,.history-card:hover,.home-quick:hover{transform:translateY(-1px);box-shadow:var(--shadow-lg)}
  .bk-ps-card.selected:hover{box-shadow:var(--shadow-lg)}
  /* 클릭 행(div/button): 살짝 뜸 + 은은한 그림자 */
  .asgn-row-clickable,.asgn-omr-row,.file-row-clickable,.lec-chap-row,.home-row{transition:transform .14s,box-shadow .14s,border-color .14s,background .14s}
  .asgn-row-clickable:hover,.asgn-omr-row:hover,.file-row-clickable:hover,.lec-chap-row:hover,.home-row:hover{transform:translateY(-1px);box-shadow:var(--shadow-low)}
}
@media (prefers-reduced-motion:reduce){
  .stat-go:hover,.vcard-go:hover,.bk-ps-card:hover,.history-card:hover,.home-quick:hover,.asgn-row-clickable:hover,.asgn-omr-row:hover,.file-row-clickable:hover,.lec-chap-row:hover,.home-row:hover{transform:none}
}
@media (max-width:900px){
  .home-grid{grid-template-columns:1fr}
  /* 모바일: 액션·클래스(내 클래스 CTA·빠른 도구·관리자) 열을 진도 데이터 위로 */
  .home-grid>.home-col:last-child{order:-1}
  .home-hero{flex-direction:column;align-items:flex-start}
  .home-resume{max-width:none;width:100%}
}
@media (max-width:560px){ .home-kpis{gap:8px} }   /* 3열 컴팩트 유지(풀폭 3행 세로나열 방지→CTA 밀림 완화) */
@media (prefers-reduced-motion:reduce){ .home-resume,.home-row{transition:none} }

/* ── A+ 홈 대시보드 C-1 ── */
.home-dashboard{display:flex;flex-direction:column;gap:var(--s4);min-width:0}
.home-dashboard-head{min-width:0}
.home-command-header{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--s3);min-height:88px;padding:var(--s3) 0;border-bottom:1px solid var(--border);background:transparent}
.home-command-local{align-self:start;padding-top:3px;color:var(--text-muted);font-size:var(--type-label);font-weight:700;white-space:nowrap}
.home-command-copy{display:flex;min-width:0;flex-direction:column;gap:3px}
.home-dashboard-title{margin:0;font-size:var(--type-screen);line-height:1.2;color:var(--text)}
.home-command-summary{margin:0;color:var(--text-muted);font-size:var(--type-body);line-height:1.45}
.home-command-context{display:flex;align-items:center;gap:var(--s2);min-width:0;color:var(--text-muted);font-size:var(--type-meta)}
.home-command-context>span+span{padding-left:var(--s2);border-left:1px solid var(--border)}
.home-dashboard-date{font-size:var(--type-meta);color:var(--text-muted)}
.home-command-role{white-space:nowrap}
.home-dashboard-primary{min-width:44px;min-height:44px}
.home-dashboard-strip{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));margin:0;border:1px solid var(--border);border-radius:var(--radius-card);background:var(--surface);overflow:hidden}
.home-dashboard-stat{min-width:0;padding:var(--s3);border-right:1px solid var(--border)}
.home-dashboard-stat:last-child{border-right:0}
.home-dashboard-stat dt{font-size:var(--type-label);color:var(--text-muted)}
.home-dashboard-stat dd{margin:3px 0 0;font-size:20px;font-weight:750;font-variant-numeric:tabular-nums;color:var(--text)}
.home-dashboard-grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(260px,.85fr);gap:var(--s4);align-items:start}
.home-dashboard-queue,.home-dashboard-panel{border:1px solid var(--border);border-radius:var(--radius-card);background:var(--surface)}
.home-dashboard-action{display:flex;align-items:center;gap:var(--s2);width:100%;min-height:56px;padding:var(--s3);border:0;border-top:1px solid var(--border);background:transparent;color:var(--text);text-align:left;cursor:pointer;transition:transform .13s,box-shadow .13s,background .15s}
.home-dashboard-action:first-of-type{border-top:0}
.home-dashboard-action-copy{display:flex;flex:1;min-width:0;flex-direction:column;gap:2px}
.home-dashboard-action-copy strong{font-size:var(--type-body);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-dashboard-action-copy span{font-size:var(--type-meta);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-dashboard-data-tag,.home-dashboard-meta-tag{display:inline-flex;align-items:center;min-height:20px;box-sizing:border-box;padding:2px 7px;border:1px solid transparent;border-radius:var(--radius-pill);background:transparent;font-size:var(--type-label);font-weight:700;line-height:1.2;white-space:nowrap}
.home-dashboard-data-tag{color:var(--data);font-variant-numeric:tabular-nums}
.home-dashboard-meta-tag{color:var(--text-muted)}
.home-class-picker button:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
@media (hover:hover){.home-dashboard-action:hover{transform:translateY(-1px);box-shadow:var(--shadow-low);background:var(--surface-2)}}
.home-dashboard-panel-title{margin:0;padding:var(--s3);font-size:var(--type-section);color:var(--text)}
.home-dashboard-aside{display:flex;min-width:0;flex-direction:column;gap:var(--s4)}
.home-dashboard-class{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);width:100%;min-height:48px;padding:var(--s3);border:0;border-top:1px solid var(--border);background:transparent;color:var(--text);text-align:left}
.home-dashboard-class:first-of-type{border-top:0}
.home-dashboard-class strong,.home-dashboard-class span:not(.semantic-status){min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-dashboard-class .semantic-status{flex:0 0 auto}
.home-dashboard-class span{font-size:var(--type-meta);color:var(--text-muted)}
/* 좁은 화면에서는 제목·지표·배지가 한 줄에서 서로를 뭉개므로
   1행 제목+상태 배지, 2행 지표로 접는다. */
@media (max-width:480px){
  .home-dashboard-class{flex-wrap:wrap;row-gap:2px}
  .home-dashboard-class strong{flex:1 1 auto}
  .home-dashboard-class .semantic-status{margin-left:auto}
  .home-dashboard-class span:not(.semantic-status){flex-basis:100%;order:4}
}
.home-dashboard-tools{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2);padding:var(--s3)}
.home-dashboard-tool{min-height:44px}
.home-class-picker-layer{position:fixed;inset:0;z-index:var(--z-overlay);display:grid;place-items:center;padding:var(--s4)}
.home-class-picker-backdrop{position:absolute;inset:0;background:var(--overlay)}
.home-class-picker{position:relative;z-index:1;width:min(420px,100%);max-height:min(70dvh,560px);overflow:auto;border:1px solid var(--border);border-radius:var(--radius-overlay);background:var(--surface);box-shadow:var(--shadow-high);padding:var(--s4)}
.home-class-picker-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s3)}
.home-class-picker-title{margin:0;font-size:var(--type-section)}
.home-class-picker-close,.home-class-picker-choice{min-height:44px;border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);color:var(--text)}
.home-class-picker-list{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s3)}
.home-class-picker-choice{width:100%;padding:var(--s3);text-align:left}
html[data-shell-mode="wide-desktop"] .home-dashboard{gap:var(--s5)}
html[data-shell-mode="wide-desktop"] .home-dashboard-grid{grid-template-columns:minmax(0,1.25fr) minmax(280px,.85fr);gap:var(--s5)}
html[data-shell-mode="desktop"] .home-dashboard{gap:var(--s4)}
html[data-shell-mode="desktop"] .home-dashboard-grid{grid-template-columns:minmax(0,1.2fr) minmax(260px,.8fr);gap:var(--s4)}
html[data-shell-mode="tablet-landscape"] .home-dashboard{gap:var(--s3)}
html[data-shell-mode="tablet-landscape"] .home-dashboard-grid{grid-template-columns:minmax(0,1.35fr) minmax(240px,.65fr);gap:var(--s3)}
html[data-shell-mode="tablet-portrait"] .home-dashboard{gap:var(--s3)}
html[data-shell-mode="tablet-portrait"] .home-command-header,
html[data-shell-mode="mobile-portrait"] .home-command-header,
html[data-shell-mode="mobile-landscape"] .home-command-header{grid-template-columns:auto minmax(0,1fr);align-items:start}
html[data-shell-mode="tablet-portrait"] .home-command-primary,
html[data-shell-mode="mobile-portrait"] .home-command-primary,
html[data-shell-mode="mobile-landscape"] .home-command-primary{grid-column:2;justify-self:start;margin-top:var(--s2)}
html[data-shell-mode="tablet-portrait"] .home-dashboard-grid{grid-template-columns:minmax(0,1fr)}
/* Task 11: 모바일 첫 화면 compact. 세로 하단 내비 클리어런스는 셸 #main이 단독 소유하므로
   #panel-home은 nav 높이·safe-area·calc를 다시 쌓지 않는다(중복 클리어런스=죽은 스크롤 방지). */
html[data-shell-mode="mobile-portrait"] #panel-home{padding:12px 14px 12px}
html[data-shell-mode="mobile-portrait"] .home-dashboard{gap:var(--s2)}
html[data-shell-mode="mobile-portrait"] .home-dashboard-head{gap:var(--s2)}
html[data-shell-mode="mobile-portrait"] .home-dashboard-date{font-size:var(--type-meta)}
html[data-shell-mode="mobile-portrait"] .home-dashboard-strip{min-height:44px}
html[data-shell-mode="mobile-portrait"] .home-dashboard-stat{padding:8px 10px}
html[data-shell-mode="mobile-portrait"] .home-dashboard-stat dd{font-size:18px}
html[data-shell-mode="mobile-portrait"] .home-dashboard-action{min-height:56px;padding:9px 12px}
html[data-shell-mode="mobile-portrait"] .home-dashboard-grid{grid-template-columns:minmax(0,1fr);gap:var(--s3)}
html[data-shell-mode="mobile-landscape"] #panel-home{padding:10px 14px 16px 70px}
html[data-shell-mode="mobile-landscape"] .home-dashboard{gap:var(--s2)}
html[data-shell-mode="mobile-landscape"] .home-dashboard-grid{grid-template-columns:minmax(0,1fr)}
html[data-shell-mode="mobile-landscape"] .home-dashboard-action{min-height:48px;padding:7px 12px}
/* Task 10: 최초·재조회 loading / empty / 영역·전체 error 상태 (토큰 전용) */
.home-dashboard-skeletons{display:flex;flex-direction:column;gap:var(--s3)}
.home-dashboard-skeleton-strip{min-height:72px}
.home-dashboard-skeleton-stat,.home-dashboard-skeleton-action{display:block;background:var(--surface-2);animation:home-skeleton-pulse 1.2s ease-in-out infinite alternate}
.home-dashboard-skeleton-stat{min-height:72px;border-right:1px solid var(--border)}
.home-dashboard-skeleton-action{min-height:56px;border-top:1px solid var(--border)}
@keyframes home-skeleton-pulse{from{opacity:.55}to{opacity:1}}
@media (forced-colors:active){.home-command-header{border-bottom:1px solid CanvasText}.home-command-primary{border:1px solid ButtonText}}
@media (prefers-reduced-motion:reduce){.home-dashboard-skeleton-stat,.home-dashboard-skeleton-action{animation:none}.home-dashboard-action,.home-command-primary{transition:none}.home-dashboard-action:hover{transform:none}}
.home-dashboard-refreshing{opacity:.55;pointer-events:none}
.home-dashboard-error{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s4);border:1px solid var(--border);border-color:var(--border);border-radius:var(--radius-card);background:var(--surface)}
.home-dashboard-error .home-dashboard-title,
.home-dashboard-error .home-dashboard-panel-title{color:var(--danger)}
.home-dashboard-empty{margin:0;padding:var(--s4);color:var(--text-muted);background:transparent}
/* Issue 400: 학생 상태 카드 3탭. 카드 그리드는 그대로 두고 카드만 native button이 된다.
   선택 표식은 색 말고 밑줄과 면 대비를 함께 쓰고, focus ring은 선택 표식과 분리한다. */
.home-dashboard-stat-tab{display:flex;min-height:44px;flex-direction:column;gap:3px;box-sizing:border-box;border:0;border-right:1px solid var(--border);border-bottom:2px solid transparent;background:transparent;color:var(--text);font:inherit;text-align:left;cursor:pointer;transition:background-color .13s,border-color .13s,color .13s}
.home-dashboard-stat-tab:last-child{border-right:0}
.home-dashboard-stat-label{font-size:var(--type-label);color:var(--text-muted)}
.home-dashboard-stat-value{font-size:20px;font-weight:750;font-variant-numeric:tabular-nums;color:var(--text)}
.home-dashboard-stat-tab[aria-selected="true"]{border-bottom-color:currentColor;background:var(--surface-2)}
.home-dashboard-stat-tab[aria-selected="true"] .home-dashboard-stat-label{color:var(--text)}
.home-dashboard-stat-tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}
@media (hover:hover){.home-dashboard-stat-tab:hover{background:var(--surface-2)}}
.home-dashboard-status-live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
html[data-shell-mode="mobile-portrait"] .home-dashboard-stat-tab .home-dashboard-stat-value{font-size:18px}
@media (prefers-reduced-motion:reduce){.home-dashboard-stat-tab{transition:none}}
@media (forced-colors:active){
  .home-dashboard-stat-tab{border-right-color:CanvasText;border-bottom-color:CanvasText;color:CanvasText}
  .home-dashboard-stat-tab[aria-selected="true"]{border-bottom-color:Highlight;color:Highlight}
  .home-dashboard-stat-tab:focus-visible{outline:2px solid Highlight;outline-offset:-2px}
}
/* ── A+ 홈 대시보드 C-1 끝 ── */

/* ── 강사 학생관리 통합 로스터 ── */
.tsm-section { margin-top: 16px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 14px 16px; }
/* 정적 표면(패널·표·차트·로스터 섹션)=그림자 0 / 실제 클릭 카드=shadow-low (Task 3 elevation 계약).
   이 위치는 위 정적 표면 기본 정의(.card·.panel·.tbl·.chart·[data-rd] .cls-card·.tsm-section)를 모두 지나서 온다. */
.panel,.tbl,.chart,.tsm-section{box-shadow:none}
.card,[data-rd] .cls-card{box-shadow:var(--shadow-low)}
.tsm-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.tsm-title { font-family: var(--display); font-size: 15px; font-weight: 800; margin: 0; color: var(--text); }
.tsm-tbl th { background: var(--surface-3); font-weight: 600; color: var(--text-muted);
  font-size: var(--type-label); letter-spacing: .01em; }
.tsm-search { flex: 0 1 200px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); color: var(--ink); font-size: .9rem; min-height: 44px; }
.tsm-search:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.tsm-tbl { width: 100%; border-collapse: collapse; font-size: .9rem; }
.tsm-tbl th, .tsm-tbl td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--line-2); }
.tsm-tbl th { color: var(--ink-2); font-weight: 600; font-size: var(--type-label); }
.tsm-th-sort { cursor: pointer; user-select: none; }
.tsm-th-sort.asc::after { content: " ▲"; font-size: var(--type-label); color: var(--ink-2); }
.tsm-th-sort.desc::after { content: " ▼"; font-size: var(--type-label); color: var(--ink-2); }
.tsm-row { cursor: pointer; }
.tsm-row td { padding-top: 13px; padding-bottom: 13px; box-sizing: border-box; }
.tsm-row:hover { background: var(--surface-2); }
.tsm-row:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.tsm-row-paused td { opacity: .55; }
.tsm-row-paused .tsm-paused-tag { opacity: 1; margin-left: 6px; }
.tsm-pcell { display: flex; align-items: center; gap: 8px; }
.tsm-strip { flex: 1; height: 8px; background: var(--surface-2); border-radius: 999px; overflow: hidden; min-width: 60px; }
.tsm-strip-fill { height: 100%; border-radius: 999px; }
.tsm-strip-lbl { color: var(--ink-2); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }
.omr-sn-input { width: 90px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: var(--type-meta); }
.omr-sn-input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.tsm-phone-input { width: 128px; }

/* ── 로스터 연락처(알림톡 수신자 관리) ── */
.tsm-contact-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 4px 0 2px; }
.tsm-upload-label { cursor: pointer; }
.tsm-upload-input { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }
.tsm-contact-note { margin: 0 0 10px; font-size: var(--type-label); color: var(--ink-3); }
/* ── 명단 일괄 등록 + 무가입 학생 열람 링크 ── */
.tsm-head-acts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tsm-bulk-panel { margin: 6px 0 12px; padding: 12px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--surface-2); }
.tsm-bulk-panel textarea { width: 100%; box-sizing: border-box; margin-bottom: 8px; }
.tsm-bulk-days { display: block; margin: 0 0 10px; font-size: var(--type-label); color: var(--ink-2); }
.tsm-bulk-days input { width: 96px; margin-left: 8px; }
.tsm-bulk-out { margin-top: 10px; }
.tsm-bulk-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.tsm-bulk-name { flex: 0 0 96px; font-size: var(--type-meta); color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tsm-bulk-link { flex: 1 1 auto; width: auto; min-width: 0; }
.tsm-guest-tag { margin-left: 6px; }
.tsm-ticket-state { margin-right: 8px; font-size: var(--type-meta); color: var(--ink-2);
  white-space: nowrap; }
@media (max-width: 640px) {
  .tsm-bulk-row { flex-wrap: wrap; }
  .tsm-bulk-name { flex: 1 0 100%; }
}
.tsm-skipped { margin: 0 0 8px; }
.tsm-skipped-item { margin: 0 0 2px; font-size: var(--type-meta); color: var(--bad); }
.tsm-report-body { margin: 8px 0; }
.tsm-report-brand { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
.tsm-report-brand:empty { display: none; }
.tsm-report-logo { max-width: 96px; max-height: 40px; }
.tsm-report-phone { margin: 0 0 6px; font-size: var(--type-meta); color: var(--ink-2); }
.tsm-report-text { margin: 0 0 10px; padding: 10px 12px; border-radius: 8px; background: var(--surface-2);
  font-size: .88rem; color: var(--ink); white-space: pre-wrap; word-break: break-word; }
@media (max-width: 640px) {
  .tsm-tbl, .tsm-tbl tbody, .tsm-tbl tr, .tsm-tbl td { display: block; width: 100%; }
  .tsm-tbl thead { display: none; }
  .tsm-tbl tr { border: 1px solid var(--line); border-radius: 10px; margin-bottom: 10px; padding: 6px 10px; }
  .tsm-tbl td { border-bottom: 1px solid var(--line-2); display: flex; justify-content: space-between; gap: 12px; }
  .tsm-tbl td:last-child { border-bottom: none; }
  .tsm-tbl td::before { content: attr(data-th); color: var(--ink-2); font-size: var(--type-label); font-weight: 600; }
  .tsm-pcell { flex: 1; max-width: 60%; }
}

/* ── 학생 상세 모달 ── */
.tsm-modal-bg { position: fixed; inset: 0; background: var(--overlay); display: flex;
  align-items: center; justify-content: center; z-index: 1000; padding: 16px; }
.tsm-modal { background: var(--surface); border-radius: var(--radius-overlay); box-shadow: var(--shadow-lg);
  width: 100%; max-width: 560px; max-height: 90vh; display: flex; flex-direction: column; }
.tsm-modal-head { display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--line-2); }
.tsm-modal-title { margin: 0; font-size: 1.1rem; color: var(--ink); }
.tsm-modal-x { background: none; border: none; font-size: 1.1rem; cursor: pointer; color: var(--ink-3);
  min-width: 44px; min-height: 44px; }
.tsm-modal-body { padding: 16px 20px; overflow-y: auto; }
/* 시청 전 동의 고지(학생 1회) — .tsm-modal 관례 재사용, 폭만 축소 */
.cls-consent { max-width: 460px; }
.cls-consent-p { margin: 0; font-size: 14px; line-height: 1.65; color: var(--ink-2); }
.cls-consent-acts { display: flex; justify-content: flex-end; margin-top: 18px; }
.tsm-detail-sec { margin-bottom: 20px; }
.tsm-detail-h { margin: 0 0 10px; font-size: .95rem; color: var(--ink-2); }
.tsm-detail-lec, .tsm-detail-asg { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.tsm-detail-lec-t, .tsm-detail-asg-t { flex: 1; color: var(--ink); font-size: .9rem; }
.tsm-detail-asg-st { font-size: var(--type-meta); font-variant-numeric: tabular-nums; }
.tsm-detail-asg-st.ok { color: var(--good); }
.tsm-detail-asg-st.no { color: var(--ink-3); }
/* 수강 관리 / 수강 이력 */
.tsm-mng-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
.tsm-remove-btn { color: var(--danger); border-color: currentColor; margin-top: 6px; }
.tsm-ev-row { display: flex; gap: 8px; flex-wrap: wrap; font-size: var(--type-meta); padding: 3px 0; }
.tsm-ev-when { color: var(--text-muted); white-space: nowrap; }
.tsm-ev-by, .tsm-ev-reason { color: var(--text-muted); }
/* 메모 */
.tsm-note-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.tsm-note { border: 1px solid var(--line-2); border-radius: 10px; padding: 10px 12px; background: var(--surface); }
.tsm-note.pinned { border-color: var(--good-line); background: var(--good-bg); }
.tsm-note-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.tsm-note-badge { font-size: var(--type-label); padding: 2px 8px; border-radius: 999px; font-weight: 600; }
.tsm-note-badge.self { background: var(--surface-2); color: var(--ink-2); }
.tsm-note-badge.admin { background: var(--good-bg); color: var(--good); border: 1px solid var(--good-line); }
.tsm-note-when { font-size: var(--type-label); color: var(--ink-3); }
.tsm-note-body { font-size: .9rem; color: var(--ink); white-space: pre-wrap; word-break: break-word; }
.tsm-note-actions { display: flex; gap: 8px; margin-top: 8px; }
.tsm-note-btn { font-size: var(--type-meta); padding: 4px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); color: var(--ink-2); cursor: pointer; min-height: 44px; }
/* 삭제 버튼: 기본은 base .tsm-note-btn 중립(--ink-2/--line) 상속(상시 빨강 회수), hover 시에만 danger */
.tsm-note-btn.danger:hover { color: var(--danger); border-color: var(--bad-line); }
.tsm-note-form { display: flex; flex-direction: column; gap: 8px; }
.tsm-note-input { width: 100%; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); color: var(--ink); font: inherit; resize: vertical; }
.tsm-note-input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.tsm-note-add { align-self: flex-end; padding: 8px 16px; border: none; border-radius: 8px;
  background: var(--accent); color: var(--accent-ink); cursor: pointer; min-height: 40px; font-weight: 600; }
.tsm-note-add:disabled { opacity: .6; cursor: default; }
@media (prefers-reduced-motion: no-preference) {
  .tsm-strip-fill { transition: width .3s ease; }
}

/* 객관식 선지 (과제·연습 풀이) */
.asgn-choices { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.asgn-choice { display: flex; align-items: center; gap: 10px; min-height: 44px;
  padding: 0 12px; border: 1px solid var(--line); border-radius: 10px; cursor: pointer; }
.asgn-choice:has(input:checked) { border-color: var(--accent); background: var(--surface-2, var(--surface)); }
.asgn-choice input { accent-color: var(--accent); }
.asgn-choice-txt { font-size: 14px; }
/* 선지 마크다운 본문 — marked 가 감싸는 <p> 를 인라인으로 눕혀 라디오와 같은 줄 유지 */
.asgn-choice-md { display: inline; }
.asgn-choice-md p { display: inline; margin: 0; }
.asgn-choice-md p + p { margin-left: .35em; }
.asgn-choice-md img { max-width: 100%; vertical-align: middle; }
.asgn-choice-md .katex-display { display: inline-block; margin: 0; }
.asgn-choices-bare { flex-direction: row; flex-wrap: wrap; gap: 6px; }
.asgn-choices-bare .asgn-choice { padding: 0 14px; }

/* ── 과제 배점 입력(생성 폼) ── */
.asgn-pts-in{width:56px;flex:0 0 auto;padding:3px 6px;border:1px solid var(--border);
  border-radius:var(--radius-sm);background:var(--surface);color:var(--text);font-size:12.5px;text-align:center}
.asgn-pts-bar{display:flex;align-items:center;gap:10px;margin-top:2px}
.asgn-pts-sum{font-size:12.5px;font-weight:600;color:var(--text-muted)}
.asgn-pts-sum.err{color:var(--bad)}

/* ── 과제 대시보드: 학생 행 드릴다운 진입 ── */
.asgn-dash-row{cursor:pointer}
.asgn-dash-row:hover{background:var(--surface-2)}
.asgn-dash-row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}

/* ── 답안 드릴다운 모달(.tsm-modal 관례 확장 — 표가 넓어 폭만 오버라이드) ── */
.asgn-drill-modal{max-width:720px}
.asgn-drill-table{width:100%}
.asgn-drill-table .asgn-drill-ans{white-space:normal;word-break:break-word;max-width:180px;text-align:left}
.asgn-drill-manual{font-size:var(--type-label);color:var(--text-muted)}
.asgn-drill-acts{display:flex;flex-wrap:wrap;gap:6px;justify-content:center}

/* ── OMR 스캔 검토 UI (.asgn-omr-* 계열) ── */
/* 업로드 구획: 라벨 있는 필드 스택 + 하단 구분선으로 대기열과 분리(요소 밀집감 해소) */
.asgn-omr-upload{display:flex;flex-direction:column;gap:14px;margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid var(--line-2)}
.asgn-omr-upload select{width:100%}
.asgn-omr-upload input[type="file"]{width:100%;font-size:13px;color:var(--text-muted);padding:12px;border:1.5px dashed var(--border);border-radius:var(--radius-sm);background:var(--bg);cursor:pointer}
.asgn-omr-queue-h{font-size:12.5px;font-weight:700;color:var(--ink-2);margin:0 0 8px}
.asgn-omr-list{max-height:400px;overflow-y:auto;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface)}
.asgn-omr-row{display:flex;align-items:center;gap:12px;padding:12px;border:1px solid transparent;cursor:pointer;transition:background 0.15s,border-color 0.15s}
.asgn-omr-row:hover{background:var(--accent-tint);border-color:var(--accent)}
.asgn-omr-row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}
.asgn-omr-match{display:flex;align-items:center;gap:12px;padding:12px 0;margin-bottom:12px}
.asgn-omr-match select{flex:1}
.asgn-omr-img{max-width:100%;border-radius:var(--radius-sm);display:block;margin:12px 0}
/* 저신뢰(confidence<0.5) 또는 플래그(blank/multiple) 문항 — 강조 배경 + ⚠ 배지.
   좌측 강조 바는 제거했다(배경과 배지만으로 구분이 선다). */
.asgn-omr-flag{background:var(--bad-bg)}
.asgn-omr-flag td:first-child::before{content:'⚠ ';color:var(--bad);font-weight:700;margin-right:2px}
.asgn-omr-actions{display:flex;gap:8px;margin-top:16px}
.asgn-omr-actions button{flex:1}

/* ── 데스크탑 밀도: 폭 확대(≥1280px) ── */
@media (min-width:1280px){
  .tool-panel{max-width:1360px}          /* 7개 SPA 패널 공용 셸(820px→) */
  .asgn-drill-modal{max-width:880px}     /* 데이터 테이블 모달(720px→) */
}

/* ── 데스크탑 밀도: 간격 컴팩트 기본(≥1280px, 사용자 compact 설정이 우선) ── */
@media (min-width:1280px){
  .card{padding:10px}
  .panel{padding:14px}
  .stat{padding:10px 12px}
  .tbl td,.tbl th{padding-top:6px;padding-bottom:6px}
}

/* ── 자료실 PDF 책넘김 뷰어 (book-viewer.js) — 라이트 크롬 ── */
.book-ov{position:fixed;inset:0;z-index:var(--z-viewer);display:flex;flex-direction:column;background:var(--bg,#f5f6fa);}
.book-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  height:52px;flex:0 0 52px;padding:0 14px;background:var(--surface,#fff);color:var(--ink,#1a2035);
  border-bottom:1px solid var(--border,#e2e6ef);}
.book-toolbar-left{display:flex;align-items:center;gap:10px;min-width:0;}
.book-title{font-size:14px;font-weight:600;color:var(--ink,#1a2035);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:36vw;}
.book-pageind{font-size:12px;color:var(--text-muted,#646d82);white-space:nowrap;}
.book-actions{display:flex;align-items:center;gap:6px;flex-shrink:0;}
.book-btn{font:inherit;font-size:13px;line-height:1;padding:7px 11px;border-radius:6px;cursor:pointer;
  border:1px solid var(--border,#e2e6ef);background:var(--surface,#fff);color:var(--ink,#1a2035);
  transition:transform .12s ease,box-shadow .12s ease,border-color .12s ease;}
.book-btn:hover{transform:translateY(-2px);box-shadow:0 4px 10px rgba(15,23,42,.12);border-color:var(--accent,#1e2638);}
.book-close{background:var(--accent,#1e2638);color:var(--accent-ink);border-color:var(--accent,#1e2638);font-weight:600;}
.book-close:hover{background:var(--accent-hover,#2c3a56);border-color:var(--accent-hover,#2c3a56);}
.book-jump{width:56px;text-align:center;font:inherit;font-size:13px;padding:6px 4px;border-radius:6px;
  border:1px solid var(--border,#e2e6ef);background:var(--surface,#fff);color:var(--ink,#1a2035);}
.book-body{flex:1;display:flex;min-height:0;}
.book-toc{width:150px;flex:0 0 150px;overflow-y:auto;background:var(--surface,#fff);
  border-right:1px solid var(--border,#e2e6ef);padding:10px 8px;
  display:none;flex-direction:column;gap:8px;}
.book-ov.toc-open .book-toc{display:flex;}
.book-thumb{position:relative;display:block;width:100%;padding:0;border:1px solid var(--border,#e2e6ef);border-radius:6px;
  background:#fff;cursor:pointer;overflow:hidden;}
.book-thumb.is-current{border:2px solid var(--accent,#1e2638);box-shadow:0 2px 8px rgba(15,23,42,.12);}
.book-thumb-cv{display:block;width:100%;height:auto;background:#fff;}
.book-thumb-num{position:absolute;right:3px;bottom:2px;font-size:var(--type-label);color:var(--accent-ink);background:var(--accent,#1e2638);
  padding:0 4px;border-radius:3px;}
.book-stage{position:relative;flex:1;min-width:0;display:flex;align-items:center;justify-content:center;
  background:var(--surface-2,#eef1f6);overflow:hidden;}
.flip-book{box-shadow:0 8px 28px rgba(15,23,42,.22),0 2px 8px rgba(15,23,42,.10);}
.book-page{background:#fff;overflow:hidden;position:relative;}
.book-page canvas{display:block;}
.book-page>.book-ann-public,.book-page>.book-ann-private,.book-page>.book-ann-input,
.book-zoom-page>.book-ann-public,.book-zoom-page>.book-ann-private,.book-zoom-page>.book-ann-input{
  position:absolute;inset:0;width:100%;height:100%;
}
.book-ann-public,.book-ann-private{pointer-events:none;}
.book-ann-input{pointer-events:none;touch-action:auto;background:transparent;}
.book-ov.is-annotating .book-ann-input{pointer-events:auto;touch-action:none;}
.book-zoom-page{position:relative;flex:0 0 auto;}
.book-ann-toolbar{position:fixed;z-index:3;display:flex;align-items:center;gap:2px;padding:4px;
  box-sizing:border-box;width:max-content;max-width:calc(100vw - 16px);overflow:hidden;
  border:1px solid var(--border);border-radius:var(--radius-overlay);background:var(--surface);
  color:var(--ink);box-shadow:var(--shadow-high);
  transition:left .16s ease,top .16s ease,transform .16s ease;}
.book-ann-toolbar:not(.is-active){display:none;}
.book-ann-toolbar.is-horizontal{flex-direction:row;overflow-x:auto;overflow-y:hidden;}
.book-ann-toolbar.is-vertical{flex-direction:column;overflow-x:hidden;overflow-y:auto;}
.book-ann-toolbar.is-dragging{transition:none;}
.book-ann-control{display:inline-flex;align-items:center;justify-content:center;flex:0 0 32px;width:32px;height:32px;
  padding:0;border:0;border-radius:var(--radius-control);background:transparent;color:inherit;cursor:pointer;touch-action:none;}
.book-ann-control:hover:not(:disabled),.book-ann-control[aria-pressed="true"]{background:var(--surface-2);color:var(--accent);}
.book-ann-control:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}
.book-ann-control:disabled{opacity:.38;cursor:default;}
.book-ann-icon{display:block;width:20px;height:20px;}
.book-ann-drag{cursor:grab;}
.book-ann-drag:active{cursor:grabbing;}
.book-ann-save{cursor:default;pointer-events:none;}
.book-ann-status-text{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
.book-ann-save[data-state="dirty"]{color:var(--legacy-warn);opacity:1}
.book-ann-save[data-state="saved"]{color:var(--legacy-good);opacity:1}
/* 동기화 충돌 alertdialog — 인라인 스타일을 클래스로 이전(D). 토큰 --radius-overlay·--shadow-high 사용 */
.book-ann-conflict{position:absolute;top:8px;left:50%;transform:translateX(-50%);z-index:4;
  max-width:calc(100% - 16px);display:flex;flex-wrap:wrap;gap:8px;align-items:center;
  padding:10px 12px;border-radius:var(--radius-overlay);background:var(--surface);color:var(--ink);
  box-shadow:var(--shadow-high);font-size:13px;}
.book-ann-conflict[hidden]{display:none;}
.book-ann-conflict-msg{margin:0;flex:1 1 100%;}
.book-ann-conflict-btn{min-height:32px;padding:6px 12px;border-radius:var(--radius-control);border:1px solid var(--border);
  background:var(--surface);color:inherit;font:inherit;cursor:pointer;}
.book-ann-conflict-btn:hover:not(:disabled),.book-ann-conflict-btn:active{background:var(--surface-2);border-color:var(--accent);}
.book-ann-conflict-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.book-download-backdrop{position:absolute;inset:0;z-index:7;display:flex;align-items:center;justify-content:center;
  padding:20px;background:var(--overlay);}
.book-download-dialog{width:min(420px,100%);padding:22px;border:1px solid var(--border);border-radius:var(--radius-overlay);
  background:var(--surface);color:var(--ink);box-shadow:var(--shadow-lg);}
.book-download-title{margin:0;font-size:19px;line-height:1.35;}
.book-download-description{margin:8px 0 0;color:var(--text-muted);font-size:13px;}
.book-download-message{margin:14px 0 0;padding:10px 12px;border-radius:var(--radius-control);font-size:13px;line-height:1.45;}
.book-download-message[hidden]{display:none;}
.book-download-error{background:var(--legacy-bad-bg);color:var(--legacy-bad);border:1px solid var(--legacy-bad)}
.book-download-warning{background:var(--surface-2);color:var(--ink);border:1px solid var(--legacy-warn)}
.book-download-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px;}
.book-download-button{min-height:40px;padding:9px 14px;border:1px solid var(--border);border-radius:var(--radius-control);
  background:var(--surface);color:var(--ink);font:inherit;font-size:13px;font-weight:600;cursor:pointer;}
.book-download-button:hover:not(:disabled){transform:translateY(-2px);box-shadow:var(--shadow-card);border-color:var(--accent);}
.book-download-button:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.book-download-button:disabled{opacity:.5;cursor:wait;}
.book-download-primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);}
.book-download-cancel{margin-left:auto;}
/* D: 모바일·태블릿은 44×44 터치 타깃, 데스크탑 밀집 티어는 32px 유지 */
@media (max-width:899px){
  .book-ann-control{flex-basis:44px;width:44px;height:44px;}
}
/* D: 모션 최소화 선호 시 도킹 전환·다운로드 호버 이동 제거 */
@media (prefers-reduced-motion:reduce){
  .book-ann-toolbar{transition:none;}
  .book-download-button:hover:not(:disabled){transform:none;}
}
.book-loading{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;color:var(--text-muted,#646d82);font-size:14px;font-weight:600;}
.book-spinner{width:42px;height:42px;border-radius:50%;border:4px solid var(--border,#e2e6ef);
  border-top-color:var(--accent,#1e2638);animation:book-spin 1s linear infinite;}
@keyframes book-spin{to{transform:rotate(360deg);}}
.book-fallback-frame{width:100%;height:100%;border:0;background:#fff;}
/* 햄버거 목차 아이콘 */
.book-ic{width:20px;height:20px;display:block;}
/* 확대 모드 */
.book-zoom{position:absolute;inset:0;z-index:5;display:flex;flex-direction:column;background:var(--bg,#f5f6fa);}
.book-zoom-bar{display:flex;align-items:center;justify-content:center;gap:6px;height:48px;flex:0 0 48px;
  background:var(--surface,#fff);border-bottom:1px solid var(--border,#e2e6ef);}
.book-zoom-scroll{flex:1;overflow:auto;display:flex;align-items:flex-start;justify-content:center;padding:16px;
  touch-action:pinch-zoom;}
.book-zoom-cv{display:block;background:#fff;box-shadow:0 4px 18px rgba(15,23,42,.18);}
/* 반응형: 좁은 화면은 목차를 오버레이 슬라이드로(display는 항상 flex, transform으로 개폐) */
@media (max-width:899px){
  .book-toc{position:absolute;left:0;top:0;bottom:0;z-index:4;display:flex;transform:translateX(-100%);
    transition:transform .2s ease;box-shadow:2px 0 16px rgba(15,23,42,.15);}
  .book-ov.toc-open .book-toc{transform:translateX(0);}
  .book-title{max-width:28vw;}
  .book-toolbar{padding:0 8px;gap:8px;}
  .book-actions{gap:4px;}
  .book-btn{padding:7px 8px;font-size:12px;}
  .book-jump{width:42px;}
  .book-fs{display:none;}      /* 모바일: 전체화면 숨김(iOS 제약·공간 확보) */
  .book-pageind{display:none;} /* 점프 입력이 현재 쪽을 이미 표시 — 중복 제거 */

  /* 모바일 툴바가 넘치면 감싸서 모든 버튼 접근 보장 */
  .book-toolbar{height:auto;flex:0 0 auto;flex-wrap:wrap;row-gap:6px;}
  /* .book-actions는 기본 flex-shrink:0(콘텐츠폭 고정)이라 flex-wrap만으로는 줄바꿈이 안 됨 —
     flex-basis:100%로 자기 줄을 강제해야 내부 버튼들이 2행으로 감싸진다 */
  .book-actions{flex-wrap:wrap;justify-content:flex-end;flex-basis:100%;}
}

/* ── 상담 탭 ─────────────────────────────────────────── */
.cns-card { padding: 16px; margin-bottom: 14px; }
.cns-cal-head { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 10px; }
.cns-title { font-size: 15px; }
.cns-dow,.cns-grid { grid-template-columns: repeat(7, minmax(0, 1fr)) }
.cns-dow { display: grid; text-align: center;
  font-size: 12px; color: var(--ink-3); padding-bottom: 6px; }
.cns-dow span:first-child { color: var(--bad); }
.cns-grid { display: grid; gap: 4px; }
.cns-cell { position: relative; min-height: 56px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: none; cursor: pointer; padding: 6px;
  text-align: left; font: inherit; color: var(--ink); }
.cns-cell.empty { border: none; cursor: default; }
.cns-cell.today { border-color: var(--accent-2); }
.cns-cell.sel { background: var(--accent-tint); border-color: var(--accent-2); }
.cns-cell-d { font-size: 12px; color: var(--ink-2); }
.cns-cell-n { position: absolute; right: 6px; bottom: 6px; min-width: 18px; height: 18px;
  border-radius: 9px; background: var(--accent-2); color: var(--accent-ink); font-size: var(--type-label);
  display: inline-flex; align-items: center; justify-content: center; padding: 0 5px; }
.cns-day-h { display: flex; align-items: center; margin-bottom: 8px; }
.cns-row { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 8px;
  border: none; border-top: 1px solid var(--line); background: none; cursor: pointer;
  font: inherit; text-align: left; color: var(--ink); }
.cns-row:hover { background: var(--accent-tint); }
.cns-row-t { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.cns-row-name { font-weight: 600; }
.cns-row-topic { flex: 1; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.cns-modal { max-width: 560px; padding: 16px 20px; }
.cns-modal-h { display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px; }
.cns-modal-body { display: flex; flex-direction: column; gap: 10px; max-height: 70vh;
  overflow-y: auto; }
.cns-field { display: flex; flex-direction: column; gap: 4px; }
.cns-field-l { font-size: 12px; color: var(--ink-3); }
.cns-input { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px;
  font: inherit; color: var(--ink); background: var(--surface, #fff); }
.cns-ta { resize: vertical; }
.cns-modal-foot { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.cns-del { color: var(--bad); }
@media (max-width: 640px) { .cns-cell { min-height: 44px; } .cns-modal { width: 94vw; } }
@media (max-width: 360px) { .cns-grid { gap: 3px } .cns-cell { min-width: 0; padding: 4px } }

/* ── 생기부 탭 ── */
.rec-row { display: flex; align-items: center; gap: 8px; border-top: 1px solid var(--line); }
.rec-row:first-child { border-top: none; }
.rec-row-main { display: flex; align-items: center; gap: 10px; flex: 1; padding: 12px 8px;
  border: none; background: none; cursor: pointer; font: inherit; text-align: left; color: var(--ink); }
.rec-row-main:hover { background: var(--accent-tint); }
.rec-row-target { color: var(--ink-3); font-size: 13px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 40%; }
.rec-row-acts { display: flex; gap: 6px; padding-right: 8px; }
.rec-preview { font-size: 13px; }

/* ── 과제 캘린더 (asgn-calendar.js) ── */
[data-assignment-disclosure],
.acal-chip,
.acal-day-action,
.acal-due{min-width:44px;min-height:44px}
.acal { margin-top: 12px; }
.acal-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.acal-title { font-family: var(--display); }
.acal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.acal-dow { text-align: center; font-size: 12px; color: var(--text-muted); padding: 4px 0; }
.acal-cell { min-height: 84px; border: 1px solid var(--line); border-radius: 8px;
  padding: 4px; background: var(--surface); display: flex; flex-direction: column; gap: 3px; }
.acal-cell.acal-pad { border: 0; background: transparent; }
.acal-cell.acal-today { outline: 2px solid var(--accent); outline-offset: -2px; }
.acal-cell.acal-clickable { cursor: pointer; }
.acal-cell.acal-clickable:hover { box-shadow: var(--shadow-card); }
.acal-cell.acal-over { background: var(--surface-2); }
.acal-dnum { font-size: 12px; color: var(--text-muted); }
.acal-day-action,.acal-due{appearance:none;border:0;background:transparent;color:inherit;font:inherit;text-align:left}
.acal-chip { display: flex; align-items: center; gap: 4px; width: 100%; text-align: left;
  border: 1px solid var(--line); border-radius: 6px; padding: 2px 6px; font-size: 12px;
  background: var(--surface); color:var(--text); cursor: pointer; }
.acal-chip:hover { box-shadow: var(--shadow-card); }
.acal-chip-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.acal-dragging { opacity: .4; }
.acal-due { display:flex;align-items:center;gap:4px;width:100%;border:0;background:transparent;color:var(--text-muted);font-size:var(--type-label);text-align:left;cursor:pointer;overflow:hidden }
.acal-due-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acal-mlist { display: none; }
.acal-mday { border: 1px solid var(--line); border-radius: 8px; padding: 8px; margin-bottom: 8px;
  display: flex; flex-direction: column; gap: 4px; background: var(--surface); }
.acal-mdate { font-size: 13px; font-weight: 600; }
.acal-mempty { font-size: 12px; color: var(--text-muted); margin: 0; }
@media (max-width: 900px) {
  .acal-grid { display: none; }
  .acal-mlist { display: block; }
}

/* ── 입시DB 탭 ── */
/* 필터 바: 인풋·셀렉트·버튼이 같은 높이(--control-standard)·같은 라운드(control 8px)로
   한 줄에 정렬된다. 예전엔 .cns-input(상담 탭 소유)을 빌려 써 높이가 버튼과 어긋났다. */
.adb-filter-card { padding: 12px 14px; }
.adb-filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.adb-input { min-height: var(--control-standard); padding: 0 12px;
  border: 1px solid var(--control-border); border-radius: var(--radius-control);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 13px;
  box-shadow: var(--shadow-control); }
.adb-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
select.adb-input { cursor: pointer; flex: 0 0 auto; }
.adb-search { flex: 1 1 240px; min-width: 180px; display: flex; }
.adb-search .adb-q { flex: 1; min-width: 0; }
.adb-filters .btn { flex: 0 0 auto; min-height: var(--control-standard); }
@media (max-width: 768px) {
  .adb-filters .adb-input, .adb-filters .btn { min-height: var(--control-touch); }
  .adb-search { flex-basis: 100%; }
  select.adb-input { flex: 1 1 45%; }
}
.adb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 12px; margin-top: 12px; }
.adb-card { padding: 14px 16px; }
.adb-card-h { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.adb-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 10px; }
.adb-src { font-size: 12px; }
.adb-date { font-size: var(--type-label); color: var(--ink-4);
  font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.adb-dot { color: var(--ink-4); }

/* ── 입시DB 대학 카드(클릭 → 상세 시트) ──
   카드 1장 = 대학 1곳. 위계는 위에서 아래로 한 방향으로만 약해진다:
   대학명 17px/700 → 지역·전형수 12.5px/ink-3 → 분포 바(형태) → 상태·확인일 12px/ink-4.
   예전엔 트랙 태그·전형 수·상태 태그가 모두 같은 무게라 눈이 어디에도 걸리지 않았다. */
.adb-uni-card { display: flex; flex-direction: column; gap: 7px; }
.adb-uni-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.adb-uni-name { font-size: 17px; font-weight: 700; line-height: 1.3; letter-spacing: -.01em; }
.adb-uni-meta { margin: -2px 0 2px; display: flex; align-items: center; gap: 5px;
  font-size: var(--type-meta); color: var(--ink-3); }
.adb-uni-n { font-variant-numeric: tabular-nums; }
/* 트랙 분포 바 — 이 대학이 어떤 전형에 무게를 싣는지 숫자보다 형태로 먼저 읽힌다. */
.adb-track-bar { display: flex; height: 6px; border-radius: var(--radius-pill);
  overflow: hidden; background: var(--surface-2); }
.adb-track-seg { display: block; min-width: 3px; }
.adb-track-seg.is-t1,.adb-track-dot.is-t1{background:var(--chart-1)}
.adb-track-seg.is-t2,.adb-track-dot.is-t2{background:var(--chart-2)}
.adb-track-seg.is-t3,.adb-track-dot.is-t3{background:var(--chart-3)}
.adb-track-seg.is-to,.adb-track-dot.is-to{background:var(--chart-other)}
.adb-track-seg,.adb-track-dot{box-shadow:inset 0 0 0 1px var(--data-mark-edge)}
.adb-track-legend { display: flex; flex-wrap: wrap; gap: 4px 12px;
  font-size: var(--type-label); color: var(--ink-3); }
.adb-track-lg { display: inline-flex; align-items: center; gap: 5px; }
.adb-track-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); flex: none; }
.adb-track-n { font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* 상태 — 모든 카드에 반복되는 '자동 수집·미검수'는 태그(색면)에서 점+글자로 낮췄다.
   예외 신호(요강 변경)만 색을 갖는다. 카드 사이를 훑을 때 눈에 걸리는 건 예외뿐이어야 한다. */
.adb-uni-state { display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--type-label); color: var(--ink-3); min-width: 0; }
.adb-state-dot { width: 6px; height: 6px; border-radius: var(--radius-pill);
  background: var(--ink-4); flex: none; }
.adb-uni-state.is-ok .adb-state-dot { background: var(--ok); }
.adb-uni-state.is-changed { color: var(--warn-2); font-weight: 600; }
.adb-uni-state.is-changed .adb-state-dot { background: var(--warn); }
.adb-uni-card .adb-foot { margin-top: auto; padding-top: 8px; border-top: 1px solid var(--line-2); }
.adb-trk{display:inline-flex;align-items:center;gap:6px;color:var(--text);
  background:transparent;border:1px solid var(--control-border)}
.adb-trk::before{content:"";width:6px;height:6px;flex:0 0 6px;border-radius:50%;
  background:var(--track-color)}
.adb-trk.is-t1{--track-color:var(--chart-1)}
.adb-trk.is-t2{--track-color:var(--chart-2)}
.adb-trk.is-t3{--track-color:var(--chart-3)}
.adb-trk.is-to{--track-color:var(--chart-other)}
@media (hover: hover) {
  .adb-uni-card { transition: transform .14s, box-shadow .14s, border-color .14s; }
  .adb-uni-card:hover { transform: translateY(-1px); box-shadow: var(--shadow-lg);
    border-color: var(--control-border); }
}
@media (prefers-reduced-motion: reduce) {
  .adb-uni-card { transition: border-color .14s; }
  .adb-uni-card:hover { transform: none; }
}

/* 목록 헤더(건수)·더 보기 — 300장 일괄 렌더 대신 30곳씩 늘린다. */
.adb-count { margin: 14px 0 0; font-size: var(--type-meta); color: var(--ink-3);
  font-variant-numeric: tabular-nums; }
.adb-more { width: 100%; margin-top: 12px; font-size: 13px; color: var(--text-muted);
  background: none; border: 1px dashed var(--border-dash); border-radius: var(--radius-sm); }
.adb-more:hover { border-color: var(--accent); color: var(--accent); }

/* 로딩 스켈레톤 — 카드의 실제 골격(제목·메타·분포 바·푸터)을 그대로 흉내 낸다.
   자리만 잡는 회색 상자였을 때는 결과가 도착하는 순간 형태가 통째로 바뀌었다. */
.adb-skeleton { min-height: 148px; background: var(--surface); border-color: var(--line-2);
  box-shadow: none; display: flex; flex-direction: column; gap: 10px;
  animation: adb-skeleton-pulse 1.3s ease-in-out infinite alternate; }
.adb-sk-line { display: block; border-radius: var(--radius-control); background: var(--surface-2); }
.adb-sk-title { height: 17px; width: 62%; }
.adb-sk-meta { height: 11px; width: 42%; }
.adb-sk-bar { height: 6px; width: 100%; border-radius: var(--radius-pill); margin-top: 2px; }
.adb-sk-foot { height: 11px; width: 54%; margin-top: auto; }
@keyframes adb-skeleton-pulse { from { opacity: .5 } to { opacity: .95 } }
@media (prefers-reduced-motion: reduce) { .adb-skeleton { animation: none; opacity: .7 } }
.adb-skeletons .adb-skeleton:hover { transform: none; box-shadow: none; }

/* ── 상태 4종(로딩·빈·에러·절단)의 단일 문법 ──
   같은 골격(제목 → 설명 → 행동), 같은 여백·라운드. 다른 것은 테두리·배경·제목 색뿐이다.
   예전엔 빈=가운데 정렬 텍스트, 에러=빨간 카드, 절단=노란 알약이라 서로 남남이었다.
   좌측 3px 강조 바는 제거했다 — 상태 구분은 테두리 색 전체가 이미 지고 있다. */
.adb-state { margin-top: 12px; padding: var(--s4); display: flex; flex-direction: column;
  align-items: flex-start; gap: 8px; border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface); }
.adb-state-t { font-size: 14px; font-weight: 700; color: var(--ink); }
.adb-state-d { margin: 0; font-size: 13px; color: var(--ink-2); line-height: 1.55; }
.adb-state-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.adb-state-empty { border-color: var(--control-border); }
.adb-state-error { border-color: var(--bad-line); background: var(--bad-bg); }
.adb-state-error .adb-state-t { color: var(--bad); }
.adb-state-trunc { border-color: var(--warn); background: var(--warn-bg); }
.adb-state-trunc .adb-state-t { color: var(--warn-2); }

/* ── mv-map: 지역 지도(choropleth) ── */
.mv-map{position:relative}
.mv-map-stage{position:relative}
.mv-map-stage svg{width:100%;max-height:520px;display:block}
/* 지역면: 기본은 조용하게, hover는 '들 수 있다'는 신호를 준다.
   예전엔 opacity .82 만 걸려 색이 바래는 느낌이라 어느 도형에 있는지 알기 어려웠다.
   → 흰 stroke를 굵혀 도형 경계를 띄우고(주변보다 앞에 놓인 것처럼 보인다) 살짝만 밝힌다.
   stroke는 non-scaling이라 드릴다운 배율과 무관하게 화면상 두께가 일정하다. */
.mv-map-region{stroke:var(--surface,#fff);stroke-width:.8;
  transition:stroke-width .14s ease,filter .14s ease,opacity .14s ease}
.mv-map-region.is-clickable{cursor:pointer}
.mv-map-region.is-clickable:hover{stroke-width:2.2;opacity:.92;
  filter:brightness(1.06) drop-shadow(0 2px 5px rgba(26,32,53,.30))}
/* fill=SVG 지역면, background=범례 칩(<i>). 두 표면이 같은 색을 공유. */
.mv-map-q0{fill:var(--map-q0,#EDF0F8);background:var(--map-q0,#EDF0F8)}
.mv-map-q1{fill:var(--map-q1,#C3CFEC);background:var(--map-q1,#C3CFEC)}
.mv-map-q2{fill:var(--map-q2,#8FA5DC);background:var(--map-q2,#8FA5DC)}
.mv-map-q3{fill:var(--map-q3,#5273C4);background:var(--map-q3,#5273C4)}
.mv-map-q4{fill:var(--map-q4,#1F3A8F);background:var(--map-q4,#1F3A8F)}
:root[data-theme="black"] .mv-map-q0{fill:#232735;background:#232735}
:root[data-theme="black"] .mv-map-q1{fill:#33405e;background:#33405e}
:root[data-theme="black"] .mv-map-q2{fill:#46599c;background:#46599c}
:root[data-theme="black"] .mv-map-q3{fill:#5f7fd9;background:#5f7fd9}
:root[data-theme="black"] .mv-map-q4{fill:#93aef2;background:#93aef2}
/* 라벨: 어두운 단계(q3·q4) 위에서도 읽히도록 흰 후광을 깐다(paint-order로 획을 글자
   뒤에 그린다 — 획이 글자를 갉아먹지 않는다). 색 자체는 본문 잉크 그대로.
   ⚠️ 획 굵기는 반드시 글자 크기에 비례(em)해야 한다. 절대값(옛 2.6px=2.6 유저단위)은
   viewBox 가 레벨마다 달라 드릴다운에서 폭발했다 — 시군 뷰의 font-size 는 0.412
   유저단위라 2.6 은 6.3em, 글자마다 흰 알약을 뒤집어쓰고 25개가 지형을 통째로 가렸다.
   0.2em = 바깥으로 0.1em 만 번지는 윤곽선 — 배경 판이 아니라 획으로만 대비를 만든다.
   (#349 때는 A+ 비대상 지도의 골든 픽셀을 지키려 시맨틱 식스로 스코프했으나, #402 에서
    지석이 재기준선을 승인해 기본 규칙으로 되돌린다 — 결함을 골든에 박제할 이유가 없다.) */
.mv-map-label{fill:var(--text,#1a1d24);pointer-events:none;text-anchor:middle;
  dominant-baseline:central;font-weight:600;
  paint-order:stroke;stroke:var(--surface,#fff);stroke-width:.2em;stroke-linejoin:round}
:root[data-theme="black"] .mv-map-label{fill:var(--text,#e6e8ee);stroke:#141416}
.mv-map-pin{fill:var(--accent,#456AFF);stroke:#fff;stroke-width:1;cursor:pointer;
  transition:r .12s ease}
.mv-map-pin:hover{stroke-width:2}
/* ── 인셋(제주·울릉도) ──
   본토에서 멀리 떨어진 조각을 같은 축척으로 그리면 사이 바다가 bbox를 지배한다
   (전체 630.6×669.3 → 본토만 497.2×558.6). 교과서·선거방송 관행대로 별도 창으로 뗀다.
   창은 '지도의 일부지만 다른 축척'임이 보이도록 파선 테두리 + 캡션을 붙인다. */
.mv-map-inset-frame{fill:none;stroke:var(--control-border,#c8cfdb);stroke-width:1;
  stroke-dasharray:4 3;pointer-events:none}
.mv-map-inset-cap{fill:var(--text-muted,#5b6472);text-anchor:middle;pointer-events:none;
  font-weight:600}
:root[data-theme="black"] .mv-map-inset-cap{fill:var(--text-muted,#a8a8b4)}
/* 인셋 진입 버튼(#399): 창 전체가 하나의 탭 타깃이다. 칠하지 않으므로 평상시 픽셀은
   그대로고, pointer-events:all 이 fill 없이도 창 내부를 잡는다. 섬 도형은 손가락보다
   작고 흩어져 있어(백령·대청은 도형 bbox 중심이 섬 사이 바다) 도형만으로는 탭이 성립하지
   않았다. 상태는 바로 뒤 형제인 테두리에 얹는다 — 핀 히트(:focus-visible+.mv-map-pin)와
   같은 방식이라 '보이지 않는 히트 영역 + 보이는 표식'이 지도 안에서 한 물건으로 읽힌다.
   투명 획은 창을 손가락 크기로 키우는 여백이다 — 핀 히트가 쓰는 수법과 같다(획 영역도
   pointer-events:all 이 잡는다). 단위는 SVG 유저단위라 화면 폭에 비례한다: 20 유저단위 =
   사방 10 유저단위 ≈ 320 에서 6.4px · 393 에서 7.8px · 1440 에서 14px. 이 여백까지 더해야
   최소 화면(320)의 백령·대청도 44px 계약을 넘는다(35.3×62.7 → 44.8×72.2 실측).
   테두리 바깥 띠를 96점씩 훑어 svg·stage·컨테이너·크럼 말고는 아무것도 없음을 확인하고
   넣었다 — 어떤 도형의 탭도 빼앗지 않는다. ⚠️ getBoundingClientRect 는 이 획을 빼고
   보고한다(Chromium) — 계약 측정치보다 실제 탭 영역이 항상 크다. */
.mv-map-inset-hit{fill:none;stroke:transparent;stroke-width:20;
  pointer-events:all;cursor:pointer;outline:none}
.mv-map-inset-hit:hover+.mv-map-inset-frame{stroke:var(--accent);stroke-dasharray:none}
.mv-map-inset-hit:focus-visible+.mv-map-inset-frame{
  stroke:var(--focus-ring);stroke-width:2.4;stroke-dasharray:none
}
/* 브레드크럼: 지나온 단계=링크, 현재 단계=본문 굵게, 사이에 옅은 구분자. */
.mv-map-crumb{display:flex;gap:2px;align-items:center;margin-bottom:8px;flex-wrap:wrap}
.mv-map-crumb-btn{border:0;background:none;color:var(--ink-3,#5b6472);cursor:pointer;
  padding:3px 6px;border-radius:var(--radius-control,8px);font:inherit;
  font-size:var(--type-meta,12.5px);font-weight:600}
.mv-map-crumb-btn:hover:not(:disabled){background:var(--surface-2,#eef1f6);color:var(--ink,#1a2035)}
.mv-map-crumb-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.mv-map-crumb-btn:disabled{color:var(--text,#1a1d24);cursor:default;font-weight:700}
.mv-map-crumb-sep{color:var(--ink-4,#aab2c2);font-size:var(--type-label,12px)}
/* 범례: 단위 라벨 + 색 칩·구간이 한 덩어리로 묶여 흐른다(칩과 숫자가 따로 놀지 않게).
   pointer-events:none — 범례는 읽는 것이지 누르는 것이 아니다. 좁은 폭에서 지도 쪽으로
   올라오던 시절 제주 인셋 탭을 통째로 삼켰다(실기기 실측). 레이아웃으로 이미 겹침을
   없앴지만, 이 선언이 '겹쳐도 조작은 지도가 받는다'를 구조로 보장한다. */
.mv-map-legend{display:flex;gap:10px;align-items:center;margin-top:8px;flex-wrap:wrap;
  pointer-events:none;
  font-size:var(--type-label,12px);color:var(--text-muted,#5b6472)}
.mv-map-legend-unit{font-weight:700;color:var(--ink-3,#5b6472)}
.mv-map-legend-scale{display:inline-flex;align-items:center;gap:0;
  border:1px solid var(--line-2,#edf0f5);border-radius:var(--radius-control,8px);
  padding:3px;background:var(--surface,#fff)}
.mv-map-legend-item{display:inline-flex;align-items:center;gap:5px;padding:0 7px 0 5px}
.mv-map-legend-item+.mv-map-legend-item{border-left:1px solid var(--line-2,#edf0f5)}
.mv-map-legend-item i{display:inline-block;width:11px;height:11px;border-radius:3px;
  border:1px solid rgba(26,32,53,.08);flex:none}
.mv-map-legend-l{font-variant-numeric:tabular-nums}
/* 좁은 폭 컴팩트: 시맨틱 식스의 구간 문구("1 이상 · 2 미만")가 53px 칸 안에서 3~4줄로
   꺾여 범례 상자가 90.5px까지 부풀었다(393폭 실측). 글자는 안 꺾고 '칸'을 접는다 —
   6칸이 두 줄로 정렬되며 상자가 65.5px로 준다. 문구 자체는 A+ 시맨틱 계약이라 불변. */
@media (max-width:768px){
  .mv-map-legend-scale{flex-wrap:wrap;justify-content:center}
  .mv-map-legend-l{white-space:nowrap}
  .mv-map-legend-item{padding:1px 6px}
}
/* 툴팁: 흰 알약 → 다크 칩. 지역명(제목)과 수치(값)를 굵기·크기로 갈라 위계를 준다. */
/* ⚠️ display 를 클래스에서 선언하는 순간 UA 의 [hidden]{display:none} 이 진다(작성자
   스타일시트가 UA 를 이긴다). 그래서 JS 의 tip.hidden=true 가 무효였고 — 드릴다운
   복귀 뒤에도 "서울 5곳" 칩이 지도 위에 그대로 떠 있었다(실측). 숨김을 명시로 복원한다.
   (#349 때는 excluded 골든 보존을 위해 시맨틱 식스로 스코프했으나, #402 에서 지석이
    재기준선을 승인해 기본 규칙으로 되돌린다 — 모든 mvMap 소비자가 같은 숨김 계약을 쓴다.) */
.mv-map-tip[hidden]{display:none}
.mv-map-tip{position:absolute;display:flex;align-items:baseline;gap:7px;
  background:var(--ink,#1a2035);color:#fff;border:0;border-radius:var(--radius-control,8px);
  padding:6px 10px;font-size:var(--type-label,12px);pointer-events:none;
  box-shadow:var(--shadow-high,0 12px 34px -14px rgba(26,32,53,.22));z-index:5;white-space:nowrap}
:root[data-theme="black"] .mv-map-tip{background:#2a2a31;color:var(--text,#ececf0)}
.mv-map-tip-t{font-weight:700;font-size:var(--type-meta,12.5px)}
.mv-map-tip-v{color:rgba(255,255,255,.72);font-variant-numeric:tabular-nums}
/* ── signature: 드릴다운 zoom 전환 ──
   떠나는 화면은 누른 지역 쪽으로 확대되며 사라지고 새 화면이 그 프레임에서 떠오른다.
   고스트는 stage 위 절대배치라 레이아웃에 영향이 없고, transform/opacity만 움직여
   합성 단계에서 끝난다(리플로 0). */
.mv-map-ghost{position:absolute;left:0;right:0;top:0;margin-inline:auto;pointer-events:none;z-index:2;
  transform-origin:0 0;opacity:1;transition:transform .22s cubic-bezier(.4,0,.2,1),opacity .22s ease-out}
.mv-map-ghost svg{width:100%;height:100%;display:block}
.mv-map-ghost.is-out{opacity:0}
.mv-map-stage svg{transition:opacity .22s ease-out}
.mv-map-stage svg.is-in{opacity:0}
@media (prefers-reduced-motion:reduce){
  .mv-map-ghost{display:none}
  .mv-map-stage svg,.mv-map-region,.mv-map-pin{transition:none}
  .mv-map-region.is-clickable:hover{filter:none;stroke-width:2.2}
}

.mv-map-region-list-btn{min-width:44px;min-height:44px}
.mv-map.mv-map--semantic-six.is-pending .mv-map-region.is-clickable{pointer-events:none}
/* 렌더 대기 중에는 인셋 진입 버튼도 함께 얼린다 — 도형과 같은 규칙, 별도 줄로 둔 이유는
   위 리터럴이 정적 계약(test_map_view_static)이라 합치면 계약이 깨져서다. */
.mv-map.mv-map--semantic-six.is-pending .mv-map-inset-hit{pointer-events:none}
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six{
  --map-q0:#e9e8ed;
  --map-q1:#f0eef8;--map-q1a:#f1eff5;--map-q1b:#eeeefb;
  --map-q2:#dcd5f4;--map-q2a:#ddd8ee;--map-q2b:#d9d1fa;
  --map-q3:#b8a9e8;--map-q3a:#aaaee4;--map-q3b:#c5a3ec;
  --map-q4:#8873cf;--map-q4a:#718bd6;--map-q4b:#9b6ed1;
  --map-q5:#56429b;--map-q5a:#455da8;--map-q5b:#673185;
  --map-ink-light:#fbf9ff;--map-ink-dark:#100c1d;
  --map-boundary-light:#fbf9ff;--map-boundary-dark:#261b53
}
:root[data-theme="black"] .mv-map.mv-map--semantic-six{
  --map-q0:#17171b;
  --map-q1:#1d1c2c;--map-q1a:#1b1926;--map-q1b:#201f35;
  --map-q2:#342c5e;--map-q2a:#2d2652;--map-q2b:#3d346b;
  --map-q3:#5b4b9f;--map-q3a:#4d3e8f;--map-q3b:#6958b1;
  --map-q4:#8c75df;--map-q4a:#826cdb;--map-q4b:#9d87ea;
  --map-q5:#c9baff;--map-q5a:#b5a3f7;--map-q5b:#ded2ff;
  --map-ink-light:#fbf9ff;--map-ink-dark:#100c1d;
  --map-boundary-light:#fbf9ff;--map-boundary-dark:#09090b
}

:root .mv-map.mv-map--semantic-six .mv-map-q0{fill:var(--map-q0);background:var(--map-q0)}
:root .mv-map.mv-map--semantic-six .mv-map-q1{fill:var(--map-q1);background:var(--map-q1)}
:root .mv-map.mv-map--semantic-six .mv-map-q2{fill:var(--map-q2);background:var(--map-q2)}
:root .mv-map.mv-map--semantic-six .mv-map-q3{fill:var(--map-q3);background:var(--map-q3)}
:root .mv-map.mv-map--semantic-six .mv-map-q4{fill:var(--map-q4);background:var(--map-q4)}
:root .mv-map.mv-map--semantic-six .mv-map-q5{fill:var(--map-q5);background:var(--map-q5)}

/* Map E Periwinkle 범례 칩 q1~q5 — 브리프 지정 135deg 쌍(SVG paint server는 좌하→우상 대각으로 별도 방향).
   q0 칩은 위 기본 규칙의 단색(var(--map-q0))을 그대로 쓴다. 지역면(fill)은 렌더러가
   render-local url(#...)로 칠하므로 여기서는 시맨틱 범례 배경만 소유한다. */
:root .mv-map.mv-map--semantic-six .mv-map-legend-item i.mv-map-q1{background:linear-gradient(135deg, var(--map-q1a), var(--map-q1b))}
:root .mv-map.mv-map--semantic-six .mv-map-legend-item i.mv-map-q2{background:linear-gradient(135deg, var(--map-q2a), var(--map-q2b))}
:root .mv-map.mv-map--semantic-six .mv-map-legend-item i.mv-map-q3{background:linear-gradient(135deg, var(--map-q3a), var(--map-q3b))}
:root .mv-map.mv-map--semantic-six .mv-map-legend-item i.mv-map-q4{background:linear-gradient(135deg, var(--map-q4a), var(--map-q4b))}
:root .mv-map.mv-map--semantic-six .mv-map-legend-item i.mv-map-q5{background:linear-gradient(135deg, var(--map-q5a), var(--map-q5b))}

:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q0,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q1,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q2,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q3,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q4{
  stroke:var(--map-boundary-dark)
}
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q5{
  stroke:var(--map-boundary-light)
}
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q0,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q1,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q2,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q3{
  stroke:var(--map-boundary-light)
}
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q4,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-region.mv-map-q5{
  stroke:var(--map-boundary-dark)
}

/* 라벨 후광 굵기(.2em)는 #402 에서 기본 규칙(.mv-map-label)으로 올라갔다 — 시맨틱 식스
   전용 override 는 계산값이 같아 중복이라 지웠다. 그 블록의 주석 참조. */

:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q0,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q1,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q2,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q3,
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q4{
  color:var(--map-ink-dark);fill:currentColor;stroke:var(--map-boundary-light)
}
:root:not([data-theme="black"]) .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q5{
  color:var(--map-ink-light);fill:currentColor;stroke:var(--map-boundary-dark)
}
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q0,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q1,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q2,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q3{
  color:var(--map-ink-light);fill:currentColor;stroke:var(--map-boundary-dark)
}
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q4,
:root[data-theme="black"] .mv-map.mv-map--semantic-six .mv-map-label.mv-map-q5{
  color:var(--map-ink-dark);fill:currentColor;stroke:var(--map-boundary-light)
}

:root .mv-map.mv-map--semantic-six .mv-map-region{
  stroke-width:1;vector-effect:non-scaling-stroke
}
:root .mv-map.mv-map--semantic-six .mv-map-region.is-clickable:hover,
:root .mv-map.mv-map--semantic-six .mv-map-region.is-clickable:active,
:root .mv-map.mv-map--semantic-six .mv-map-region.is-selected{
  opacity:1;filter:drop-shadow(var(--shadow-control));stroke-width:2.2
}
:root .mv-map.mv-map--semantic-six .mv-map-region.is-clickable:focus-visible{
  outline:none;opacity:1;filter:drop-shadow(var(--shadow-control));stroke-width:3.2
}
.mv-map--semantic-six .mv-map-pin-hit{
  fill:transparent;stroke:transparent;stroke-width:44px;
  vector-effect:non-scaling-stroke;pointer-events:stroke;cursor:pointer
}
.mv-map--semantic-six .mv-map-pin{pointer-events:none}
.mv-map--semantic-six .mv-map-pin-hit:focus-visible+.mv-map-pin{
  stroke:var(--focus-ring);stroke-width:3
}
.adb-region-list{list-style:none;margin:0;padding:0;display:grid}
.adb-region-list-item+.adb-region-list-item{border-top:1px solid var(--border)}
.adb-region-list-button{width:100%;min-height:44px;padding:10px 0;display:grid;
  grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:center;text-align:left;
  background:transparent;color:var(--text);border:0}
.adb-region-list-button:disabled{color:var(--text-muted)}
.adb-region-list-button:focus-visible{outline:none;
  box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)}
.adb-region-list-name{min-width:0;font-weight:700}
.adb-region-list-value{color:var(--text-muted);font-variant-numeric:tabular-nums}

/* ── 입시DB 지도+카드 통합 화면: 지도 카드 + 핀 상세 패널 ── */
/* 지도와 카드 목록이 한 화면에 공존한다. 블록 간 간격은 .adb-grid gap(12px)과 맞춘다. */
.adb-map-card{padding:12px 14px;margin-bottom:12px;cursor:default}
.adb-map-card:hover{box-shadow:var(--shadow);transform:none}   /* 지도는 클릭 카드가 아님 — 리프트 제거 */
/* 지도 확대: 공용 기본(max-height 520px)은 그대로 두고 이 탭에서만 키운다.
   높이 780px = 1.5배. viewBox 종횡비(--mv-map-ar, map-view.js 주입)로 폭을 맞춰
   좌우 빈 공간 없이 컨테이너에 밀착시킨다.
   ※ 아래 '주인공 지도' 블록이 이 규칙을 덮어써 실제 높이는 min(78vh,940px)이다.
     이 선언은 정적 계약(test_admdb_map_static)이 문자열로 고정하고 있어 남겨 둔다. */
.adb-map-card .mv-map-stage{display:flex;justify-content:center}
.adb-map-card .mv-map-stage svg{max-height:780px;width:auto;max-width:100%;
  aspect-ratio:var(--mv-map-ar,1)}
/* ── 지도를 화면의 주인공으로 ──
   ① bleed: 지도 블록만 카드 좌우 패딩을 벗어나 콘텐츠 폭을 100% 쓴다.
   ② 높이 예산 --adb-map-h: 뷰포트 기준 min(88vh,1040px) — 1440×900에서 약 790px.
   ③ 낭비 0 fit: 폭을 '가용폭'과 '높이예산×종횡비' 중 작은 값으로 잡고 높이는 종횡비로
      역산한다(height:auto + aspect-ratio). SVG는 preserveAspectRatio 기본값이라 박스
      종횡비가 viewBox와 다르면 안쪽에서 레터박스가 생긴다 — 실제로 width:100%만 주었을 때
      폭의 42.6%가 빈 상자였다. 이 식은 박스=viewBox 종횡비라 여백이 0이다.
      · 전국(세로로 긴 종횡비 0.73): 높이 예산을 다 쓰고 폭이 결정된다.
      · 시도 드릴다운(가로로 넓음): 폭이 콘텐츠 폭을 꽉 채우고 높이가 줄어든다. */
.adb-map-card{--adb-map-h:min(88vh,1040px);padding:12px 0 10px}
.adb-map-card .mv-map{padding:0}
.adb-map-card .mv-map-crumb,
.adb-map-card .mv-map-legend{padding:0 14px}
.adb-map-card .mv-map-stage{display:block}
.adb-map-card .mv-map-stage svg{
  width:min(100%, calc(var(--adb-map-h) * var(--mv-map-ar,1)));
  height:auto;max-height:none;aspect-ratio:var(--mv-map-ar,1);margin:0 auto}
/* 확대된 지도 주변 여백은 상대적으로 과해 보인다 → 크럼·범례를 타이트하게. */
.adb-map-card .mv-map-crumb{margin-bottom:4px}
.adb-map-card .mv-map-legend{margin-top:4px}

/* ── 상세 시트(대학 카드 클릭·지도 핀 클릭 공통) ──
   예전엔 지도 위 인라인 패널이라 목록에서 카드를 눌러도 갈 곳이 없었다. 이제 하나의
   시트가 두 진입점을 모두 받는다. 데스크톱=중앙 모달, 모바일=바텀시트. */
#adb-map-detail{position:fixed;inset:0;z-index:var(--z-overlay);display:flex;
  align-items:center;justify-content:center;padding:var(--s4);background:var(--overlay);margin:0;border:0}
#adb-map-detail[hidden]{display:none}
/* 등장: 백드롭은 페이드, 시트는 아주 짧게 아래에서 올라온다(200ms 이내). 모션은
   '어디서 왔는지'만 말하고 사라진다 — 장식적 스프링·바운스 금지. */
@keyframes adb-sheet-back{from{opacity:0}to{opacity:1}}
@keyframes adb-sheet-in{from{opacity:0;transform:translateY(10px) scale(.985)}
  to{opacity:1;transform:none}}
#adb-map-detail:not([hidden]){animation:adb-sheet-back .16s ease-out}
.adb-sheet{width:min(680px,100%);max-height:min(82vh,760px);display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-overlay);
  box-shadow:var(--shadow-high);overflow:hidden;
  animation:adb-sheet-in .2s cubic-bezier(.4,0,.2,1)}
@media (prefers-reduced-motion:reduce){
  #adb-map-detail:not([hidden]),.adb-sheet{animation:none}
}
/* 머리말 고정 — 대학명이 스크롤에 밀려 사라지면 어느 대학을 보는지 잃는다.
   .is-stuck(본문이 스크롤된 상태)에서만 그늘이 켜져 '위에 더 있다'가 보인다. */
.adb-sheet-head{position:relative;z-index:1;flex:0 0 auto;display:flex;align-items:flex-start;
  justify-content:space-between;gap:var(--s3);padding:var(--s4);
  border-bottom:1px solid var(--line-2);background:var(--surface);
  transition:box-shadow .16s ease}
.adb-sheet-head.is-stuck{box-shadow:var(--shadow-control)}
.adb-sheet-heads{min-width:0}
.adb-sheet-title{margin:0;font-size:19px;font-weight:700;color:var(--ink);letter-spacing:-.01em}
.adb-sheet-sub{margin:3px 0 0;font-size:var(--type-meta);color:var(--ink-3)}
.adb-sheet-acts{display:flex;align-items:center;gap:6px;flex:0 0 auto}
.adb-sheet-x{background:none;border:1px solid var(--control-border);border-radius:var(--radius-control);
  color:var(--ink-2);cursor:pointer;font-size:13px;padding:6px 12px;min-height:var(--control-dense);flex:0 0 auto}
.adb-sheet-x:hover{border-color:var(--accent);color:var(--accent)}
.adb-sheet-x:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.adb-sheet-guide{min-height:var(--control-dense)}
/* flex column + overflow-y:auto 조합에서 자식은 기본적으로 '줄어들어' 스크롤이 생기지
   않는다(실측: 8그룹·210행이 들어 있는데 scrollHeight == clientHeight, 1508px 표가
   417px로 눌리고 행 높이가 43px로 뭉갬). 자식 축소를 끄면 실제 높이를 되찾아 스크롤된다. */
.adb-sheet-body{padding:var(--s4);overflow-y:auto;display:flex;flex-direction:column;gap:8px;
  overscroll-behavior:contain}
.adb-sheet-body>*{flex:0 0 auto}
.adb-sheet-count{margin:0 0 2px;font-size:var(--type-meta);color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.adb-sheet-count strong{color:var(--ink-2)}
.adb-sheet-empty{margin:0;font-size:13px;color:var(--ink-2);padding:8px 2px}
/* ── 전형 그룹(= <details>) ──
   서버는 '전형 × 학과' 곱집합을 준다. 강원대 811행 = 전형 33개 × 학과들 — 예전 시트는
   같은 전형명·전형방법·일정을 112번 반복해 찍었다. 이제 전형이 한 덩어리고, 학과는
   그 안의 표다. 머리말(항상 보임)에는 전형명·트랙·모집인원·수능최저만 둔다. */
.adb-grp{border:1px solid var(--line);border-radius:var(--radius-card);background:var(--surface);
  overflow:hidden}
.adb-grp[open]{border-color:var(--control-border)}
.adb-grp-h{display:flex;flex-direction:column;gap:7px;padding:11px 13px;cursor:pointer;
  list-style:none;position:relative;padding-right:36px}
.adb-grp-h::-webkit-details-marker{display:none}
.adb-grp-h:hover{background:var(--surface-3)}
.adb-grp-h:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.adb-grp-top{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.adb-grp-name{font-size:14.5px;font-weight:700;color:var(--ink);line-height:1.35}
/* 트랙 배지 — 카드의 분포 바와 같은 색 슬롯을 쓴다(같은 전형=같은 색, 화면이 바뀌어도). */
.adb-trk{display:inline-flex;align-items:center;gap:6px;color:var(--text);
  background:transparent;border:1px solid var(--control-border);font-size:var(--type-label);
  font-weight:700;padding:2px 8px;border-radius:var(--radius-pill);flex:0 0 auto;line-height:1.5}
.adb-trk::before{content:"";width:6px;height:6px;flex:0 0 6px;border-radius:50%;
  background:var(--track-color)}
.adb-trk.is-t1{--track-color:var(--chart-1)}
.adb-trk.is-t2{--track-color:var(--chart-2)}
.adb-trk.is-t3{--track-color:var(--chart-3)}
.adb-trk.is-to{--track-color:var(--chart-other)}
/* 접힘 아포던스 — 오른쪽 caret이 열림에 따라 회전한다. 눌러도 되는 곳임을 정지 상태에서 보여 준다. */
.adb-grp-caret{position:absolute;right:13px;top:14px;width:8px;height:8px;flex:none;
  border-right:2px solid var(--ink-3);border-bottom:2px solid var(--ink-3);
  transform:rotate(45deg);transition:transform .16s ease}
.adb-grp[open]>.adb-grp-h .adb-grp-caret{transform:rotate(-135deg)}
@media (prefers-reduced-motion:reduce){.adb-grp-caret{transition:none}}
.adb-grp-meta{display:flex;flex-wrap:wrap;gap:6px}
.adb-chip{display:inline-flex;align-items:baseline;gap:5px;font-size:var(--type-label);
  background:var(--surface-2);border-radius:var(--radius-pill);padding:3px 10px;max-width:100%}
.adb-chip-l{color:var(--ink-3);flex:0 0 auto}
.adb-chip-v{font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.adb-chip.is-off .adb-chip-v{color:var(--ink-3);font-weight:500}
.adb-grp-b{padding:0 13px 12px;display:flex;flex-direction:column;gap:9px;
  border-top:1px solid var(--line-2);padding-top:11px}
/* 전형 공통 정보(전형방법·일정) — 그룹에서 값이 하나일 때만 여기 온다. */
.adb-grp-line{display:flex;gap:9px;font-size:12.5px;line-height:1.55}
.adb-grp-line-l{flex:0 0 56px;color:var(--ink-3);font-weight:700}
.adb-grp-line-v{flex:1;min-width:0;color:var(--ink-2);word-break:break-word}
/* 모집단위(학과) 표 — 학과명 / 인원 / (그룹 안에서 다를 때만) 수능최저. */
.adb-majors{display:flex;flex-direction:column;border:1px solid var(--line-2);
  border-radius:var(--radius-control);overflow:hidden}
.adb-major-row{display:flex;align-items:baseline;gap:10px;padding:6px 10px;font-size:12.5px;
  border-bottom:1px solid var(--line-2)}
.adb-major-row:last-child{border-bottom:0}
.adb-major-row.is-head{background:var(--surface-2);font-size:var(--type-label);font-weight:700;
  color:var(--ink-3);position:sticky;top:0}
.adb-major-row:not(.is-head):nth-child(even){background:var(--surface-3)}
.adb-major-n{flex:1;min-width:0;color:var(--ink);word-break:break-word}
.adb-major-q{flex:0 0 60px;text-align:right;font-variant-numeric:tabular-nums;color:var(--ink-2)}
.adb-major-m{flex:0 0 40%;color:var(--ink-3);word-break:break-word}
.adb-major-more{align-self:flex-start}
/* 고교 핀 상세(같은 시트 골격) */
.adb-map-track{font-weight:600;color:var(--accent)}
/* 지도 데이터 소스 토글([대학|고교]) — 공용 .segmented 문법. 고교 데이터가 있을 때만 렌더. */
.adb-srcbar{margin:0 14px 8px}
.adb-srcbar button[aria-pressed="true"]{background:var(--surface);color:var(--ink);
  border-color:var(--control-border);box-shadow:var(--shadow-control)}
/* 위 pressed 규칙은 공용 포커스 규칙(.segmented button:focus-visible)과 특정도가 (0,2,1)로 같고
   소스상 뒤에 와서 box-shadow 링을 덮는다 — outline:none만 남아 '선택됨+포커스'가 무표시가 된다.
   선택 그림자 위에 링을 다시 얹어 4번째 상태를 복원한다(.mob-tab-item[aria-current] 선례와 동일 문법). */
.adb-srcbar button[aria-pressed="true"]:focus-visible{
  outline:none;
  box-shadow:var(--shadow-control),0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)}
/* 현재 지역 범위 칩(지도 드릴다운 ↔ 카드 목록 연동 표시) — 필터 바 아래.
   칩 자체가 해제 버튼이라 '무엇이 걸려 있고 어떻게 푸는지'가 한 자리에 있다. */
.adb-scope{display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap}
.adb-scope-l{font-size:var(--type-label);color:var(--ink-3);font-weight:600}
.adb-scope-chip{font:inherit;font-size:var(--type-label);font-weight:600;gap:7px}
.adb-scope-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.adb-scope-x{opacity:.7;font-size:13px;line-height:1}
.adb-scope-chip:hover .adb-scope-x{opacity:1}
/* 모바일: 지도 높이를 뷰포트에 비례시켜 카드 목록이 접혀 보이지 않게(비율은 aspect-ratio가 유지).
   데스크톱처럼 78vh를 주면 첫 화면이 지도로만 차서 목록이 안 보인다 → 세로 과점유 방지. */
@media (max-width:768px){
  .adb-map-card{--adb-map-h:min(58vh,600px);padding:10px 0 8px}
  .adb-map-card .mv-map-crumb,.adb-map-card .mv-map-legend{padding:0 10px}
  .adb-srcbar{margin:0 10px 8px}
  /* 상세는 바텀시트로 — 엄지 도달 범위, 전체 폭. 아래에서 올라오는 모션도 방향이 맞다. */
  #adb-map-detail{align-items:flex-end;padding:0}
  .adb-sheet{width:100%;max-height:min(84vh,680px);
    border-radius:var(--radius-overlay) var(--radius-overlay) 0 0;border-bottom:0;
    animation-name:adb-sheet-up}
  .adb-sheet-body{padding:var(--s3)}
  .adb-sheet-x,.adb-sheet-guide{min-height:var(--control-touch)}
  /* 좁은 폭에서 수능최저 열까지 넣으면 학과명이 세 글자마다 꺾인다 → 열을 접고
     최저는 학과명 아래 줄로 흐르게 둔다(값 자체는 유지). */
  .adb-major-row{flex-wrap:wrap;gap:2px 10px}
  .adb-major-m{flex:1 1 100%;font-size:var(--type-label)}
  .adb-major-row.is-head .adb-major-m{display:none}
}
@keyframes adb-sheet-up{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
/* 고교 핀 상세: 확보율·교과서 정적 필드 */
.adb-map-rate{font-weight:600;margin:2px 0}
.adb-map-textbook{color:var(--text-muted);margin:2px 0}

/* ── 클래스 게시판 ── */
.board-cats { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.board-cat-chip { border: 1px solid var(--line); border-radius: 999px; padding: 4px 12px;
  background: transparent; color: var(--ink-2); font-size: 13px; cursor: pointer; }
.board-cat-chip.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.board-row { display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 10px 4px; border-bottom: 1px solid var(--line-2); cursor: pointer; }
.board-row:hover { background: var(--bg-2, rgba(0,0,0,.02)); }
.board-row-title { font-weight: 600; color: var(--ink); }
.board-edited { font-size: 12px; color: var(--ink-3); margin-left: 6px; }
.board-row-meta { font-size: 12px; color: var(--ink-3); margin-top: 2px; }
.board-body { white-space: pre-wrap; word-break: break-word; line-height: 1.6; margin: 12px 0; }
.board-file-card { display: flex; align-items: center; gap: 8px; border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 8px 10px; margin-top: 6px; cursor: pointer; font-size: 13px; }
.board-file-card.deleted { cursor: default; color: var(--ink-3); }
.board-cm { padding: 8px 0; border-top: 1px solid var(--line-2); }
.board-cm-child { margin-left: 24px; }
.board-cm-meta { font-size: 12px; color: var(--ink-3); }
.board-cm-deleted { color: var(--ink-3); font-style: italic; }
.board-cm-form { display: flex; gap: 8px; margin-top: 10px; }
.board-cm-form textarea { flex: 1; min-height: 40px; }
/* ── 클래스 QnA ── 게시판 목록(.board-*)의 간격·토큰을 그대로 쓴다. 새 색은 없다. */
.cls-qna-head-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cls-qna-unanswered { display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--radius-pill);
  background: var(--accent); color: var(--accent-ink);
  font-size: var(--type-label); font-weight: 700; line-height: 1; }
/* 탭 막대의 QnA 라벨 옆 미답변 수. .cls-qna-unanswered 와 같은 토큰, 탭 높이에 맞춰 한 치수 작게. */
.cls-qna-tab-badge { display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; margin-left: 6px; padding: 0 5px;
  border-radius: var(--radius-pill); background: var(--accent); color: var(--accent-ink);
  font-size: var(--type-label); font-weight: 700; line-height: 1; }
.cls-qna-cap { margin-top: 6px; }
/* 진입점 버튼(오답노트·과제 결과·강의·문제풀이·클래스 시험). 연습·자료 행은 제목
   버튼의 ::after 가 행 전체를 덮어 행 클릭을 만든다. 그 위로 올라오지 않으면
   이 버튼은 화면에 보이면서도 눌리지 않는다. */
.cls-qna-ask { position: relative; z-index: 2; }
.cls-qna-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.cls-qna-filter { border: 1px solid var(--line); border-radius: 999px; padding: 4px 12px;
  background: transparent; color: var(--ink-2); font-size: 13px; cursor: pointer; white-space: nowrap; }
.cls-qna-filter.on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.cls-qna-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;
  padding: 10px 4px; border-bottom: 1px solid var(--line-2); cursor: pointer; }
.cls-qna-row:hover { background: var(--surface-2); }
.cls-qna-row:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.cls-qna-row-main { flex: 1 1 auto; min-width: 0; }
.cls-qna-row-title { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.cls-qna-row-subject { font-weight: 600; color: var(--ink); word-break: break-word; }
.cls-qna-badge { white-space: nowrap; line-height: 1.45; }
.cls-qna-badge.open { background: var(--warn-bg); color: var(--warn-2); }
.cls-qna-badge.done { background: var(--good-bg); color: var(--good); }
.cls-qna-secret { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap;
  background: var(--surface-2); color: var(--ink-2); }
.cls-qna-lock { width: 12px; height: 12px; }
.cls-qna-ref { display: inline-block; max-width: 100%; margin-top: 5px;
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 9px;
  font-size: 12px; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-qna-row-meta { font-size: 12px; color: var(--ink-3); margin-top: 4px; }
.cls-qna-row-answers { flex: 0 0 auto; padding-top: 2px; font-size: 12px; color: var(--ink-3);
  white-space: nowrap; }

/* QnA 작성·상세 오버레이 — .tsm-modal 골격과 게시판 본문(.board-*) 토큰을 그대로 쓴다. */
.cls-qna-modal { max-width: 640px; }
.cls-qna-ref-card { display: flex; align-items: center; gap: 6px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: 6px 6px 6px 12px;
  background: var(--surface-2); }
.cls-qna-ref-card-text { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-qna-ref-drop { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; border: none; border-radius: var(--r-sm);
  background: transparent; color: var(--ink-3); cursor: pointer; }
.cls-qna-ref-drop:hover { color: var(--ink); background: var(--surface); }
.cls-qna-ref-drop .ic { width: 14px; height: 14px; }
.cls-qna-preview { min-height: 46px; max-height: 220px; overflow: auto;
  border: 1px solid var(--line-2); border-radius: var(--r-sm); padding: 10px 12px;
  background: var(--surface-2); color: var(--ink-2);
  font-size: 14px; line-height: 1.75; white-space: pre-wrap; word-break: break-word; }
.cls-qna-math { white-space: normal; }
.cls-qna-attach input[type="file"] { max-width: 100%; font-size: 12.5px; color: var(--ink-2); }
.cls-qna-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cls-qna-chip { display: inline-flex; align-items: center; gap: 2px; max-width: 100%;
  border: 1px solid var(--line); border-radius: var(--radius-pill); padding: 2px 4px 2px 10px;
  font-size: 12px; color: var(--ink-2); }
.cls-qna-chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-qna-chip-x { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: none; border-radius: var(--radius-pill);
  background: transparent; color: var(--ink-3); cursor: pointer; }
.cls-qna-chip-x:hover { color: var(--ink); }
.cls-qna-chip-x .ic { width: 11px; height: 11px; }
.cls-qna-detail-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.cls-qna-detail-meta { font-size: 12px; color: var(--ink-3); }
.cls-qna-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.cls-qna-files { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cls-qna-files .board-file-card { margin-top: 0; max-width: 100%; }
.cls-qna-file-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-qna-thread { margin-top: 14px; }
.cls-qna-teacher { background: var(--accent-soft); color: var(--accent); }
.cls-qna-answer-form { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-2); }

/* ── 클래스 수강후기 ── QnA 목록(.cls-qna-*)의 간격·토큰을 그대로 쓴다. 새 색은 없다.
   별점과 분포 막대는 값 표현이라 데이터 색(--data)을 쓴다. 폭은 390/820/1440 세
   화면에서 같은 규칙으로 접히도록 고정 폭 없이 flex 로만 잡는다. */
.cls-review-head { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cls-review-note { margin: 0; }
.cls-review-summary { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 14px;
  margin-top: 12px; }
.cls-review-avg { display: inline-flex; align-items: baseline; gap: 8px; min-width: 0; }
.cls-review-avg-num { font-size: var(--type-screen); line-height: 1.1; color: var(--ink); }
.cls-review-stars { color: var(--data); letter-spacing: 1px; white-space: nowrap; }
.cls-review-count { margin: 0; font-size: 12px; color: var(--ink-3); }
.cls-review-empty { margin: 0; }
.cls-review-dist { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.cls-review-dist-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cls-review-dist-label { flex: 0 0 auto; min-width: 30px; font-size: 12px; color: var(--ink-3); }
.cls-review-dist-track { flex: 1 1 auto; min-width: 0; height: 6px;
  border-radius: var(--radius-pill); background: var(--line-2); overflow: hidden; }
.cls-review-dist-fill { display: block; height: 100%; border-radius: var(--radius-pill);
  background: var(--data); }
.cls-review-dist-n { flex: 0 0 auto; min-width: 22px; text-align: right;
  font-size: 12px; color: var(--ink-3); }
.cls-review-list { margin-top: 14px; }
.cls-review-item { padding: 10px 4px; border-bottom: 1px solid var(--line-2); }
.cls-review-item-top { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.cls-review-item-name { font-weight: 600; color: var(--ink); word-break: break-word; }
.cls-review-item-meta { font-size: 12px; color: var(--ink-3); }
.cls-review-anon { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap;
  background: var(--surface-2); color: var(--ink-2); }
.cls-review-lock { width: 12px; height: 12px; }
.cls-review-item-body { margin-top: 5px; color: var(--ink-2); font-size: 14px; line-height: 1.7;
  white-space: pre-wrap; word-break: break-word; }

/* 학생 갈래 — 별점 라디오는 네이티브라 키보드 이동을 그대로 얻는다. */
.cls-review-form { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.cls-review-rating { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  margin: 0; padding: 0; border: none; }
.cls-review-legend { padding: 0; font-size: 12px; color: var(--ink-3); }
.cls-review-star-opt { display: inline-flex; align-items: center; gap: 4px;
  min-height: var(--control-dense); padding: 2px 8px 2px 4px;
  border: 1px solid var(--line); border-radius: var(--radius-pill); cursor: pointer; }
.cls-review-star-opt input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.cls-review-star-face { color: var(--data); letter-spacing: 1px; white-space: nowrap; }
.cls-review-star-num { font-size: 12px; color: var(--ink-2); white-space: nowrap; }
.cls-review-body { width: 100%; min-height: 88px; resize: vertical; }
.cls-review-anon-row { display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--ink-2); cursor: pointer; }
.cls-review-caveat { margin: 0; font-size: 12px; color: var(--ink-3); }
/* 상시 고지가 아니라 실명에서 익명으로 바꾸는 순간에만 뜨는 두 번째 문장. */
.cls-review-switch-warn { margin: 0; padding: 8px 10px; border-radius: var(--r-sm);
  background: var(--warn-bg); color: var(--warn-2); font-size: 12.5px; }
.cls-review-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cls-review-notice:empty { display: none; }
@media (max-width: 520px) {
  .cls-review-star-num { display: none; }
}

/* ── 클래스 시간표 ── 수강후기(.cls-review-*)의 간격과 토큰을 그대로 쓴다. 새 색은 없다.
   DOM 은 한 벌이고 배치만 두 가지다: 넓은 폭에서는 시간 축이 붙은 주간 그리드,
   640 이하에서는 요일 세로 목록. 자바스크립트는 폭을 모른다 — 기하는 전부
   --tt-* 변수로 들어오고 배치 전환은 이 파일에서만 일어난다. 그래서 같은 항목이
   두 화면에서 서로 다른 계산을 타는 일이 없다.
   시간 축 높이는 등록된 슬롯 범위에서 나온 --tt-rows(시간 칸 수)로만 정해진다. */
.cls-tt-head { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cls-tt-note { margin: 0; }
.cls-tt-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  margin-top: 12px; min-width: 0; }
.cls-tt-week-label { font-weight: 600; color: var(--ink); }
.cls-tt-nav-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.cls-tt-week { margin-top: 12px; min-width: 0; }
.cls-tt-empty { margin: 0; }

.cls-tt-grid { --tt-row-h: 46px; --tt-head-h: 22px;
  display: flex; align-items: stretch; gap: 6px; min-width: 0; }
.cls-tt-axis { flex: 0 0 auto; display: flex; flex-direction: column; }
.cls-tt-axis-spacer { height: var(--tt-head-h); }
.cls-tt-axis-body { display: flex; flex-direction: column;
  height: calc(var(--tt-rows) * var(--tt-row-h)); }
.cls-tt-axis-hour { flex: 1 1 0; font-size: var(--type-label); color: var(--ink-3);
  white-space: nowrap; }
.cls-tt-days { flex: 1 1 auto; min-width: 0;
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.cls-tt-day { min-width: 0; }
.cls-tt-day-head { height: var(--tt-head-h); font-size: 12px; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cls-tt-day-body { position: relative; height: calc(var(--tt-rows) * var(--tt-row-h));
  border-top: 1px solid var(--line-2); }
.cls-tt-lane { position: absolute; left: 0; right: 0;
  top: var(--tt-top); height: var(--tt-height); }
.cls-tt-item { position: absolute; top: var(--tt-item-top); height: var(--tt-item-height);
  left: var(--tt-left); width: var(--tt-width);
  display: flex; flex-direction: column; gap: 1px; min-width: 0; overflow: hidden;
  box-sizing: border-box; padding: 3px 4px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2);
  /* 12px 아래로 내려가지 않는다(본문 최소 크기 계약). 좁은 열에서는 글자를 줄이지
     않고 넘치는 부분을 잘라 낸다 — 읽을 수 없는 크기는 없는 것과 같다. */
  font-size: var(--type-label); line-height: 1.35; }
.cls-tt-item-time { font-weight: 600; white-space: nowrap; }
.cls-tt-item-class, .cls-tt-item-memo { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.cls-tt-badge { align-self: flex-start; padding: 0 5px; border-radius: var(--radius-pill);
  background: var(--surface); font-size: var(--type-label); font-weight: 600;
  white-space: nowrap; }
.cls-tt-event-hint { margin: 6px 0 0; }
.cls-tt-event-hint:empty { display: none; }
/* 휴강은 취소선과 이름표를 함께 단다. 취소선만 두면 흑백 출력에서 아무 말도 하지 않는다. */
.cls-tt-item-cancel .cls-tt-item-time,
.cls-tt-item-cancel .cls-tt-item-class { text-decoration: line-through; }
.cls-tt-item[data-kind="cancel"] { background: var(--bad-bg); color: var(--bad);
  border-color: var(--bad-line); }
.cls-tt-item[data-kind="makeup"] { background: var(--good-bg); color: var(--good);
  border-color: var(--good-line); }
.cls-tt-item[data-kind="change"] { background: var(--warn-bg); color: var(--warn-2); }
/* 시각을 읽을 수 없어 캔버스에 자리를 못 잡은 항목. 사라지게 두지 않는다. */
.cls-tt-loose { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.cls-tt-loose .cls-tt-item { position: static; height: auto; width: auto; }

/* 강사 편집. 학생 갈래에는 이 묶음 자체가 만들어지지 않는다. */
.cls-tt-edit { display: flex; flex-direction: column; gap: 16px; margin-top: 16px;
  padding-top: 12px; border-top: 1px solid var(--line-2); }
.cls-tt-editor-title { margin: 0 0 6px; font-size: var(--type-label); color: var(--ink-3); }
.cls-tt-slot-list, .cls-tt-event-list { display: flex; flex-direction: column; gap: 2px; }
.cls-tt-slot-row, .cls-tt-event-row { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; padding: 6px 4px; border-bottom: 1px solid var(--line-2); min-width: 0; }
.cls-tt-slot-when, .cls-tt-event-when { font-weight: 600; color: var(--ink);
  white-space: nowrap; }
.cls-tt-slot-memo, .cls-tt-event-memo { flex: 1 1 120px; min-width: 0; font-size: 12px;
  color: var(--ink-3); word-break: break-word; }
.cls-tt-slot-empty, .cls-tt-event-empty { margin: 0; }
.cls-tt-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px;
  min-width: 0; }
.cls-tt-form .field { min-width: 0; max-width: 100%; }
.cls-tt-form .cls-tt-memo, .cls-tt-form .cls-tt-event-note { flex: 1 1 140px; }
.cls-tt-notice:empty { display: none; }

/* 홈 주간표 카드 — 클래스 탭과 같은 그리드를 그대로 쓴다. */
.home-week-card { padding: var(--s3); min-width: 0; }

@media (max-width: 640px) {
  /* 요일 세로 목록. 축은 항목마다 적힌 시각과 같은 말이라 접어 둔다. */
  .cls-tt-axis { display: none; }
  .cls-tt-days { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .cls-tt-day[data-empty="1"] { display: none; }
  .cls-tt-day-head { height: auto; }
  .cls-tt-day-body { position: static; height: auto; margin-top: 4px;
    display: flex; flex-direction: column; gap: 6px; }
  /* 겹친 항목은 좁은 폭에서도 나란히 선다. 위아래로 밀면 같은 시각이라는 사실이 사라진다. */
  .cls-tt-lane { position: static; height: auto; display: flex; gap: 6px; }
  .cls-tt-item { position: static; height: auto; width: auto; flex: 1 1 0; }
  .cls-tt-item-class, .cls-tt-item-memo { white-space: normal; word-break: break-word; }
}
/* ── 클래스 출석부 ── 시간표(.cls-tt-*)의 간격·토큰을 그대로 쓴다. 새 색은 없다.
   상태는 색과 글자를 함께 단다. 색만으로 구분하면 색각 이상 사용자가 지각과 결석을
   가르지 못하고, 흑백 출력에서는 아무 말도 하지 않는다. */
.cls-att-head { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cls-att-note-line { margin: 0; }
.cls-att-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  margin-top: 12px; min-width: 0; justify-content: space-between; }
.cls-att-month-label { font-weight: 600; color: var(--ink); }
.cls-att-nav-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.cls-att-notice:empty { display: none; }
.cls-att-views { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.cls-att-view[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink);
  border-color: var(--accent); font-weight: 600; }
.cls-att-host { margin-top: 12px; min-width: 0; }
.cls-att-legend { margin: 8px 0 0; }
.cls-att-rate { margin: 8px 0 0; font-weight: 600; color: var(--ink); }
.cls-att-picker { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px; min-width: 0; }
.cls-att-picker-label { font-size: var(--type-label); color: var(--ink-3); }
.cls-att-picker .field { flex: 1 1 160px; min-width: 0; max-width: 320px; }

.cls-att-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px;
  min-width: 0; }
.cls-att-wd { font-size: var(--type-label); color: var(--ink-3); text-align: center;
  padding-bottom: 2px; }
.cls-att-cell { display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  min-width: 0; min-height: 62px; box-sizing: border-box; padding: 4px 5px;
  border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2);
  font-size: var(--type-label); line-height: 1.35; text-align: start; }
/* 그 달에 없는 앞뒤 빈칸. 테두리까지 지워 격자만 남긴다. */
.cls-att-cell-void { border-color: transparent; background: transparent; }
.cls-att-daynum { font-weight: 600; color: var(--ink); }
/* 수업일은 눌러서 체크한다. 버튼으로 그려지는 칸만 손 모양이 된다. */
button.cls-att-cell { cursor: pointer; font: inherit; }
button.cls-att-cell:hover { background: var(--surface); border-color: var(--line); }
button.cls-att-cell:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.cls-att-cell[data-kind="class"], .cls-att-cell[data-kind="manual"] {
  border-color: var(--line); background: var(--surface); }
.cls-att-cell[data-kind="cancel"] { background: var(--bad-bg); border-color: var(--bad-line);
  color: var(--bad); }
.cls-att-cell[data-today="1"] { box-shadow: inset 0 0 0 2px var(--accent-soft); }
.cls-att-note { color: var(--ink-3); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%; }
/* 수업일이 아닌 칸의 '수업 추가'. 늘 보이면 한 달 서른 칸 중 스물다섯에 같은 글씨가
   깔려 정작 수업일이 묻힌다. 손이 닿거나 포커스가 왔을 때만 드러낸다. 화면 낭독기는
   opacity 와 무관하게 읽으므로 안내가 사라지는 것은 아니다. */
.cls-att-add { opacity: 0; transition: opacity .12s ease; }
/* 좁은 폭에서만 짧은 말로 바꾼다. 글자 크기를 줄이는 대신 말을 줄인다 —
   본문은 12px 아래로 내려가지 않는다는 계약을 우회하지 않는다. */
.cls-att-short { display: none; }
button.cls-att-cell:hover .cls-att-add,
button.cls-att-cell:focus-visible .cls-att-add { opacity: 1; }
/* 손가락에는 hover 가 없다. 흐리게 두면 --ink-3 가 1.9:1 까지 떨어져 읽을 수 없으므로
   대비를 깎지 않는다. 다만 상시 표시는 짧은 말('＋')이 걸리는 폭에서만이다 — 그 위
   태블릿에서 긴 '수업 추가'를 전 칸에 깔면 이 PR 이 고치려던 도배가 그대로 돌아온다. */
@media (hover: none) and (max-width: 640px) {
  .cls-att-add { opacity: 1; }
}
/* 넓은 폭 터치(아이패드)에는 안내를 드러낼 자리가 없다. :active 를 걸어 봤지만
   그 누름이 곧 시트를 여는 누름이라, 읽히기 전에 화면이 바뀐다. 대신 달력 위
   안내문이 그 길을 말해 준다(app.js buildAttendanceBox 의 머리말). 칸마다 같은
   말을 스물다섯 번 깔지 않는다. */
@media (prefers-reduced-motion: reduce) { .cls-att-add { transition: none; } }
.cls-att-tally { font-weight: 600; color: var(--ink-2); white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
/* 휴강으로 바뀌었는데 표시가 남은 날. 감추면 출석률만 조용히 깎인다. */
.cls-att-stale { font-weight: 600; color: var(--warn-2); }
.cls-att-hint { margin: 0 0 10px; }
.cls-att-chip { display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--radius-pill);
  font-weight: 700; line-height: 1; background: var(--surface-2); color: var(--ink-2); }
.cls-att-chip[data-status="present"] { background: var(--good-bg); color: var(--good); }
.cls-att-chip[data-status="late"], .cls-att-chip[data-status="early"] {
  background: var(--warn-bg); color: var(--warn-2); }
.cls-att-chip[data-status="absent"] { background: var(--bad-bg); color: var(--bad); }
.cls-att-chip[data-status="excused"] { background: var(--accent-soft); color: var(--ink-2); }

/* 하루 명단 시트. 좁은 폭에서는 화면을 가득 채운다 — 달력 칸 안에 명단을 밀어 넣으면
   글자가 읽을 수 없는 크기가 된다. */
.cls-att-sheet-back { position: fixed; inset: 0; z-index: var(--z-overlay);
  display: flex; align-items: center; justify-content: center; padding: 16px;
  background: var(--overlay); }
.cls-att-sheet { display: flex; flex-direction: column; gap: 10px;
  width: min(680px, 100%); max-height: 88vh; overflow-y: auto; box-sizing: border-box;
  padding: 16px; border-radius: var(--card-radius); background: var(--surface);
  border: 1px solid var(--line); }
.cls-att-sheet-head { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 8px; }
.cls-att-sheet-title { margin: 0; font-size: 15px; color: var(--ink); }
.cls-att-rows { display: flex; flex-direction: column; gap: 2px; }
.cls-att-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px 2px; border-bottom: 1px solid var(--line-2); min-width: 0; }
.cls-att-name { flex: 0 0 84px; font-weight: 600; color: var(--ink); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-att-seg { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.cls-att-opt { padding: 5px 9px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2); font: inherit;
  font-size: var(--type-label); cursor: pointer; white-space: nowrap; }
.cls-att-opt:hover { background: var(--surface); }
.cls-att-opt:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.cls-att-opt[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink);
  border-color: var(--accent); font-weight: 600; }
.cls-att-memo { flex: 1 1 120px; min-width: 0; }
.cls-att-sheet-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.cls-att-sheet-msg:empty { display: none; }

@media (max-width: 640px) {
  /* 좁은 폭: 칸은 숫자와 표시만, 명단 시트는 전체 화면. */
  .cls-att-cal { gap: 2px; }
  .cls-att-cell { min-height: 56px; padding: 3px; }
  /* 7열을 390 에 나누면 칸이 45px 안팎이라 '미체크'도 '남은 기록'도 한 줄에 못 든다.
     글자를 12px 아래로 줄일 수는 없으니(본문 최소 크기 계약) 좁은 폭에서만 더 짧은
     말로 바꾼다. 낭독기는 칸의 title 을 읽으므로 안내가 줄어들지는 않는다. */
  /* 줄바꿈을 풀지 않는다. 풀면 학생 뷰의 메모(최대 40자)까지 함께 풀려 한 주 행이
     두 배 넘게 늘어난다. 짧은 말은 nowrap 으로도 46px 칸에 한 줄로 들어간다. */
  .cls-att-long { display: none; }
  .cls-att-short { display: inline; }
  .cls-att-sheet-back { padding: 0; }
  .cls-att-sheet { width: 100%; max-height: 100vh; height: 100%; border-radius: 0;
    border: none; }
  .cls-att-name { flex: 1 1 100%; }
  .cls-att-memo { flex: 1 1 100%; }
  /* 손가락으로 학생마다 다섯 번 누르는 흐름이다. 좁은 폭에서는 터치 규격을 지킨다.
     다섯 칸이 한 줄에 균등하게 들어가 어느 것도 가장자리에 끼지 않는다. */
  .cls-att-seg { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 4px; width: 100%; }
  .cls-att-opt { min-height: var(--control-touch); padding: 5px 2px;
    display: flex; align-items: center; justify-content: center;
    /* 320 에서 '사유결석' 네 글자가 53px 칸을 넘긴다. 자르면 무슨 상태인지 알 수
       없으므로 자간을 좁혀 넣는다. 글자 크기는 건드리지 않는다. */
    letter-spacing: -0.04em; }
}

/* ── 클래스 채팅 ── 시간표(.cls-tt-*)의 간격과 토큰을 그대로 쓴다. 새 색은 없다.
   DOM 은 한 벌이고 배치만 두 가지다: 넓은 폭에서는 방 목록과 대화가 나란히,
   640 이하에서는 data-view 가 가리키는 한 쪽만. 자바스크립트는 폭을 모른다 —
   전환은 이 파일에서만 일어난다. */
.cls-chat-head { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cls-chat-note { margin: 0; }
/* 열람 고지. 눈에 띄되 대화를 밀어내지 않는다 — 머리에 붙어 두 배치 모두에서 남는다. */
.cls-chat-disclosure { margin: 0; color: var(--ink-3); font-size: var(--type-label); }
.cls-chat { display: grid; grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  gap: 12px; margin-top: 12px; align-items: start; min-width: 0; }
.cls-chat-rooms { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.cls-chat-rooms-head { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 6px; min-width: 0; }
.cls-chat-rooms-title { margin: 0; font-size: var(--type-label); color: var(--ink-3); }
.cls-chat-room-list { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cls-chat-rooms-empty { margin: 0; }
/* 강사가 상대를 고르는 자리. 방 목록 위에 접혀 있다가 열린다. */
.cls-chat-picker { display: flex; flex-direction: column; gap: 2px; min-width: 0;
  padding: 6px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface-2); max-height: 220px; overflow-y: auto; }
.cls-chat-picker[hidden] { display: none; }
.cls-chat-picker-empty { margin: 2px 0; }
.cls-chat-picker-row { width: 100%; min-width: 0; padding: 7px 8px;
  border: none; border-radius: var(--r-sm); background: transparent;
  color: var(--ink-2); font: inherit; text-align: start; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-chat-picker-row:hover { background: var(--surface); color: var(--ink); }
.cls-chat-picker-row:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.cls-chat-room { display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0;
  padding: 8px 10px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--ink-2); font: inherit; text-align: start; cursor: pointer; }
.cls-chat-room:hover { background: var(--surface-2); }
.cls-chat-room:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.cls-chat-room[aria-pressed="true"] { border-color: var(--line); background: var(--surface-2);
  color: var(--ink); font-weight: 600; }
.cls-chat-room-label { flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-chat-unread { flex: 0 0 auto; display: inline-flex; align-items: center;
  justify-content: center; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--radius-pill); background: var(--accent); color: var(--accent-ink);
  font-size: var(--type-label); font-weight: 700; line-height: 1; }
.cls-chat-unread[hidden] { display: none; }

.cls-chat-view { position: relative; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.cls-chat-view-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.cls-chat-view-title { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 넓은 폭에서는 두 칸이 함께 보이므로 되돌아갈 곳이 없다. */
.cls-chat-back { display: none; }
.cls-chat-log { display: flex; flex-direction: column; gap: 8px; min-width: 0;
  max-height: 420px; overflow-y: auto; overflow-x: hidden;
  padding: 10px; border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--surface-2); }
.cls-chat-empty { margin: 0; }
.cls-chat-daysep { display: flex; align-items: center; justify-content: center; }
.cls-chat-daysep-label { padding: 2px 10px; border-radius: var(--radius-pill);
  background: var(--surface); color: var(--ink-3); font-size: var(--type-label); }
.cls-chat-msg { display: flex; flex-direction: column; gap: 2px; max-width: 82%;
  min-width: 0; padding: 8px 10px; border: 1px solid var(--line-2);
  border-radius: var(--r-sm); background: var(--surface); }
/* 내 메시지는 오른쪽에 선다. 정렬의 근거는 이 표시 하나뿐이다. */
.cls-chat-msg[data-mine="1"] { margin-inline-start: auto; align-items: flex-end;
  border-color: var(--line); background: var(--accent-soft); }
.cls-chat-msg-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  min-width: 0; font-size: var(--type-label); color: var(--ink-3); }
.cls-chat-author { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-chat-teacher { background: var(--accent-soft); color: var(--accent); }
.cls-chat-time { white-space: nowrap; }
.cls-chat-body { margin: 0; color: var(--ink-2); font-size: 14px; line-height: 1.7;
  white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; }
.cls-chat-deleted { color: var(--ink-3); font-style: italic; }
.cls-chat-deleted-by { font-size: var(--type-label); color: var(--ink-3); }
.cls-chat-delete { align-self: flex-end; }
.cls-chat-more { align-self: center; }
/* 위로 올려 옛 대화를 읽는 중에 화면이 끌려 내려가지 않게 하고, 대신 이 칩으로 알린다. */
.cls-chat-jump { position: absolute; inset-inline-start: 50%; bottom: 96px;
  transform: translateX(-50%); z-index: 2;
  padding: 4px 12px; border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--ink); font-size: 12px; cursor: pointer; }
.cls-chat-jump[hidden] { display: none; }
.cls-chat-composer { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 6px;
  min-width: 0; }
.cls-chat-input { flex: 1 1 160px; min-width: 0; min-height: 60px; resize: vertical; }
.cls-chat-count { margin: 0; font-size: 12px; color: var(--ink-3); text-align: end; }
.cls-chat-notice { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cls-chat-notice:empty { display: none; }

/* ── 인앱 알림 벨 ── 헤더 우측. 드롭다운은 벨에 매달린다. */
.notify-wrap { position: relative; display: inline-flex; }
.notify-bell { position: relative; }
.notify-badge { position: absolute; top: -6px; inset-inline-end: -6px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: var(--radius-pill);
  background: var(--accent); color: var(--accent-ink);
  font-size: var(--type-label); font-weight: 700; line-height: 1; }
.notify-badge[hidden] { display: none; }
.notify-panel { position: absolute; top: calc(100% + 6px); inset-inline-end: 0; z-index: 60;
  width: min(320px, calc(100vw - 24px)); max-height: 60vh; overflow-y: auto;
  padding: 8px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--shadow-high); }
.notify-panel[hidden] { display: none; }
.notify-panel-head { display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 6px; }
.notify-panel-title { margin: 0; font-size: var(--type-label); color: var(--ink-3); }
.notify-list { display: flex; flex-direction: column; gap: 2px; }
.notify-empty { margin: 4px 0; }
.notify-item { display: flex; align-items: flex-start; gap: 8px; width: 100%; min-width: 0;
  padding: 8px; border: none; border-radius: var(--r-sm); background: transparent;
  color: var(--ink-2); font: inherit; text-align: start; cursor: pointer; }
.notify-item:hover { background: var(--surface-2); }
.notify-item:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.notify-item[data-read="0"] { color: var(--ink); font-weight: 600; }
.notify-item-icon { flex: 0 0 auto; margin-top: 2px; }
.notify-item-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.notify-item-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notify-item-meta { font-size: 12px; font-weight: 400; color: var(--ink-3); }

@media (max-width: 640px) {
  /* 한 번에 한 쪽만 보여준다. 어느 쪽이냐는 data-view 가 이미 말해 두었다. */
  .cls-chat { grid-template-columns: minmax(0, 1fr); }
  .cls-chat[data-view="rooms"] .cls-chat-view { display: none; }
  .cls-chat[data-view="room"] .cls-chat-rooms { display: none; }
  .cls-chat-back { display: inline-flex; }
  .cls-chat-msg { max-width: 92%; }
  .cls-chat-log { max-height: 300px; }
}

.cls-tile-strip>i,
.lec-bar-fill,
.lec-bar-fill.done,
.lec-summary .lec-bar-fill,
.tsm-strip-fill,
.tsm-strip-fill.done,
.cls-dashboard-progress-mark{background:var(--data)}
.lec-summary .lec-bar-lg,
:root[data-theme="black"] .lec-summary .lec-bar-lg{background:var(--surface)}
/* 제외 플레이어는 Task 1 픽셀 계약의 기존 accent 진행 막대를 유지한다. */
.cls-player-box .lec-bar-fill{background:var(--accent)}

/* ── A+ 클래스 상세 C-2 ── */
.cls-c2-context{display:flex;align-items:center;gap:var(--s2);min-height:38px;margin:0 0 var(--s3);padding:0 0 var(--s2);border-bottom:1px solid var(--border);color:var(--text-muted);font-size:var(--type-meta)}
.cls-c2-back{display:inline-flex;align-items:center;gap:4px;min-height:36px;padding:6px 8px;border:0;border-radius:var(--radius-control);background:transparent;color:var(--text);font:inherit;font-weight:700;cursor:pointer}
.cls-c2-back:hover{background:var(--surface-2)}
@media (pointer: coarse){
  .cls-c2-back,.cls-mini{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
}
.cls-c2-back:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.cls-c2-current{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cls-c2-heading{display:flex;align-items:center;gap:var(--s4);min-width:0;margin-bottom:var(--s2)}
.cls-c2-heading-copy{flex:1;min-width:0}
.cls-c2-title{margin:0;font-family:var(--display);font-size:24px;line-height:1.2;color:var(--text)}
.cls-c2-meta{margin:4px 0 0;color:var(--text-muted);font-size:var(--type-meta);line-height:1.45}
.cls-c2-primary{flex:none}
.cls-c2-actions{margin:0 0 var(--s3);flex-wrap:wrap}
.cls-c2-sheet-overlay{position:fixed;inset:0;z-index:var(--z-overlay);display:flex;align-items:center;justify-content:center;padding:var(--s4);background:var(--overlay)}
.cls-c2-sheet{width:min(420px,100%);max-height:min(560px,calc(100vh - 32px));overflow:auto;border:1px solid var(--border);border-radius:var(--radius-card);background:var(--surface);box-shadow:var(--shadow-high)}
.cls-c2-sheet-head{display:flex;align-items:center;gap:var(--s3);padding:var(--s4);border-bottom:1px solid var(--border)}
.cls-c2-sheet-title{flex:1;margin:0;font-family:var(--display);font-size:16px;color:var(--text)}
.cls-c2-sheet-close{min-width:44px;min-height:44px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);color:var(--text);cursor:pointer}
.cls-c2-sheet-list{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3)}
.cls-c2-sheet-row{display:flex;align-items:center;gap:var(--s3);width:100%;min-height:52px;padding:10px 12px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);color:var(--text);text-align:left;cursor:pointer}
.cls-c2-sheet-row:hover{background:var(--surface-2);border-color:var(--control-border)}
.cls-c2-sheet-row:focus-visible{outline:none;box-shadow:0 0 0 2px var(--surface),0 0 0 4px var(--focus-ring)}
.cls-c2-sheet-row.active{background:var(--surface);border-color:var(--selection-outline)}
.cls-c2-sheet-row.active::after{content:"✓";color:var(--text);font-weight:800}
.cls-c2-sheet-copy{display:flex;flex:1;min-width:0;flex-direction:column;gap:2px}
.cls-c2-sheet-copy strong{font-size:14px}.cls-c2-sheet-copy small{color:var(--text-muted);font-size:var(--type-meta)}
.cls-c2-mobile-tabs{display:none}
.cls-c2-mobile-tablist{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px;min-width:0}
.cls-c2-more{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (prefers-reduced-motion:reduce){.cls-c2-sheet-row,.cls-c2-back{transition:none}}
html[data-shell-mode="mobile-portrait"] .cls-c2-context,
html[data-shell-mode="mobile-landscape"] .cls-c2-context{min-height:34px;margin-bottom:var(--s2);padding-bottom:var(--s1)}
html[data-shell-mode="mobile-portrait"] .cls-c2-heading,
html[data-shell-mode="mobile-landscape"] .cls-c2-heading{align-items:center;gap:var(--s2)}
html[data-shell-mode="mobile-portrait"] .cls-c2-title,
html[data-shell-mode="mobile-landscape"] .cls-c2-title{font-size:18px}
html[data-shell-mode="mobile-portrait"] .cls-c2-meta,
html[data-shell-mode="mobile-landscape"] .cls-c2-meta{font-size:var(--type-label)}
html[data-shell-mode="mobile-portrait"] .cls-c2-primary,
html[data-shell-mode="mobile-landscape"] .cls-c2-primary{min-height:44px;padding-inline:12px;white-space:nowrap}
html[data-shell-mode="mobile-portrait"] .cls-c2-actions,
html[data-shell-mode="mobile-landscape"] .cls-c2-actions{gap:6px;margin-bottom:var(--s2)}
html[data-shell-mode="mobile-portrait"] .cls-c2-root .cls-summary,
html[data-shell-mode="mobile-landscape"] .cls-c2-root .cls-summary{grid-template-columns:repeat(4,minmax(0,1fr));gap:4px}
html[data-shell-mode="mobile-portrait"] .cls-c2-root .cls-tile,
html[data-shell-mode="mobile-landscape"] .cls-c2-root .cls-tile{min-width:0;padding:7px 6px}
html[data-shell-mode="mobile-portrait"] .cls-c2-root .cls-tile-lbl,
html[data-shell-mode="mobile-landscape"] .cls-c2-root .cls-tile-lbl{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
html[data-shell-mode="mobile-portrait"] .cls-c2-root .cls-tile-val,
html[data-shell-mode="mobile-landscape"] .cls-c2-root .cls-tile-val{font-size:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
html[data-shell-mode="mobile-portrait"] .cls-c2-desktop-tabs,
html[data-shell-mode="mobile-landscape"] .cls-c2-desktop-tabs{display:none}
html[data-shell-mode="mobile-portrait"] .cls-c2-mobile-tabs,
html[data-shell-mode="mobile-landscape"] .cls-c2-mobile-tabs{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,1fr);gap:2px;overflow:visible}
html[data-shell-mode="mobile-portrait"] .cls-c2-mobile-tabs .cls-tab,
html[data-shell-mode="mobile-landscape"] .cls-c2-mobile-tabs .cls-tab{min-width:0;min-height:44px;padding:8px 4px;font-size:12px}
html[data-shell-mode="mobile-portrait"] .cls-c2-sheet-overlay,
html[data-shell-mode="mobile-landscape"] .cls-c2-sheet-overlay{align-items:flex-end;padding:0}
html[data-shell-mode="mobile-portrait"] .cls-c2-sheet,
html[data-shell-mode="mobile-landscape"] .cls-c2-sheet{width:100%;max-height:min(70vh,520px);border-radius:var(--radius-card) var(--radius-card) 0 0;border-bottom:0}
@media(max-width:640px){
  .cls-c2-root .tsm-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px}
  .cls-c2-root .tsm-title{grid-column:1;grid-row:1;min-width:0}
  .cls-c2-root .tsm-head>.cls-mini{grid-column:2;grid-row:1;justify-self:end}
  /* 버튼 묶음은 검색줄 아래 한 줄을 통째로 쓴다(좁은 화면에서 제목·검색과 겹치지 않게) */
  .cls-c2-root .tsm-head-acts{grid-column:1/-1;grid-row:3;justify-self:stretch}
  .cls-c2-root .tsm-head-acts>.cls-mini{flex:1 1 auto;min-width:0}
  .cls-c2-root .tsm-search{grid-column:1/-1;grid-row:2;width:100%;min-width:0}
  .cls-c2-root .tsm-section,.cls-c2-root .tsm-body,.cls-c2-root .tsm-tbl{min-width:0;max-width:100%}
  .cls-c2-root .tsm-phone-input{width:100%;max-width:128px;min-width:0}
}
/* ── A+ 클래스 상세 C-2 끝 ── */
/* ── A+ 클래스·과제 목록 C-3 ── */
.cls-command-header{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--s3);min-height:88px;margin-bottom:18px;padding:var(--s3) 0;border-bottom:1px solid var(--border);background:transparent}
.cls-command-local{align-self:start;padding-top:3px;color:var(--text-muted);font-size:var(--type-label);font-weight:700;white-space:nowrap}
.cls-command-copy{display:flex;min-width:0;flex-direction:column;gap:3px}
.cls-command-copy #cls-list-title{margin:0;font-size:var(--type-screen);line-height:1.2;color:var(--text)}
.cls-command-summary{margin:0;color:var(--text-muted);font-size:var(--type-body);line-height:1.45}
.cls-command-context{display:flex;align-items:center;gap:var(--s2);min-width:0;color:var(--text-muted);font-size:var(--type-meta)}
.cls-command-context>span{flex:0 0 auto;white-space:nowrap}
.cls-command-context>.page-sub{min-width:0;margin:0;padding-left:var(--s2);border-left:1px solid var(--border);color:var(--text-muted);font-size:var(--type-meta);overflow-wrap:anywhere}
.cls-command-actions{display:flex;align-items:center;justify-content:flex-end;gap:var(--s2);min-width:0}
.cls-command-actions .btn{min-width:44px;min-height:44px}
#cls-command-status:empty{display:none}
#cls-command-status:not(:empty){margin:-10px 0 18px}
html[data-shell-mode="tablet-portrait"] .cls-command-header,
html[data-shell-mode="mobile-portrait"] .cls-command-header,
html[data-shell-mode="mobile-landscape"] .cls-command-header{grid-template-columns:auto minmax(0,1fr);align-items:start}
html[data-shell-mode="tablet-portrait"] .cls-command-actions,
html[data-shell-mode="mobile-portrait"] .cls-command-actions,
html[data-shell-mode="mobile-landscape"] .cls-command-actions{grid-column:2;justify-self:start;justify-content:flex-start;flex-wrap:wrap;width:100%;margin-top:var(--s2)}
html[data-shell-mode="tablet-portrait"] .cls-command-actions .btn-primary,
html[data-shell-mode="mobile-portrait"] .cls-command-actions .btn-primary,
html[data-shell-mode="mobile-landscape"] .cls-command-actions .btn-primary{order:-1}
@media (forced-colors:active){.cls-command-header{border-bottom:1px solid CanvasText}.cls-command-actions .btn{border:1px solid ButtonText}}
@media (prefers-reduced-motion:reduce){.cls-command-actions .btn{transition:none}}
.cls-c3-section-title{margin:24px 0 10px;font-size:15px;font-weight:800;color:var(--text)}
.cls-c3-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.cls-c3-card{position:relative;min-width:0;border:1px solid var(--line);border-radius:11px;background:var(--surface);padding:16px;box-shadow:var(--shadow-low);transition:border-color 120ms,background-color 120ms}
.cls-c3-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.cls-c3-title{min-width:0;margin:0;font-size:18px;line-height:1.35}
.cls-c3-title-btn{display:flex;align-items:center;width:100%;min-width:44px;min-height:44px;max-width:100%;padding:6px 0;border:0;background:transparent;color:var(--text);font:inherit;font-weight:800;text-align:left;white-space:normal;overflow-wrap:anywhere;cursor:pointer;text-decoration:none}
.cls-c3-title-btn:hover{text-decoration:none}
.cls-c3-title-btn::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
.cls-c3-description{display:-webkit-box;overflow:hidden;margin:8px 0 0;color:var(--text-muted);font-size:13px;line-height:1.55;-webkit-box-orient:vertical;-webkit-line-clamp:2}
.cls-c3-exceptions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:4px;margin:0;padding:0;list-style:none}
.cls-c3-exception{border:1px solid var(--control-border);padding:3px 6px;color:var(--text-muted);font-size:12px;font-weight:700}
.cls-c3-facts{display:grid;grid-template-columns:auto 1fr;gap:6px 10px;margin:14px 0 0;font-variant-numeric:tabular-nums}
.cls-c3-fact-label,.cls-c3-fact-value{margin:0;font-size:13px}
.cls-c3-fact-label{color:var(--text-muted)}
.cls-c3-fact-value{color:var(--text);font-weight:700}
.cls-c3-actions{position:relative;z-index:2;display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:16px;pointer-events:none}
.cls-c3-actions button{min-width:44px;min-height:44px;pointer-events:auto}
.cls-c3-card:has(.cls-c3-title-btn:hover){border-color:var(--control-border);background:var(--surface-3)}
.cls-c3-card:has(.cls-c3-title-btn:focus-visible){outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c3-title-btn:focus-visible{outline:0}
.cls-c3-actions button:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c3-empty-wrap{display:grid;place-items:center;min-height:96px;border:1px dashed var(--border-dash);padding:24px 16px;background:var(--surface)}
.cls-c3-empty{margin:0;color:var(--text-muted);font-size:14px;line-height:1.5;text-align:center}
.cls-c3-refreshing{opacity:.55}
.cls-c3-skeleton{min-height:190px;border:1px solid var(--line);border-radius:11px;background:var(--surface-2)}
.cls-c3-inline-status{display:flex;align-items:center;gap:8px;min-height:44px;color:var(--text-muted)}
.cls-c3-more-wrap{position:relative;display:inline-flex;min-width:44px;max-width:100%}
.cls-c3-more{appearance:none;display:grid;place-items:center;inline-size:44px;block-size:44px;padding:0;border:1px solid var(--control-border);border-radius:var(--radius-control);outline:1px solid var(--text);outline-offset:-1px;background:var(--surface);color:var(--text);font:inherit;font-size:20px;font-weight:800;line-height:1;transition:background-color 120ms,color 120ms,border-color 120ms}
.cls-c3-more:hover{background:var(--surface-2)}
.cls-c3-more-list{position:absolute;inset-inline-end:0;z-index:8;min-inline-size:160px;max-inline-size:min(220px,calc(100vw - 32px));margin:0;padding:4px;border:1px solid var(--control-border);border-radius:var(--radius-control);outline:1px solid var(--text);outline-offset:-1px;background:var(--surface);box-shadow:var(--shadow-low);list-style:none;pointer-events:auto}
.cls-c3-more-list[data-placement="bottom"]{top:calc(100% + 4px);bottom:auto}
.cls-c3-more-list[data-placement="top"]{top:auto;bottom:calc(100% + 4px)}
.cls-c3-more-row{margin:0;padding:0}
.cls-c3-more-item{appearance:none;display:block;width:100%;min-height:44px;padding:8px;border:0;border-radius:var(--radius-control);background:transparent;color:var(--text);font:inherit;font-size:12px;font-weight:700;line-height:1.3;text-align:left;white-space:normal;overflow-wrap:anywhere;transition:background-color 120ms,color 120ms,border-color 120ms}
.cls-c3-more-item:hover,.cls-c3-more-item:focus-visible{background:var(--surface-2)}
.cls-c3-actions .cls-c3-more:focus-visible,.cls-c3-actions .cls-c3-more-item:focus-visible{outline:2px solid var(--text);outline-offset:2px}
.cls-c3-inline-status button,.cls-c3-more,.cls-c3-more-item{min-width:44px;min-height:44px}
@media (max-width:1050px){.cls-c3-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
html[data-shell-mode="mobile-portrait"] .cls-c3-grid,
html[data-shell-mode="mobile-landscape"] .cls-c3-grid{grid-template-columns:minmax(0,1fr)}
html[data-shell-mode="mobile-portrait"] .cls-c3-card,
html[data-shell-mode="mobile-landscape"] .cls-c3-card{box-shadow:none}
@media (pointer:coarse){.cls-c3-card{box-shadow:none}}
@media (prefers-reduced-motion:reduce){.cls-c3-card,.cls-c3-card *{transition:none!important}}
@media (forced-colors:active){.cls-c3-card{border:1px solid CanvasText;box-shadow:none}.cls-c3-title-btn:focus-visible,.cls-c3-actions button:focus-visible{outline:2px solid Highlight}.cls-c3-more,.cls-c3-more-list{border:1px solid CanvasText;background:Canvas;color:CanvasText;box-shadow:none;forced-color-adjust:none}.cls-c3-more-item{background:Canvas;color:CanvasText;forced-color-adjust:none}.cls-c3-more:hover{background:Highlight;color:HighlightText}.cls-c3-more-item:hover,.cls-c3-more-item:focus-visible{background:Highlight;color:HighlightText}.cls-c3-actions .cls-c3-more:focus-visible,.cls-c3-actions .cls-c3-more-item:focus-visible{outline-color:Highlight}}

/* C-3B AssignmentProcessingRow: ruled document-register rows only. */
.asgn-c3-root,.asgn-c3-panel,.asgn-c3-group,.asgn-c3-list{min-width:0;max-width:100%}
.asgn-c3-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;min-width:0;border-bottom:2px solid var(--text);padding-bottom:12px}
.asgn-c3-head-copy{min-width:0}
.asgn-c3-title-main{min-width:0;margin:0;color:var(--text);font-size:24px;line-height:1.2;overflow-wrap:anywhere}
.asgn-c3-scope{margin:6px 0 0;color:var(--text-muted);font-size:12px;line-height:1.4;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.asgn-c3-primary{flex:0 0 auto;min-width:44px;min-height:44px}
.asgn-c3-filters{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;min-width:0;margin:16px 0;flex-wrap:wrap}
.asgn-c3-tabs{display:flex;gap:0 14px;max-width:100%;border-bottom:1px solid var(--line);flex-wrap:wrap}
.asgn-c3-tab{min-width:44px;min-height:44px;padding:8px 2px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--text-muted);font:inherit;font-size:12px;font-weight:750;line-height:1.25;white-space:normal;overflow-wrap:anywhere;transition:background-color 120ms,color 120ms,border-color 120ms}
.asgn-c3-tab[aria-selected="true"]{border-bottom-color:currentColor;color:var(--text)}
.asgn-c3-class-label{display:flex;align-items:center;gap:8px;min-width:160px;max-width:100%;color:var(--text-muted);font-size:12px;line-height:1.3}
.asgn-c3-class-filter{width:min(260px,100%);min-width:0;min-height:44px;padding:8px 10px;border:1px solid var(--control-border);border-radius:var(--radius-control);background:var(--surface);color:var(--text);font-size:12px;line-height:1.25}
.asgn-c3-group{margin-top:22px}
.asgn-c3-group-title{min-width:0;margin:0;padding:8px 0;border-bottom:1px solid var(--control-border);color:var(--text);font-size:14px;font-weight:850;line-height:1.35;overflow-wrap:anywhere}
.asgn-c3-list{margin:0;padding:0;list-style:none;border-top:0}
.asgn-c3-row{display:grid;grid-template-columns:92px minmax(180px,2fr) minmax(120px,1fr) minmax(180px,1.3fr) minmax(92px,.7fr) auto auto;align-items:center;gap:12px;width:100%;min-width:0;box-sizing:border-box;border-bottom:1px solid var(--line);border-radius:0;padding:10px 0;box-shadow:none;color:var(--text)}
.asgn-c3-status{min-width:0;color:var(--text-muted);font-size:12px;font-weight:800;line-height:1.35;overflow-wrap:anywhere}
.asgn-c3-title{display:flex;align-items:center;min-width:44px;min-height:44px;max-width:100%;padding:8px 0;border:0;background:transparent;color:var(--text);font:inherit;font-size:14px;font-weight:800;line-height:1.35;text-align:left;overflow-wrap:anywhere;word-break:break-word;transition:background-color 120ms,color 120ms,border-color 120ms}
.asgn-c3-facts{display:contents;margin:0;min-width:0;font-size:12px;line-height:1.35;font-variant-numeric:tabular-nums}
.asgn-c3-fact{display:flex;min-width:0;flex-direction:column;gap:3px;overflow-wrap:anywhere;word-break:break-word}
.asgn-c3-fact dt,.asgn-c3-fact dd{min-width:0;margin:0;overflow-wrap:anywhere;word-break:break-word}
.asgn-c3-fact dt{color:var(--text-muted);font-size:12px;font-weight:650}
.asgn-c3-fact dd{color:var(--text);font-size:12px}
.asgn-c3-primary,.asgn-c3-action,.asgn-c3-more,.asgn-c3-more-item{min-width:44px;min-height:44px}
.asgn-c3-action{max-width:100%;padding-inline:10px;white-space:normal;overflow-wrap:anywhere;transition:background-color 120ms,color 120ms,border-color 120ms}
.asgn-c3-more-wrap{position:relative;display:inline-flex;min-width:44px;max-width:100%;justify-self:end}
.asgn-c3-more{max-width:100%;padding:8px;border:1px solid transparent;border-radius:0;background:transparent;color:var(--text);font:inherit;font-size:12px;line-height:1.25;overflow-wrap:anywhere;transition:background-color 120ms,color 120ms,border-color 120ms}
.asgn-c3-more-list{position:absolute;right:0;top:calc(100% + 4px);z-index:8;min-width:132px;max-width:min(240px,calc(100vw - 24px));border:1px solid var(--control-border);background:var(--surface);padding:4px}
.asgn-c3-more-item{width:100%;max-width:100%;padding:8px;border:0;border-radius:0;background:transparent;color:var(--text);font:inherit;font-size:12px;line-height:1.3;text-align:left;white-space:normal;overflow-wrap:anywhere;transition:background-color 120ms,color 120ms,border-color 120ms}
.asgn-c3-more-item:hover,.asgn-c3-more-item:focus-visible{background:var(--surface-2)}
.asgn-c3-note{grid-column:1/-1;min-width:0;margin:0;color:var(--text-muted);font-size:12px;line-height:1.35;overflow-wrap:anywhere}
.asgn-c3-title:hover{text-decoration:underline;text-underline-offset:3px}
.asgn-c3-tab:focus-visible,.asgn-c3-title:focus-visible,.asgn-c3-action:focus-visible,.asgn-c3-more:focus-visible,.asgn-c3-more-item:focus-visible,.asgn-c3-class-filter:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}

/* Compact desktop keeps the seven ledger columns without creating a scroll rail. */
@media (max-width:1050px) and (min-width:951px){
  .asgn-c3-row{grid-template-columns:minmax(76px,.7fr) minmax(140px,2fr) minmax(92px,1fr) minmax(140px,1.2fr) minmax(84px,.7fr) auto auto;gap:8px}
  .asgn-c3-action{padding-inline:8px}
}

/* Tablet uses a nested facts grid so the register reflows without display:contents. */
@media (min-width:761px) and (max-width:950px){
  .asgn-c3-row{grid-template-columns:82px minmax(0,1fr) auto auto;grid-template-areas:"status title action more" "facts facts facts facts" "note note note note";gap:8px;align-items:start}
  .asgn-c3-status{grid-area:status;align-self:center}
  .asgn-c3-title{grid-area:title}
  .asgn-c3-facts{display:grid;grid-area:facts;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px 12px}
  .asgn-c3-action{grid-area:action;align-self:center}
  .asgn-c3-more-wrap{grid-area:more;align-self:center}
  .asgn-c3-note{grid-area:note}
}
html[data-shell-mode="tablet-landscape"] .asgn-c3-row,
html[data-shell-mode="tablet-portrait"] .asgn-c3-row{
  grid-template-columns:82px minmax(0,1fr) auto auto;
  grid-template-areas:"status title action more" "facts facts facts facts" "note note note note";
  gap:8px;
  align-items:start;
}
html[data-shell-mode="tablet-landscape"] .asgn-c3-status,
html[data-shell-mode="tablet-portrait"] .asgn-c3-status{grid-area:status;align-self:center}
html[data-shell-mode="tablet-landscape"] .asgn-c3-title,
html[data-shell-mode="tablet-portrait"] .asgn-c3-title{grid-area:title}
html[data-shell-mode="tablet-landscape"] .asgn-c3-facts,
html[data-shell-mode="tablet-portrait"] .asgn-c3-facts{display:grid;grid-area:facts;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px 12px}
html[data-shell-mode="tablet-landscape"] .asgn-c3-action,
html[data-shell-mode="tablet-portrait"] .asgn-c3-action{grid-area:action;align-self:center}
html[data-shell-mode="tablet-landscape"] .asgn-c3-more-wrap,
html[data-shell-mode="tablet-portrait"] .asgn-c3-more-wrap{grid-area:more;align-self:center}
html[data-shell-mode="tablet-landscape"] .asgn-c3-note,
html[data-shell-mode="tablet-portrait"] .asgn-c3-note{grid-area:note}

/* Mobile landscape uses the same compact ledger order as mobile portrait. */
html[data-shell-mode="mobile-landscape"] .asgn-c3-filters{align-items:stretch;flex-direction:column;gap:8px}
html[data-shell-mode="mobile-landscape"] .asgn-c3-class-label{width:100%;min-width:0;flex-direction:column;align-items:stretch;gap:4px}
html[data-shell-mode="mobile-landscape"] .asgn-c3-class-filter{width:100%}
html[data-shell-mode="mobile-landscape"] .asgn-c3-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"status action" "title action" "facts more" "note note";gap:4px 8px;align-items:start;padding:12px 0}
html[data-shell-mode="mobile-landscape"] .asgn-c3-status{grid-area:status}
html[data-shell-mode="mobile-landscape"] .asgn-c3-title{grid-area:title}
html[data-shell-mode="mobile-landscape"] .asgn-c3-facts{display:grid;grid-area:facts;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px}
html[data-shell-mode="mobile-landscape"] .asgn-c3-action{grid-area:action;align-self:center}
html[data-shell-mode="mobile-landscape"] .asgn-c3-more-wrap{grid-area:more;align-self:end;justify-self:end}
html[data-shell-mode="mobile-landscape"] .asgn-c3-note{grid-area:note}
html[data-shell-mode="mobile-landscape"] .asgn-c3-root{padding-bottom:16px}

/* Mobile portrait retains DOM order while allowing each fact to wrap. */
@media (max-width:760px){
  .asgn-c3-head{align-items:flex-start;flex-direction:column;gap:8px}
  .asgn-c3-title-main{font-size:20px}
  .asgn-c3-primary{width:100%}
  .asgn-c3-filters{align-items:stretch;flex-direction:column;gap:8px}
  .asgn-c3-tabs{width:100%;gap:0;justify-content:space-between}
  .asgn-c3-tab{flex:1 1 25%;padding-inline:4px}
  .asgn-c3-class-label{width:100%;min-width:0;flex-direction:column;align-items:stretch;gap:4px}
  .asgn-c3-class-filter{width:100%}
  .asgn-c3-group{margin-top:16px}
  .asgn-c3-row{grid-template-columns:minmax(0,1fr) auto;gap:6px 8px;align-items:start;padding:10px 0}
  .asgn-c3-status{grid-column:1/-1;grid-row:1}
  .asgn-c3-title{grid-column:1;grid-row:2}
  .asgn-c3-action{grid-column:2;grid-row:2;align-self:center}
  .asgn-c3-facts{display:grid;grid-column:1;grid-row:3;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;min-width:0}
  .asgn-c3-fact-submission{grid-column:1/-1}
  .asgn-c3-more-wrap{grid-column:2;grid-row:3;align-self:end}
  .asgn-c3-note{grid-column:1/-1;grid-row:4}
}
html[data-shell-mode="mobile-portrait"] .asgn-c3-head{align-items:flex-start;flex-direction:column;gap:8px}
html[data-shell-mode="mobile-portrait"] .asgn-c3-title-main{font-size:20px}
html[data-shell-mode="mobile-portrait"] .asgn-c3-primary{width:100%}
html[data-shell-mode="mobile-portrait"] .asgn-c3-filters{align-items:stretch;flex-direction:column;gap:8px}
html[data-shell-mode="mobile-portrait"] .asgn-c3-tabs{width:100%;gap:0;justify-content:space-between}
html[data-shell-mode="mobile-portrait"] .asgn-c3-tab{flex:1 1 25%;padding-inline:4px}
html[data-shell-mode="mobile-portrait"] .asgn-c3-class-label{width:100%;min-width:0;flex-direction:column;align-items:stretch;gap:4px}
html[data-shell-mode="mobile-portrait"] .asgn-c3-class-filter{width:100%}
html[data-shell-mode="mobile-portrait"] .asgn-c3-group{margin-top:16px}
html[data-shell-mode="mobile-portrait"] .asgn-c3-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"status action" "title action" "facts more" "note note";gap:4px 8px;align-items:start;padding:12px 0}
html[data-shell-mode="mobile-portrait"] .asgn-c3-status{grid-area:status}
html[data-shell-mode="mobile-portrait"] .asgn-c3-title{grid-area:title}
html[data-shell-mode="mobile-portrait"] .asgn-c3-action{grid-area:action;align-self:center}
html[data-shell-mode="mobile-portrait"] .asgn-c3-facts{display:grid;grid-area:facts;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;min-width:0}
html[data-shell-mode="mobile-portrait"] .asgn-c3-more-wrap{grid-area:more;align-self:end;justify-self:end}
html[data-shell-mode="mobile-portrait"] .asgn-c3-note{grid-area:note}
html[data-shell-mode="mobile-portrait"] .asgn-c3-root{padding-bottom:16px}

/* 320px narrow screens split filters and facts rather than scrolling horizontally. */
@media (max-width:360px){
  .asgn-c3-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));width:100%}
  .asgn-c3-tab{width:100%}
  .asgn-c3-facts,
  html[data-shell-mode="mobile-portrait"] .asgn-c3-facts{grid-template-columns:minmax(0,1fr)}
  .asgn-c3-fact-submission{grid-column:1}
}

@media (prefers-reduced-motion:reduce){
  .asgn-c3-tab,.asgn-c3-title,.asgn-c3-action,.asgn-c3-more,.asgn-c3-more-item,.asgn-c3-class-filter{transition:none!important}
}
@media (forced-colors:active){
  .asgn-c3-group-title,.asgn-c3-row{border-color:CanvasText}
  .asgn-c3-tab{border-bottom-color:CanvasText;color:CanvasText}
  .asgn-c3-tab[aria-selected="true"]{border-bottom-color:Highlight;color:Highlight}
  .asgn-c3-more-list{border-color:CanvasText;background:Canvas;color:CanvasText}
  .asgn-c3-more-item:hover,.asgn-c3-more-item:focus-visible{background:Highlight;color:HighlightText}
  .asgn-c3-tab:focus-visible,.asgn-c3-title:focus-visible,.asgn-c3-action:focus-visible,.asgn-c3-more:focus-visible,.asgn-c3-more-item:focus-visible,.asgn-c3-class-filter:focus-visible{outline:2px solid Highlight;outline-offset:2px}
}
.asgn-c3-status-region{display:flex;align-items:center;gap:10px;min-height:28px;color:var(--text-muted);font-size:12px}
.asgn-c3-root.is-stale .asgn-c3-panel{opacity:.55}
.asgn-c3-skeleton{margin-top:8px;border-top:1px solid var(--control-border)}
.asgn-c3-skeleton-row{display:grid;grid-template-columns:92px minmax(180px,2fr) minmax(300px,2fr) 96px;align-items:center;gap:12px;min-height:64px;border-bottom:1px solid var(--line)}
.asgn-c3-skeleton-row>span{display:block;min-height:12px;background:var(--surface-2)}
.asgn-c3-skeleton-status{max-width:72px}.asgn-c3-skeleton-title{max-width:220px}.asgn-c3-skeleton-action{min-height:44px}
.asgn-c3-empty,.asgn-c3-error{display:grid;gap:10px;justify-items:start;padding:28px 0;border-top:1px solid var(--control-border)}
.asgn-c3-error button,.asgn-c3-status-region button{min-width:44px;min-height:44px}
.asgn-c3-empty-title,.asgn-c3-empty-copy{margin:0}
.asgn-c3-empty-copy{color:var(--text-muted);font-size:12px}
@media (max-width:950px){
  .asgn-c3-skeleton-row{grid-template-columns:82px minmax(0,1fr) auto;gap:8px}
}
html[data-shell-mode="mobile-portrait"] .asgn-c3-skeleton-row,
html[data-shell-mode="mobile-landscape"] .asgn-c3-skeleton-row{grid-template-columns:minmax(0,1fr) auto;gap:8px;min-height:72px}
/* ── A+ 클래스·과제 목록 C-3 끝 ── */
/* ── 320px 반응형 오버플로 보강 ── */
@media(max-width:768px){
  .tool-panel{padding:24px 16px}
}
@media(max-width:360px){
  .grid,.cls-grid,.adb-grid{grid-template-columns:minmax(0,1fr)}
  .cls-grid,.cls-card,.cls-cover,.cls-body{min-width:0;max-width:100%}
  [data-rd] .cls-code{max-width:calc(100% - 24px);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  [data-rd] .cls-code-copy{flex:0 0 auto}
}
/* ── 320px 반응형 오버플로 보강 끝 ── */

/* V8 슬3: 공유 WebExamRenderer — 고정크기 2단 종이 페이지(viewport 무관, scale만) */
.exam-web-viewer{display:flex;flex-direction:column;align-items:center;overflow:auto}
.exam-page-shell{transform:scale(var(--page-scale,1));transform-origin:top center;display:flex;flex-direction:column;align-items:center;gap:22px}
.exam-page{position:relative;flex:none;background:#fff;border:1px solid var(--border);box-shadow:0 2px 24px rgba(20,28,48,.16);box-sizing:border-box;padding:14mm;display:grid;grid-template-columns:1fr 1px 1fr;gap:0 8mm;overflow:hidden}
.exam-column{min-width:0}
.exam-column-divider{background:var(--border)}
.exam-page-footer{position:absolute;bottom:5mm;left:0;right:0;text-align:center;font-size:12px;color:var(--text-muted);font-variant-numeric:tabular-nums}
.exam-spacer{flex:none}
/* 활자 수치는 눈대중이 아니라 Golden 자산 유도값이다 —
   templates/all_day_csat_native_v1/semantic-style-map.json 의 charPr height(1/100pt)
   와 paraPr lineSpacing(%)에서 exam_style_tokens.py 가 계산한다. var(--x, 값) 의
   폴백까지 같은 값이라 서버 토큰이 없는 호출자(학생 뷰어)도 근사치로 돌아가지
   않는다. 손으로 고치지 말 것 — tests/test_web_renderer_golden.py 가 자산에서
   다시 계산해 대조하므로 어긋나면 빨간불이 켜진다. */
.exam-q{break-inside:avoid;margin:0;font-size:var(--exam-q-size,11.5pt);line-height:var(--exam-q-line,1.8);color:var(--ink,#1a2035)}
/* 문항번호는 실물에서 제 줄상자를 키우지 않는 marker 다 — 크기만 유도값, 행간은 1. */
.exam-q-no{font-weight:800;display:inline-block;margin-right:4px;font-size:var(--exam-q-no-size,20pt);line-height:1;vertical-align:-.08em}
.exam-q-stem{display:inline}
/* 배점 [N점] — HWPX 와 같은 표기. 발문 끝에 붙어 줄바꿈되지 않는다. */
.exam-q-score{margin-left:.35em;font-size:var(--exam-score-size,11.5pt);white-space:nowrap}
.exam-choice{font-size:var(--exam-choice-size,11.5pt);line-height:var(--exam-choice-line,1.8)}
.exam-q .bogi-box,.exam-q blockquote{font-size:var(--exam-box-size,11.5pt);line-height:var(--exam-box-line,1.75)}
.exam-q-fig img{max-width:100%;height:auto}
.exam-q-choices{margin-top:3mm}
.exam-choices-inline_5{display:flex;gap:10px;flex-wrap:wrap}
.exam-choices-grid_3_2{display:grid;grid-template-columns:1fr 1fr 1fr}
.exam-choices-grid_2_2_1{display:grid;grid-template-columns:1fr 1fr}
.exam-choices-vertical .exam-choice,.exam-choices-image_grid .exam-choice{display:block}

/* ── 표지(Golden section0) ──
   본문 구역과 달리 1단이고 여백도 독립이라, .exam-page 의 2단 grid 를 끈다.
   여백은 JS 가 section-metrics 의 hwpunit 을 mm 로 환산해 인라인으로 넣는다.
   흑백 실물 재현이 목표다 — 색 강조 바·카드 테두리 같은 장식을 넣지 않는다. */
.exam-cover{display:block;grid-template-columns:none;gap:0;
  font-family:"Noto Serif KR","Nanum Myeongjo",Batang,"Apple SD Gothic Neo",serif;color:#141414}
.exam-cover-body{display:flex;flex-direction:column;align-items:center;text-align:center;
  min-height:100%;box-sizing:border-box}
.exam-cover-line{max-width:100%;overflow-wrap:anywhere;
  font-size:var(--exam-cover-text-size,14pt);line-height:var(--exam-cover-text-line,2.2)}
/* 교시는 왼쪽 위, 형 상자는 오른쪽 위 — 실물 표지의 두 모서리. */
.exam-cover-period{align-self:flex-start;border:1.2px solid #1f1f1f;border-radius:16px;
  padding:1px 14px;font-weight:700;line-height:1.5;
  font-family:"Noto Sans KR","Malgun Gothic","Apple SD Gothic Neo",sans-serif}
.exam-cover-track{align-self:flex-end;border:1.8px solid #1f1f1f;padding:1px 12px;
  font-weight:900;line-height:1.5;margin-top:6mm;
  font-family:"Noto Sans KR","Malgun Gothic","Apple SD Gothic Neo",sans-serif}
.exam-cover-year{margin-top:26mm;font-weight:700;letter-spacing:.04em}
/* 영역명은 표지에서 가장 큰 활자(cover_area 유도값)이고 위아래 굵은 괘선을 문다. */
.exam-cover-area{margin-top:8mm;padding:5mm 10mm;
  border-top:2.4px solid #1f1f1f;border-bottom:2.4px solid #1f1f1f;
  font-size:var(--exam-cover-area-size,52pt);line-height:var(--exam-cover-area-line,2.2);
  font-weight:900;letter-spacing:.22em;text-indent:.22em}
.exam-cover-title{margin-top:12mm;font-weight:700}
.exam-cover-foot{margin-top:auto;font-size:var(--exam-cover-text-size,14pt);line-height:1.5;
  font-family:"Noto Sans KR","Malgun Gothic","Apple SD Gothic Neo",sans-serif}

/* ── 캠페인 D 시험지 문구 입력칸(빌더 패널) ── */
.bk-skin-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:6px}
.bk-skin-f{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--muted,#666);min-width:0}
.bk-skin-f.bk-skin-wide{grid-column:1/-1}
.bk-skin-f input{min-width:0;width:100%}
.bk-skin-reset{margin-top:8px;font-size:12px}
.bk-skin-note{font-size:12px;color:var(--muted,#666);margin:6px 0 0;line-height:1.5}
@media (max-width:640px){.bk-skin-grid{grid-template-columns:1fr}}

/* ── 캠페인 D 시험지 스킨: 수능 실물 머리글·꼬리글(표시 계층 전용) ──
   배치는 서버 플랜 그대로다. 머리글은 페이지 grid 의 첫 행을 전폭으로 차지하고
   본문 두 단은 그 아래 행에 그대로 놓인다(단·괘선 구조 불변).
   활자: 본문 명조 / 머리글 견고딕 근사. 실물 서체는 라이선스 때문에 임베드하지
   않고 로컬 폴백 스택으로만 근사한다(CSP 상 외부 폰트 로드 불가). */
/* 머리글 행은 내용 높이만(auto), 본문 두 단이 남은 높이를 전부 가져간다.
   이 지정이 없으면 grid 가 남는 세로 공간을 두 행에 고루 늘려 머리글이 붕 뜬다. */
.exam-page-skinned{padding:9mm 12mm 14mm;grid-template-rows:auto 1fr;
  font-family:"Noto Serif KR","Nanum Myeongjo",Batang,"Apple SD Gothic Neo",serif}
.exam-page-skinned .exam-q{font-family:inherit}
.exam-skin-head{grid-column:1/-1;position:relative;display:flex;align-items:flex-end;
  margin-bottom:3mm;padding-bottom:2mm;border-bottom:1.8px solid #1f1f1f;
  font-family:"Noto Sans KR","Malgun Gothic","Apple SD Gothic Neo",sans-serif;color:#141414}
/* 1쪽은 쪽번호 아래에 형 상자가 한 칸 더 들어가므로 머리글 띠가 더 높다. */
.exam-skin-head-first{min-height:18mm}
.exam-skin-head-inner{min-height:12mm}
.exam-skin-mid{flex:1;min-width:0;text-align:center}
.exam-skin-year{font-size:9pt;font-weight:700;letter-spacing:.02em;line-height:1.3}
.exam-skin-area{font-size:19.5pt;font-weight:900;letter-spacing:.18em;text-indent:.18em;line-height:1.25}
.exam-skin-head-inner .exam-skin-area{font-size:15.75pt}
.exam-skin-pno{position:absolute;top:0;font-size:22.5pt;font-weight:600;line-height:1;
  font-family:"Noto Serif KR","Nanum Myeongjo",Batang,serif}
.exam-skin-odd .exam-skin-pno{right:0}
.exam-skin-even .exam-skin-pno{left:0}
.exam-skin-period{position:absolute;left:0;top:2px;border:1.2px solid #1f1f1f;
  border-radius:14px;padding:2px 11px;font-size:8.25pt;font-weight:700;line-height:1.4}
.exam-skin-track{position:absolute;bottom:2mm;border:1.6px solid #1f1f1f;
  padding:2px 8px;font-size:9pt;font-weight:900;line-height:1.4}
/* 1쪽은 쪽번호(우상단) 아래 오른쪽. 안쪽 쪽은 쪽번호 **반대편**에 둔다
   (바깥 모서리 쪽번호: 홀수쪽 우·짝수쪽 좌 → 형 상자는 그 반대). */
.exam-skin-head-first .exam-skin-track{right:0}
.exam-skin-head-inner.exam-skin-odd .exam-skin-track{left:0;right:auto}
.exam-skin-head-inner.exam-skin-even .exam-skin-track{right:0;left:auto}
.exam-skin-qtype{display:inline-block;border:1.2px solid #1f1f1f;padding:1px 13px;
  font-family:"Noto Sans KR","Malgun Gothic",sans-serif;font-size:7.875pt;font-weight:700;
  color:#141414;margin:0 0 4mm}
.exam-skin-foot{display:grid;grid-template-columns:1fr auto 1fr;align-items:end;
  bottom:6mm;left:12mm;right:12mm;text-align:initial;color:#141414}
.exam-skin-frac{grid-column:2;font-family:"Noto Serif KR","Nanum Myeongjo",Batang,serif;
  font-size:8.25pt;line-height:1.1}
.exam-skin-frac-cur{font-weight:600}
.exam-skin-frac-slash{font-size:10.5pt;padding:0 1px}
.exam-skin-copy{grid-column:3;justify-self:end;color:#2b46c8;font-size:6.375pt;line-height:1.3;
  font-family:"Noto Sans KR","Malgun Gothic",sans-serif}

/* V8 슬4: 클래스 학생 canonical 뷰어 헤더 컨트롤 */
.cev-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 16px;border-bottom:1px solid var(--border)}
.cev-bar:empty{display:none}
.cev-group{display:inline-flex;gap:4px}
.cev-btn{padding:4px 10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);font-size:12px;font-weight:600;color:var(--text2);cursor:pointer}
.cev-btn.on{background:var(--accent);border-color:var(--accent);color:#fff}
.cev-toggle{margin-left:auto}

/* ── A+ C-4A 상담 전용 ── */
#panel-counsel { min-width: 0; overflow-wrap: anywhere; }
#panel-counsel .cns-card { min-width: 0; }
#panel-counsel .cns-dow,
#panel-counsel .cns-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
#panel-counsel .cns-cell { min-width: 0; min-height: 56px; }
#panel-counsel #cns-new { min-height: 44px; }
#panel-counsel .btn,
.c4a-counsel-modal .btn,
.c4a-counsel-modal .cns-modal-foot button { min-height: 44px; }
#panel-counsel .cns-cell:focus-visible,
#panel-counsel .cns-row:focus-visible,
.c4a-counsel-modal :is(button, input, select, textarea):focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}
#panel-counsel .cns-cell.today { border: 2px solid var(--accent-2); }
#panel-counsel .cns-cell.sel { border: 2px solid var(--accent); background: var(--accent-tint); }
#panel-counsel .cns-row { min-height: 44px; flex-wrap: wrap; }
#panel-counsel .cns-row-topic { min-width: 8rem; }
#panel-counsel #cns-list-status,
.c4a-counsel-modal .cns-modal-status { display: flex; align-items: center; gap: 8px; min-height: 28px; }
#panel-counsel #cns-day { min-width: 0; }
#panel-counsel .cns-day-list { margin: 0; padding: 0; list-style: none; }
#panel-counsel .cns-day-item { min-width: 0; }
.c4a-counsel-modal { width: min(560px, 94vw); max-width: 560px; max-height: calc(100vh - 24px); box-sizing: border-box; }
.c4a-counsel-modal .cns-modal-body { min-width: 0; max-height: min(70vh, calc(100vh - 180px)); overflow-y: auto; }
.c4a-counsel-modal .cns-input { min-height: 44px; box-sizing: border-box; }
.c4a-counsel-modal .cns-ta { min-height: 88px; }
.c4a-counsel-modal .cns-modal-foot { flex-wrap: wrap; }
@media (min-width: 1361px) {
  #panel-counsel { margin-inline: -16px; }
}
@media (max-width: 1024px) {
  #panel-counsel { margin-inline: 0; }
}
@media (max-width: 640px) {
  #panel-counsel { margin-inline: 0; }
  #panel-counsel .cns-cell { min-height: 44px; }
  #panel-counsel .cns-row { align-items: flex-start; }
  #panel-counsel .cns-row-topic { flex: 1 1 100%; min-width: 0; white-space: normal; }
  .c4a-counsel-modal { width: 94vw; max-height: calc(100vh - 12px); }
  .c4a-counsel-modal .cns-modal-body { max-height: calc(100vh - 160px); }
}
/* 401px is the first width where the standard gutters still leave seven 44px cells. */
@media (max-width: 400px) {
  #panel-counsel { margin-inline: 0; }
  #panel-counsel .cns-card { padding: 4px 0; }
  #panel-counsel .cns-grid { gap: 0; padding-left: 0; padding-right: 0; }
  #panel-counsel .cns-cell { padding: 2px; }
  #panel-counsel .cns-cell-n { right: 2px; bottom: 2px; min-width: 14px; height: 14px; padding: 0 3px; font-size: var(--type-label); }
  #panel-counsel .cns-row { gap: 6px; padding-inline: 4px; }
}
@media (max-width: 360px) {
  #panel-counsel { padding-inline: 0; }
}
@media (forced-colors: active) {
  #panel-counsel .cns-cell,
  #panel-counsel .cns-row,
  .c4a-counsel-modal .cns-input { border: 1px solid CanvasText; }
  #panel-counsel .cns-cell.today,
  #panel-counsel .cns-cell.sel { border: 2px solid CanvasText; }
  #panel-counsel .cns-cell:focus-visible,
  #panel-counsel .cns-row:focus-visible,
  .c4a-counsel-modal :is(button, input, select, textarea):focus-visible { outline: 2px solid CanvasText; }
}
@media (prefers-reduced-motion: reduce) {
  #panel-counsel .cns-cell,
  #panel-counsel .cns-row,
  .c4a-counsel-modal,
  .c4a-counsel-modal :is(button, input, select, textarea) { transition: none; }
}
/* ── /A+ C-4A 상담 전용 ── */

/* ── C-4C 사용량·추정 비용 ── */
/* 이 화면 전용 — 다른 표면이 grid/여백을 물려받지 않도록 #panel-history로 한정한다. */
#panel-history .usage-basis { margin: 6px 0 14px; font-size: 13px; color: var(--ink-3); }
#panel-history .usage-basis > summary { cursor: pointer; }
#panel-history .usage-basis ul { margin: 8px 0 0 18px; display: grid; gap: 4px; }
/* 표는 최근 500건 표본이다 — 각주·미등록 표식도 이 화면 전용으로 한정한다. */
#panel-history .unpriced-tag { display: block; margin-top: 2px; font-size: 12px; color: var(--ink-3); }
#panel-history .unpriced-tag::before { content: '└ '; }
#panel-history .tbl-cap { caption-side: top; text-align: left; padding: 0 0 8px; font-size: 13px; color: var(--ink-3); }
#panel-history .usage-note { margin: 6px 0 0; font-size: 13px; color: var(--ink-3); }
/* .two의 fr 트랙은 자동 최소치가 min-content다 — .tbl{min-width:560px}이 트랙 자체를
   560px로 부풀려 .tbl-wrap이 가로 스크롤을 열 기회를 잃는다. 넘친 폭은 그대로
   #main{overflow-x:hidden}에 잘려 오른쪽 열(비용·날짜)이 영구히 도달 불가가 된다.
   minmax(0,·)로 최소치를 풀어 트랙을 컨테이너에 가두고, 넘침은 .tbl-wrap이 맡는다. */
#panel-history .two { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
/* 요약이 로딩·실패면 제공사 비중은 비워진다(loadSummary). 트랙이 그대로 남으면 표는
   좁아진 채 옆에 아무것도 없는 넓은 빈 칸이 붙는다 — 빈 칸을 위해 표를 좁히지 않는다. */
#panel-history .two:has(> #cost-legend-body:empty) { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 768px) {
  /* 공용 .two의 1단 전환(0,1,0)보다 위 규칙(1,1,0)이 세므로 여기서 다시 못 박는다. */
  #panel-history .two { grid-template-columns: minmax(0, 1fr); }
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   족보 아카이브(#panel-jokbo)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
/* .card는 문항 카드용이라 cursor:pointer + 호버 리프트가 붙는다 — 섹션 컨테이너로 쓰므로 되돌린다. */
.jb-card { cursor: default; }
.jb-card:hover { box-shadow: var(--shadow); transform: none; }
.jb-note { font-size: 13px; color: var(--ink-3); }
/* ⚠️ .toolbar가 display:flex를 클래스에서 선언하므로 UA의 [hidden]{display:none}이 진다
   (작성자 스타일 승). 등록 바는 파일 선택 전까지 숨겨야 하므로 id로 다시 못 박는다. */
#jb-commit-bar[hidden] { display: none; }
.jb-f-input { width: auto; max-width: 160px; }
.jb-f-year { max-width: 96px; }
/* 미리보기 표는 9열 전부가 입력칸 — 좁히면 못 쓰므로 .tbl-wrap 가로 스크롤에 맡긴다. */
#jb-preview .tbl { min-width: 1040px; }
#jb-preview .field { min-width: 84px; }
/* 파일·관리 열은 칩이 여러 개 — td 직계 자식 1개(=이 래퍼)로 묶어 카드 모드 정렬을 지킨다. */
.jb-cell-actions { display: flex; flex-wrap: wrap; gap: 6px; }
/* ≤768px에서 전역 .toolbar는 nowrap+가로스크롤이 된다(3451행). 족보 바는 검색 버튼까지
   전부 보여야 하므로 은행 툴바(2323행)와 같은 처방으로 줄바꿈을 되돌린다 —
   .jb-card .jb-bar(0,0,2,0)가 뒤에 오므로 .toolbar(0,0,1,0)를 이긴다. */
@media (max-width: 768px) {
  .jb-card .jb-bar { flex-wrap: wrap; overflow-x: visible; }
  /* input의 min-width:auto는 min-content(≈20자)라 줄바꿈해도 한 줄에 하나씩 떨어진다 — 0으로 풀어 둘씩 앉힌다. */
  .jb-card .jb-bar .jb-f-input { flex: 1 1 120px; min-width: 0; max-width: none; }
  .jb-card .jb-bar .btn { flex: 0 0 auto; }
}
@media (max-width: 640px) {
  /* .tbl.tbl-cards(0,0,2,0)보다 위 id 규칙(0,1,1,0)이 세므로 카드 모드에서 다시 못 박는다. */
  #jb-preview .tbl.tbl-cards { min-width: 0; }
  #jb-preview .tbl.tbl-cards .field { min-width: 0; max-width: 62%; }
  .tbl.tbl-cards .jb-cell-actions { justify-content: flex-end; }
}

/* 문항 오류 신고(W5) 학생 진입점 — 과제 풀이·오답 노트에서 문항 옆 작은 폼.
   기존 .field/.btn 토큰만 쓰고 색은 새로 만들지 않는다. */
.rep-entry{margin-top:8px}
.rep-entry-block{margin:0 0 10px}
.rep-open{background:none;border:none;padding:2px 0;font:inherit;font-size:12.5px;
  color:var(--ink-3);cursor:pointer;text-decoration:underline}
.rep-open:hover{color:var(--text)}
.rep-open:disabled{color:var(--ink-3);text-decoration:none;cursor:default}
.rep-form{display:flex;flex-direction:column;gap:6px;margin-top:6px;max-width:520px}
.rep-form .rep-detail{resize:vertical;line-height:1.6}
.rep-acts{display:flex;gap:6px;align-items:center}
.rep-msg{margin:0;font-size:12.5px;color:var(--ink-3)}
.rep-msg.err{color:var(--danger)}

/* ── A+ C-4O 학생 클래스 ── */
.cls-c4o-card{position:relative;transition:border-color 120ms,background-color 120ms}
.cls-c4o-card-heading{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
.cls-c4o-card-open{display:inline-flex;align-items:center;min-width:44px;min-height:44px;max-width:100%;padding:6px 0;border:0;background:transparent;color:var(--text);font:inherit;font-weight:800;text-align:left;white-space:normal;overflow-wrap:anywhere;cursor:pointer}
.cls-c4o-card-open::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
.cls-c4o-card:has(.cls-c4o-card-open:hover){border-color:var(--control-border);background:var(--surface-3)}
.cls-c4o-card:has(.cls-c4o-card-open:focus-visible){outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c4o-card-open:focus-visible{outline:0}
.cls-c4o-card-facts,.cls-c4o-command-context,.cls-c4o-progress-facts,.cls-c4o-lec-facts,.cls-c4o-file-facts{display:grid;grid-template-columns:auto minmax(0,1fr);gap:4px 10px;margin:10px 0 0;font-size:12.5px;font-variant-numeric:tabular-nums}
.cls-c4o-fact-label{color:var(--text-muted)}
.cls-c4o-fact-value{margin:0;min-width:0;color:var(--text);overflow-wrap:anywhere}

.cls-c4o-command-title{margin:0;min-width:0;overflow-wrap:anywhere}
.cls-c4o-command-summary{margin:4px 0 0;color:var(--text-muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.cls-c4o-command-back{min-width:44px;min-height:44px;display:inline-flex;align-items:center;gap:4px;white-space:nowrap}

.cls-c4o-tabs{margin:0 0 14px}
.cls-c4o-tab{min-height:44px;cursor:pointer}
.cls-c4o-tab[aria-selected="true"]{border-bottom-color:var(--selection-outline)}
.cls-c4o-tab:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c4o-panel{min-width:0}
.cls-c4o-panel[hidden]{display:none}

.cls-c4o-progress{display:block}
/* 진도 요약 카드는 강조면 위에 놓이므로 사실 목록이 컨테이너 글자색을 물려받아야 한다. */
.cls-c4o-progress .cls-c4o-fact-value{color:inherit}
.cls-c4o-progress .cls-c4o-fact-label{color:inherit;opacity:.72}
.cls-c4o-progress .cls-c4o-progress-facts{margin:0 0 14px;font-size:13.5px}
.cls-c4o-due-strip{min-width:0;max-width:100%}

.cls-c4o-lec-row{position:relative}
.cls-c4o-lec-select{min-width:44px;min-height:44px;max-width:100%;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-weight:700;text-align:left;white-space:normal;overflow-wrap:anywhere;cursor:pointer}
.cls-c4o-lec-select::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
.cls-c4o-lec-row:has(.cls-c4o-lec-select:focus-visible){outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c4o-lec-select:focus-visible{outline:0}
.cls-c4o-lec-play{position:relative;z-index:2;min-width:44px;min-height:44px;border:0;background:transparent;color:inherit;cursor:pointer}
.cls-c4o-lec-play:focus-visible{outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c4o-lec-card{display:block}

.cls-c4o-practice-row,.cls-c4o-file-row{position:relative;transition:border-color .15s,background .15s}
/* 행 전체가 클릭 대상이므로(::after 오버레이) 클릭 가능함을 알리는 hover 피드백을
   유지한다. 이전 asgn-row-clickable·file-row-clickable이 주던 신호와 같은 역할이다. */
.cls-c4o-practice-row:has(.cls-c4o-practice-title:hover){border-color:var(--accent);background:var(--accent-tint)}
.cls-c4o-file-row:has(.cls-c4o-file-open:hover){background:var(--surface-2)}
.cls-c4o-lec-row:has(.cls-c4o-lec-select:hover){border-color:var(--accent)}
.cls-c4o-practice-title,.cls-c4o-file-open{min-width:44px;min-height:44px;max-width:100%;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-weight:700;text-align:left;white-space:normal;overflow-wrap:anywhere;cursor:pointer}
.cls-c4o-practice-title::after,.cls-c4o-file-open::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
.cls-c4o-practice-row:has(.cls-c4o-practice-title:focus-visible),.cls-c4o-file-row:has(.cls-c4o-file-open:focus-visible){outline:2px solid var(--focus-ring,var(--accent));outline-offset:2px}
.cls-c4o-practice-title:focus-visible,.cls-c4o-file-open:focus-visible{outline:0}

.cls-c4o-section-head{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}
.cls-c4o-section-acts{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cls-c4o-utility{min-width:44px;min-height:44px}
.cls-c4o-section-status{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 0}
.cls-c4o-section-message{margin:0;color:var(--text-muted)}
.cls-c4o-retry{min-width:44px;min-height:44px}
.cls-c4o-empty{margin:0}
.cls-c4o-skeleton{display:grid;gap:8px;padding:6px 0}
.cls-c4o-skeleton-line{display:block;height:12px;border-radius:6px;background:var(--surface-3)}
.cls-c4o-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

.cls-c4o-open-failure{display:grid;gap:12px;justify-items:start}
.cls-c4o-open-failure-message{margin:0;color:var(--text)}
.cls-c4o-open-failure-acts{display:flex;gap:8px;flex-wrap:wrap}
.cls-c4o-open-failure-back,.cls-c4o-open-failure .cls-c4o-retry{min-height:44px}

.cls-c4o-dialog{display:grid;gap:12px;max-width:min(420px,92vw)}
.cls-c4o-dialog-title{margin:0;font-size:15px;font-weight:800}
.cls-c4o-dialog-body{margin:0;color:var(--text-muted)}
.cls-c4o-dialog-acts{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap}
.cls-c4o-dialog-acts button{min-height:44px}

.cls-c4o-exam-marks{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:6px}
.cls-c4o-exam-publish{color:var(--text-muted);font-size:12px}

html[data-shell-mode="tablet-portrait"] .cls-c4o-tabs,
html[data-shell-mode="mobile-portrait"] .cls-c4o-tabs,
html[data-shell-mode="mobile-landscape"] .cls-c4o-tabs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0;width:100%}
html[data-shell-mode="tablet-portrait"] .cls-c4o-tab,
html[data-shell-mode="mobile-portrait"] .cls-c4o-tab,
html[data-shell-mode="mobile-landscape"] .cls-c4o-tab{width:100%;min-width:0;padding-inline:4px;font-size:12px;text-align:center}
html[data-shell-mode="mobile-portrait"] .cls-c4o-command-context,
html[data-shell-mode="mobile-landscape"] .cls-c4o-command-context{grid-template-columns:auto minmax(0,1fr)}
@media (pointer:coarse){.cls-c4o-tab,.cls-c4o-utility,.cls-c4o-retry,.cls-c4o-command-back,.cls-c4o-lec-play{min-height:48px}}
@media (prefers-reduced-motion:reduce){.cls-c4o-card,.cls-c4o-tab,.cls-c4o-lec-row,.cls-c4o-practice-row,.cls-c4o-file-row{transition:none!important}}
@media (forced-colors:active){
.cls-c4o-card{border:1px solid CanvasText}
.cls-c4o-tab{border-bottom-color:CanvasText;color:CanvasText}
.cls-c4o-tab[aria-selected="true"]{border-bottom-color:Highlight;color:Highlight}
.cls-c4o-tab:focus-visible,.cls-c4o-card-open:focus-visible,.cls-c4o-lec-select:focus-visible,.cls-c4o-practice-title:focus-visible,.cls-c4o-file-open:focus-visible,.cls-c4o-lec-play:focus-visible{outline:2px solid Highlight;outline-offset:2px}
.cls-c4o-skeleton-line{border:1px solid CanvasText;background:Canvas}
.cls-c4o-dialog{border:1px solid CanvasText;background:Canvas;color:CanvasText;forced-color-adjust:none}
}
/* ── A+ C-4O 학생 클래스 끝 ── */

/* ══════════════════════════════════════════════════════════════════
   Amicro 마이크로 인터랙션 1차 — 컨트롤·피드백 공유 계층
   후보 출처: Amicro (MIT, github.com/Subhan-code/Amicro--Micro-transitions-).
   풀다 토큰만 쓴다(새 하드코딩 색 금지). 상태는 색만으로 알리지 않는다 —
   문구·aria 가 함께 바뀌는 것이 계약이고 색은 거들 뿐이다.
   모션은 이 절 끝의 prefers-reduced-motion 블록에서 한 번에 꺼진다.
   ══════════════════════════════════════════════════════════════════ */

/* ── 1. 버튼 결과 피드백 ─────────────────────────────────────────
   클래스를 두 번 적는 것은 특이도(0,2,0)를 올려 .btn-primary·.bk-icon-btn
   같은 기존 규칙을 !important 없이 이기기 위해서다. */
.mv-fb-ok.mv-fb-ok{background:var(--ok);border-color:var(--ok);color:#fff}
.mv-fb-armed.mv-fb-armed{background:var(--danger);border-color:var(--danger);color:#fff}
.mv-fb-shake{animation:mv-shake .4s}
@keyframes mv-shake{0%,100%{transform:none}20%,60%{transform:translateX(-4px)}40%,80%{transform:translateX(4px)}}
/* 아이콘 전용 버튼이 확인 단계로 들어가면 문구가 붙어 폭이 늘어난다.
   빨간색만으로 한 번 더 눌러야 한다는 뜻을 전하지 않기 위한 것이다. */
.mv-fb-label{margin-left:5px;font-size:var(--type-label);font-weight:700;white-space:nowrap}
.bk-icon-btn.mv-fb-armed{width:auto;min-height:28px;padding:0 9px;gap:2px}
/* 진행 링 — 버튼 안 SVG. 서버가 파일을 만드는 구간은 진행률을 알 수 없어
   회전(비결정)으로만 알린다. 퍼센트를 지어내지 않는다. */
.mv-dl-ring{width:15px;height:15px;flex:none}
.mv-dl-ring circle{fill:none;stroke:currentColor;stroke-width:3;opacity:.3}
.mv-dl-ring .mv-dl-arc{opacity:1;stroke-linecap:round;stroke-dasharray:50.3;stroke-dashoffset:37.7;
  transform-origin:50% 50%;animation:mv-dl-spin .9s linear infinite}
@keyframes mv-dl-spin{to{transform:rotate(360deg)}}
/* 진행률을 실제로 아는 호출자만 켠다(MVKit.downloadButton().progress(0..1)). */
.mv-dl-ring.is-determinate .mv-dl-arc{animation:none;transform:rotate(-90deg);
  transition:stroke-dashoffset .12s linear}

/* ── 2. 필터 칩 스프링 팝 ──────────────────────────────────────── */
.chip,.bk-chip{transition:background .15s,color .15s,border-color .15s,
  transform .18s cubic-bezier(.34,1.56,.64,1)}
.chip.on{transform:scale(1.06)}
/* 전체 칩은 모든 그룹의 기본값이라 늘 켜져 있다. 늘 부풀어 있으면 강조가 아니다. */
.bk-chip.active:not([data-v=""]){transform:scale(1.06)}
.chip.mv-pop,.bk-chip.mv-pop{animation:mv-pillpop .32s cubic-bezier(.34,1.56,.64,1)}
@keyframes mv-pillpop{0%{transform:scale(.92)}55%{transform:scale(1.12)}100%{transform:scale(1.06)}}
/* 칩 안 개수 병기(문항 수 등). 목업은 11px 였지만 이 저장소의 최소 본문 크기는
   12px 라(tests/test_type_contract_static.py) --type-label 을 쓴다. */
.chip .n,.bk-chip .n{font-size:var(--type-label);opacity:.72;font-variant-numeric:tabular-nums}

/* ── 3. 세그먼트 썸 슬라이드(옵트인) ────────────────────────────
   MVKit.segmented(..., {slide:true}) 만 켠다. 기본 .segmented 는 불변. */
.segmented.mv-seg-slide{position:relative}
.segmented.mv-seg-slide .mv-seg-thumb{position:absolute;top:3px;bottom:3px;left:0;
  width:var(--mv-seg-w,0px);transform:translateX(var(--mv-seg-x,0px));
  background:var(--accent);border-radius:6px;box-shadow:var(--shadow-control);
  pointer-events:none;z-index:0;opacity:0;
  transition:transform .28s cubic-bezier(.4,0,.2,1),width .28s cubic-bezier(.4,0,.2,1)}
.segmented.mv-seg-slide.mv-seg-ready .mv-seg-thumb{opacity:1}
.segmented.mv-seg-slide button{position:relative;z-index:1}
.segmented.mv-seg-slide.mv-seg-ready button.on{background:none;border-color:transparent;
  box-shadow:none;color:var(--accent-ink)}

/* ── 4. 언더라인 탭 슬라이딩 인디케이터 ──────────────────────────
   인디케이터가 실제로 붙었을 때만(.mv-ind-ready) 탭 자체 밑줄을 끈다.
   JS 가 실패하면 종전 밑줄이 그대로 남는다. */
.bk-tabs .mv-tab-ind{position:absolute;left:0;bottom:-1px;height:2px;
  width:var(--mv-ind-w,0px);transform:translateX(var(--mv-ind-x,0px));
  background:var(--pri);border-radius:2px;pointer-events:none;z-index:3;opacity:0;
  transition:transform .28s cubic-bezier(.4,0,.2,1),width .28s cubic-bezier(.4,0,.2,1)}
.bk-tabs.mv-ind-ready .mv-tab-ind{opacity:1}
.bk-tabs.mv-ind-ready .bk-tab.active{border-bottom-color:transparent}

/* ── 5. 페이지네이션 활성 썸 슬라이드 ──────────────────────────
   .bk-pagination 은 wrap 하므로 세로 오프셋(--mv-pg-y)까지 같이 옮긴다. */
.bk-pagination{position:relative}
.bk-pagination .mv-pg-thumb{position:absolute;left:0;top:0;height:34px;
  width:var(--mv-pg-w,0px);transform:translate(var(--mv-pg-x,0px),var(--mv-pg-y,0px));
  background:var(--accent);border-radius:8px;pointer-events:none;z-index:0;opacity:0;
  transition:transform .3s cubic-bezier(.4,0,.2,1),width .3s cubic-bezier(.4,0,.2,1)}
.bk-pagination.mv-pg-ready .mv-pg-thumb{opacity:1}
.bk-pagination .bk-page-btn{position:relative;z-index:1}
.bk-pagination.mv-pg-ready .bk-page-btn.active{background:transparent;border-color:transparent}

/* ── 6. 토스트: 필 형태 + 결과 아이콘 ──────────────────────────
   .toast/.toast.err 계약은 그대로 두고 실사용 경로(.mv-toast)만 손본다. */
.mv-toast{display:flex;align-items:center;gap:9px;padding:9px 16px 9px 10px;
  border-radius:var(--radius-pill);box-shadow:var(--shadow-high);
  transform:translate(-50%,8px) scale(.94);
  transition:opacity .2s,transform .26s cubic-bezier(.34,1.3,.64,1)}
.mv-toast.on{transform:translate(-50%,0) scale(1)}
.mv-toast-ic{flex:none;width:20px;height:20px;border-radius:var(--radius-pill);
  display:inline-flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;line-height:1;background:var(--ok);color:#fff}
.mv-toast.err .mv-toast-ic{background:var(--accent-ink);color:var(--danger)}

/* ── 7. 모달·시트 등장 ─────────────────────────────────────────
   .adb-sheet 가 이미 쓰는 짧은 상승 + 페이드를 공통 키프레임으로 맞춘다.
   장식적 스프링·바운스는 쓰지 않는다(그 파일의 기존 결정을 따른다).
   display 토글 구조는 건드리지 않는다. */
@keyframes mv-overlay-in{from{opacity:0}to{opacity:1}}
/* 상승 + 페이드만 쓴다. 축소로 들어오면 등장 200ms 동안 모달 안의 모든 표적이
   그 비율만큼 작아진다 — scale(.985)는 44px 표적을 43.34px 로 만들어 터치 표적
   계약을 깼다(문제 은행 선택 다이얼로그 닫기 버튼에서 실측). 1.5% 축소는 눈에
   거의 띄지도 않는 장식인데 대가가 표적 크기다. 상승이 그 일을 대신한다. */
@keyframes mv-pop-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.ui-modal-overlay{animation:mv-overlay-in .16s ease-out}
.ui-modal-overlay .ui-modal{animation:mv-pop-in .2s cubic-bezier(.4,0,.2,1)}
.mv-annc-bg.open{animation:mv-overlay-in .16s ease-out}
.mv-annc-bg.open .mv-annc-card{animation:mv-pop-in .2s cubic-bezier(.4,0,.2,1)}
.cls-c2-sheet-overlay{animation:mv-overlay-in .16s ease-out}

/* ── 8. 아코디언 높이 전환 ────────────────────────────────────
   입시DB 그룹은 <details> 라 ::details-content 로만 손댈 수 있다. 미지원
   브라우저는 종전대로 즉시 접힌다(점진 향상). interpolate-size 는 .adb-grp
   안으로만 상속시켜 다른 화면의 auto 전환 계산을 건드리지 않는다.
   캐럿 회전은 .adb-grp-caret 이 이미 갖고 있다. */
@supports selector(::details-content){
  .adb-grp{interpolate-size:allow-keywords}
  .adb-grp::details-content{block-size:0;overflow:hidden;content-visibility:hidden;
    transition:block-size .28s cubic-bezier(.4,0,.2,1),content-visibility .28s allow-discrete}
  .adb-grp[open]::details-content{block-size:auto;content-visibility:visible}
}
/* 시험지 구성 접기 — 캐럿은 이미 돌고, 본문은 높이로 접힌다. */
.bk-build-body{display:grid;grid-template-rows:1fr;
  transition:grid-template-rows .28s cubic-bezier(.4,0,.2,1)}
.bk-build-body>*{overflow:hidden;min-height:0}
.bk-builder.build-collapsed .bk-build-body{grid-template-rows:0fr}

/* ── 9. 알림 배지 팝 ──────────────────────────────────────────── */
.cls-qna-tab-badge.mv-pop{animation:mv-badge-pop .45s cubic-bezier(.34,1.56,.64,1)}
@keyframes mv-badge-pop{0%{transform:scale(.6)}55%{transform:scale(1.35)}100%{transform:scale(1)}}

/* ── 10. 업로드 존: 드래그 반응 + 존 안 진행 표시 ────────────────
   진행률을 알려 주는 경로가 없으므로 흐르는 막대로 일하는 중임만 말한다. */
.upload-zone{transition:border-color .15s,background .15s,transform .2s}
.upload-zone.drag-over{border-color:var(--data);
  background:color-mix(in srgb,var(--data) 8%,transparent);transform:translateY(-2px)}
.mv-upz-bar{width:100%;height:5px;margin-top:12px;border-radius:4px;
  background:var(--surface-2);overflow:hidden;opacity:0;transition:opacity .2s}
.upload-zone.mv-busy .mv-upz-bar,.upload-zone.mv-done .mv-upz-bar{opacity:1}
.mv-upz-bar i{display:block;width:36%;height:100%;border-radius:4px;background:var(--data);
  animation:mv-upz-slide 1.1s ease-in-out infinite}
@keyframes mv-upz-slide{from{transform:translateX(-110%)}to{transform:translateX(320%)}}
.upload-zone.mv-done .mv-upz-bar i{animation:none;width:100%;transform:none;background:var(--ok)}

/* ── 11. 모션 축소·터치·강제색 대응 ─────────────────────────────── */
@media (pointer:coarse){
  .chip{min-height:44px}
  .segmented.mv-seg-slide button{min-height:44px}
}
@media (prefers-reduced-motion:reduce){
  .chip,.bk-chip,.mv-toast,.upload-zone,.mv-upz-bar,
  .segmented.mv-seg-slide .mv-seg-thumb,.bk-tabs .mv-tab-ind,.bk-pagination .mv-pg-thumb,
  .bk-build-body,.adb-grp::details-content{transition:none}
  .mv-fb-shake,.chip.mv-pop,.bk-chip.mv-pop,.cls-qna-tab-badge.mv-pop,
  .ui-modal-overlay,.ui-modal-overlay .ui-modal,.mv-annc-bg.open,.mv-annc-bg.open .mv-annc-card,
  .cls-c2-sheet-overlay,.mv-upz-bar i{animation:none}
  .chip.on,.bk-chip.active:not([data-v=""]){transform:none}
  .mv-toast{transform:translate(-50%,8px)}
  .mv-toast.on{transform:translate(-50%,0)}
  .upload-zone.drag-over{transform:none}
  /* 회전만으로 알리던 링은 모션을 끄면 아무 말도 못 한다. 문구가 대신한다. */
  .mv-dl-ring{display:none}
}
@media (forced-colors:active){
  .bk-tabs .mv-tab-ind,.bk-pagination .mv-pg-thumb,.segmented.mv-seg-slide .mv-seg-thumb{display:none}
  .bk-tabs.mv-ind-ready .bk-tab.active{border-bottom-color:Highlight}
  .bk-pagination.mv-pg-ready .bk-page-btn.active{border:1px solid Highlight;color:Highlight}
  .segmented.mv-seg-slide.mv-seg-ready button.on{border-color:Highlight;color:Highlight}
  .mv-toast-ic{border:1px solid CanvasText}
}
/* ── Amicro 1차 끝 ── */

/* ══════════════════════════════════════════════════════════════════
   Amicro 마이크로 인터랙션 2차 — 문제은행 카드·데이터·상태
   1차와 같은 규칙: 풀다 토큰만 쓰고(새 하드코딩 색 금지), 색 하나로 상태를
   말하지 않으며(문구·title·aria 가 함께 든다), 모션은 이 절 끝의
   prefers-reduced-motion 블록에서 한 번에 꺼진다.
   범주형 색은 P6 정체성 색 원칙을 따른다 — 순차 램프는 히트맵 하나뿐이고,
   그건 한 축의 크기를 말하므로 순차가 맞다.
   ══════════════════════════════════════════════════════════════════ */

/* ── 1. 문제 카드 글랜스 바 ─────────────────────────────────────
   실데이터가 있는 필드만 bank.js 가 채운다. 없으면 바 자체가 만들어지지 않는다.
   fine 포인터: 카드 아래에서 밀려 올라온다(호버·포커스). coarse 포인터에는
   호버가 없으므로 늘 보인다 — 카드 즐겨찾기 버튼이 이미 쓰는 갈래
   (html[data-input="touch"])와 같은 분기다.
   자리는 카드가 늘 비워 둔다(.has-glance 의 padding-bottom). 높이를 바꿔 가며
   여닫으면 그 카드만 커지는 게 아니라 격자 줄 전체가 밀려서, 마우스 밑에 있던
   카드가 커버 밖으로 빠져나가고 다시 들어오는 떨림이 생긴다(실측: 픽셀 고정
   테스트가 같은 트리에서 실행마다 다른 그림을 냈다). 바는 그 빈 자리 안에서만
   미끄러진다 — 카드 크기는 어느 상태에서도 그대로다. */
.bk-ps-card.has-glance{padding-bottom:30px}
.bk-card-glance{position:absolute;left:0;right:0;bottom:0;height:28px;overflow:hidden;
  pointer-events:none;border-radius:0 0 var(--radius-card) var(--radius-card)}
.bk-card-glance>span{display:flex;align-items:center;gap:4px 10px;height:100%;
  padding:0 16px;background:var(--surface-2);border-top:1px solid var(--line-2);
  white-space:nowrap;overflow:hidden;
  transform:translateY(100%);opacity:0;
  transition:transform .24s cubic-bezier(.4,0,.2,1),opacity .18s}
.bk-ps-card:hover .bk-card-glance>span,
.bk-ps-card:focus-within .bk-card-glance>span{transform:none;opacity:1}
.bk-glance-i{display:inline-flex;align-items:center;gap:4px;
  font-size:var(--type-label);color:var(--ink-4);white-space:nowrap;min-width:0}
.bk-glance-i b{font-weight:700;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis}
/* 터치: 호버가 없으니 늘 올라와 있다. 연출이 없으니 전이도 없다. */
html[data-input="touch"] .bk-card-glance>span{transform:none;opacity:1;transition:none}

/* ── 2. 찜 별: 회전 + 스케일 ────────────────────────────────────
   색은 --fav 를 그대로 둔다. 즐겨찾기 색은 이 앱에서 이미 정체성 색이고
   (.bk-fav-chip.active, 상세 패널 .fav-active), 카드만 다른 색을 쓰면
   같은 뜻이 두 색으로 갈린다. */
.bk-card-fav-btn svg{transition:transform .28s cubic-bezier(.34,1.56,.64,1)}
.bk-card-fav-btn.fav-active svg{transform:scale(1.12)}
.bk-card-fav-btn.mv-fav-pop svg{animation:mv-fav-spin .42s cubic-bezier(.34,1.56,.64,1)}
@keyframes mv-fav-spin{0%{transform:rotate(0) scale(.7)}60%{transform:rotate(200deg) scale(1.3)}
  100%{transform:rotate(180deg) scale(1.12)}}

/* ── 3. ⋯ 작업 메뉴 ────────────────────────────────────────────
   position:fixed 라 카드·패널의 overflow 에 잘리지 않는다. */
.mv-menu{position:fixed;z-index:400;min-width:168px;padding:5px;
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  box-shadow:var(--shadow-high);display:flex;flex-direction:column;gap:1px;
  animation:mv-pop-in .16s cubic-bezier(.4,0,.2,1)}
.mv-menu-it{display:flex;align-items:center;gap:8px;width:100%;min-height:34px;
  padding:7px 10px;border:1px solid transparent;border-radius:7px;background:none;cursor:pointer;
  font-size:var(--type-button);font-weight:600;color:var(--ink-2);text-align:left;
  transition:background .14s,color .14s}
.mv-menu-it:hover:not(:disabled){background:var(--surface-2);color:var(--ink)}
.mv-menu-it:disabled{opacity:.45;cursor:default}
.mv-menu-it.is-danger{color:var(--danger)}
.mv-menu-it.is-danger:hover:not(:disabled){background:color-mix(in srgb,var(--danger) 10%,transparent)}
.mv-menu-ic{flex:none;display:inline-flex;width:16px;height:16px;align-items:center;justify-content:center}
.mv-menu-lb{flex:1;min-width:0}
.mv-menu-sep{height:1px;margin:4px 6px;background:var(--line-2)}

/* ── 4. 보기 전환(그리드 ↔ 리스트) ──────────────────────────────
   리스트는 한 줄에 한 문항이고 본문 클램프가 짧아져 더 많이 훑힌다.
   전환은 원근 회전 한 번뿐이다 — 카드마다 다시 돌지 않는다. */
.bk-listtools{display:flex;align-items:center;gap:8px;margin-left:auto;flex:none;align-self:center}
/* ⋯ 버튼은 글자 하나뿐이라 그냥 두면 표적이 너무 작다. */
.bk-card-menu-btn{margin-left:auto;min-width:26px;min-height:22px;line-height:1;
  cursor:pointer;font-weight:800;letter-spacing:.5px}
@media (pointer:coarse){.bk-card-menu-btn{min-width:44px;min-height:32px}}
.bk-problem-list.is-list{grid-template-columns:1fr}
.bk-problem-list.is-list .bk-ps-card{display:grid;
  grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"top top" "body meta" "glance glance";
  gap:2px 14px;align-items:start;padding:11px 14px}
.bk-problem-list.is-list .bk-card-top{grid-area:top}
.bk-problem-list.is-list .bk-card-content{grid-area:body;-webkit-line-clamp:2;margin-top:2px}
.bk-problem-list.is-list .bk-card-choices{display:none}
.bk-problem-list.is-list .bk-card-footer{grid-area:meta;justify-content:flex-end;
  align-self:center;flex-wrap:wrap;max-width:min(52%,340px)}
.bk-problem-list.is-list .bk-card-glance{grid-area:glance}
.bk-problem-list.mv-view-swap .bk-ps-card{animation:mv-view-flip .34s cubic-bezier(.4,0,.2,1)}
@keyframes mv-view-flip{from{opacity:.25;transform:perspective(760px) rotateX(-9deg) translateY(6px)}
  to{opacity:1;transform:none}}
@media(max-width:560px){
  /* 좁은 화면에서 리스트는 이미 1열이라 뜻이 없다 — 격자와 같게 둔다. */
  .bk-problem-list.is-list .bk-ps-card{display:block}
  .bk-problem-list.is-list .bk-card-footer{max-width:none;justify-content:flex-start}
}

/* ── 5. KPI 스파크라인 ──────────────────────────────────────────
   폭은 카드를 다 쓰고 선 굵기는 non-scaling-stroke 가 2px 로 지킨다. */
.mv-spark{display:block;width:100%;height:30px;margin-top:8px;overflow:visible}
.mv-spark-line{fill:none;stroke:var(--data);stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.mv-spark-end{stroke:var(--data-strong);stroke-width:5.5;stroke-linecap:round}

/* ── 6. 반원 아크 미터 ──────────────────────────────────────────
   ring 과 병존한다. 세로를 절반만 먹어 값과 라벨이 호 안쪽에 앉는다. */
.mv-arc{position:relative;width:var(--mv-arc-w,168px);max-width:100%;margin:6px auto 0}
.mv-arc svg{display:block;width:100%;height:auto}
.mv-arc-track{fill:none;stroke:var(--surface-2);stroke-width:11;stroke-linecap:round}
.mv-arc-val{fill:none;stroke:var(--data);stroke-width:11;stroke-linecap:round;
  transition:stroke-dashoffset .6s cubic-bezier(.4,0,.2,1)}
.mv-arc-lbl{position:absolute;left:0;right:0;bottom:4px;text-align:center;line-height:1.15}
.mv-arc-lbl b{display:block;font-size:26px;font-weight:800;color:var(--ink);
  font-variant-numeric:tabular-nums}
.mv-arc-lbl span{display:block;font-size:var(--type-label);color:var(--ink-4);margin-top:2px}

/* ── 7. 분절 진행 바 ────────────────────────────────────────────
   칸 하나가 건수 하나다. 칸을 세면 값이 읽힌다. */
.mv-segbar{display:flex;align-items:center;gap:9px;min-width:0}
/* 문장 옆에 끼어 앉을 때 — 칸이 화면 폭만큼 늘어나면 세는 뜻이 사라진다. */
.mv-segbar.is-inline{max-width:300px}
.mv-segbar-track{display:flex;gap:3px;flex:1;min-width:60px;height:9px}
.mv-segbar-track i{flex:1;min-width:3px;border-radius:3px;background:var(--surface-2);
  border:1px solid var(--line-2)}
.mv-segbar-track i.is-on{background:var(--data);border-color:var(--data);
  animation:mv-seg-fill .3s cubic-bezier(.34,1.4,.64,1) both;
  animation-delay:calc(var(--mv-si,0) * 24ms)}
.mv-segbar-track.is-ratio{gap:0;background:var(--surface-2);border-radius:5px;overflow:hidden}
.mv-segbar-track.is-ratio i{flex:none;border:0;border-radius:5px}
@keyframes mv-seg-fill{from{transform:scaleY(.25);opacity:.3}to{transform:none;opacity:1}}
.mv-segbar-n{flex:none;font-size:var(--type-label);font-weight:700;color:var(--ink-3);
  font-variant-numeric:tabular-nums}

/* ── 8. 불릿 막대(목표선) ───────────────────────────────────────
   목표선은 색이 아니라 위치로 말한다 — 잉크색 세로선 하나다. */
.mv-bullet{display:flex;align-items:center;gap:10px;min-width:0;margin:5px 0}
.mv-bullet-lb{flex:none;font-size:var(--type-label);color:var(--ink-4);
  min-width:74px;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mv-bullet-track{position:relative;flex:1;min-width:70px;height:10px;border-radius:5px;
  background:var(--surface-2);overflow:hidden}
.mv-bullet-fill{position:absolute;left:0;top:0;bottom:0;border-radius:5px;background:var(--data);
  transition:width .5s cubic-bezier(.4,0,.2,1)}
.mv-bullet-goal{position:absolute;top:-2px;bottom:-2px;width:2px;border-radius:1px;
  background:var(--ink-2);transform:translateX(-1px)}
.mv-bullet-n{flex:none;font-size:var(--type-label);font-weight:700;color:var(--ink-3);
  font-variant-numeric:tabular-nums}

/* ── 9. 학습 스트릭 히트맵 ──────────────────────────────────────
   이 파일에서 순차 램프를 쓰는 곳은 여기 하나뿐이다. 한 축의 크기를 말하므로
   순차가 맞다(범주 구분이 아니다). 값은 색 말고 title 로도 읽힌다. */
.mv-heat{display:flex;flex-direction:column;gap:8px;overflow-x:auto}
.mv-heat-grid{display:grid;grid-auto-flow:column;grid-template-rows:repeat(7,11px);
  gap:3px;justify-content:start}
.mv-heat-c{width:11px;height:11px;border-radius:3px;display:block}
.mv-heat-l0{background:var(--surface-2);box-shadow:inset 0 0 0 1px var(--line-2)}
.mv-heat-l1{background:color-mix(in srgb,var(--data) 18%,var(--surface))}
.mv-heat-l2{background:color-mix(in srgb,var(--data) 38%,var(--surface))}
.mv-heat-l3{background:color-mix(in srgb,var(--data) 58%,var(--surface))}
.mv-heat-l4{background:color-mix(in srgb,var(--data) 79%,var(--surface))}
.mv-heat-l5{background:var(--data)}
.mv-heat-lg{display:flex;align-items:center;gap:4px;
  font-size:var(--type-label);color:var(--ink-4)}

/* ── 10. 필 막대: 라운드 + 스태거 진입 + 최댓값 강조 ─────────────
   최댓값은 다른 색이 아니라 같은 색의 진한 쪽이다(순위가 아니라 크기 축이다). */
.bars.mv-bars-anim .b{transform-origin:bottom;transform:scaleY(.02);opacity:.25;
  border-radius:6px;transition:transform .5s cubic-bezier(.34,1.2,.64,1),opacity .3s;
  transition-delay:calc(var(--mv-bi,0) * 45ms)}
.bars.mv-bars-anim.mv-in .b{transform:none;opacity:1}
.bars.mv-bars-hi .b{background:color-mix(in srgb,var(--data) 42%,var(--surface-2))}
.bars.mv-bars-hi .b.is-max{background:var(--data)}
.bars.mv-bars-hi .b.is-max span{color:var(--ink-2)}

/* ── 11. 표 행 미니 바 ──────────────────────────────────────────
   숫자를 밀어내지 않는다. 숫자 아래 얇은 띠 하나로만 크기를 겹쳐 읽힌다. */
.mv-cellbar{display:inline-flex;flex-direction:column;gap:3px;min-width:52px}
.mv-cellbar-n{font-variant-numeric:tabular-nums}
.mv-cellbar-track{display:block;height:3px;border-radius:2px;background:var(--surface-2);
  overflow:hidden}
.mv-cellbar-track i{display:block;height:100%;border-radius:2px;background:var(--data);
  min-width:2px}

/* ── 12. 자릿수 휠 카운터 ───────────────────────────────────────
   굴러가는 열은 aria-hidden 이고, 스크린리더는 옆의 숨은 값 하나만 읽는다. */
.mv-wheel{display:inline-flex;align-items:baseline;font-variant-numeric:tabular-nums;
  line-height:1.15}
.mv-wheel-d{display:inline-block;height:1.15em;overflow:hidden;vertical-align:bottom}
.mv-wheel-s{display:block;transition:transform .55s cubic-bezier(.4,0,.2,1)}
.mv-wheel-s>span{display:block;height:1.15em;line-height:1.15}
.mv-wheel-x{display:inline-block}
.mv-wheel-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ── 13. 생성 대기: 스테퍼 + 스켈레톤 + 시머 문구 ────────────────
   단계는 실제로 일어난 사건에서만 넘어간다. 서버가 진행률을 주지 않는 구간은
   단계를 지어내지 않고 스켈레톤과 문구로만 일하는 중임을 말한다. */
.mv-wait{display:flex;flex-direction:column;gap:12px;padding:4px 0}
.mv-wait-steps{list-style:none;display:flex;flex-wrap:wrap;gap:6px 16px;margin:0;padding:0}
.mv-wait-step{display:flex;align-items:center;gap:7px;
  font-size:var(--type-label);color:var(--ink-4)}
.mv-wait-dot{width:9px;height:9px;flex:none;border-radius:var(--radius-pill);
  background:var(--surface-2);box-shadow:inset 0 0 0 1px var(--line-2);
  transition:background .2s,box-shadow .2s}
.mv-wait-step.is-now{color:var(--ink-2);font-weight:700}
.mv-wait-step.is-now .mv-wait-dot{background:var(--data);box-shadow:none;
  animation:mv-wait-pulse 1.1s ease-in-out infinite alternate}
.mv-wait-step.is-done{color:var(--ink-3)}
.mv-wait-step.is-done .mv-wait-dot{background:var(--ok);box-shadow:none}
@keyframes mv-wait-pulse{from{transform:scale(.72);opacity:.55}to{transform:scale(1);opacity:1}}
/* 시머는 문구 위를 한 번 훑는 밝은 띠다. 배경이 아니라 글자에만 든다. */
.mv-wait-note{margin:0;font-size:var(--type-body);font-weight:600;color:var(--ink-3);
  background:linear-gradient(90deg,var(--ink-3) 0%,var(--ink-3) 38%,var(--ink) 50%,
    var(--ink-3) 62%,var(--ink-3) 100%);
  background-size:260% 100%;-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;animation:mv-shimmer 2.1s linear infinite}
@keyframes mv-shimmer{from{background-position:130% 0}to{background-position:-130% 0}}
.mv-wait-sk{display:flex;flex-direction:column;gap:9px}
.mv-wait-ln{display:block;height:11px;border-radius:5px;background:var(--surface-2);
  animation:mv-sk-pulse 1.25s ease-in-out infinite alternate;
  animation-delay:calc(var(--mv-sk-i,0) * 110ms)}
.mv-wait-ln:nth-child(2){width:92%}
.mv-wait-ln:nth-child(3){width:78%}
.mv-wait-ln:nth-child(4){width:55%}
@keyframes mv-sk-pulse{from{opacity:.5}to{opacity:1}}

/* ── 14. 터치·모션 축소·강제색 대응 ──────────────────────────── */
@media (pointer:coarse){
  .mv-menu-it{min-height:44px}
  .bk-listtools .segmented button{min-height:44px}
}
@media (prefers-reduced-motion:reduce){
  .bk-card-glance,.bk-card-glance>span,.bk-card-fav-btn svg,.mv-arc-val,.mv-bullet-fill,
  .mv-wheel-s,.mv-menu-it,.mv-wait-dot,.bars.mv-bars-anim .b{transition:none}
  .bk-card-fav-btn.mv-fav-pop svg,.bk-problem-list.mv-view-swap .bk-ps-card,
  .mv-menu,.mv-segbar-track i.is-on,.mv-wait-step.is-now .mv-wait-dot,
  .mv-wait-ln{animation:none}
  /* 문구는 시머가 아니라 그냥 글자로 남는다 — 배경 클립을 통째로 되돌린다. */
  .mv-wait-note{animation:none;background:none;-webkit-text-fill-color:currentColor;color:var(--ink-2)}
  /* 스태거 진입을 끄면 막대가 0 높이로 굳는다. 최종 상태를 못 박는다. */
  .bars.mv-bars-anim .b{transform:none;opacity:1}
}
@media (forced-colors:active){
  .mv-spark-line,.mv-arc-val{stroke:Highlight}
  .mv-arc-track{stroke:CanvasText}
  .mv-segbar-track i,.mv-heat-c,.mv-cellbar-track,.mv-bullet-track{border:1px solid CanvasText}
  .mv-segbar-track i.is-on,.mv-cellbar-track i,.mv-bullet-fill,.mv-heat-l5{background:Highlight}
  .mv-menu{border:1px solid CanvasText;background:Canvas}
  .mv-wait-ln{border:1px solid CanvasText}
  .mv-wait-note{-webkit-text-fill-color:CanvasText;background:none}
}
/* ── Amicro 2차 끝 ── */
