/* ==========================================================================
   수강생 관리 — 디자인 시스템 (딥네이비 · Wanted Sans)
   ========================================================================== */
:root {
  color-scheme: light;
  /* 브랜드 기본층 v2 (2026-09-18 대표 결정 · 골드 제거) — 로고 배경 #011830 을 축으로 한 딥네이비 한 갈래 */
  --navy-950: #000E1F; --navy-900: #011830; --navy-800: #00385A; --navy-700: #0F4A70;
  --navy-600: #2B6A92; --navy-500: #6A90B4; --navy-400: #94A2BF; --navy-300: #B3BFD3;
  --navy-200: #D2DBEB; --navy-100: #E6ECF4; --navy-50: #F2F5F9;
  --navy-ink: #00385A; /* 네이비 글자·아이콘색 (채움 아님) */
  /* 어두운 채움면은 한 톤만 — 사이드바·탑바·오늘 머리띠·기본 버튼·토스트 (2026-09-23 대표 지시) */
  --navy-fill: var(--navy-900);   /* 로고 배경과 같은 #011830 (2026-09-23 대표 정정: 950 아님) */
  --navy-fill-hover: var(--navy-800);   /* 네이비 채움 사각 버튼(종)의 hover 한 톤 #00385A(2026-10-01 실장 지적 3) */
  /* 그라데이션 시안 4종 (결정 대기 · 제품에는 아직 안 씀, 시안 design/specimens/2026-09-23/grad-*.css) */
  --grad-a: linear-gradient(135deg, var(--navy-900), var(--navy-200));
  --grad-b: linear-gradient(135deg, var(--navy-800), var(--navy-200));
  --grad-c: linear-gradient(135deg, var(--navy-200), var(--navy-900));
  --grad-d: linear-gradient(135deg, var(--navy-900), var(--navy-500));
  --ink: #0B1B2B; --ink-2: #3A4A5E; --ink-3: #5F6E87; --ink-4: #97A3B4;
  --line: #E4E9F0; --line-2: #CDD6E2; --bg: #F5F7FA; --card: #FFFFFF;
  /* 의미색: OKLCH 로 밝기·채도를 맞춘 값 (글자 L .50 · 배경 L .955 · soft L .74) */
  --ok: #267543; --ok-bg: #E3F6E7; --warn: #835A01; --warn-bg: #FBEEDC;
  --bad: #984742; --bad-bg: #FFEBE9; --info: #2A669F; --info-bg: #E5F2FF;
  --vid: #65569C; --vid-bg: #F0EEFF;
  --sup: #067272; --sup-bg: #DCF6F6;
  --ok-soft: #79BD8C; --warn-soft: #E3B35C; --bad-soft: #E3928B; --bad-line: #EFC4BF; --navy-150: #DCE4EF;   /* 진행 막대·토스트 선·입력 오류 테두리·사이드바 링크 */
  --chip-on: #FFFFFF;
  /* 보조 버튼(.btn.ghost) = 아주 옅은 바탕 + 얇은 틀 · 글자·아이콘 navy-800(2026-09-28 구조 5차 sub5=C · "푸른 글씨가 조금 더 어두운 푸른색이면") */
  --btn-sub-bg: color-mix(in srgb, var(--navy-800) 4%, transparent);
  --btn-sub-bg-h: color-mix(in srgb, var(--navy-800) 8%, transparent);
  --btn-sub-line: color-mix(in srgb, var(--navy-800) 10%, transparent);
  --accent-y-lt: #FFCD37;   /* 개수 띠 면(2026-10-13 대표 W199 · D7 Figma 137:99858 · 글자 --ink 와 11.6:1) */
  --accent-y: #F1C249;   /* 노랑 포인트(2026-09-23 결정 D16) · 채움·점·막대로만, 글자색 금지 · 홈 학생 수 막대·답변 대기 점 · 사이드바·더보기 개수 배지 면(글자 --navy-ink 7.3:1 · 2026-09-28 4h) */
  --radius: 14px; --radius-sm: 10px;
  --shadow: 0 1px 2px rgba(1, 22, 43, .03), 0 2px 6px rgba(1, 22, 43, .04);
  --shadow-lg: 0 8px 24px rgba(1, 22, 43, .14);
  --sidebar-w: 236px; --tabbar-h: 62px; --topbar-h: 52px;   /* 상단바 52(2026-10-13 대표 짝수 규칙 · 옛 53) */
  --font: "Wanted Sans Latin", "Wanted Sans Variable", "Wanted Sans", "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, system-ui,
          Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", sans-serif;
  /* ---- 파운데이션 토큰 (디자인 방향서 v1, 2026-09-04) — Figma 변수와 이름 1:1, 정본은 design/tokens.json ---- */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px;
  --space-8: 32px; --space-10: 40px; --space-12: 48px;
  --fs-2xs: 11.5px; --fs-xs: 12px; --fs-sm: 13px; --fs-md: 14.5px; --fs-lg: 16px; --fs-xl: 18px; --fs-2xl: 22px; --fs-3xl: 28px; --fs-4xl: 40px;
  --lh-body: 1.5; --lh-head: 1.25; --lh-display: 1;
  --r-xs: 8px; --r-sm: 10px; --r-md: 14px; --r-lg: 20px; --r-pill: 999px;
  /* 홈 최종안 (2026-09-25) — Seed 글자 단계 중 위 --fs-* 에 없는 14·20·26 · 카드 반경 12 · 제목 서체 --font-head 는 본문과 같은 Wanted Sans(2026-09-26 서체 체계 v2 · Pretendard 파일은 되돌리기 대비로 남김) */
  --fs-base: 14px; --fs-title: 20px; --fs-display: 26px; --r-card: 12px;
  --fs-btn-lg: 16.5px;   /* 큰 버튼(.btn.lg · 바닥 바 버튼) 글자 · 16 에서 3배 화면 잉크가 +1/3px 어긋남(2026-10-10 대표 Z5 · w28 실측) */
  --fs-up: 15px;   /* 폰 상단바 위치 표시의 상위 이름 '고2 통합사회 A › 학생 명단'(2026-09-27 D 구조 3차 ttl3) */
  --r-tag: 6px;   /* 네이비 꼬리표(다음 수업 제목·오늘 날짜) · 조금만 둥글게(2026-09-25 대표 메모) */
  /* 홈 날짜 바(PC) · 네이비 그라데이션 + 옅은 그레인(2026-09-25 대표 선택 Dc) */
  --grad-bar: linear-gradient(115deg, #011830 0%, #06243F 55%, #0F3656 100%);   /* token-ok */
  /* 네이비 채움(--navy-fill·--grad-bar) 위 글자·보조 글자·막대 바탕 */
  --on-navy: #FFFFFF; --on-navy-2: var(--navy-200); --on-navy-track: rgba(255, 255, 255, .16);   /* token-ok */
  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 .55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='.09'/></svg>");
  --font-head: var(--font);
  --el-0: none; --el-1: var(--shadow); --el-2: var(--shadow-lg);
  --dur-1: 120ms; --dur-2: 200ms; --dur-3: 320ms;
  --ease-standard: cubic-bezier(.2, 0, 0, 1); --ease-decel: cubic-bezier(0, 0, 0, 1); --ease-exit: cubic-bezier(.4, 0, 1, 1);
  --ease-spring: linear(0, .25 8%, .68 16%, 1.02 27%, 1.06 35%, 1.01 47%, .985 58%, 1); --ease-sine: cubic-bezier(.37, 0, .63, 1);
  --rail-w: 64px;   /* 접힌 사이드바(아이콘 레일) 폭 */
  /* 창 크기 5밴드(미디어 쿼리는 변수 불가, 문서용 · 2026-09-23 D10 · 조사 7 §4):
     앱 ~599 탭바 · 분할 600–839 탭바 · 확장 840–1199 사이드바(기본 레일 64) · 웹 1200–1599 사이드바 236 · 넓은 웹 1600~ 본문 1400 가운데 */
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font); background: var(--bg); color: var(--ink); font-size: var(--fs-md);
  line-height: 1.45; font-variant-numeric: normal; -webkit-font-smoothing: antialiased;
  /* 숫자 폭: 본문 글 속 숫자는 글자 사이가 벌어지지 않게 자연폭(비례) · 세로로 줄이 맞아야 하는 칸(표·통계·코드·날짜)만 아래에서 고정폭(tabular) */
  /* Wanted Sans는 화면용 자간이 내장되어 별도 보정 불필요 */
  letter-spacing: 0;
  word-break: keep-all; overflow-wrap: break-word; /* 한국어는 어절 단위로 줄바꿈, 긴 URL은 잘라서 */
}
/* 줄바꿈 규칙 (2026-09-23 대표 지시 · CLAUDE.md §3): 글 전체는 마지막 줄에 한 어절만 남지 않게(pretty, 상속),
   제목·안내·메타 줄·가운데 정렬 짧은 글은 줄 길이를 고르게(balance). 그래도 남으면 문구를 줄인다 · 검사 tests/check_wrap.py
   text-wrap 줄임형은 white-space(nowrap)까지 wrap 으로 되돌리므로 스타일 속성(text-wrap-style)만 쓴다 */
body { text-wrap-style: pretty; }
h1, h2, h3, h4, .card-head h3, [class*="title"], .meta, .checkline { text-wrap-style: balance; }   /* 제목·메타 줄만 balance · 안내 글(.sub .empty p .hint .banner .toast)은 body pretty 상속 (G0-3 · 2026-10-10) */
/* 짧은 안내 글은 pretty 가 두 줄 고아(마지막 줄 한두 단어)를 못 막아 balance · .empty p .banner .toast .meta 는 pretty 유지 */
.hint, .page-head .sub { text-wrap-style: balance; }
.banner.bal > span { text-wrap-style: balance; }   /* 목록이 길어 여러 줄이 되는 안내 띠만(문자 템플릿 자리표시자 목록 · 2026-10-10 w30 고아 줄) · 나머지 .banner 는 pretty 유지 */
.banner.bal .hint { display: block; line-height: inherit; }   /* 띠 안 둘째 줄 안내는 제 덩어리로 balance(.hint) · 줄높이는 띠 19 그대로(옛 inline 과 같은 높이) */
/* 끊기면 안 되는 말 덩어리(전화번호·"마지막 점검 날짜" 같은 이름+값)는 한 줄로 */
.nw, a[href^="tel:"] { white-space: nowrap; }
a { color: var(--navy-600); text-decoration: none; }   /* 글 링크 대비 4.5 이상(흰 바탕 5.87 · 5판 clink 대표 선택 2026-09-28) */
@media (hover: hover) { a:hover { text-decoration: underline; } }
b, strong { font-weight: 700; }
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
img { max-width: 100%; }

/* ---------- 앱(PWA) 터치 규칙: 회색 탭 하이라이트 제거, 더블탭 확대 지연 제거, 길게 눌러도 글자 선택 안 됨 ---------- */
a, button, .chip, .seg label, .tabs a, .item, .swatch { -webkit-tap-highlight-color: transparent; }
.chip, .seg label, .tabs a, .swatch, .icon-btn, .hwslide input[type=range] { touch-action: manipulation; user-select: none; -webkit-user-select: none; }
/* ---------- 키보드 포커스 표시: 탭 키로 옮겨 다닐 때만 보인다(마우스 클릭에는 안 붙음) ·
              칩·세그먼트·색상 칸은 input 이 숨어 있어 겉 라벨에 표시한다 ---------- */
.btn:focus-visible, .tabs a:focus-visible, .item-link:focus-visible, .icon-btn:focus-visible,
.chip:focus-visible, .chip:has(input:focus-visible),
.seg label:has(input:focus-visible), .swatch:has(input:focus-visible) {
  outline: 4px solid var(--navy-700); outline-offset: 2px;
}
.btn.danger:focus-visible { outline-color: var(--bad); }   /* 위험 버튼 포커스는 붉은 계열(W132) */
@media (prefers-reduced-motion: reduce) {
  .btn:active, .class-card:hover { transform: none; }
  .class-card, .btn, .chip, .seg label > span { transition: none; }
  .toast { animation: toastfade .2s ease-out; }
  .stats .num { animation: none; }
}   /* 2026-09-26 모션 1묶음의 모션 줄이기는 파일 맨 끝(뒤에 있어야 같은 선택자를 이긴다) */
@keyframes toastfade { from { opacity: 0; } to { opacity: 1; } }
/* 모션 카탈로그(방향서 v2 → 2026-09-26 D 모션 1차): 숫자 등장 · 화면 이동 · 탭 밑줄. 행동에 답하고, 화면당 자동 재생 1개 · 출결 칸 도장은 미끄러지는 틀로 바뀌어 없앴다 */
@keyframes numin { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.stats .num { animation: numin 600ms var(--ease-decel) both; }
/* 화면 이동(모션 8): 새 화면 240ms 4px 올라오며 나타남 · 옛 화면 200ms 사라짐 · 탭 밑줄(모션 3)은 따로 떼어 옆 탭으로 200ms 미끄러진다 · 미지원 브라우저는 즉시 */
@view-transition { navigation: auto; }
@keyframes vt-in { from { opacity: 0; transform: translateY(4px); } }
@keyframes vt-fade-in { from { opacity: 0; } }
@keyframes vt-out { to { opacity: 0; } }
::view-transition-old(root) { animation: vt-out var(--dur-2) var(--ease-standard) both; }
::view-transition-new(root) { animation: vt-in 240ms var(--ease-standard) both; }
::view-transition-group(tab-ink) { animation-duration: var(--dur-2); animation-timing-function: var(--ease-standard); }
::selection { background: var(--navy-200); }


/* ---------- 아이콘 기본 크기 · 정렬 (2026-09-18) ----------
   아이콘 옆에 글자가 오는 칸은 전부 flex 가운데 정렬로 맞추고,
   flex 를 못 쓰는 문장 속 아이콘만 글자 크기(em)에 맞춰 vertical-align 으로 내린다 */
svg.i { width: 1.1em; height: 1.1em; flex: none; vertical-align: -0.18em; }
summary svg, .icon-btn svg { width: 18px; height: 18px; flex: none; vertical-align: -0.18em; }  /* 클래스 없는 아이콘이 화면 가득 커지는 것 방지 */
.banner svg { width: 18px; height: 18px; flex: none; }
h1 svg, h2 svg, h3 svg { width: 18px; height: 18px; flex: none; vertical-align: -0.18em; }
.hint svg, .small svg { width: 1.1em; height: 1.1em; flex: none; vertical-align: -0.18em; }
.topbar .tacts svg { width: 18px; height: 18px; flex: none; }   /* 글자 있는 버튼 아이콘 = 글자 13.5 의 1.26배(2026-10-12 대표 W105 · 사양 1.2~1.3) */
.topbar .tacts [aria-label] svg, .topbar .tacts .bell svg { width: 20px; height: 20px; }   /* 글자 없는 아이콘 버튼은 20 그대로 */
.topbar .tacts a:not([aria-label]) svg, .topbar .tacts button:not([aria-label]) svg { stroke-width: calc(var(--stem-b) * 1.2em); position: relative; top: 2px; }   /* 글자 있는 상단바 버튼(2026-10-12 G0 · 3배 픽셀 실측): 어두운 면 위 흰 글씨 획이 1.84 로 그려져 +가 1.59 면 0.84배 → 선 1.9(1.2배) · + 가 글자 잉크보다 0.67 위라 아이콘만 내림(svg 는 css 1px 단위로 앉아 .33~.67 은 0 또는 1 로 붙는다 · 1 이면 +0.33) */
.tabs svg { width: 16px; height: 16px; flex: none; }
.sidebar .foot svg { width: 14px; height: 14px; flex: none; vertical-align: -0.18em; }
/* 네이비 바탕 위 듀오톤 면(2026-09-27 아이콘 7차 확정 · C): 면 흰 10% · 두 번째 음영 흰 16% · 선 색은 그대로
   사이드바 · 네이비 채움 버튼(기본 .btn) · 상단바 버튼 아이콘은 면 없이 선만(D 구조 2차 tb2=B) */
.sidebar svg .f, .btn:not(.ghost):not(.soft):not(.danger) svg .f { fill: var(--on-navy); fill-opacity: .10; }
.sidebar svg .f2, .btn:not(.ghost):not(.soft):not(.danger) svg .f2 { fill: var(--on-navy); fill-opacity: .16; }
.topbar svg .f, .topbar svg .f2 { fill: none; }
/* 아이콘 선 굵기 = 옆 글자 획(2026-10-12 대표 W105 · 아이콘은 글자 굵기에 맞춘다): svg 속성 1.75 는 24칸 기준이라 아이콘 크기가 달라지면 실제 굵기가 달라진다(16 아이콘 ÷ 13 글자 = 선이 획의 0.82배).
   화면 px 로 고정(vector-effect)하고 글자 크기(em)에 비례해 정한다 · 계수 = 글자 세로획 굵기(Wanted Sans '이' ㅣ · fontTools 실측): 600 .1097 · 400 .0762
   검사: tests/check_center.py --ink-all 의 '선굵기'(선 ÷ 획 0.85~1.20) */
:root { --stem-b: .1181; --stem-r: .0876; }   /* b = 600~700 글자 곁 아이콘(700 은 0.87배) · r = 400~500 글자 곁 아이콘(400 은 1.15배) */
.btn svg *, .chip svg *, .badge svg *, .pill svg *, .tabs a svg *, .tabs button svg *, summary svg *, .go svg *, .back svg *, .st svg *, .topbar .tacts a svg *, .topbar .tacts button svg *, a.h-qta svg *, .item-link svg *, a.ilink svg * { vector-effect: non-scaling-stroke; }
.btn svg, .chip svg, .badge svg, .pill svg, .tabs a svg, .tabs button svg, summary svg, .go svg, .back svg, .st svg, .topbar .tacts a svg, .topbar .tacts button svg, a.h-qta svg, .item-link svg, a.ilink svg { stroke-width: calc(var(--stem-b) * 1em); }
.menu-list .item > svg:not(.chev) *, .menu-list .item > .lead * { vector-effect: non-scaling-stroke; }
.menu-list .item > svg:not(.chev), .menu-list .item > .lead, a.ilink svg, summary.hint svg, summary.h-more svg { stroke-width: calc(var(--stem-r) * 1em); }   /* 메뉴 줄 22 아이콘 곁 글자는 400 */

/* ---------- 레이아웃 ---------- */
.layout { display: flex; min-height: 100vh; min-height: 100dvh; }
.sidebar {
  width: var(--sidebar-w); flex-shrink: 0; background: var(--navy-fill); color: #fff;
  position: sticky; top: 0; height: 100vh; height: 100dvh; overflow-x: hidden; overflow-y: auto;
  display: flex; flex-direction: column; padding: 18px 12px 16px;
}
/* 사이드바 맨 위 (W133 · Figma 사이드바 40:18019): 펼침 = 한 줄 로고 → 이름 → 접기 단추(오른쪽 끝) 세로 가운데 · 줄 위 22 아래 34 = 첫 메뉴 y114
   레일 = 로고 → 단추 세로 한 줄 · 마크업 순서가 곧 탭 순서 · 로고 가운데 x=32 = 아이콘 줄(Figma x16 이면 33 이라 x=32 유지)
   (종은 2026-09-28 D 구조 4차 bellpos=C 로 본문 맨 위 줄 오른쪽 끝으로 옮겼다) */
.side-top { display: flex; align-items: center; gap: 4px; margin: 22px 0 34px; }
.side-top .brand { flex: 1 1 auto; min-width: 0; }
.side-toggle { flex: none; width: 40px; height: 40px; padding: 0; border: 0; background: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-sm); color: var(--navy-150); }
.side-toggle svg { width: 20px; height: 20px; }
.side-toggle:focus-visible { outline: 4px solid var(--navy-700); outline-offset: -4px; }
.bell { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; }
@media (hover: hover) { .sidebar .side-toggle:hover { background: rgba(255,255,255,.08); color: #fff; } }
/* 알림 종(2026-09-27 D 모션 4차 확정 1 · 2026-09-28 구조 4차 종 모양): 새 소식 없음 = 흰 선 종 · 있음(.on) = 노랑으로 채운 종(윤곽선 없음 · 몸통·추 모두 채움) + 빛 선 3개(노랑 2) 켜져 머묾 · 숫자 배지 없음
   울림(.ring · app.js 가 본 값보다 늘었을 때 + 마우스를 올렸을 때(.on 만 · 울리는 중엔 다시 걸지 않음 · 2026-09-27)): 600ms · 구간마다 (.36,.07,.19,.97) · 1.08배 −10° → 8° → 1.04배 −4° → 제자리
   윗고리(12, 3) 기준 · 빛 선 0 →(.10) 0 →(.16) 1 →(.34) 1 →(.40) 0 →(.56) 0 →(.64) 1 → 끝까지 켜짐 */
.bell svg { overflow: visible; }
.bell .bg { transform-box: view-box; transform-origin: 12px 2px; }
.bell .rays { opacity: 0; }
.bell.on svg { stroke: var(--accent-y); }   /* 노랑은 채움·선으로만(글자색 금지 · D16) · 몸통·추의 선도 같은 노랑이라 윤곽선이 보이지 않는다 */
.bell.on .bd, .bell.on .cl { fill: var(--accent-y); }
.bell.on .rays { opacity: 1; }
.bell.ring .bg { animation: bell-ring 600ms cubic-bezier(.36, .07, .19, .97) both; }
.bell.ring .rays { animation: bell-rays 600ms linear both; }
@keyframes bell-ring { 0% { transform: none; } 15% { transform: scale(1.08) rotate(-10deg); } 40% { transform: scale(1.08) rotate(8deg); } 65% { transform: scale(1.04) rotate(-4deg); } 100% { transform: none; } }
@keyframes bell-rays { 0%, 10% { opacity: 0; } 16%, 34% { opacity: 1; } 40%, 56% { opacity: 0; } 64%, 100% { opacity: 1; } }
/* 종 자리(2026-09-28 D 구조 4차 bellpos=C) · PC: 홈은 날짜 바 오른쪽 끝(테두리 없음) · 다른 화면은 맨 위 줄 오른쪽 끝 네이비 사각 40·r10 · 폰·분할(<840)은 상단바 종
   맨 위 줄은 40(종 버튼 높이) · 경로 줄 글자는 그 가운데 · 누름 44 는 ::after(크기 규칙 A) */
.mtop { display: flex; align-items: center; gap: 12px; height: 40px; margin-bottom: 8px; }
.mtop .crumb { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }
.mtop .bell { margin-left: auto; }
.mtop.nc { margin-bottom: 16px; }   /* 경로 줄이 없는 맨 위 줄 · 바로 아래 네이비 주 버튼과 한 쌍으로 묶이지 않게(2026-10-01 실장 지적 2) */
.bell.sq, .h-bar .bell { width: 40px; height: 40px; border-radius: var(--r-sm); color: var(--on-navy); }
.bell.sq { background: var(--navy-fill); }
.bell.sq svg, .h-bar .bell svg { width: 20px; height: 20px; }
.bell.sq::after, .h-bar .bell::after { content: ""; position: absolute; inset: -2px; }
.bell.sq, .h-bar .bell { transition: background-color var(--dur-1) linear; }
@media (hover: hover) { .bell.sq:hover { background: var(--navy-fill-hover); } .h-bar .bell:hover { background: color-mix(in srgb, var(--on-navy) 8%, transparent); } }   /* 2026-10-01 실장 지적 3 · 홈 바 값은 사이드바 접기 단추 hover 와 같다 */
.bell:focus-visible { outline: 4px solid var(--navy-700); outline-offset: 2px; }
@media (max-width: 839px) { .h-bar .bell { display: none; } }

/* 알림 팝업(2026-09-28 D 구조 4차 alert=A · 내용은 app.js 가 /alerts 로 채움): 웹 = 종 아래 380 · 최대 540 스크롤 / 폰 = 아래에서 올라오는 창 최대 86vh · 손잡이
   머리 '알림' 15/700 · 새 소식 줄 = 아이콘 32 사각(navy-50 · navy-600) + 제목 14/600 · 설명 12.5 ink-3 + 시각 12 ink-3 + › · 안 본 것은 노란 점 8(흰 테두리 2)
   할 일 = 종류 줄 44(이름 누르면 그 목록 · › 누르면 90° 돌며 세부 펼침 200ms 표준 곡선 · 높이+페이드) · 세부 줄 들임 58 · 13.5/19 + 12/17 */
.alp { position: fixed; z-index: 40; inset: auto; margin: 0; padding: 0; width: 380px; max-width: calc(100vw - 32px); max-height: 540px; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); color: var(--ink); box-shadow: var(--shadow-lg); }
.alp[open] { animation: vt-fade-in var(--dur-1) linear both; }
.alp-in { display: flex; flex-direction: column; max-height: inherit; }
.alp-grab { display: none; }
.alp-t { flex: none; margin: 0; padding: 16px 16px 4px; font-size: 15px; line-height: 22px; font-weight: 700; color: var(--ink); }
.alp-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-bottom: var(--space-2); }
.alp-gt { margin: 0; padding: 12px 16px 4px; font-size: var(--fs-sm); line-height: 20px; font-weight: 600; color: var(--ink-3); }
.alp-r, .alp-kr { display: flex; align-items: center; gap: 10px; padding: 0 0 0 16px; color: var(--ink); }   /* 오른쪽 여백 0 · › 칸(38)이 잉크 오른쪽 16 을 만든다(아이콘 왼쪽 16 과 짝 · 2026-10-01 실장 지적 10) */
.alp-r { min-height: 56px; padding-top: var(--space-2); padding-bottom: var(--space-2); }
.alp-kr { min-height: 44px; }
.alp-k { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0; align-self: stretch; color: var(--ink); }
@media (hover: hover) { .alp-r:hover, .alp-kr:hover, .alp-d:hover, .alp-m:hover { background: var(--navy-50); text-decoration: none; } .alp-k:hover { text-decoration: none; }
  .alp-r:hover .alp-ic, .alp-kr:hover .alp-ic { background: var(--navy-100); } }
.alp-ic { position: relative; flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--r-xs); background: var(--navy-50); color: var(--navy-600); }
.alp-ic svg { width: 18px; height: 18px; }
.alp-ic.dot::after { content: ""; position: absolute; top: -2px; right: -2px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent-y); box-shadow: 0 0 0 2px var(--card); }
.alp-x { flex: 1 1 auto; min-width: 0; }
.alp-x b, .alp-x span, .alp-n, .alp-d b, .alp-d span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alp-x b, .alp-n { font-size: var(--fs-base); line-height: 20px; font-weight: 600; }
.alp-x span { font-size: var(--fs-xs); line-height: 18px; color: var(--ink-3); }
.alp-tm { flex: none; font-size: var(--fs-xs); line-height: 18px; color: var(--ink-3); white-space: nowrap; }   /* ink-3 = 대비 5.16(옛 ink-4 2.56 · 2026-10-01 실장 지적 12) */
.alp-r.two .alp-tm { align-self: flex-start; margin-top: 2px; line-height: 22px; }   /* 두 줄 글(제목+설명) 행: 시각은 제목 줄 가운데(2026-10-01 실장 지적 8) */
.alp-c { flex: none; margin-left: auto; font-size: var(--fs-sm); line-height: 20px; font-weight: 600; color: var(--ink-3); white-space: nowrap; }
.alp-cv, .alp-tog { position: relative; flex: none; display: grid; place-items: center; width: 38px; height: 40px; padding: 0; border: 0; border-radius: var(--r-sm); background: none; color: var(--ink-3); }
.alp-n + .alp-cv { margin-left: auto; }
.alp-tog { cursor: pointer; }
.alp-tog::after { content: ""; position: absolute; inset: -2px -2px; }
.alp-cv svg, .alp-tog svg { width: 16px; height: 16px; }
.alp-tog svg { transition: transform var(--dur-2) var(--ease-standard); }
.alp-tog[aria-expanded="true"] svg { transform: rotate(90deg); }
.alp-tog:focus-visible, .alp-r:focus-visible, .alp-k:focus-visible, .alp-d:focus-visible, .alp-m:focus-visible { outline: 4px solid var(--navy-700); outline-offset: -4px; }
.alp:focus { outline: none; }
.alp-sub { overflow: hidden; }
.alp-sub[hidden] { display: none; }
.alp-d { display: block; padding: 6px 16px 6px 58px; color: var(--ink); }
.alp-d b { font-size: 13.5px; line-height: 20px; font-weight: 500; }
.alp-d span { font-size: var(--fs-xs); line-height: 18px; color: var(--ink-3); }
.alp-d.nq { position: relative; }
.alp-d .alp-nd { position: absolute; left: 46px; top: 12px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent-y); }   /* 새 질문 점 6 · 제목 시작선 58 에서 6 떨어진 왼쪽 여백(2026-10-01 실장 지적 7) */
.alp-d .alp-sr, .alp-k .alp-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }   /* 화면 읽기용 */
.alp-m { display: flex; align-items: center; gap: 2px; min-height: 44px; padding: 0 16px 0 58px; font-size: 13.5px; line-height: 20px; font-weight: 600; color: var(--navy-700); }   /* '모두 보기' 링크 · 폰 44 · 웹 40(2026-10-01 실장 지적 6) */
.alp-m span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alp-m svg { flex: none; width: 16px; height: 16px; }
@media (min-width: 840px) { .alp-m { min-height: 40px; } }
.alp-none { margin: 0; padding: 8px 16px; font-size: var(--fs-sm); line-height: 20px; color: var(--ink-3); }
.alp-empty { margin: 0; padding: 32px 16px; text-align: center; font-size: var(--fs-base); line-height: 20px; color: var(--ink-3); }
@media (max-width: 839px) {
  .alp { inset: auto 0 0 0; margin: 0 auto; width: min(100%, 480px); max-width: 100%; max-height: 86vh; max-height: 86dvh; border: 0;
    border-radius: var(--radius) var(--radius) 0 0; padding-bottom: env(safe-area-inset-bottom); }
  .alp[open] { animation: ntf-up 260ms var(--ease-standard) both; }
  .alp::backdrop { background: color-mix(in srgb, var(--navy-950) 40%, transparent); }
  .alp-grab { display: block; flex: none; width: 36px; height: 4px; margin: var(--space-2) auto 0; border-radius: 2px; background: var(--line-2); }
  .alp-t { padding-top: var(--space-3); }
}
.brand { display: flex; align-items: center; gap: 10px; padding: 0 6px 0 4px; color: #fff; }   /* 로고 가운데 x=32 = 12+4+16 = 아이콘 줄 */
.brand:hover { text-decoration: none; }
.brand .mark { width: 32px; height: 32px; border-radius: 8px; flex-shrink: 0; display: block; }
.brand > span { min-width: 0; }
.brand .t { font-weight: 700; font-size: var(--fs-lg); letter-spacing: -0.02em; line-height: 20px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand .s { font-size: var(--fs-2xs); color: var(--navy-300); font-weight: 500; line-height: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-group { font-size: 11px; font-weight: 700; color: var(--navy-300); letter-spacing: .06em;
  padding: 14px 12px 6px; text-transform: uppercase; line-height: 16px; white-space: nowrap; overflow: hidden; }   /* 11px 글 · 반여백 1 */
.nav a {
  display: flex; align-items: center; gap: 10px; color: var(--navy-100); padding: 8px 12px;
  border-radius: var(--r-sm); font-size: var(--fs-md); font-weight: 500; line-height: 22px; margin-bottom: 2px;   /* 줄 21 정수: 물려받은 21.025 가 줄마다 쌓여 아래쪽 줄부터 글자가 1px 내려앉던 것(2026-09-28 대표 '아이콘이 텍스트보다 위') */
  position: relative; white-space: nowrap;   /* 접고 펴는 동안 글자가 두 줄로 꺾이지 않게 · 아이콘 가운데 x=32 는 레일과 같다 */
}
.nav a .lbl { min-width: 0; }
.nav a svg { width: 16px; height: 16px; flex-shrink: 0; opacity: .95; }
@media (hover: hover) { .nav a:hover { background: rgba(255,255,255,.08); text-decoration: none; color: #fff; } }
.nav a.on { background: rgba(255,255,255,.12); color: #fff; font-weight: 700; box-shadow: inset 0 0 0 1px rgba(255,255,255,.08); }
.nav a.on svg { opacity: 1; }
.nav a.on svg * { vector-effect: non-scaling-stroke; }
.nav a.on svg { stroke-width: calc(var(--stem-b) * 1em); }   /* 선택 줄은 글자가 700 · 아이콘 선도 그 세로획에 맞춘다 */
.nav .cnt { margin-left: auto; display: inline-flex; align-items: center; justify-content: center; background: var(--accent-y-lt); }   /* 면은 종 '새 소식'과 같은 노랑(2026-09-28 5판 대표 메모 · 4h) · 규격은 아래 '개수 띠' */
.sidebar .foot { margin-top: auto; padding: 14px 12px 0; font-size: var(--fs-xs); color: var(--navy-300);
  border-top: 1px solid rgba(255,255,255,.08); display: flex; justify-content: space-between; align-items: center; }
.sidebar .foot a { color: var(--navy-200); }

main { flex: 1; min-width: 0; padding: 18px 32px 60px; max-width: 1180px; }   /* 위 18 = 맨 위 줄(종 40) 가운데 38 = 사이드바 접기 단추(패딩 18 + 20) 가운데 · 경로 줄 글자 가운데도 같이(2026-10-01 실장 지적 1 · 옛 16 은 2.25 어긋남 · 2026-09-28 bellpos=C 옛 26) */
.topbar { display: none; }

/* ---------- 사이드바 접기 · 아이콘 레일 (2026-09-23 D1 · D10) ----------
   html.side-rail 은 base.html 머리 인라인 스크립트가 첫 그림 전에 붙인다(저장값 없으면 1200px 미만 = 레일).
   아이콘 가운데(x=32)는 두 상태가 같다 · 글자는 폭 0 으로 접히고 무리 제목 자리는 비워 두어 아이콘 사이 간격이 그대로다.
   움직임은 누를 때만(html.side-anim, app.js) · 줄이기 설정이면 즉시 */
@media (min-width: 840px) {
  .side-rail .sidebar { width: var(--rail-w); scrollbar-width: none; }
  .side-rail .sidebar::-webkit-scrollbar { display: none; }   /* 64px 안에 스크롤 막대가 끼면 아이콘이 한쪽으로 밀린다 · 휠·터치 스크롤은 그대로 */
  .side-rail .side-top { flex-direction: column; gap: 6px; margin: 0 0 12px; }
  .side-rail .side-top .brand { flex: none; padding: 0; }
  .side-rail .brand > span, .side-rail .sidebar .foot .today { display: none; }
  .side-rail .nav a { gap: 0; justify-content: center; }
  .side-rail .nav a .lbl, .side-rail .sidebar .foot .lbl { width: 0; overflow: hidden; opacity: 0; }
  .side-rail .nav-group { opacity: 0; visibility: hidden; }   /* 무리 사이 간격은 남겨 아이콘 자리가 움직이지 않게 */
  /* 개수 배지는 아이콘 오른쪽 위 점으로 */
  .side-rail .nav .cnt { position: absolute; top: 6px; right: 6px; width: 10px; height: 10px; min-height: 0; min-width: 0; padding: 0;
    border-radius: 50%; font-size: 0; background: var(--accent-y); box-shadow: 0 0 0 2px var(--navy-fill); }   /* 펼친 배지와 같은 노랑(4h) */
  .side-rail .sidebar .foot { justify-content: center; padding: 14px 0 0; }
  .side-rail .sidebar .foot a { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 32px; }
  .side-rail .sidebar .foot svg { width: 16px; height: 16px; }
  .side-anim .sidebar { transition: width var(--dur-2) var(--ease-standard); }
  .side-anim .nav a .lbl, .side-anim .nav-group { transition: opacity var(--dur-2) var(--ease-standard), visibility var(--dur-2); }
}
/* 840–900px 에서 사이드바를 펼치면 본문이 540–600px 로 옛 PC 최소 폭(601)보다 좁다 · 두·세 칸 격자는 한 칸으로
   (시험 결과의 점수 분포 6칸이 칸 밖으로 42px 새던 것 · check_width_sweep --side open) */
@media (min-width: 840px) and (max-width: 900px) {
  html:not(.side-rail) .grid2, html:not(.side-rail) .grid3 { grid-template-columns: 1fr; }
}
@media (min-width: 840px) and (prefers-reduced-motion: reduce) {
  .side-anim .sidebar, .side-anim .nav a .lbl, .side-anim .nav-group { transition: none; }
}
/* 넓은 웹(1600px~): 본문은 1400px 까지만 넓히고 남는 폭 가운데에 */
@media (min-width: 1600px) {
  main { max-width: 1400px; margin: 0 auto; }
}

/* ---------- 페이지 헤더 ---------- */
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 18px; flex-wrap: wrap; }   /* 제목 묶음과 오른쪽 버튼을 상하 가운데로 (2026-09-23 · 위 정렬이라 버튼이 5~10px 떠 보였다) */
.page-head h1 { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; line-height: 1.25; }
.page-head .sub { color: var(--ink-3); font-size: var(--fs-sm); line-height: 20px; }
/* 제목 → 부제 = 6(2026-09-26 비평 v7 1~4 · 옛 음수 여백 −3 은 칩으로 시작하는 줄을 제목에 1~3px 로 붙였다)
   제목 상자를 글자 바닥선(alphabetic)에서 끝내 제목 크기(23·20·19)와 무관하게 하고, 부제는 양수 여백만 준다
   글자 부제 = 잉크 ↔ 잉크 6 · 칩(수업 칩·학기 꼬리표·배지)이 든 부제 = 제목 잉크 ↔ 칩 위 변 6(칩 22 가 줄 19 보다 커 위로 나온다)
   text-box 를 모르는 브라우저는 제목 상자를 자르지 않으므로 여백만 따로(글자 7.5~8.5 · 칩 6) */
.page-head h1:has(+ .sub), .page-head h1:has(+ .sub) > .h1t { text-box: trim-end cap alphabetic; }
.page-head h1:has(+ .sub) .muted { display: inline-block; text-box: trim-end cap alphabetic; }   /* 제목 안 작은 글자(8회차)도 바닥선에서 끝나게 · 글자 자리는 그대로(바닥선 맞춤) */
@supports (text-box: trim-end cap alphabetic) {
  .page-head h1 + .sub { margin-top: calc(var(--sub-gap, 4px) + var(--h1-hang, 0px)); }
  .page-head h1 + .sub:has(.cls-tag, .badge) { --sub-gap: 8px; }   /* 글줄(19·20) 안의 칩은 글자보다 위로 나온다 · 여백은 정수(아래 탭·카드가 0.5px 에 걸리면 글자 가운데가 흔들린다) */
  .page-head h1:has(.badge) + .sub { --h1-hang: 4px; }   /* 제목 안 배지(종료됨·퇴원·동의)는 글자 바닥선 아래로 내려온다 → 배지 아래 변부터 잰다 */
}
@supports not (text-box: trim-end cap alphabetic) {
  .page-head h1 + .sub:has(.cls-tag, .badge) { margin-top: 2px; }
}
/* 수업 점이 있는 제목(수업 상세·시험 수업): 이름(.h1t)만 잘리므로 점은 위에 붙이고 줄 높이 가운데에 둔다(옛 flex 가운데 · 정수로 내림 → 제목 높이가 0.5px 에 걸리지 않게) */
.page-head h1 > .cls-dot { margin-top: calc((1lh - 14px) / 2); margin-top: round(down, (1lh - 14px) / 2, 1px); }
.page-head .acts { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* 수업 상세만: 학기 꼬리표로 제목 줄이 길어져 가운데 정렬이면 버튼 아래 공백이 27px까지 커졌다 · 버튼을 제목 줄 바닥에 맞추고 탭까지 8, 탭 밑줄→카드도 8(2026-09-26 대표 메모 · 다른 화면은 .page-head 기본값 그대로) */
.page-head:has(.cls-acts) { align-items: flex-end; margin-bottom: 8px; }
.page-head:has(.cls-acts) + .tabs { margin-bottom: 8px; }
.page-head.ntc-ph { margin-bottom: 12px; }   /* 공지사항: 부제 아래 공백 18→12(2026-09-26 대표 메모, 폰·PC 공통 · 폭<840 은 아래 미디어의 선택칸 grid 규칙과 별개) */
/* 항목 나열(수업 부제 · 출석부 시험 줄) · 구분자 '·' 는 다음 항목 앞(::before 12) · 목록을 왼쪽으로 12 내밀고 바깥을 잘라
   줄 첫머리에 온 '·' 만 안 보이게 한다 → 줄 끝에도 줄 처음에도 '·' 가 남지 않는다(2026-09-26 비평 5 · 폭이 늘 같아 줄이 다시 흔들리지 않는다) */
/* 항목 상자는 글자에서 시작하고 '·' 는 항목 앞 여백(--sep) 안에 그린다(2026-10-10 w30 · 옛: '·' 가 항목 상자 안이라 줄 첫 항목 상자가
   카드 안여백보다 12 바깥에서 시작 → 카드 왼쪽 시작선 결함) · 보이는 자리는 옛과 같다 */
.seps { display: block; overflow-x: clip; }
@property --sep { syntax: "<length>"; inherits: true; initial-value: 12px; }   /* 줄 상자에서 px 로 굳혀 자식(작은 글자 배지 등)의 em 어긋남을 막는다 */
.seps > .sl { --sep: 0.75em; display: flex; flex-wrap: wrap; align-items: center; margin-left: calc(-1 * var(--sep)); }
.seps > .sl > * { margin-left: var(--sep); }
.seps > .sl > *::before { content: "·"; display: inline-block; width: var(--sep); margin-left: calc(-1 * var(--sep)); text-align: center; }
.seps > .sl.bd { align-items: baseline; }   /* 배지가 든 메타 줄(시험 수업): 배지 글자 기준선 = 옆 글자 기준선 · 밀지 않고 정렬 방식으로(2026-10-10 대표 T2) */
.seps > .sl > .terms { display: inline-flex; gap: var(--space-1); margin-right: -6px; }   /* 학기 칩 묶음은 늘 첫머리 · 뒤 항목과 6 */
.seps > .sl > .terms::before { content: none; }
.seps > .sl > .terms + *::before { content: ""; }
.sum { font-size: var(--fs-base); line-height: 20px; color: var(--ink-2); }   /* 큰 숫자 카드 대신 한 줄 요약 문장(성적 요약·시험 통계·영상 진도 · 2026-10-09 대표 취향) · 숫자만 600 */
.sum b { font-weight: 600; color: var(--ink); }   /* 문장 속 숫자는 자연폭(65행 규칙 · 묶음 4 비평) */
/* 수업 상세 꼬리표 한 판(2026-09-27 구조 4차 tag=D): 이름 위 · navy-100 판 24 · r6 · 칸 사이 12 · 아이콘 14 ink-3 + 4 + 글 12.5/600
   글자 navy-800(구조 5차 sub5 메모 "위에 색띠에서도") · 칸이 넘치면 칸 단위로 다음 줄 */
.cls-plate { display: inline-flex; flex-wrap: wrap; align-items: center; column-gap: var(--space-3); max-width: 100%; margin-bottom: 8px; padding: 0 10px;
  border-radius: 6px; background: var(--navy-100); color: var(--navy-800); font-size: var(--fs-xs); font-weight: 600; line-height: 14px; }
.cls-plate > span { display: inline-flex; align-items: center; gap: var(--space-1); height: 24px; white-space: nowrap; }
.cls-plate svg { flex: none; width: 14px; height: 14px; color: var(--ink-3); }
.crumb { font-size: var(--fs-sm); color: var(--ink-2); margin-bottom: 8px; display: flex; gap: 6px; align-items: center; line-height: 20px; }   /* 13px 글 · 반여백 2 · 제목까지 잉크 16.5(2026-09-29 D3 대표 메모 '살짝 더 간격' 6→8) */
/* 경로 줄 ‹ (2026-09-29 D3 pcback=D): 바탕 없는 16px · 잉크를 제목 시작선에(-6) · ‹ 뒤 잉크 간격 14 이상(D3 critic) · 누름 영역은 위·아래·왼쪽 8, 오른쪽 4('홈'을 덮지 않게) · 줄 높이 19 그대로 */
.crumb .bk { position: relative; display: inline-flex; align-items: center; height: 20px; padding: 0; border: 0; background: none; color: var(--ink-2); cursor: pointer; margin-left: -6px; margin-right: 4px; }
.crumb .bk svg { width: 16px; height: 16px; transform: translateY(-.5px); }   /* PC '‹ 홈' ‹ 잉크 가운데 = '홈' 잉크 가운데(W106b 측정 차 0) */
.crumb .bk::after { content: ""; position: absolute; inset: -8px -4px -8px -8px; }
.crumb > a, .crumb > span:not(.sep) { white-space: nowrap; }
.crumb.clip > :last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }   /* '…' 로 접어도 넘칠 때만(app.js) · 직계 부모 한 칸이 아주 긴 경우의 마지막 수단 */
.crumb a { color: var(--ink-2); }   /* 대비 4.5 이상(D3 critic) · 구분자만 ink-4 */
.crumb .sep { color: var(--ink-3); }   /* 대비 5.16(옛 ink-4 2.56) */
h2.sec { font-size: var(--fs-lg); line-height: 22px; font-weight: 700; margin: 22px 0 10px; display: flex; align-items: center; gap: 8px; }   /* 16/22(B 체계 1 · 본문 1.45 상속 23.2 대신) */
h2.sec:first-child { margin-top: 0; }
h2.sec .hint { font-weight: 500; }
h2.sec:has(> .hint) { align-items: baseline; }   /* 제목 16 + 작은 힌트: 가운데가 아니라 글자 아래선을 맞춘다(2026-10-09 대표 '숫자와 한글 하단 정렬') */
h3 { font-size: var(--fs-md); font-weight: 700; margin-bottom: 10px; }
/* 아이콘·배지가 들어간 제목도 글자와 상하 가운데 (2026-09-18 정렬 규칙) */
.card-head h3, h3:has(svg), h1:has(svg) { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ---------- 카드 · 그리드 ---------- */
.card { background: var(--card); border-radius: var(--radius); padding: 18px 20px; margin-bottom: 16px; border: 1px solid var(--line); box-shadow: var(--shadow); }
.card.tight { padding: 12px 14px; }
.card.narrow { max-width: 620px; }
.card.flat { box-shadow: none; border: 1px solid var(--line); }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.card-head h3 { margin: 0; font-size: var(--fs-lg); line-height: 22px; color: var(--ink); }   /* 카드 제목 16/22 · 700 · ink(홈 카드 제목과 같게 · 2026-09-27 B 체계 2) */
/* 출석부 '과제'·'수업 내용'·'수업 영상'·'수업 자료' · 공지 '올린 공지' 카드(2026-09-27 B 체계 3·4 · 묶음 3 출석부 카드 리듬 통일 · 다른 카드는 B 다음 판)
   카드 가장자리 ↔ 첫·마지막 잉크 폰 16 · PC 20(위 = 아래) · 제목 잉크 → 첫 항목 잉크 18(sp3 · 공지는 묶음 머리 값) · 가로 안여백 그대로 · 값은 잉크 계측 */
#homework, #ses-info, #videos, #files, .ntc-ph + .card { padding-top: 16px; }   /* 제목(16/22) 잉크 위 20 */
#homework > .card-head, #ses-info > .card-head, #videos > .card-head, #files > .card-head { margin-bottom: 10px; }  /* 제목 잉크 → 첫 항목 잉크 18(옛 14) */
.ntc-ph + .card > .card-head { margin-bottom: 6px; }                    /* 제목 잉크 → 묶음 머리 '고정됨' 잉크 18(sp3 l2 · 첫 이름 위 4) */
#homework { padding-bottom: 16px; }                                     /* 마지막 설명 줄(12/18) 잉크 아래 20 */
#ses-info { padding-bottom: 20px; }                                     /* 마지막 입력칸 아래 20(칸 이름 묶음 아래 여백 0) */
#ses-info .vform > :last-child { margin-bottom: 0; }
#videos, #files { padding-bottom: 20px; }                               /* 마지막 추가 줄(입력칸·드롭존 테두리) 아래 20 */
#videos > .card-head + .list > .item:first-child, #files > .card-head + .list > .item:first-child { padding-top: 0; }   /* 제목 → 첫 영상·자료 줄 잉크 18 */
#videos > .row, #files > .row { margin-top: 10px; }                     /* 목록 → 추가 줄 10(옛 인라인 값 그대로) */
#videos > .card-head + .row, #files > .card-head + .row { margin-top: 14px; }   /* 목록이 없으면 제목 → 추가 줄(입력칸·드롭존 테두리) 잉크 18.5(제목 줄 아래 10 과 겹쳐 14) */
/* W412 critic3 12: 자료 행 메타 아래 = 위(제목 잉크 → 첫 자료 잉크 18.5) · 마지막 자료 아래 빈 공간(12+10) 줄임 → 메타 잉크 → 올리기 줄 19 안팎 */
#files > .list > .item:last-child { padding-bottom: 0; }
#files > .list + .row { margin-top: var(--space-4); }
/* 수업 영상 줄(2026-09-27 실장 지적 3): 주소 한 줄 말줄임 + 진도 덩어리 · [학생별 진도][삭제] 한 묶음(좁으면 둘이 함께 아랫줄 오른쪽) */
.item .meta.vmeta { display: flex; align-items: baseline; min-width: 0; white-space: nowrap; line-height: 18px; }   /* 12/18(B 줄높이 표 · 반여백 정수라 주소 칸 글자가 가운데) · 주소와 진도는 한 글줄처럼 기준선 맞춤 */
.vmeta .vurl { min-width: 0; overflow: hidden; text-overflow: ellipsis; }   /* 주소 링크는 이 칸 안의 글줄(인라인) 그대로 · 칸이 줄면 말줄임 */
.vmeta .vst { flex: none; }
.vmeta .vst::before { content: "·"; display: inline-block; width: 12px; text-align: center; }   /* 항목 나열 .seps 와 같은 12 */
.vacts { flex: none; display: flex; align-items: center; gap: 12px; margin-left: auto; }   /* 사이 12 = 행 간격 그대로 */
.ntc-ph + .card { padding-bottom: 16px; }                               /* 마지막 줄 본문 미리보기(13/19) 잉크 아래 20 */
@media (max-width: 839px) {
  #homework, #ses-info, #videos, #files, .ntc-ph + .card { padding-top: 12px; }   /* 폰 16 */
  #homework { padding-bottom: 12px; }
  #ses-info { padding-bottom: 16px; }
  #files { padding-bottom: 16px; }
  #videos { padding-bottom: 16px; }   /* 마지막 추가 줄 입력칸 아래 = 제목 잉크 위(820 계측 위 16.0 · 아래 17.3 → 16.3) */
  .ntc-ph + .card { padding-bottom: 12px; }                             /* 마지막 줄 둘째 줄(게시 위치 · 미리보기 19 · sp3 p1 구조) 잉크 아래 16 */
  #homework > .card-head + .hw-item { margin-top: -4px; }               /* 첫 과제 줄 알약(22)이 삭제 버튼(누름 36) 가운데라 위 반여백 흡수 */
}
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.grid2.eq { align-items: start; }   /* 두 카드 높이는 내용 높이대로(2026-10-10 대표 E4 · 옛 아래 끝 맞춤 stretch 폐기) */
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 18px; }
.stat { background: var(--card); border-radius: var(--radius); padding: 14px 16px; border: 1px solid var(--line); box-shadow: var(--shadow); }
.stat .num { font-size: var(--fs-3xl); font-weight: 700; color: var(--navy-ink); letter-spacing: -0.02em; line-height: var(--lh-display); font-variant-numeric: tabular-nums; }
.stat .lbl { color: var(--ink-3); font-size: var(--fs-xs); margin-top: 4px; line-height: 18px; }
/* 큰 숫자 + 작은 '/ 전체'(점수·순위·횟수 머리 숫자 · 2026-09-28 대표 채택 '9 / 10' · 매크로 _macros.html frac)
   숫자 → 빗금 .28em · 빗금 뒤 띄어쓰기 한 칸 · 기준선 맞춤 · 문장 속 분수·한도 문장은 쓰지 않는다 */
.frac { display: inline-flex; align-items: baseline; }
.frac small { margin-left: 4px; }
.stat.accent { background: var(--navy-fill); border-color: var(--navy-fill); }
.stat.accent .num { color: #fff; } .stat.accent .lbl { color: var(--navy-300); }

/* ---------- 버튼 ---------- */
/* 4등급: 기본(navy-fill 채움) · soft(navy-100) · ghost(navy-50) · danger(bad-bg) — 테두리형은 없앴다
   크기 사다리(2026-09-26 대표 결정 '크기 규칙 A'): 기본 40 · sm 31(2026-10-16 대표 W70 · 옛 32) · lg 48 · 글자 14/13/16 · 600 · 좌우 14/12/18
   폰(≤839)에서도 보이는 높이는 같고, 누름 영역 44 는 아래 모바일 절의 보이지 않는 ::after 로 늘린다 */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; background: var(--navy-fill); color: #fff;
  border: 1px solid var(--navy-fill); border-radius: 10px; padding: 0 16px; height: 40px; font-size: var(--fs-base); font-weight: 600;
  cursor: pointer; line-height: 1; white-space: nowrap; transition: background .12s, box-shadow .12s, transform .08s;
  box-shadow: 0 1px 2px rgba(1, 22, 43, .18);
  touch-action: manipulation; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
}
.btn svg { flex: none; width: 16px; height: 16px; }
.btn.sm svg { width: 15px; height: 15px; }   /* 작은 버튼 31 안 아이콘은 15: (31-15)/2 = 8 정수 칸에 앉는다 · 16 이면 7.5 칸이라 진짜 3배에서 아이콘 달린 버튼 11곳 잉크가 2기기px 처짐(2026-10-17 W70 ①) · 상자 크기로 맞추고 밀지 않는다 */
/* 채움이 가장 어두운 톤이라 hover 는 더 어둡게 갈 수 없다 — 흰 겹침으로 (2026-09-23) */
@media (hover: hover) { .btn:hover { background-image: linear-gradient(rgba(255,255,255,.08), rgba(255,255,255,.08)); text-decoration: none; } }
.btn:active { transform: scale(.98); }
button.btn[type="submit"]:active, form button.btn:not([type]):active { transform: scale(.97); }   /* 저장·보내기 누름 0.97 · 80ms(2026-09-25 모션 submit=B · 처리 중 글자는 ux.js) */
.btn.ghost { background: var(--btn-sub-bg); color: var(--navy-800); border-color: transparent; box-shadow: inset 0 0 0 1px var(--btn-sub-line); }
@media (hover: hover) { .btn.ghost:hover { background: var(--btn-sub-bg-h); border-color: transparent; } }
.btn.soft { background: var(--navy-100); color: var(--navy-800); border-color: transparent; box-shadow: none; }
@media (hover: hover) { .btn.soft:hover { background: var(--navy-200); } }
/* 바탕(--bg) 위 선택칸 · 면(navy-50)은 바탕과 거의 같아 안 읽힌다 → soft 면(navy-100)으로(2026-09-26 비평 3)
   ghost 버튼은 얇은 틀(--btn-sub-line)로 바탕 위에서도 읽혀 바탕·카드 어디서나 같은 보조 버튼(2026-09-28 구조 5차 sub5=C) */
.page-head .selbox { background: var(--navy-100); }
@media (hover: hover) { .page-head .selbox:hover { background: var(--navy-200); } }
.btn.danger { background: var(--bad-bg); color: var(--bad); border-color: transparent; box-shadow: none; }
@media (hover: hover) { .btn.danger:hover { background: var(--bad-soft); color: var(--card); } }
.btn.sm { padding: 0 12px; font-size: var(--fs-sm); height: 31px; border-radius: var(--r-xs); }   /* 31 · 줄높이 1(.btn): 13px 글자 잉크가 3배·2배·1배 모두 위아래 차 1기기px 이하(32 는 3배에서 1px 뜸 · 2026-10-16 대표 W70 '31로 낮춤' · 같은 줄 32 부품과 1px 차는 받아들임) */
.btn.lg { padding: 0 18px; font-size: var(--fs-btn-lg); height: 48px; border-radius: 12px; line-height: normal; }   /* 16px 에서 줄높이 1 은 반여백 -1.5 → 잉크 0.5px 위로 */
.btn.block { width: 100%; }
.btn.icon { padding: 0; height: 32px; width: 32px; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn.soft[disabled] { opacity: 1; background: var(--navy-50); color: var(--ink-3); }   /* soft 비활성은 투명도 대신 색 토큰: 연한 면 + ink-3 글자 = 대비 4.72(투명도 .5 는 2.76) · 안 눌리는 것은 면이 더 연하고 글자가 회색으로 보인다(2026-10-13 F0 사양) */
.acts, .actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
/* 바닥 고정 바 · 불투명 바탕 + 위 선(2026-09-26 대표 메모 '명단 마지막 행과 겹쳐 보인다' · 옛 그라데이션은 뒤 글자가 비쳤다) */
.sticky-actions {
  position: sticky; bottom: 0; background: var(--bg); border-top: 1px solid var(--line);
  padding: 8px 0 8px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; z-index: 5; box-shadow: var(--shadow-lg);
}
/* 하단 바 버튼은 한 줄에 한 등급 L48(2026-09-26 크기 규칙 A · 저장 48 옆 시험·휴지통 40 이 섞이던 것) */
.sticky-actions .btn { height: 48px; font-size: var(--fs-btn-lg); border-radius: 12px; }
.sticky-actions .btn.danger:not(:has(span)) { width: 48px; padding: 0; justify-content: center; }
form.inline { display: inline; }

/* ---------- 폼 ---------- */
.vform label, .field { display: block; margin-bottom: 12px; font-weight: 600; font-size: var(--fs-sm); color: var(--ink-2); line-height: 20px; }   /* 13px 글 · 반여백 2 (1.45 면 0.93px 위로 떴다) */
/* 칩·세그·색상 칸도 label 이지만 폼 '칸'은 아니다 — 위 display:block·margin 때문에
   줄마다 12px 빈틈이 생기고 칩 글자가 위로 밀리던 것을 되돌린다 */
.chips .chip, .seg label, .swatches .swatch { margin: 0; }
.chips .chip { display: inline-flex; }
.swatches .swatch { display: grid; }
.vform input:not([type=checkbox]):not([type=radio]), .vform select, .vform textarea,
.input, select.input, textarea.input {
  display: block; width: 100%; margin-top: 4px; padding: 10px 12px; border: 1px solid var(--line-2);
  border-radius: var(--r-sm); font-size: var(--fs-md); font-weight: 400; background: var(--card); color: var(--ink); min-height: 40px;
  transition: border-color .12s, box-shadow .12s;
}
.vform input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]), .vform textarea, .input:not(select), textarea.input { appearance: none; -webkit-appearance: none; }
/* 한 줄 입력·선택은 고정 높이 + 세로 여백 0 → 글자가 칸 한가운데 (2026-09-18 정렬 규칙, 여러 줄 textarea 는 제외)
   높이 40 = 기본 버튼과 같은 줄 높이(2026-09-26 크기 규칙 A · 폰도 40, 폰 글자는 16 유지) */
.vform input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]), .vform select,
.input:not(textarea):not([type=file]):not([type=range]):not([type=color]), select.input {
  height: 40px; padding-top: 0; padding-bottom: 0; line-height: normal;   /* 좌우 여백은 기본값·검색칸(36px) 그대로 */
}
.vform input:not([type=checkbox]):not([type=radio]):focus, .vform select:focus, .vform textarea:focus, .input:focus {
  outline: none; border-color: var(--navy-700); box-shadow: none;
}
.vform textarea { resize: vertical; line-height: 1.5; }
/* hidden 속성으로 접어 둔 칸(예: 과목 '기타'·학기 직접 입력)은 위 display:block 에 지지 않게 (:not 3개로 우선순위를 더 높인다) */
.vform input[hidden]:not([type=checkbox]):not([type=radio]), .vform select[hidden], .vform textarea[hidden], .input[hidden] { display: none; }
/* 날짜·시간 칸 한 부품(2026-09-28 대표 iOS 실기기 '2026. 9. 26.'이 칸 위에 붙고 아래가 빔 · 템플릿 26곳 전부)
   iOS WebKit 은 이 칸을 inline-flex + 가운데로 그리는데 위 display:block 이 덮어 값 상자가 칸 맨 위로 갔다
   → 칸은 세로 flex + 가운데(.vform 규칙과 같은 우선순위라 뒤에 둔다 · 가로 flex 면 크롬 안쪽 묶음이 글자 폭으로 줄어 달력 아이콘이 글자 뒤에 붙는다)
   · 값 상자는 칸 폭 그대로(stretch)·여백 0·왼쪽 정렬·빈 값도 한 줄 · 크롬 달력 아이콘은 자리 그대로 흐리게
   높이 40·반경·테두리·폰 글자 16 은 위 입력칸 규칙 그대로(여기서 다시 적지 않는다) */
input:is([type=date], [type=time], [type=month], [type=datetime-local]) { -webkit-appearance: none; appearance: none; }
input:is([type=date], [type=time], [type=month], [type=datetime-local]):not([hidden]),
.vform input:is([type=date], [type=time], [type=month], [type=datetime-local]):not([hidden]) { display: flex; flex-direction: column; justify-content: center; align-items: stretch; }
input::-webkit-date-and-time-value { margin: 0; text-align: left; font: inherit; min-height: 1.2em; min-height: 1lh; }
input::-webkit-datetime-edit, input::-webkit-datetime-edit-fields-wrapper { padding: 0; }
input::-webkit-calendar-picker-indicator { margin: 0 0 0 6px; padding: 0; opacity: .5; cursor: pointer; }
/* 두 칸 줄(개강일·종강일 등)의 날짜 칸 · 크롬 날짜 칸은 글자 폭(약 173)보다 줄지 않아 좁은 폰(≤375)에서 칸이 줄 밖으로 나가 가로 스크롤이 생겼다 → 그 칸만 줄어들게(칸 안 width:100% 그대로 · 2026-09-28 R0 q27) */
.form-row > :has(> input:is([type=date], [type=time], [type=month], [type=datetime-local])) { min-width: 0; }
@media (max-width: 359px) { .form-row.duo:has(input:is([type=date], [type=time], [type=month], [type=datetime-local])) { grid-template-columns: 1fr; } }   /* 360 미만은 반 칸에 날짜 글자가 다 안 들어가 잘리므로 위아래로(344 에서 '2026-08-0' 까지만 보였다) */
/* 선택칸(select) 한 부품(2026-09-28 R0 q29 · 템플릿 50여 곳 전부) · WebKit(iOS·맥 사파리) 기본 회색 단추 대신 입력칸과 같은 면 + 오른쪽 ⌄(토큰 색 두 빗금 · 그림 파일 없이)
   면·테두리·높이·반경·글자는 각 자리 규칙(.vform select · select.input · select.mini …) 그대로 · 글자가 ⌄ 밑으로 들어가지 않게 오른쪽 안여백 32 는 인라인 padding 보다 앞선다(!important)
   여러 줄 목록(multiple·size)은 그대로 · 투명하게 덮어 쓰는 선택칸(.selbox select)은 보이지 않아 영향 없음 */
select:not([multiple]):not([size]) {
  -webkit-appearance: none; appearance: none; padding-right: 32px !important;
  background-image: linear-gradient(45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)),
    linear-gradient(-45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px));
  background-size: 6px 6px; background-repeat: no-repeat; background-position: right 18px center, right 12px center;
}
.vform .checkline, .checkline { font-weight: 600; display: flex; align-items: center; gap: 8px; cursor: pointer; flex-wrap: wrap; }
.checkline input { width: 18px; height: 18px; accent-color: var(--navy-600); margin: 0; }
/* ---------- 글자 상하 가운데 보정 (2026-09-23 계측) ----------
   크롬은 줄상자의 위아래 반여백(half-leading)을 정수 px 로 내려 잡는다. 줄높이 1.45 처럼
   반여백이 소수로 떨어지면 글자가 칸 안에서 최대 1.25px 위로 뜬다(tests/check_center.py 로 잼).
   그래서 한 줄짜리 부품은 줄높이를 normal(반여백 0)로, 흐르는 글은 반여백이 정수가 되는
   px 줄높이로 고정한다. 글자 크기를 바꾸면 이 값도 다시 재야 한다. */
.hint, .small { line-height: 18px; }   /* 12px 글 · 반여백 2 (1.45 는 반여백 1.7 → 잉크 1.2px 위로) */
.hint { font-weight: 400; font-size: var(--fs-xs); color: var(--ink-3); }
#support > h3 + .hint { margin-bottom: 10px; }   /* 설정 '위티에 문의' 칸(2026-09-28 master · 옛 인라인 여백 값 그대로) · 설명 → 버튼 줄 10 · 버튼 줄 → 메일 주소 10 */
#support > .row + .hint { margin-top: 10px; }
.req { color: var(--bad); }
/* 접근성(2026-09-27 · axe): 문장 속 글 링크는 색만이 아니라 밑줄로도 구분 · 버튼·꼬리표처럼 클래스가 있는 링크는 그대로 */
:is(p, .sub, .hint, .banner > span) a:not([class]) { text-decoration: underline; text-underline-offset: 2px; }
.ilink .u { text-decoration: underline; text-underline-offset: 2px; }   /* 아이콘이 앞에 붙은 문장 속 링크는 글자만 밑줄(아이콘 뒤 빈칸·제출 수·꼬리표는 빼고 · 2026-09-28) */
/* 화면에는 안 보이고 읽기 도구만 읽는 글(보이지 않는 제목 등) · 일부러 자른 상자라 스크롤 상자가 아닌 clip(옛 브라우저는 hidden) */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; overflow: clip; clip-path: inset(50%); white-space: nowrap; }
/* 접어 둔 칸을 여는 작은 글자 버튼 — 라벨 줄에 붙어 세로 여백을 만들지 않는다 */
.linkbtn { background: none; border: 0; padding: 0 2px; font: inherit; font-size: var(--fs-xs); font-weight: 700; color: var(--navy-ink); cursor: pointer; text-decoration: underline; }
/* ux.js 가 넣는 입력 중 안내 — 한 줄로만 (색은 토큰) */
.err-line { margin: var(--space-2) 0; font-weight: 600; font-size: var(--fs-xs); color: var(--bad); }   /* 위 8 = 아래 8 · 굵기 600 하나(학생 화면 student.css 와 같음 · 2026-10-01 실장 8) */
.vform label:has(> .err-line:not([hidden])), .field:has(> .err-line:not([hidden])) { margin-bottom: 0; }   /* 오류가 보이는 칸은 라벨 아래 12 대신 오류 줄 아래 8 */
[aria-invalid="true"] { border-color: var(--bad-line) !important; }
.draft-tip { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; margin-bottom: 10px; padding: 8px 12px; border-radius: var(--r-sm);
  background: var(--navy-50); border: 1px solid var(--line); font-size: var(--fs-xs); color: var(--ink-3); }
.draft-tip button { background: none; border: 0; padding: 0; font: inherit; font-weight: 700; color: var(--navy-ink); cursor: pointer; text-decoration: underline; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.inline-form { display: flex; gap: 8px; align-items: center; }
.inline-form[hidden] { display: none; }   /* 수납 납부 입력 줄 · flex 가 hidden 을 덮어 처음부터 펼쳐지던 것 */
.btn[hidden] { display: none; }   /* hidden 단추가 flex 에 덮여 보이던 것 · 수납 되돌리기 */
.inline-form .input { margin-top: 0; flex: 1; }
/* 누름 영역용 감싸기 label(.tap) · 보이는 배치는 감싸기 전과 같게 · 입력 폼 안 label 의 아래 여백·글자 규칙을 받지 않는다 · 폰에서만 위아래 안여백 2 / 마진 -2(--tap-p·--tap-m) */
label.tap, .vform label.tap { display: block; margin: var(--tap-m, 0px) 0; padding: var(--tap-p, 0px) 0; }
.inline-form > .tap:has(> .input:only-child) { flex: 1; display: grid; }   /* 감싸기 전 .inline-form .input{flex:1} 이 칸을 늘리던 것을 label 이 대신하고 칸은 label 안에서 같은 flex:1 로 채운다 */
.search svg { z-index: 1; pointer-events: none; }
.search { position: relative; }
.search .input { padding-left: 36px; margin-top: 0; }
.search svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--ink-4); }

/* 체크 칩 (요일 선택 · 수업 선택) */
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.stu-range { display: contents; }
/* 한 줄짜리 가로 묶음 안에서는 칩 아래 여백을 없앤다 — 12px 여백 때문에 칩만 6px 위로 떠 보였다 (2026-09-23 계측) */
.row > .chips, .acts > .chips, .card-head > .chips, .inline-form > .chips { margin-bottom: 0; }
.page-head .sub + .chips { margin: 6px 0 0; }   /* 공지 보기 머리 게시 대상 꼬리표 줄 · 부제 아래 6(2026-09-28 · 옛 인라인 값 그대로 · 꼬리표 사이는 띄어쓰기 대신 6) */
.chip { display: inline-flex; align-items: center; gap: 6px; background: var(--card); border: 1px solid var(--line-2); border-radius: var(--r-xs); padding: 6px 12px; color: var(--ink-2); font-size: var(--fs-sm); font-weight: 500; cursor: pointer; line-height: normal; min-height: 32px; }   /* 칩 보이는 높이 32 · 반경 8(2026-10-13 대표 W233 · 홀수 31·34 → 32) */   /* 줄높이 1.2 일 때 잉크 0.8px 위로 떴다 */
@media (hover: hover) { .chip:hover { border-color: var(--navy-400); text-decoration: none; } }
.chip.on, .chip:has(input:checked) { background: var(--navy-fill); border-color: var(--navy-fill); color: #fff; font-weight: 700; }
.chip input { display: none; }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.chip.on .dot, .chip:has(input:checked) .dot { box-shadow: 0 0 0 2px rgba(255,255,255,.5); }
/* 칩 안 개수(시기 필터) — 선택되면 네이비 위 글자라 색 대신 불투명도로 낮춘다 */
.chip .n { font-weight: 700; font-size: var(--fs-xs); color: var(--ink-3); }
.chip.on .n { color: inherit; opacity: .72; }
/* 균등 그리드 칩 — 요일 7 · 과목 8 · 학기 8: 칸을 꽉 채워 줄 끝이 뜨지 않게 */
.chips.grid { display: grid; grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr)); gap: 8px; margin: 6px 0 var(--space-3); }
.chips.grid .chip { justify-content: center; text-align: center; padding: 6px 4px; min-width: 0; white-space: nowrap; }
.chips.g7 { --cols: 7; }
.chips.g8 { --cols: 8; }
@media (min-width: 840px) { .chips.g8 { grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); } }   /* PC 좁은 카드에서 8칸 고정이라 '제2외국어'가 칸 밖으로 새던 문제 → 들어가는 만큼만 놓고 줄 바꿈 (2026-09-19 넘침 검사) · 폰은 아래 4칸 규칙 */
/* 색상: 손가락으로 누를 만한 크기(36px 이상)를 지키느라 폰에서는 5개씩 두 줄 */
.swatches { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 6px; margin: 6px 0 0; max-width: 400px; }
@media (max-width: 460px) { .swatches { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; } .swatch { max-width: 40px; } }
.swatch { width: 100%; max-width: 30px; aspect-ratio: 1 / 1; justify-self: center; border-radius: 50%; cursor: pointer; display: grid; place-items: center;border: 2px solid transparent; }
.swatch input { display: none; }
.swatch svg { width: 16px; height: 16px; color: var(--navy-900); }
.swatch:has(input:checked) { border-color: var(--ink); box-shadow: 0 0 0 2px var(--bg) inset; }

/* 세그먼트(출결·과제 선택 — 탭 한 번으로 저장) */
.seg { display: inline-flex; background: var(--navy-50); border: 1px solid var(--line); border-radius: var(--r-xs); padding: 4px; gap: 2px; }   /* 작은 부품 반경 8 · 안 칸 6(2026-09-27 D 구조 2차 rad2) */
.seg label { position: relative; cursor: pointer; display: flex; }   /* flex: 인라인 베이스라인 여백 제거 → 줄 높이 최소화 */
.seg input { position: absolute; opacity: 0; width: 0; height: 0; }
.seg label > span { display: inline-flex; align-items: center; justify-content: center; padding: 0 12px; height: 36px; border-radius: 6px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3); white-space: nowrap; transition: all .1s; min-width: 44px; line-height: normal; }   /* 잉크 0.9px 보정 */
@media (hover: hover) { .seg label:hover > span { color: var(--ink); } }
.seg input:checked + span { background: var(--chip-on); color: var(--ink); box-shadow: 0 1px 2px rgba(1,22,43,.14); }
/* 값 색은 옅은 채움 + 그 색 글자 · 그림자 없음 (2026-09-18 고르기 2호 B안 · 도장 모션은 2026-09-26 미끄러지는 틀로 바뀜) */
.seg input[value="출석"]:checked + span { background: var(--ok-bg); color: var(--ok); box-shadow: none; }
.seg input[value="지각"]:checked + span, .seg input[value="조퇴"]:checked + span { background: var(--warn-bg); color: var(--warn); box-shadow: none; }
.seg input[value="결석"]:checked + span { background: var(--bad-bg); color: var(--bad); box-shadow: none; }
.seg input[value="영상"]:checked + span { background: var(--vid-bg); color: var(--vid); box-shadow: none; }
/* 과제 완료율 6칸 (0·20·40·60·80·100) — 80 이상 초록 · 40~60 노랑 · 20 이하 빨강 */
.seg.hw label > span { min-width: 40px; padding: 0 8px; }
.seg > .seg-lab { display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; width: auto; font-size: 11px; font-weight: 700; color: var(--ink-4); padding: 0 4px 0 var(--space-1); white-space: nowrap; line-height: normal; }
.seg.hw input[value="100"]:checked + span, .seg.hw input[value="80"]:checked + span { background: var(--ok-bg); color: var(--ok); box-shadow: none; }
.seg.hw input[value="60"]:checked + span, .seg.hw input[value="40"]:checked + span { background: var(--warn-bg); color: var(--warn); box-shadow: none; }
.seg.hw input[value="20"]:checked + span, .seg.hw input[value="0"]:checked + span { background: var(--bad-bg); color: var(--bad); box-shadow: none; }
.seg.hw .hwcur { color: var(--ink-2); }
/* 과제 건별(settings.homework_model=items): 완료·일부·미제출 3칸 — 완료율 세그먼트와 같은 의미색 (2026-09-16) */
.seg input[value="완료"]:checked + span { background: var(--ok-bg); color: var(--ok); box-shadow: none; }
.seg input[value="일부"]:checked + span { background: var(--warn-bg); color: var(--warn); box-shadow: none; }
.seg input[value="미제출"]:checked + span { background: var(--bad-bg); color: var(--bad); box-shadow: none; }
/* 출석부 한 칸 = 미끄러지는 틀 하나(2026-09-26 D 모션 2) · app.js 가 .seg-ind 를 넣고 고른 칸 자리·폭으로 옮긴다
   이동·폭·색 200ms standard · 출발은 지금 보이는 자리(연타해도 이어짐) · 첫 그림·창 크기 변화는 애니메이션 없이 · 고른 칸 자체의 채움은 틀이 대신한다 */
.seg.has-ind { position: relative; }
.seg-ind { position: absolute; left: 0; top: 0; width: 0; height: 0; border-radius: 6px; background: var(--chip-on); opacity: 0; pointer-events: none; }
.seg-ind.on { opacity: 1; }
.seg.has-ind.ready .seg-ind { transition: transform var(--dur-2) var(--ease-standard), width var(--dur-2) var(--ease-standard), background-color var(--dur-2) var(--ease-standard), opacity var(--dur-1) linear; }
.check-list.x-fade .seg.has-ind.ready .seg-ind { transition: background-color var(--dur-1) linear, opacity var(--dur-1) linear; }   /* 전원 출석: 칸 색만 120ms 교차 */
.check-row .seg.has-ind input:checked + span { background: transparent; box-shadow: none; }
.seg-ind[data-v="출석"], .seg-ind[data-v="100"], .seg-ind[data-v="80"], .seg-ind[data-v="완료"] { background: var(--ok-bg); }
.seg-ind[data-v="지각"], .seg-ind[data-v="조퇴"], .seg-ind[data-v="60"], .seg-ind[data-v="40"], .seg-ind[data-v="일부"] { background: var(--warn-bg); }
.seg-ind[data-v="결석"], .seg-ind[data-v="20"], .seg-ind[data-v="0"], .seg-ind[data-v="미제출"] { background: var(--bad-bg); }
.seg-ind[data-v="영상"] { background: var(--vid-bg); }
.hw-item + .hw-item { margin-top: 12px; padding-top: var(--space-3); border-top: 1px solid var(--line); }
/* 과제 입력 방식 전환: 탭 6칸(기본) ↔ 10% 슬라이드 — .check-list.hw-slider 클래스로 표시 전환 */
.hw-cell { display: flex; align-items: center; min-width: 0; justify-content: flex-start; }
.hwslide { display: none; align-items: center; gap: 8px; width: 100%; max-width: 520px; min-width: 250px; }
.check-list.hw-slider .seg.hw { display: none; }
.check-list.hw-slider .hwslide { display: flex; }
/* '출결만' (2026-09-07 점검 J): 과제 칸을 숨겨 폰 한 화면에 4명 → 9명 */
.check-list.att-only .hw-cell { display: none; }
.check-list.att-only .check-row { grid-template-columns: minmax(120px, 190px) max-content; }
@media (max-width: 839px) { .check-list.att-only .check-row { grid-template-columns: minmax(54px, max-content) 1fr; padding: 4px 0; } }
.hwslide .seg-lab { font-size: 11px; font-weight: 700; color: var(--ink-4); white-space: nowrap; }
.hwslide input[type=range] { flex: 1; min-width: 0; height: 34px; margin: 0; cursor: pointer; accent-color: var(--c, var(--navy-400)); }
.hwslide input[type=range].unset { opacity: .45; }
.hwslide .val { min-width: 50px; text-align: center; font-weight: 700; font-size: 13px; border-radius: 8px; padding: 4px 6px; background: var(--navy-50); color: var(--ink-3); border: 1px solid var(--line); white-space: nowrap; }
.hwslide .val.good { background: var(--ok-bg); color: var(--ok); border-color: transparent; }
.hwslide .val.mid { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.hwslide .val.bad { background: var(--bad-bg); color: var(--bad); border-color: transparent; }
.seg.mode label > span { min-width: 0; padding: 0 8px; height: 28px; font-size: var(--fs-xs); }
.seg.mode input:checked + span { background: var(--navy-fill); color: #fff; }

/* ---------- 수업 시간 고르기 (오전·오후 + 시 + 분 30분 단위) ---------- */
/* 시작·종료 두 블록을 PC 좌우 2열로, 요약 줄은 아래 한 줄에 (모바일은 세로 1열) */
.tpick { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 6px; }
.tp { border: 1px solid var(--line); border-radius: var(--r-sm); padding: var(--space-2) 10px; }
.tp-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.tp-head b { font-size: var(--fs-sm); color: var(--ink-2); margin-right: 2px; }
.tpick .chips { gap: var(--space-1); margin: 0; }
.tpick .tp-h { --cols: 6; }
.tpick .tp-h .chip { min-width: 0; padding: 6px 2px; justify-content: center; }   /* 시 12칸을 6칸씩 두 줄로 */
.tpick .seg.mode label > span { height: 32px; min-width: 40px; padding: 0 8px; font-size: var(--fs-sm); }
.tp-foot { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tp-sum { margin: 0; flex: 1 1 190px; font-weight: 700; font-size: var(--fs-sm); color: var(--navy-ink); }
.tp-sum.bad { color: var(--bad); }

/* ---------- 테이블 · 리스트 ---------- */
.tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -4px; padding: 0 var(--space-1); }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; font-variant-numeric: tabular-nums; }
th { background: var(--navy-50); font-size: var(--fs-xs); color: var(--ink-2); white-space: nowrap; font-weight: 700; line-height: 18px; }   /* 12px · 잉크 1.46px 위로 뜨던 것 보정 */
th:first-child { border-top-left-radius: var(--r-xs); } th:last-child { border-top-right-radius: var(--r-xs); }
tr:last-child td { border-bottom: 0; }
tr.dim { opacity: .5; }
td.num, th.num { text-align: right; }
/* 넓은 표(.tbl-wrap 가로 스크롤): 밀어도 첫 열(이름·날짜)은 제자리 (2026-09-23 조사 7 §4-3) */
.tbl-wrap th:first-child, .tbl-wrap td:first-child { position: sticky; left: 0; z-index: 1; }
.tbl-wrap td:first-child { background: var(--card); }
.tbl-wrap th:first-child { z-index: 2; }
/* 표 칸 안 칩·배지는 글자 기준선에 매달려 칸 가운데보다 1.5~2px 내려앉는다 — 그만큼 올린다 (2026-09-23 계측) */
td .st, td .pill, td .badge, td .cls-tag { vertical-align: 1.5px; }
/* 표 칸 안 버튼 여러 개: 아이콘만 있는 버튼은 기준선이 없어 기본 baseline 정렬이 글자 있는 버튼과 3.5px 어긋난다 — middle 로 고정 (2026-09-24 계측) */
td .btn { vertical-align: middle; }
.list { display: flex; flex-direction: column; }
.list .item { display: flex; align-items: center; gap: 12px; padding: 12px 4px; border-bottom: 1px solid var(--line); color: inherit; }
.list .item:last-child { border-bottom: 0; }
.card .list .item { padding-left: 0; padding-right: 0; }   /* 카드 안 행 글자 시작선 = 카드 제목 시작선(2026-09-27 B sp3 l2 · 누름 영역은 행 전체 그대로) */
.list .item > svg.lead { width: 20px; height: 20px; flex: none; color: var(--navy-600); }   /* 행 앞 아이콘(자료·영상·공지) */
@media (hover: hover) { .list a.item:hover { background: var(--navy-50); text-decoration: none; border-radius: 8px; } }
.item .main { flex: 1; min-width: 0; }
.item .selbox { display: flex; align-items: center; padding: 6px; margin: -6px 0 -6px -4px; cursor: pointer; }
.item .selbox input { width: 18px; height: 18px; accent-color: var(--navy-500); cursor: pointer; }
.item-link { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; color: inherit; }
.item-link:hover { text-decoration: none; }
.item .title { font-weight: 700; font-size: var(--fs-md); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; overflow-wrap: anywhere; }   /* 띄어쓰기 없는 긴 입금자명 375 넘침 (W165) */
.item .meta { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 0; line-height: 1.35; }
.list.wk .item .title { line-height: 20px; } .list.wk .item .meta { line-height: 18px; }   /* 시험 주차 줄: 글줄을 짝수 정수로 → 행 높이가 정수라 '시험 넣기' 버튼이 3배 픽셀 칸에 앉는다(W331) */
.item .right { text-align: right; font-size: var(--fs-sm); color: var(--ink-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.item .chev { color: var(--ink-4); width: 18px; height: 18px; flex-shrink: 0; }
.stu-list .title .ph, .stu-list .title .nophone, .stu-rep svg { display: none; }   /* 폰 학생 명단 전용 조각 · PC·분할은 지금 모양(글자 버튼) */
.item > a.hide-m { display: flex; }   /* 행 끝 › 링크: 글줄(높이 23 · 아이콘이 기준선에 앉아 2.5 위)이 아니라 아이콘 18 칸 그대로 → 행 가운데 · 폰은 .hide-m 이 숨김(2026-10-10 w30) */
/* 지난 주차(시험 없음)는 흐리게 · 옛 opacity .75 는 ink-3 글을 대비 3.13 으로 떨어뜨렸다 → 색 토큰으로(홈 .past 와 같은 방식: 글 ink-2·ink-3 그대로 · 칸 navy-50 · 대비 4.5 이상 · 2026-10-10 w30) */
.item.past .title { color: var(--ink-2); }
.item.past .avatar { background: var(--navy-50); color: var(--ink-3); }
/* 강사 시험 상세 '수강 해제된 학생의 응시 기록' 한 줄(2026-09-28 master #10 · 옛 인라인 값 그대로): 이름·상태·답 개수 줄 사이 8 · 아래 '답안 보기' 4 */
.item.orph { display: block; }
.item.orph .row .row { gap: 8px; }
.item.orph > details { margin-top: 4px; }
/* 수업 명단(2026-09-26 대표 메모): 이름 [연락처 뒷 4자리] · 학교 학년 / (연락처 없음) / 출결 배지 · 줄 사이 간격을 같게
   학교·학년은 .ph 와 같은 12 · ink-3 · 한 덩어리(.nw)라 좁으면 그 덩어리만 아랫줄로 */
/* 수업 명단 한 줄(W235 · 2026-10-13 D7 · 폰·PC 같게): 줄 74 · 이름 상자 58×38 · 오른쪽 두 줄 묶음 = 메타 16 / 배지 22 · 사이 4 · 묶음은 상자와 세로 가운데 */
.list.roster .item { box-sizing: border-box; height: 74px; padding: 0; padding-right: 0; gap: var(--space-2); border-bottom: 0; box-shadow: inset 0 -1px 0 var(--line); }
.roster .item .main { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }
.roster .rn { flex: none; box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 64px; height: 38px; padding: 0 4px; text-overflow: ellipsis; border-radius: var(--r-sm); overflow: hidden;
  background: var(--navy-50); color: var(--navy-900); font-size: var(--fs-up); font-weight: 700; line-height: 18px; white-space: nowrap; }   /* 이름 전체 · 3글자 45 + 안여백 */
.roster .rn:hover { text-decoration: none; }
.roster .rm { display: flex; align-items: center; gap: var(--space-1); max-width: 100%; height: 16px; font-size: var(--fs-xs); font-weight: 500; line-height: 16px; color: var(--ink-3); white-space: nowrap; overflow: hidden; }
.roster .rm .warn { font-weight: 600; }
.roster .att { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.roster .att span { padding: 0 6px; }
/* 줄 끝 ⋯ 메뉴(2026-09-27 구조 4차 rowmenu=A): ⋯ 36 · ink-2 · 연 동안 navy-50 · 행 가운데 · 폰·PC 같게(옛 [학습 리포트]·× 두 버튼 → 폰 두 칸 쌓임 없앰)
   메뉴 188 폭 · r10 · 그림자만 · 행 36 · 아이콘 18 ink-3('명단에서 제외'는 빨강) */
.row-more { position: relative; flex: none; margin-left: auto; margin-right: -12px; }   /* ⋯ 잉크 끝(상자 36 · 점 오른쪽 여백 11.4)이 구분선·머리 버튼 끝선에(2026-10-09 비평 578) */
.row-more .more-btn { width: 36px; height: 36px; }
.menu.rowmenu { width: 188px; min-width: 0; padding: 4px; border: 0; border-radius: 10px; }
.rowmenu form { display: block; }
.rowmenu .menu-i { justify-content: flex-start; gap: 10px; height: 36px; padding: 0 12px; border-radius: 6px; font-weight: 600; }
.rowmenu .menu-i svg { width: 18px; height: 18px; color: var(--ink-3); }
.rowmenu .menu-i.bad svg { color: currentColor; }
/* 학생 명단 카드(2026-09-28 sp4 C1 · 홈 카드와 같은 규칙): 카드 가장자리 ↔ 첫·마지막 잉크 PC 20 · 폰 16 · 머리 줄(버튼 포함) → 첫 행 잉크 18 */
.card:has(.roster) { padding-top: 20px; padding-bottom: 20px; }
.card:has(.roster) > .card-head { margin-bottom: 0; row-gap: 6px; }   /* 두 줄로 감기면 제목 잉크 → 도구 버튼 위 7.5(옛 11.5 · 2026-09-28 구조 5차 tools5 "학생명단이랑 조금 더 붙이기" 8) */
.roster .item:first-child { margin-top: -2px; }   /* 머리 줄 → 첫 상자 16 */
.roster .item:last-child { margin-bottom: -18px; box-shadow: none; }   /* 마지막 상자 ↔ 카드 아래 = 카드 안여백만 */
@media (max-width: 839px) {
  .card:has(.roster) { padding-top: 16px; padding-bottom: 16px; }
}
/* 명단 카드 머리가 두 줄로 감기면(카드 안 폭 341 미만 = '학생 명단' 59 + 사이 10 + 버튼 셋 272 · 폰 400 미만 · 두 칸 배치) 첫 표시가 버튼 면이 아니라 제목 잉크다
   → 제목 줄 22 → 16(글자 크기): 줄 위 반여백 3 이 빠져 카드 위 ↔ 첫 잉크 = 마지막 잉크 ↔ 카드 아래(2026-09-28 4i-2 A10 · 390 에서 19/16 → 16/16)
   (text-box 자르기는 cap 이면 한글 획이 2 넘치고 text 면 2 남는다 · 한 줄에 버튼과 같이 있을 때는 32 줄 가운데라 그대로) */
.card:has(.roster) { container-type: inline-size; }
@container (max-width: 340.9px) { .card:has(.roster) > .card-head h3 { line-height: 16px; } }
/* 수업 화면 머리 버튼 셋(오늘 회차 만들기 · 수업 설정 · 학기 마무리)은 폰 375 이상에서 한 줄(2026-09-26 대표 메모 · 390 기준)
   sm 32 그대로 · 좌우 여백 12 → 10 · 아이콘 사이 6 → 4 · 버튼 사이 8 → 6 · 360 이하는 두 줄로 감긴다 */
@media (max-width: 599px) {
  .page-head .cls-acts { gap: 6px; }
  .cls-acts .btn.sm { padding: 0 10px; gap: var(--space-1); }
}
/* W412 critic3 11: 머리 단추 셋은 '잉크' 간격을 같게 · 마지막 '학기 마무리' 글자 끝 = 카드 오른쪽 끝
   유령 단추는 면이 거의 안 보여 글자가 기준 → 채움 단추 뒤에 유령 안여백만큼 더 띄우고, 마지막 단추는 안여백만큼 오른쪽으로 내민다 */
/* 제목이 길어 단추 줄이 아랫줄로 내려가도(폰·좁은 PC) 오른쪽 끝에 붙는다 */
.page-head .cls-acts { margin-left: auto; }
.page-head .cls-acts > :first-child { margin-right: var(--space-3); }
.page-head .cls-acts > :last-child { margin-right: calc(-1 * var(--space-3)); }
@media (max-width: 599px) {
  /* 폰: 유령 안여백이 10이라 10(4의 배수 아님 · 위 폰 안여백 10을 따름) · 양 끝 벌리기는 430 이상에서 간격이 64까지 벌어져 안 씀 */
  .page-head .cls-acts > :first-child { margin-right: 10px; } /* token-ok */
  .page-head .cls-acts > :last-child { margin-right: -10px; } /* token-ok */
}
/* 공지 목록 한 항목(2026-09-27 D 구조 2차 ntc2=A · 3차 menu3=A)
   날짜·시각 · 게시 위치(글자 · 11.5/18) / 제목 한 줄(20) / PC 본문 한 줄(13 · ink-3) · 오른쪽 ⋯ 하나(행 세로 가운데) · 앞 아이콘은 폰 제목 줄 · PC 행 가운데 */
.ntc .main { display: flex; flex-direction: column; }
.ntc a.main, .ntc a.ntc-dt { color: inherit; }   /* 행을 눌러 공지 보기(/notices/<id> · master F4 #7) · 링크 색 대신 원래 글자 색 · 마우스를 올리면 제목에만 밑줄 */
@media (hover: hover) { .ntc a.main:hover, .ntc a.ntc-dt:hover { text-decoration: none; } .ntc a.main:hover .title { text-decoration: underline; } }
.ntc-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }   /* 날짜 → 제목 2 */
.ntc .meta { font-size: var(--fs-2xs); line-height: 18px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 11.5px(--fs-2xs · 2026-09-26 서체 체계 v2) */
.ntc-upd::before { content: "·"; display: inline-block; width: 12px; text-align: center; }   /* 구분점은 글자가 아니라 부품으로(.seps 와 같은 방식 · 2026-09-30 실장 A3) */
.ntc .title { display: block; line-height: 20px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 날짜 줄 18 · 제목 20(옛 16 · 22 · 행 높이 같음): 글 묶음 잉크가 위 선·아래 선에서 같은 거리(2026-09-27 정렬 수정 · 폰 −0.33 · PC 0 계측) */
.ntc-pv { font-size: var(--fs-sm); line-height: 20px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 행 앞 = 날짜·시각 칸(아이콘 자리 · 폭 72 · 왼쪽 맞춤 · '9.26 (토)' 13/19 600 ink-2 / '오전 3:54' 12/18 ink-3)
   제목 위 줄에서는 날짜·시각을 빼고 게시 위치만(2026-09-27 B 체계 7 N1 · PC) · 폰도 같은 칸(2026-09-27 B sp3 p1 구조 ·
   날짜 칸 폭 max-content·게시 위치 꼬리표 모양은 다음 판 대표 확인 뒤라 폭 72 · 글자 그대로) */
.ntc > svg.lead, .ntc .ntc-when { display: none; }
.ntc-dt { flex: none; width: 66px; display: flex; flex-direction: column; gap: 2px; }   /* 72 → 65(2026-09-28 sp4 dcol · 가장 긴 '12.28 (수)'·'오후 12:00' 과 제목 사이 약 20) */
/* 게시 위치 꼬리표(2026-09-28 sp4 S2) · 18 · 좌우 6 · 반경 6 · bg 면 · 12/500 ink-3 · 길면 꼬리표 안에서 말줄임
   (줄 18 · 글자 기준선 = 줄 가운데 · 말줄임은 안쪽 이름 .nm 에 걸어 inline-flex 로(2026-09-28 4i-2 · 옛 inline-block 은 꼬리표째 말줄임)) */
.ntc-txt .meta .ntc-where { display: inline-flex; vertical-align: top; height: 18px; max-width: 100%; padding: 0 6px; border-radius: var(--r-tag); background: var(--wb, var(--wb-d, var(--bg)));
  font-size: var(--fs-xs); font-weight: 500; line-height: 18px; color: var(--wf, var(--ink-3)); white-space: nowrap; }
/* 띠 색(2026-09-26 대표 dot3 '게시 위치를 옅은 색의 띠로 · 수업이면 그 수업 지정된 색 · 전체라면 키컬러 변형' · 구조 4차 scope = A)
   수업 = 그 수업 색 |tint 면 · |tink 글자(인라인 --wb·--wf) · 전체 = navy-100 · navy-800 · 비공개 = 회색 그대로 */
.ntc-where.all { --wb: var(--navy-100); --wf: var(--navy-800); }
/* 대상이 여럿이면 '첫 대상 외 n'(2026-09-28 4i-2 실장 A4 · 옛 '고2 통합사회 A, …' 가 꼬리표 안에서 잘렸다) · 말줄임은 첫 대상 이름에만 · '외 n'은 늘 보인다 · 사이 = 붙는 빈칸 한 칸(&nbsp; · flex 는 보통 빈칸을 지운다) */
.ntc-where .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ntc-where .more { flex: none; }
.ntc-where .more:empty { display: none; }
.ntc-dt b { font-size: var(--fs-sm); line-height: 20px; font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.ntc-dt span { font-size: var(--fs-xs); line-height: 18px; color: var(--ink-3); white-space: nowrap; }
/* 폰 글 묶음(sp3 p1) = 제목 한 줄 전체 / 둘째 줄 게시 위치 · 본문 미리보기(남는 폭 · 줄임표) · 두 글자 크기는 기준선 맞춤 */
@media (max-width: 839px) {
  .ntc-txt { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px 0; align-items: baseline; }   /* 칸 사이 0 · PC 의 gap 2 가 남으면 '·' 앞 8 · 뒤 6 으로 어긋난다(2026-09-28) */
  .ntc .title { grid-row: 1; grid-column: 1 / -1; }
  /* 둘째 줄 말줄임은 하나만(2026-09-28 4i-2 실장 A4 · 옛 최대 96 이라 '고2 통합사회 A…' + 미리보기 '…' 두 번):
     게시 위치 꼬리표는 제 폭 그대로(넘치면 첫 대상 이름만 말줄임) · '· n월 n일 수정'은 폰에서 뺀다 · 미리보기는 남는 폭이 12자(12em)보다 좁으면 숨긴다 */
  .ntc .meta { grid-row: 2; grid-column: 1; text-overflow: clip; align-self: start; }   /* 꼬리표 글자가 baseline 정렬 기준 아래로 처지던 것 보정(2026-09-30 실장 A2) */
  .ntc .meta .ntc-upd { display: none; }
  /* 같은 줄 시각 글자 잉크 아래 = 게시 위치 띠 아래 선(2026-09-27 대표 scope 메모 '날짜 텍스트만 내려서' · 띠는 그대로 · 계측 차 3.98 → 0) */
  .ntc-dt span { margin-top: 8px; line-height: 12px; }   /* 잉크만 4 내림 · 상자 아래는 제목 칸 아래와 같아 행 높이·넘침 그대로 */
  .ntc-pv { grid-row: 2; grid-column: 2; padding-left: 6px; container-type: inline-size; }   /* 게시 위치 꼬리표와 미리보기 사이 6(점 대신 간격 · 2026-09-28 sp4) */
}
.ntc-pv > span { display: block; overflow: hidden; text-overflow: ellipsis; }   /* 줄임표를 안쪽 글에 · 숨길 때 줄임표도 같이 숨게 */
@container (max-width: 12em) { .ntc-pv > span { visibility: hidden; } }   /* 줄 높이(19)는 남겨 행 높이가 줄마다 같게 */
/* PC 날짜 칸도 폰처럼 날짜 = 제목 줄 · 시각 = 미리보기 줄(2026-09-28 4i-2 실장 A6 · 옛 칸째 가운데라 9.8 어긋남)
   글 묶음(게시 위치 18 · 사이 2 · 제목 20 · 사이 2 · 미리보기 19)처럼 빈 줄 18 · 날짜 줄 20 = 제목 줄 · 시각 줄 18(19 로 맞추면 12px 획이 줄 가운데서 1 뜬다 · 잉크 차 0.5)
   둘 다 행 위에 붙인다 · 미리보기가 없는 공지도 행 높이는 같다 */
@media (min-width: 840px) {
  .ntc > .ntc-dt, .ntc > a.main { align-self: flex-start; }
  .ntc-dt::before { content: ""; height: 18px; }
  .ntc-dt b { line-height: 20px; }
  /* 띠 옆 'n월 n일 수정' 잉크 아래 = 띠 아래 선: 줄 높이 18 안에서 이미 같다(옛 top:4px 은 글자를 2 내려 계측 차 2.0 · 지워서 0 · 2026-10-12 W87b) */
}
/* ⋯ 메뉴 · ⋯ 32(폰 누름 44) · 점 색 ink-2 · 오른쪽 끝 = 카드 안여백 선(행 오른쪽 안여백 0 · 음수 여백 없음) · 글과 12(행 gap)
   메뉴 = ⋯ 아래 오른쪽 맞춤(아래가 모자라면 위) · 행 40 · '게시 위치 바꾸기 ›'는 같은 틀이 목록으로 바뀐다(notices.html · 200ms standard · 12px)
   맨 위 '‹ 게시 위치' 13/500 ink-3 · ‹(14) 잉크 시작 = 목록 글자 잉크 시작(안여백 12 · 글자 앞 빈칸까지 계측 차 0.2) · 지금 위치 행 navy-50 + 오른쪽 체크 */
.ntc-more { position: relative; flex: none; margin-right: -8px; }   /* 잉크 끝(상자 32 · 점 오른쪽 여백 9.4)을 구분선 끝선에(2026-10-09 비평 578) */
.more-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 0;
  border-radius: var(--r-xs); background: none; color: var(--ink-2); cursor: pointer; }
.more-btn svg { width: 20px; height: 20px; }
.more-btn[aria-expanded="true"] { background: var(--navy-50); }
@media (hover: hover) { .more-btn:hover { background: var(--navy-50); } }
.more-btn:focus-visible { outline: 4px solid var(--navy-700); outline-offset: 2px; }
.menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 30; min-width: 200px; max-width: min(280px, calc(100vw - 32px)); padding: 6px 0;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-lg); overflow: hidden; }
.menu.up { top: auto; bottom: calc(100% + 4px); }
.menu[hidden], .menu-pg[hidden] { display: none; }
.menu-pg form { display: block; }
.menu-i { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; height: 40px; padding: 0 16px; border: 0; background: none;
  color: var(--ink); font: inherit; font-size: var(--fs-md); font-weight: 500; line-height: 1; text-align: left; white-space: nowrap; cursor: pointer; }
.menu-i .l { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.menu-i.bad { color: var(--bad); }
.menu-i svg { flex: none; width: 16px; height: 16px; color: var(--ink-4); }
.menu-i[data-go] svg { margin-right: -4px; }   /* '게시 위치 바꾸기 ›' 꺾쇠는 16 칸 안 오른쪽 빈칸 5 · 잉크 오른끝 → 메뉴 안쪽 16 = 글자 시작 안여백(2026-09-27 실장 지적 7 · '외 n건 ›' 과 같은 방식) */
.menu-i[role="menuitemradio"] svg { visibility: hidden; color: var(--navy-ink); }
.menu-i[aria-checked="true"] { background: var(--navy-50); }
.menu-i[aria-checked="true"] svg { visibility: visible; }
@media (hover: hover) { .menu-i:hover { background: var(--navy-50); text-decoration: none; } }
.menu-hd { display: flex; align-items: center; gap: var(--space-1); width: 100%; height: 40px; margin-bottom: 4px; padding: 0 16px 0 12px; border: 0; border-bottom: 1px solid var(--line);
  background: none; color: var(--ink-3); font: inherit; font-size: var(--fs-sm); font-weight: 500; line-height: 1; cursor: pointer; }
.menu-hd svg { flex: none; width: 14px; height: 14px; }
@media (min-width: 840px) { .menu-i, .menu-hd { height: 36px; } }   /* 줄 높이 웹 36 · 폰 40 으로 모두 같게(2026-09-27 대표 모션 5차 menu5 = A) */
.ntc-list .item.off { display: none; }   /* 머리의 수업 선택칸이 거른 줄 */
.ntc-list .item:nth-last-child(1 of :not(.off)) { border-bottom: 0; padding-bottom: 2px; }   /* 거른 뒤 보이는 마지막 줄도 밑줄 없이
   · 카드 마지막 잉크 아래 = 제목 위(PC 24 · 23.5 · 2026-09-26 비평 10 계측 · 옛 34 · 27) · PC 마지막 잉크는 본문 미리보기 줄 */
@media (max-width: 839px) { .ntc-list .item:nth-last-child(1 of :not(.off)) { padding-bottom: 2px; } }   /* 폰 마지막 잉크는 게시 위치 띠 · 카드 아래 = 위 15.5(옛 0 → 13.0) */
.ntc-list > .item:nth-child(1 of :not(.off)) { padding-top: 4px; }   /* 묶음 머리 없이 줄로 시작하면(고정 없음 · 거른 뒤) 제목 잉크 → 첫 줄 잉크 18 = 묶음 머리로 시작할 때(sp3 · 옛 14) */
@media (max-width: 839px) {
  .more-btn::after { content: ""; position: absolute; inset: -6px; }   /* 누름 영역 44 */
}
/* 폰 공지 머리: 제목 줄 그대로 · 둘째 줄 = 부제(넘치면 줄임표) + 오른쪽 수업 선택칸(sm 32 · 누름 44) (2026-09-26 비평 12) */
@media (max-width: 839px) {
  .page-head.ntc-ph { display: block; position: relative; }   /* 선택칸을 grid 흐름에서 빼 부제 줄(19)만으로 머리 높이를 재게(2026-09-26 대표 메모 '부제 아래 공백 큼' · 선택칸이 32짜리 칸을 만들어 부제가 그 안에 뜨던 것) */
  .ntc-ph > div:first-child { display: contents; }
  .ntc-ph .sub { min-width: 0; padding-right: 172px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 오른쪽 선택칸(160 + gap 12) 자리만큼 */
  .ntc-ph .ntc-head { position: absolute; top: 50%; right: 0; transform: translateY(-50%); }   /* 부제 줄만이 아니라 제목+부제 묶음 전체의 세로 가운데(2026-09-27 대표 메모 · 옛 부제 줄 기준은 묶음 중심보다 12px 낮았다) */
  .ntc-ph .ntc-head .selbox { height: 32px; padding-left: var(--space-3); font-size: var(--fs-sm); max-width: 160px; }
  .ntc-ph .ntc-head .selbox .v { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .ntc-ph .ntc-head .selbox select { inset: -6px 0; }
}
/* 행 끝 부품은 구분선 끝(카드 안여백 선)에 맞춘다(2026-09-26 비평 8 · 행 오른쪽 안여백 4 를 뺀다) */
.list .item.ntc { padding-right: 0; }
/* 공지 묶음 머리 '고정됨'·'공지'(2026-09-26 D 모션 9) · 고정이 없으면 둘 다 .off · 다시 나타날 때 120ms 페이드 · 옮긴 줄은 navy-50 → 투명 600ms(300ms 뒤) */
/* 묶음 이름 13/19 · 700 · ink-2 · 글자 기준 앞 행 → 이름 28 · 이름 → 첫 행 8 · 카드 제목 → 첫 이름 18(2026-09-27 B sp3 l2 · 폰 padding-top 9 · PC 8) */
/* W412 critic3 6: 섹션 라벨 위·아래 여백 통일 · '공지' 라벨 위(고정 면 끝→잉크) = 아래(잉크→다음 줄 잉크) = 9.5 · '고정됨' 아래(잉크→고정 면) 9(픽셀 스냅 · 4.5로 올리면 10이 돼 4 유지)
   6·−11은 4의 배수가 아님: 라벨 줄높이 20 안 잉크 위아래 4.25 + 다음 줄 위 여백을 맞춘 값(래스터 실측) */
.ntc-grp { padding: 6px 0 0; margin-bottom: -11px; font-size: var(--fs-sm); line-height: 20px; font-weight: 700; color: var(--ink-2); }
.ntc-grp:first-child { padding-top: 4px; }
@media (max-width: 839px) { .ntc-grp { padding-top: 6px; } }
.ntc-grp.off { display: none; }
.ntc-grp.in { animation: vt-fade-in var(--dur-1) linear both; }
.ntc.ntc-land { animation: ntc-land 600ms ease-out 300ms both; }
@keyframes ntc-land { from { background-color: var(--ntc-land, var(--navy-50)); } to { background-color: var(--ntc-bg, transparent); } }
/* 고정 줄 옅은 하이라이트(2026-09-27 대표 ba4 '고정됨의 항목들에는 옅은 하이라이트 배경색' · 9/28 pin5 '고정됨이랑 저 바탕색이 겹치면 안되는게 당연')
   면은 카드 안여백까지 번진다(box-shadow · 카드 테두리 안쪽에서 멈춤) · '고정됨' 머리는 면 위로 겹치지 않게 아래 여백을 양수로 · 마지막 고정 줄은 밑줄 없음 */
.ntc-list { --ntc-bleed: 20px; }
@media (max-width: 839px) { .ntc-list { --ntc-bleed: 14px; } }
.ntc-list .ntc[data-pinned="1"] { --ntc-bg: var(--navy-50); --ntc-land: var(--navy-100); --wb-d: var(--card); background: var(--navy-50);
  box-shadow: calc(-1 * var(--ntc-bleed)) 0 0 var(--navy-50), var(--ntc-bleed) 0 0 var(--navy-50); }
.ntc-list .ntc[data-pinned="1"]:has(+ .ntc-grp) { border-bottom: 0; }
.ntc-grp[data-grp="pin"] { margin-bottom: 4px; }
/* 카드 안 제목 줄을 뺀 뒤(nhead5 = B) 첫 잉크('고정됨' 또는 첫 줄) = 카드 위 PC 20 · 폰 16(옛 제목 잉크 자리) */
.ntc-ph + .card.ntc-card { padding-top: 16px; }
.ntc-card .ntc-list > .ntc-grp:first-child { padding-top: 0; }
.ntc-card .ntc-list > .item:nth-child(1 of :not(.off)) { padding-top: 4px; }   /* 고정 없이 줄로 시작할 때(계측 21 → 20) */
@media (max-width: 839px) { .ntc-ph + .card.ntc-card { padding-top: var(--space-3); } .ntc-card .ntc-list > .item:nth-child(1 of :not(.off)) { padding-top: 0; } }   /* 폰 20 → 16 */
.avatar { width: 38px; height: 38px; border-radius: 50%; background: var(--navy-100); color: var(--navy-ink); display: grid; place-items: center; font-weight: 700; font-size: var(--fs-md); flex-shrink: 0; line-height: normal; }   /* 동그라미 안 이름 잉크 1.2px 보정 */
.avatar.sm { width: 30px; height: 30px; font-size: var(--fs-xs); }
.empty { text-align: center; padding: 36px 14px; color: var(--ink-3); }
.empty .big { font-size: 34px; margin-bottom: 8px; }
.empty .big svg { display: block; width: 40px; height: 40px; margin: 0 auto; color: var(--navy-400); }   /* 빈 화면 큰 아이콘 · 이모지 대신 (2026-09-25) */
.empty p { margin-bottom: 12px; }

/* ---------- 배지 · 필 ----------
   작은 알약 한 등급(2026-09-26 크기 규칙 A): .badge · .pill · .st · .cls-tag 모두 높이 22 · 글자 12/600 · 좌우 8 · line-height 1
   (min-height 22 · 한 줄이면 늘 22 · 화면에서 일부러 키운 큰 배지(인라인 padding)와 폰에서 줄바꿈되는 배지만 늘어난다)
   위아래 여백 0 · 위 1px 밀어내기는 뺐다(한글은 위로·숫자·영문은 아래로 어긋나 보이던 원인 · 세로 보정은 글꼴 지표로 따로 · 2026-09-26) */
.badge { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); background: var(--navy-100); color: var(--navy-ink); border-radius: var(--r-xs); min-height: 22px; padding: 0 8px; font-size: var(--fs-xs); font-weight: 600; line-height: 1; white-space: nowrap; }
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.err, .badge.bad { background: var(--bad-bg); color: var(--bad); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }
.badge.grade { background: var(--navy-fill); color: #fff; }
/* 개수 띠 한 규격(2026-10-12 대표 W105 e): 높이 18 · 12/600 · 숫자 --ink · tabular · 노랑 면은 --accent-y-lt · 시험 허브 '문제은행' 옆 숫자(.badge.cnt) · 폰 메뉴 · 사이드바 · 학생 '해야 할 일'(student.css) 가 같은 규격
   탭 줄 .tabs .cnt 는 면이 없는 글자 숫자라 띠가 아니다 · 탭바 .cnt 는 크기만 아이콘 위 배지로 10px · 상단 인원 판 .cnt-plate 는 인원 표시(20)라 별도 */
.badge.cnt { box-sizing: border-box; height: 18px; min-height: 18px; padding: 0 6px; border-radius: var(--r-xs); color: var(--ink); font-size: var(--fs-xs); font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.nav .cnt, .menu-list .title .badge { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 16px; min-height: 16px; min-width: 16px; padding: 0 var(--space-1); border-radius: var(--r-tag); color: var(--ink); font-size: var(--fs-2xs); font-weight: 700; line-height: 12px; font-variant-numeric: tabular-nums; }   /* 노란 개수 배지 한 규격(2026-10-13 대표 W199 · 16 · 700 11.5/12 · 반경 6) */
/* 학기 꼬리표는 기본 .badge(navy-100 면 + navy-ink 글자) 그대로(v1 모양 · 2026-09-26 대표 메모 "v1이 더 예쁨" · 선만은 폐기) */
.pill { display: inline-flex; align-items: center; gap: var(--space-1); border-radius: var(--r-pill); min-height: 22px; padding: 0 8px; font-size: var(--fs-xs); margin: 2px 4px 2px 0; font-weight: 600; white-space: nowrap; line-height: 1; }
@media (min-resolution: 3dppx) { .pill { padding-top: calc(2px / 3); vertical-align: calc(-1px / 3); } td .pill { vertical-align: calc(1.5px - 1px / 3); } }   /* 폰(3배 화면)에서만 알약 글자 1/3px 내림: 진짜 3배에서 12px 글자 잉크가 1기기px 뜨던 것(경계차 -2 → 0) · 높이 22 그대로(border-box) · 글줄 안 알약은 기준선이 1/3 내려간 만큼 vertical-align 으로 되돌려 상자 자리는 그대로 · 배지·꼬리표는 그대로 · 2026-10-16 대표 W70 '폰에서만 알약 1/3px 내림'(witty-design '글자를 밀지 않는다'의 예외) */
.pill.good { background: var(--ok-bg); color: var(--ok); }
.pill.mid { background: var(--warn-bg); color: var(--warn); }
.pill.bad { background: var(--bad-bg); color: var(--bad); font-weight: 700; }
.pill.vid { background: var(--vid-bg); color: var(--vid); }
.pill.plain { background: var(--navy-50); color: var(--ink-2); }
.cls-tag { display: inline-flex; align-items: center; gap: 4px; background: var(--navy-100); color: var(--navy-ink);
  border-radius: var(--r-xs); min-height: 22px; padding: 0 8px; font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; line-height: 1; }
.cls-tag::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--c, currentColor); flex-shrink: 0; }
.item .title .cls-tag { white-space: normal; max-width: 100%; line-height: 1.3; padding-block: 3px; }   /* 긴 수업 이름은 칩 안에서 줄바꿈(375 넘침 · 수납 명단) */
.cls-tag.lead { margin-right: 6px; }   /* 칩 뒤에 공백으로 글이 바로 이어지는 부제(출석부·주차·영상 진도)만 · 잉크 간격 3.5→9.5 · 칩 뒤 가운데점 화면은 그대로(2026-09-29 D3 대표 메모 '붙어 답답함') */
.cls-dot { display: inline-block; width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.st { display: inline-flex; align-items: center; gap: var(--space-1); border-radius: var(--r-tag); min-height: 22px; padding: 0 8px; font-size: var(--fs-xs); font-weight: 600; line-height: 1; }   /* 꼬리표 반경 6(2026-10-10 대표 E2 · 배지·cls-tag는 그대로 8) */
.st-출석, .st-good { background: var(--ok-bg); color: var(--ok); }
.st-mid { background: var(--warn-bg); color: var(--warn); }
.st-bad { background: var(--bad-bg); color: var(--bad); }
.st-info { background: var(--info-bg); color: var(--info); }   /* 홈 '오늘 이어서' 시험 표시 */
.st-지각, .st-조퇴 { background: var(--warn-bg); color: var(--warn); }
.st-결석 { background: var(--bad-bg); color: var(--bad); }
.st-영상 { background: var(--vid-bg); color: var(--vid); }
.st-none { background: var(--navy-50); color: var(--ink-3); font-weight: 500; }
/* 응시 현황·주차(제출·통과·재시험 칩): 글자 잉크가 칩 상자보다 0.8px 위로 뜬다 · 자리는 그대로, 그림만 살짝 내린다
   (vertical-align 숫자 보정은 줄 높이 계산에 끼어 폭마다 결과가 달라졌다 · transform 은 배치에 영향이 없어 폭·행에 걸쳐 안정적, 2026-09-26 재계측) */
.st-meta .st { transform: translateY(0.5px); }
.warn { color: var(--bad); font-weight: 700; }
.muted { color: var(--ink-3); }
.small { font-size: var(--fs-xs); }
.pt-u { margin-left: .1em; }   /* 점수 숫자와 뒤 '점' 사이 .1em · 줄 끝에서 갈리지 않게 앞에 붙임 글자(2026-09-28 5판 대표 결정) */
.pt-u::before { content: "\2060"; }
.mono { font-family: ui-monospace, "JetBrains Mono", Consolas, "SF Mono", monospace; letter-spacing: 1.5px; font-variant-numeric: tabular-nums; }
.up { color: var(--ok); font-weight: 700; font-size: var(--fs-xs); margin-left: 4px; }
.down { color: var(--bad); font-weight: 700; font-size: var(--fs-xs); margin-left: 4px; }
.kbd { font-family: inherit; background: var(--navy-50); border: 1px solid var(--line-2); border-radius: 6px; padding: 0 6px; font-size: var(--fs-xs); font-weight: 600; color: var(--navy-ink); white-space: nowrap; }

/* ---------- 알림 · 배너 ---------- */
.toasts { position: fixed; top: 16px; right: 16px; z-index: 100; display: flex; flex-direction: column; gap: 8px; max-width: min(420px, calc(100vw - 32px)); }
.toast { background: var(--navy-fill); color: #fff; border-radius: var(--r-sm); padding: 8px 16px; min-height: 40px; font-weight: 600; font-size: var(--fs-md); box-shadow: var(--shadow-lg); display: flex; gap: 10px; align-items: center; animation: toastin 260ms var(--ease-standard); }   /* 한 줄일 때 버튼 기본 높이(40)와 맞춘다 · 안여백 9는 글자 잉크가 가운데 오는 값(2026-09-26 대표 메모) · 두 줄이면 자연히 늘어난다 · 들어옴 260ms(모션 10) · 나감은 app.js closeToast(120ms 페이드 → 남은 알림 200ms 이동) */
.toast::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--navy-400); }   /* 상태 점 · 왼쪽 띠 대신 (2026-09-25) */
.toast.err::before { background: var(--bad-soft); } /* 네이비 면 위라 밝은 값 */
.toast.ok::before { background: var(--ok-soft); }
.pay-all-row { padding: 6px 4px 8px; border-bottom: 1px solid var(--line); font-size: var(--fs-sm); color: var(--ink-3); }   /* 수납 '전체 선택' 줄(W9 K3) */
.item .selbox.off input { visibility: hidden; }   /* 납부할 게 없는 줄은 체크칸 자리만 둔다(제목 시작선 유지) */
#pay-bulk[hidden] { display: none; }   /* 수납 바닥 바 · 선택이 있을 때만 */
#pay-bulk b { font-size: var(--fs-lg); }
.toast .undo { margin: 0 0 0 auto; }   /* 지운 직후 되돌리기(W9 F0-3) · 닫기 × 앞 */
.toast .undo button { background: none; border: 0; padding: 4px 6px; color: inherit; font: inherit; font-weight: 600; text-decoration: none; position: relative; cursor: pointer; }   /* 밑줄은 올려 볼 때만(K 건 4) */
@media (hover: hover) { .toast .undo button:hover { text-decoration: underline; text-underline-offset: 2px; } }
.toast .undo + .x { margin-left: 0; }
.toast .x { margin: -4px -6px -4px auto; padding: 4px 6px; min-width: 28px; cursor: pointer; opacity: .6; background: none; border: 0; color: #fff; font-size: 16px; line-height: 1; }
@keyframes toastin { from { opacity: 0; transform: translateY(-8px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes toastin-up { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.banner { padding: 12px 14px; border-radius: var(--r-sm); margin-bottom: 14px; font-size: var(--fs-sm); display: flex; gap: 10px; align-items: center; line-height: 20px; }
.banner.test { background: var(--warn-bg); border: 1px solid var(--line-2); color: var(--warn); }
.banner.live { background: var(--bad-bg); border: 1px solid var(--line-2); color: var(--bad); }
.banner.info { background: var(--info-bg); border: 1px solid var(--line-2); color: var(--info); }
/* W412 critic3 7: 새 회차 안내 띠는 카드 규격(반경·그림자 = .card · 직각 아님) · 글자 시작 x = 카드 안여백(PC 20 · 폰은 띠 14 = 카드 14 그대로) */
.banner.ses-new { border-radius: var(--radius); box-shadow: var(--shadow); }
@media (min-width: 840px) { .banner.ses-new { padding-inline: var(--space-5); } }
.banner.pend { flex-wrap: wrap; }   /* 보관 명단 띠: 좁은 폭에서 버튼 줄이 아래로 내려오게(W92 · 375 가로 넘침) */
.banner.ok { background: var(--ok-bg); border: 1px solid var(--line-2); color: var(--ok); }
/* flash 와 같은 이름의 변형 — 구독 안내 띠(체험 종료 D-7 · 미납)가 쓴다 (2026-09-19) */
.banner.warn { background: var(--warn-bg); border: 1px solid var(--line-2); color: var(--warn); }
.banner.err { background: var(--bad-bg); border: 1px solid var(--line-2); color: var(--bad); }
.banner.warn .btn, .banner.err .btn { margin-left: auto; }

/* ---------- 탭 ---------- */
/* 밑줄은 상자 안 테두리 대신 겹쳐 그린다(바닥 선 = 안쪽 그림자 · 선택 밑줄 = ::after) → 글자가 탭 높이 36(폰도 36 · 누름 영역만 44) 전체의 가운데
   (2026-09-26 대표 메모 '탭 글자가 살짝 높다' → 40에서 36으로 줄여 글자↔밑줄 간격을 좁혔다 · 밑줄은 계속 탭 줄 바닥 선에 붙는다) */
.tabs { display: flex; gap: 2px; box-shadow: inset 0 -2px 0 var(--line); margin-bottom: 16px; overflow-x: auto; }
.tabs a { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: 0 14px; height: 36px; font-weight: 600; color: var(--ink-3); white-space: nowrap; font-size: var(--fs-md); line-height: 18px; transition: color var(--dur-2) var(--ease-standard); }   /* 글자 상자 18(정수) → 36 칸 안 위치가 늘 9 · line-height normal(17.4)은 탭 줄이 정수 y 에 오면 글자가 0.8 위로 떴다(2026-09-26 v8 계측) */
.tabs a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: transparent; transition: background-color var(--dur-2) var(--ease-standard); }
@media (hover: hover) { .tabs a:hover { color: var(--ink); text-decoration: none; } }
.tabs a.on { color: var(--navy-ink); }
.tabs a.on::after { background: var(--navy-ink); view-transition-name: tab-ink; }
.tabs .cnt { font-size: var(--fs-xs); color: var(--ink-3); font-weight: 600; line-height: 18px; }   /* 탭 글자(15)보다 작은 12 개수는 가운데 맞춤이면 글줄 바닥이 2 높다 → 안여백 위 4 로 글자만 2 내려 아래선을 맞춘다(W331 · 밀지 않고 안여백으로) */   /* 줄높이 정수 = 탭 줄높이(옛 normal 은 소수라 3배 화면 잉크 +0.5px · 2026-10-10 대표 Z5 확장) */

/* ---------- 그래프류 ---------- */
.bar { position: relative; background: var(--navy-50); border-radius: 6px; height: 20px; min-width: 110px; overflow: hidden; }
.bar .fill { height: 100%; background: var(--navy-400); border-radius: 6px; }
.bar .fill.bad { background: var(--bad-soft); }
.bar .fill.ok { background: var(--ok-soft); }
.bar span { position: absolute; left: 8px; top: 2px; font-size: var(--fs-xs); font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.spark { width: 90px; height: 26px; vertical-align: middle; }   /* 글자 기준선에 매달려 칸 안에서 2px 위로 뜨던 것 보정 */
.spark polyline { fill: none; stroke: var(--navy-500); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.spark.big { width: 130px; height: 30px; vertical-align: middle; margin-left: var(--space-2); }
.dist { display: flex; align-items: flex-end; gap: 10px; margin: 6px 0 14px; }
.dist-col { text-align: center; width: 46px; }
.dist-bar { background: var(--navy-400); border-radius: 6px 6px 0 0; margin: 0 6px; }
.dist-cnt { font-size: var(--fs-xs); font-weight: 700; color: var(--ink-2); height: 16px; line-height: 16px; font-variant-numeric: tabular-nums; }
.dist-lbl { font-size: 11px; color: var(--ink-3); border-top: 2px solid var(--line-2); padding-top: 4px; line-height: 16px; }
.choice { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-2xs); color: var(--ink-3); margin-right: 6px; line-height: 16px; }
.choice b { color: var(--ink); }
.choice.ans b { color: var(--ok); }
.choice .cb { display: inline-block; height: 8px; background: var(--navy-200); border-radius: 2px; vertical-align: middle; }
.choice.ans .cb { background: var(--ok); }

/* ---------- 홈 (2026-09-25 홈 최종안 · 대표 확정 · 정본 design/specimens/2026-09-24/final · 값은 생성기 gen.py) ----------
   날짜 바(날짜 · 학생 수 막대 · 네이비 그라데이션 + 그레인) → PC 2열(다음 수업 | 확인할 일 · 이번 주 보드 | 다가오는 시험 · 오른쪽 352 · 첫 줄 292)
   폰(≤599) 날짜 바 → 다음 수업 → 확인할 일 → 날짜 띠 → 시험 · 분할(600–839) 한 열(가운데 560, 보드) · 한 화면(PC 1280×680 · 폰 402×874)이 목표
   면 = 흰 카드(반경 --r-card 12 · 테두리·그림자 없음) on navy-50 · 날짜 바 반경 --r-lg 20 · 글자는 Seed 단계, 줄높이는 하프 리딩 정수
   (12/16 13/19 14/20 16/22 18/24 20/26 22/28 26/32 · 2026-09-27 B 간격·글자 체계 1차 줄높이 표 · 작은 글씨는 그대로) · 날짜·반 이름만 제목 서체(--font-head = 본문 Wanted Sans, 2026-09-26 서체 체계 v2)
   카드 위아래(B 체계 3): 카드 가장자리 ↔ 첫·마지막 잉크 폰 16 · PC 20(위 = 아래) · 제목 잉크 ↔ 첫 항목 잉크 18(2026-09-27 sp3 · 옛 14 · 다음 수업 꼬리표 → 이름은 14 그대로) · 가로 안여백은 그대로 · 값은 잉크 계측(2배 촬영)
   노랑(--accent-y)은 채움·점·막대로만: 학생 수 막대 · 답변 대기 점 · 손톱 없음 · 그라데이션은 날짜 바 하나 · 오늘 표시는 네이비 꼬리표(2026-09-25 대표 선택) */
body:has(main.main-home) { background: var(--navy-50); }
.home { container: home / inline-size; display: flex; flex-direction: column; gap: 12px; }
@media (hover: hover) { .home a:hover { text-decoration: none; } }

/* 날짜 바 · 네이비 그라데이션 + 옅은 그레인(2026-09-25 대표 선택 Dc · 폰·분할·PC 같은 방향) · 폰 53(안여백 16 · 2026-09-26 대표 메모 '살짝 줄이고' · 52는 배율 2·3 에서 잉크 −0.75·−0.83 이라 상단바와 같은 53) · PC 64(24) · 좁으면 막대가 줄어들다 사라진다 */
.h-bar { container: hbar / inline-size; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  height: 52px; padding: 0 20px; background: var(--grain), var(--grad-bar); border-radius: var(--radius); }   /* 좌우 안여백 16→20(2026-09-27 대표 메모 '여백 조금 좁아') */
.h-bar h1 { flex: none; margin: 0; font-family: var(--font-head); font-size: var(--fs-lg); line-height: 22px; font-weight: 600; color: var(--on-navy); white-space: nowrap; }   /* 폰·분할 16/600(2026-09-26 서체 체계 v2 · 바 56→53) · PC 20/700 은 아래 */
.h-qta { flex: 0 1 auto; margin-left: auto; display: flex; align-items: center; gap: var(--space-1); align-self: stretch; min-width: 0;
  font-size: var(--fs-sm); line-height: 20px; font-weight: 500; color: var(--on-navy-2); white-space: nowrap; }   /* 사람 아이콘 + 숫자만(2026-09-28 대표) · 폰·분할 13 · PC 14 는 아래 */
.h-qta b { font-weight: 600; color: var(--on-navy); }   /* 폰·분할 600 · PC 700 은 아래 */
.h-qta svg { flex: none; width: 16px; height: 16px; }
.h-qta.full b { color: var(--bad-soft); }   /* 상한이 찼을 때 옛 막대 붉은색을 숫자 색으로 */
@media (hover: hover) { .h-qta:hover { color: var(--on-navy); } }

/* 플랜 이름표(2026-09-28 대표) · 알약 22 · 12/600 · 폰은 상단바 종 왼쪽, PC 는 홈 날짜 바·다른 화면 맨 위 줄의 종 왼쪽 · 누름 영역 44 는 ::after */
.plan-badge { position: relative; flex: none; display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border: 0; border-radius: 999px;
  background: var(--navy-100); color: var(--navy-900); font-size: var(--fs-xs); line-height: 16px; font-weight: 600; white-space: nowrap; }   /* 밝은 바탕에서 캡슐이 묻히지 않게 navy-100(실장 비평 3) */
a.plan-badge::after { content: ""; position: absolute; inset: -10px -4px; }
a.plan-badge { transition: background-color var(--dur-1) linear; }
@media (hover: hover) { a.plan-badge:hover { background: var(--navy-200); } }
/* 네이비 위(홈 날짜 바·폰 상단바): 흰 16% 판 + 흰 글자 · 날짜보다 튀지 않게 · 학생 수와 떨어뜨리고 종 쪽에 묶음(실장 비평 1·2) */
.h-bar .plan-badge { margin-left: var(--space-2); margin-right: -8px; background: var(--on-navy-track); color: var(--on-navy); }
@media (hover: hover) { .h-bar a.plan-badge:hover { background: var(--on-navy-track); color: var(--on-navy-2); } }
.mtop .plan-badge { margin-left: auto; }
.mtop .plan-badge + .bell { margin-left: 0; }
@media (max-width: 839px) { .h-bar .plan-badge { display: none; } }

/* 폰(≤599) 주간 날짜 띠 · 확인할 일 아래 · 흰 카드(.h-days) 안(2026-09-26 대표 메모)
   오늘 = PC 보드와 같은 방향(2026-09-25 대표 지시 '모바일도 웹과 같은 방향'): 칸 옅은 면(바탕보다 한 단계 진한 navy-100 · 배치에 영향 없게 가상 요소)
   + 날짜 네이비 꼬리표 30×24·흰 글자 + 요일 굵게 */
.h-strip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.h-sd { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); min-width: 0; color: var(--ink-3); }
.h-sd .wd { font-size: var(--fs-xs); line-height: 16px; font-weight: 500; }
.h-sd .dn { display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: var(--r-pill);
  font-size: var(--fs-base); line-height: 20px; font-weight: 500; color: var(--ink-2); }
.h-sd.past .dn { color: var(--ink-3); }
.h-sd.today { position: relative; isolation: isolate; }
.h-sd.today::before { content: ""; position: absolute; inset: -2px 2px; z-index: -1; border-radius: var(--r-card); background: var(--navy-100); }
.card.h-card.h-days { padding: 18px 16px; }   /* 오늘 칸 면(위아래 2 내밈)이 첫·마지막 잉크 → 카드 위·아래 16 = 다른 카드 안여백(2026-09-26 비평 10 · 옛 12) */
.h-sd.today .wd { font-weight: 700; color: var(--navy-900); }
.h-sd.today .dn { width: 30px; height: 24px; border-radius: var(--r-tag); background: var(--navy-fill); font-weight: 700; color: var(--on-navy); }   /* 높이 24 = 다른 날 원 24(누를 때만 보이는 원 · 카드 안으로 들어가며 폰 한 화면 예산 4px 회수, 2026-09-26) · 점 줄이 같은 높이에 */
.h-sd .dots { display: flex; gap: 2px; height: 6px; margin-top: 2px; }
.h-sd .dots i { width: 6px; height: 6px; border-radius: var(--r-pill); }
@media (hover: hover) { .h-sd:not(.today):hover .dn { background: var(--navy-100); } }

/* 카드 · 기존 .card 에서 테두리·그림자·아래 여백을 뺀 홈 면 */
.h-grid { display: flex; flex-direction: column; gap: 12px; }
.h-col { display: contents; }   /* 폰·좁은 PC: 열 묶음을 풀어 카드가 .h-grid 한 줄에 · 순서는 order */
.h-next { order: 1; } .h-todo { order: 2; } .h-days, .h-week { order: 3; } .h-exams { order: 4; }
.card.h-card { display: flex; flex-direction: column; min-width: 0; min-height: 0; margin: 0; padding: 16px;
  border: 0; border-radius: var(--radius); box-shadow: none; }
.card.h-todo, .card.h-exams, .card.h-week { padding-top: 12px; }   /* 제목 글자로 시작하는 카드 · 제목 잉크 위 16(26 줄 안 16/22 글자 · 꼬리표로 시작하는 다음 수업은 16 그대로) */
.h-ch { flex: none; display: flex; align-items: center; height: 26px; }   /* 제목 왼쪽 · '외 n건'은 margin-left:auto 로 오른쪽 끝 · 폰·PC 26 = '다음 수업' 꼬리표 높이(네 카드 제목 줄이 같다) */
.h-ch h2 { margin: 0 var(--space-3) 0 0; font-size: var(--fs-lg); line-height: 22px; font-weight: 700; color: var(--ink); }   /* 카드 제목 16/22 · 700 · ink(폰·PC 같게 · 2026-09-27 B 체계 2) */
/* '다음 수업' 제목만 네이비 꼬리표(2026-09-25 대표 선택 Na · 반경은 줄여 --r-tag)
   옅은 네이비 면 + 네이비 글자(2026-09-26 대표 메모 '다음 수업 버튼과 출석부 버튼 색이 똑같은게 맘에 안듦' · 채움은 누르는 출석부만) */
.h-next .h-ch h2 { display: inline-flex; align-items: center; height: 26px; padding: 0 10px; border-radius: var(--r-tag);
  background: var(--navy-100); color: var(--navy-ink); font-size: var(--fs-base); font-weight: 600; line-height: 1; }   /* 꼬리표 26 · 글자 14/600(B 체계 2) · 위아래 여백 0(1px 밀어내기 없음 · 2026-09-26) */
/* '외 n건 ›' · 폰 구조는 누르는 영역 44(위아래로 내민다) · 꺾쇠 안쪽 빈칸만큼 오른쪽으로 내어 글자 끝선을 카드 안여백에 맞춘다
   확인할 일은 details(누르면 접어 둔 줄을 그 자리에서 펼침 · 다시 누르면 접기) · 시험은 학교 시험 일정 링크 */
.h-fold { display: contents; }   /* details 상자는 크롬에서 요약 줄 아래로 한 줄을 더 잡는다 · 요약(summary)이 바로 제목 줄 칸이 되게 */
.h-fold::details-content { display: none; }   /* 펼칠 내용은 카드 목록에 있다 · 빈 내용 칸이 제목 줄 flex 칸으로 끼지 않게 */
.h-more { flex: none; display: flex; align-items: center; gap: 2px; height: 44px; margin: -8px -4px -8px auto; cursor: pointer; list-style: none;
  font-size: var(--fs-sm); line-height: 22px; font-weight: 500; color: var(--ink-2); }   /* 줄높이 22 = 짝수 44 칸 가운데라 글자 윗선이 정수 · 제목(16/22)과 잉크 가운데가 1px 안(2026-10-12 W105 · 홀수 19 는 1.17 어긋남) */
.h-more::-webkit-details-marker { display: none; }
.h-more svg { width: 16px; height: 16px; color: var(--ink-4); transition: transform var(--dur-2) var(--ease-standard); }
.h-more .cl { display: none; }
.h-card:has(.h-fold[open]) .h-more .cnt { display: none; }
.h-card:has(.h-fold[open]) .h-more .cl { display: inline; }
.h-card:has(.h-fold[open]) .h-more svg { transform: rotate(-90deg); }
@media (hover: hover) { .h-more:hover { color: var(--ink); } }
.h-list { display: flex; flex-direction: column; }   /* 제목 → 첫 줄 간격(margin-top)은 카드·폭마다 아래 미디어에서(행 높이가 달라 위 반여백을 음수로 흡수 · B 체계 4) */
.h-none { margin: 4px 0 0; font-size: var(--fs-base); line-height: 20px; color: var(--ink-3); }   /* '… 없음' · 제목 잉크 → 글자 잉크 14(B 체계 4) */
/* 카드 아래 여백 = 위 여백(글자 잉크 기준 ±1 · 2026-09-26 대표 메모 '아래 공백이 더 큰 것도 상하 정렬 안 맞는 것')
   마지막 줄이 높은 행(44·32)이면 글자 아래 행 안 빈칸만큼 카드 아래 안여백을 줄인다 · 폰(<840) 값 · PC 는 아래 ≥840 */
.card.h-card:has(> .h-list:last-child) { padding-bottom: 4px; }   /* 행 44 · 글자 아래 13.5 → 16 + 13.5 를 위(17.5)와 같게 */
.card.h-todo:has(> .h-list:last-child) { padding-bottom: 4px; }    /* 폰 계측(2026-09-27 B 체계 3): 행 44 마지막 잉크 아래 16 = 위 16 */
.card.h-exams:has(> .h-list:last-child) { padding-bottom: 4px; }   /* D-n 배지 22 가 마지막 잉크 · 아래 16 = 위 16 */
.card.h-card:has(> .h-none:last-child) { padding-bottom: 12px; }   /* '… 없음' 한 줄 · 글자 아래 16.5 · 위 16 */
.card.h-week { padding-bottom: 16px; }                              /* 분할(600–839) 보드 · 마지막 잉크 = 보드 아래 끝(칸 사이 선 끝 · 오늘 칸 면이 가장 길면 면 끝) → 아래 16(PC 20 · 2026-09-28 5판 실장 2차 5 · 옛 28 은 면이 12 내밀던 때) */
.card.h-next:has(.h-later) { padding-bottom: 8px; }                /* '오늘 이어서' 행 32 · 글자 아래 16.5 = 구분선→글자 16.5 = 위 꼬리표 16(비평 7·10) */
.h-next .h-prep:last-child .h-pc { padding-bottom: 4px; }          /* 준비 3칸으로 끝나면(오늘 이어서 없음) 값 줄 아래를 줄여 위 21 과 같게(폰·PC 같은 4) */
.h-dot { flex: none; width: 8px; height: 8px; border-radius: var(--r-pill); }

/* 다음 수업 · 점(10)은 안여백 시작선에, 이름은 점 뒤 10 · 시각·준비 칸은 점 왼쪽 시작선에 */
.h-nx { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 10px; }   /* 꼬리표 아래 → 이름 잉크 14(B 체계 4 · 폰은 아래 미디어) */
.h-next .h-nx:has(> .h-nx-none) { margin-top: 14px; }   /* 수업 없음 · 첫 잉크가 버튼 위 변 → 꼬리표와 14 */
.h-nx-t { display: flex; flex-direction: column; gap: 2px; min-width: 0; }   /* 이름 28 + 1 + 시각 18 (줄높이는 하프 리딩 정수로 · 22/28 B 체계 1) */
.h-nx-n { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0;   /* 점-이름 간격 10→8(2026-09-26 대표 메모) */
  font-family: var(--font-head); font-size: var(--fs-2xl); line-height: 28px; font-weight: 700; color: var(--ink); }
.h-nx-n .h-dot { width: 10px; height: 10px; }
.h-nx-n .tx { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-nx-w { font-size: var(--fs-base); line-height: 18px; font-weight: 500; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* 시각 뒤 학원명(master 학원명 · 2026-09-27)이 길면 한 줄에서 말줄임(폭 320 넘침 방지) */
.h-nx-none { margin: 0; font-size: var(--fs-base); line-height: 20px; color: var(--ink-3); }
.btn.h-go { flex: none; gap: 8px; height: 40px; padding: 0 16px; border: 0; border-radius: 10px; font-size: var(--fs-base); font-weight: 700; box-shadow: none; }   /* 기본 40 · 14/700 · 반경 10(폰·PC 같음 · 2026-09-26 대표 메모 '아이콘만 고치면 되는데 크기는 왜 늘어나') · 폰 누름 영역 44 는 .btn::after */
.btn.h-go svg { width: 18px; height: 18px; }
.h-gos .btn.h-go:not(.h-ex) { min-width: 95px; justify-content: center; }   /* 출석부 칸(.h-gos 안만)을 정수 폭으로(글자 36.31 → 폭 94.31 이라 왼쪽 변이 3배 기기 픽셀 밖 · 2026-10-18 W202 P2 반점) · 수업 없음 칸의 수업 보기·첫 수업 만들기는 그대로 */
.h-go-f { flex: none; margin: 0; }
.h-gos { flex: none; display: flex; align-items: center; gap: 8px; }   /* 출석부 · 시험(그 회차에 시험이 있을 때만 · 2026-09-27 D 구조 3차 home3) */
@media (max-width: 599px) {   /* 폰 띠: 시험은 같은 디자인의 아이콘만 버튼 40×40 · 출석부 옆 8(2026-09-27 D 확인 · 94 + 8 + 40 이 358 카드에 들어간다) */
  .btn.h-go.h-ex { width: 40px; padding: 0; }
  .btn.h-go.h-ex .t { display: none; }
}
@media (max-width: 374px) { .h-nx-w { white-space: normal; } }   /* 좁은 폰은 날짜·시각이 버튼 밑으로 들어가지 않게 필요할 때만 두 줄('9월 28일 (월)' / '오후 7시' · pretty 상속 · 320–355 에서 넘치던 것) */
/* 폰에서 이름이 잘리면(home.html fit 이 .nx-wrap · 360 바쁜 날 '고2 통합사…' · 2026-09-28 5판 실장 2차 4) 출석부·시험 버튼을 '다음 수업' 꼬리표 줄 오른쪽으로 올려 이름·시각에 폭을 다 준다
   버튼 크기 그대로 · 꼬리표 줄 26→40(버튼 위 = 카드 위 16) · 시각 줄로 내리면 +21 이라 바쁜 날 360×640 이 다 접어도 4 넘친다(+14 는 들어간다) */
.card.h-next.nx-wrap { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "ch go" "nx nx" "tl tl" "b b"; align-items: center; column-gap: var(--space-3); }
.h-next.nx-wrap .h-tails { grid-area: tl; }
.h-next.nx-wrap .h-ch { grid-area: ch; }
.h-next.nx-wrap .h-nx { display: contents; }
.h-next.nx-wrap .h-nx-t { grid-area: nx; margin-top: 10px; }
.h-next.nx-wrap .h-gos { grid-area: go; }
.h-next.nx-wrap .h-nx-b { grid-area: b; }
.h-nx-b { flex: none; display: flex; flex-direction: column; margin-top: 16px; }
/* 작은 꼬리표(2026-09-28 대표 구조 5차 home5 = E · 메모 '작은 꼬리 위치 살짝 올리거나') · 시각 잉크 → 꼬리표 폰 5 · PC 8 · 꼬리표 → 구분선 16
   배지 등급 22 · 12/600 · 반경 6 · 시험 = bad 면 + 안쪽 D-n 흰 칸 · 보강 = navy-50 면 + 달력 아이콘 */
.h-tails { flex: none; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.home.fit-tails .h-tails { display: none; }   /* 폰 한 화면 접기 · 확인할 일 다음, 오늘 이어서 앞(home.html fit) */
.h-tail { display: inline-flex; align-items: center; gap: 6px; height: 22px; max-width: 100%; padding: 0 8px; border-radius: var(--r-tag);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1; white-space: nowrap; }
.h-tail .tx { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.h-tail.ex { padding-left: 2px; background: var(--bad-bg); color: var(--bad); }
.h-tail.ex .d { flex: none; display: inline-flex; align-items: center; height: 18px; padding: 0 4px; border-radius: calc(var(--r-tag) - 2px); background: var(--card); font-weight: 600; }
.h-tail.cl { background: var(--navy-50); color: var(--navy-800); }
.h-tail.cl svg { flex: none; width: 14px; height: 14px; color: var(--navy-600); }
@media (hover: hover) { .h-tail:hover { text-decoration: none; } .h-tail:hover .tx { text-decoration: underline; } }
@media (max-width: 839px) { .h-tail { position: relative; } .h-tail::after { content: ""; position: absolute; inset: -8px 0; } }   /* 폰 누름 영역(위 출석부 버튼과 겹치지 않는 만큼) */
/* 준비 3칸(2026-09-26 대표 메모 '글자 크기는 이전 그대로 · 가운데 정렬 + 구분선만'): 라벨 12/16 · 값 16/22(폰·PC 같음) · 칸 안 가운데 · 칸 사이 세로선 = 위 가로선과 같은 1px --line */
.h-prep { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--line); }
.h-pc { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0; padding: var(--space-2) var(--space-1); color: var(--ink); text-align: center; }
.h-pc + .h-pc::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px; background: var(--line); }   /* 세로선(보드 칸 사이 선과 같은 방식) · 칸 폭을 먹지 않아 값이 칸 정가운데 */
.h-pc .lb { max-width: 100%; font-size: var(--fs-xs); line-height: 16px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.h-pc .v { font-size: var(--fs-lg); line-height: 22px; font-weight: 700; color: var(--ink); }
.h-pc .v.none { font-weight: 500; color: var(--ink-3); }
@media (hover: hover) { a.h-pc:hover .lb { color: var(--ink-2); } }
/* 오늘 이어서 · 시간순 최대 2줄 · 블록 하나가 그날 출결 링크 */
.h-later { display: grid; grid-template-columns: max-content 8px minmax(0, 1fr) auto; column-gap: var(--space-2); padding-top: 8px; border-top: 1px solid var(--line); color: var(--ink); }   /* 구분선→글자 16.5(폰) · PC 는 아래 ≥840 에서 24.5 */
.h-li { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: center; height: 32px; min-width: 0; }   /* 줄마다 같은 칸(시각 | 점 | 이름 | 외 n개) → 이름 시작선이 한 줄 */
.h-li .tm { grid-column: 1; font-size: var(--fs-base); line-height: 20px; font-weight: 500; color: var(--ink-2); white-space: nowrap; }   /* 비서 말투 '오후 4시'(2026-09-26 비평 6) · 문장이라 비례폭 */
.h-li .h-dot { grid-column: 2; }
.h-li .h-dot.none { visibility: hidden; }   /* 클리닉 줄 · 점 자리만 비워 이름 시작선을 맞춘다 */
.h-li .nmw { grid-column: 3; display: flex; align-items: center; gap: 8px; min-width: 0; }
.h-li .nmw:last-child { grid-column: 3 / -1; }   /* '외 n개' 가 없는 줄은 이름이 끝까지 */
/* 점 있는 줄(수업)이 하나도 없으면(클리닉만) 점 칸을 접어 '오후 4시 클리닉 · 2명 예약' 한 문장 간격(8) */
.h-later:not(:has(.h-dot:not(.none))) { grid-template-columns: max-content minmax(0, 1fr) auto; }
.h-later:not(:has(.h-dot:not(.none))) .h-dot { display: none; }
.h-later:not(:has(.h-dot:not(.none))) .nmw { grid-column: 2; }
.h-later:not(:has(.h-dot:not(.none))) .nmw:last-child { grid-column: 2 / -1; }
.h-later:not(:has(.h-dot:not(.none))) .more { grid-column: 3; }
.h-li .nm { min-width: 0; font-size: var(--fs-base); line-height: 20px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-li .st { flex: none; }   /* 크기는 알약 한 등급(.st) 그대로 */
.h-li .more { grid-column: 4; display: flex; align-items: center; gap: 2px; margin: 0 -4px 0 0;
  font-size: var(--fs-sm); line-height: 20px; font-weight: 500; color: var(--ink-2); }
.h-li .more svg { width: 16px; height: 16px; color: var(--ink-4); }
@media (hover: hover) { .h-later:hover .nm { color: var(--navy-ink); } }

/* 확인할 일 · 행 전체가 링크 · 폰 44 · PC 40 · 답변 대기 아이콘 오른쪽 위 노랑 점(카드 면 색 테두리 2) */
.h-tr { flex: none; display: flex; align-items: center; gap: 12px; height: 44px; color: var(--ink); }
.h-tr + .h-tr { border-top: 1px solid var(--line); }
.h-tr .ic { position: relative; flex: none; display: flex; color: var(--navy-ink); }
.h-tr .ic svg { width: 20px; height: 20px; }
.h-tr .ic.dot::after { content: ""; position: absolute; top: -4px; right: -4px; box-sizing: border-box; width: 12px; height: 12px;
  border: 2px solid var(--card); border-radius: var(--r-pill); background: var(--accent-y); }   /* 노랑 2/2 · 답변 대기(아이콘 장식이라 글자 줄과 맞추지 않는다) */
.h-tr .lb { flex: 1; min-width: 0; font-size: var(--fs-base); line-height: 20px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-tr .ct { flex: none; font-size: var(--fs-base); line-height: 20px; font-weight: 700; }
/* 숫자 + 단위(준비 3칸 '11명' · 확인할 일 '2건' · 2026-09-27 B 체계 5 u): 단위는 .84em · 600 · 숫자 뒤 1 · 숫자는 .08em 내려
   숫자·단위 아래 끝이 같은 선(사양 명시 값 · 행마다 차 0 계측) · 숫자와 단위는 템플릿에서 나눈다 */
.h-pc .v .n, .h-tr .ct .n { position: relative; top: .08em; }
.h-tr .ct .n { display: inline-block; min-width: 10px; text-align: left; }   /* 확인할 일 개수 숫자 칸을 정수 폭으로(숫자마다 글자 폭이 .3~1.3 달라 오른쪽 끝 맞춤 때 시작이 어긋남 · 서체는 그대로 · 2026-10-18 W202 P6 첫 글자) */
.nb { position: relative; top: .07em; top: round(calc(var(--nb-u, 1em) * .07), 1px); }   /* 전 화면 숫자+한글 아래선(2026-10-09 · static/nb.js 가 한글이 바로 붙는 숫자만 감싼다 · 서체상 한글 바닥이 숫자보다 약 .07em 낮다 · 화면은 글자를 1px 단위로 놓으므로 1px 로 반올림 · 단위가 다른 크기면 nb.js 가 --nb-u) */
.h-pc .v .n { top: .07em; }   /* 폰 캡처 계측: 홈 준비 칸 숫자 잉크 아래가 '명'·'없음'보다 .39px 아래였다 · .h-tr 은 .08em 유지 */
.st .nb, .badge .nb, .pill .nb, .chip .nb, .btn .nb, .tabs a .nb { top: 0; }   /* 높이 고정 부품 안은 숫자 내림 해제(숫자를 한글에 맞춰 올림 · 2026-10-10 대표 Z1) · 줄글의 아래선 맞춤은 그대로 */
.ses-t .n .nb { top: round(.0875em, 1px); }   /* 출석부 회차 머리 '8회차' 20px: 숫자 잉크가 한글보다 1.75px 위 → 2px 내림(2026-10-09 대표 결정 · 폰 1.75 = 웹 1.75) */
.h-pc .v .u, .h-tr .ct .u { font-size: .84em; font-weight: 600; margin-left: 2px; }   /* token-ok */
.h-tr.h-x { display: none; }
.h-card:has(.h-fold[open]) .h-tr, .h-card.h-closing .h-tr { display: flex; }   /* 펼치면 접어 둔 줄(PC 5번째부터 · 폰 4번째부터)을 모두 · 접는 200ms 동안(app.js h-closing)은 보인 채 높이만 줄인다 */
@media (hover: hover) { .h-tr:hover .lb { color: var(--navy-ink); } }

/* 다가오는 시험 · 폰은 한 줄(시험명 · 날짜 · 배지) · PC 는 두 줄(시험명 / 날짜) */
.h-er { flex: none; display: flex; align-items: center; gap: 8px; height: 44px; color: var(--ink); }
.h-er + .h-er { border-top: 1px solid var(--line); }
.h-er .tx { display: contents; }
.h-er .nm { min-width: 0; font-size: var(--fs-base); line-height: 20px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.h-er .dt { flex: 1 0 auto; font-size: var(--fs-sm); line-height: 20px; color: var(--ink-3); white-space: nowrap; }
.h-er .st { flex: none; justify-content: center; min-width: 48px; }   /* D-n 배지 왼쪽 · 폭 고정이라 시험명 시작선이 한 줄로 */
@media (hover: hover) { .h-er:hover .nm { color: var(--navy-ink); } }

/* 이번 주 보드(세부 디자인 G5 B · 2026-09-25 대표 요청) · 600 이상(폰은 날짜 띠) · 제목 오른쪽 주 범위
   7칸 같은 폭(사이 8) · 칸 머리 한 줄 26('21 월' · 숫자 정가운데) · 머리와 블록 사이 8
   오늘 칸 = 칸 전체(세로 열 전부) 옅은 면(navy-50, 칸 경계에 맞춰 칸 사이 선은 그대로) + 날짜 네이비 꼬리표·흰 글자 + 요일 굵게(2026-09-25 대표 선택 Ta+Tb · 2026-09-30 대표 지시로 면을 칸 전체 높이로, 양옆 선 복원)
   블록 = 수업 색 파스텔(|tint 바탕 · |tink 글자, 인라인 --p·--t) · 반경 8 · 두 줄 40(시각 / 반 요약어) · 사이 6
   지난 날은 파스텔 35% + ink-3 글자 · 하루 최대 2개 + '+n' · 진한 채움·색 띠 없음 */
.h-rng { flex: none; margin-left: auto; font-size: var(--fs-sm); line-height: 20px; color: var(--ink-3); white-space: nowrap; }
.h-bd { --bd-pb: 12px; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-rows: 1fr; flex: 1 1 auto; column-gap: var(--space-2); margin-top: 20px; padding-bottom: var(--bd-pb); }   /* 카드 높이를 채워 칸 사이 선이 카드 아래까지 · 제목 잉크 → 오늘 칸 면 15.5 그대로(면 위가 4 올라가 20 · 옛 16)
   아래 안여백 = 오늘 칸 면이 칸 내용 아래로 내미는 몫(블록 12 · '+n' 8) → 오늘 칸이 가장 길 때 면 끝 = 보드 끝 = 칸 사이 선 끝(2026-09-28 5판 실장 2차 5) */
.h-bd:has(> .h-bc.today > .h-bm) { --bd-pb: 8px; }
.h-bc { position: relative; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.h-bc + .h-bc::before { content: ""; position: absolute; left: -4px; top: 34px; bottom: calc(-1 * var(--bd-pb)); width: 1px; background: var(--line); }   /* 칸 사이 얇은 선(머리 아래부터 보드 아래 끝까지) */
.h-bh { display: flex; align-items: center; justify-content: center; gap: var(--space-1); height: 26px; margin-bottom: 2px; }
.h-bh .wd { font-size: var(--fs-xs); line-height: 16px; font-weight: 500; color: var(--ink-3); }
.h-bh .dn { display: flex; align-items: center; justify-content: center; flex: none; width: 26px; height: 26px; border-radius: var(--r-pill);
  font-size: var(--fs-base); line-height: 20px; font-weight: 700; color: var(--ink); }   /* 원 26 · 숫자 가운데 · 원 없는 날도 같은 자리 */
.h-bc.past .h-bh .dn { color: var(--ink-3); }
.h-bc.today { isolation: isolate; }   /* 다른 칸과 같이 보드 높이만큼 늘어난다(칸 사이 선이 늘 카드 아래까지 가는 것과 같은 기준, 2026-09-30 대표 지시: 오늘은 칸 전체에 옅은 배경) */
.h-bc.today::after { content: ""; position: absolute; inset: -10px -4px calc(-1 * var(--bd-pb)); z-index: -1; border-radius: var(--r-card) var(--r-card) 0 0; background: var(--navy-50); }   /* 면 위 = 날짜 꼬리표(24 · 머리 26 안 1) 윗변 12 · 좌우는 칸 사이 선 안쪽 끝까지(선이 면 위에 그려져 겹침 안 보임) · 아래는 칸 사이 선 끝과 같은 y(--bd-pb만큼 더 내려가 보드 끝까지) */
.h-bc.today .h-bh { gap: 8px; }   /* 꼬리표 밖 간격이 꼬리표 안여백(6)보다 넓게 · 요일이 꼬리표에 붙어 보이지 않게 */
.h-bc.today .h-bh .wd { font-weight: 700; color: var(--navy-900); }
.h-bc.today .h-bh .dn { width: 30px; height: 24px; border-radius: var(--r-tag); background: var(--navy-fill); color: var(--on-navy); }
.h-bk { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; min-height: 40px; min-width: 0; padding: 4px 6px;
  border-radius: var(--r-xs); background: var(--p); color: var(--t); }
.h-bk .t, .h-bk .n { max-width: 100%; min-width: 0; font-size: var(--fs-xs); line-height: 16px; overflow: hidden; }
.h-bk .t { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; text-overflow: ellipsis; }
.h-bk .n { font-weight: 700; white-space: nowrap; text-overflow: ellipsis; }   /* 반 요약어(서초 B · 고2 A) 한 줄 · 블록은 늘 두 줄 */
.h-bc.past .h-bk { background: color-mix(in oklch, var(--p) 35%, var(--card)); color: var(--ink-3); }
.h-bc.past .h-bk .n { color: var(--ink-2); }   /* 지난 날도 반 이름은 한 단계 진하게(2026-09-26 대표 메모 · 시각은 ink-3 그대로) */
.h-bm { text-align: center; font-size: var(--fs-xs); line-height: 16px; font-weight: 500; color: var(--ink-3); }
@media (hover: hover) { .h-bk:hover { filter: brightness(.97); } }
@media (max-width: 599px) { .card.h-week { display: none; } }
@media (min-width: 600px) { .card.h-days { display: none; } }
@media (max-width: 839px) { .h-bk { min-height: 44px; } }   /* 분할(600–839) 탭 타깃 44 */

/* 폰 구조(<840) · 본문 여백 위 12 · 옆 16 · 아래 탭바 + 16 · 넷째 줄 확인할 일·둘째 줄부터 시험은 접는다 */
@media (max-width: 839px) {
  main.main-home { padding: 12px max(16px, env(safe-area-inset-right)) calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left)); }
  .h-bar { border-radius: var(--r-card); }   /* 폰 날짜 바 반경 20 → 12 = 홈 카드(2026-09-27 D 구조 2차 rad2) */
  .h-tr.h-mx, .h-er.h-mx { display: none; }
  .h-next .h-nx { margin-top: 10px; }   /* 꼬리표 아래 → 이름·출석부 잉크 14(B 체계 4 계측) */
  .h-todo .h-list { margin-top: -4px; }   /* 첫 행을 Figma 홈 프레임 위치로(2026-10-17 W202 D0 · 옛 -2 는 카드 위에서 2px 아래 · 카드도 2 짧아짐) · 노랑 점 유무와 무관 · 행 44 위 반여백 포함 */
  .h-exams .h-list { margin-top: 0; }     /* 제목 잉크 → D-n 배지 18(sp3) */
}
@media (min-width: 600px) and (max-width: 839px) {
  .home { max-width: 560px; margin: 0 auto; }
}
/* 폰 홈 한 화면 접기(CLAUDE.md §3 · 2026-09-27 · 2026-09-28 5판 실장 A1~A4 · 2차 2·3): home.html 이 탭바 화면(<840)에서 넘칠 때만 .home 에 fit-* 를 차례로 붙인다
   날짜 띠 → 카드 사이 12→8 → 시험(제목 줄 대신 가장 가까운 시험 한 줄 'D-n 시험명 외 n개 ›') → 확인할 일 셋째 줄('외 n건') → 오늘 이어서 둘째 줄(첫 줄 '외 n개') · .fit-yes 는 접었을 때만, .fit-no 는 안 접었을 때만 */
.h-todo .fit-yes, .h-exams .fit-yes, .h-li .more.fit-yes { display: none; }
.home.fit-days .h-days { display: none; }
.home.fit-gap, .home.fit-gap .h-grid { gap: 8px; }   /* 12 → 8 두 단계만(9~11 중간값 없음 · 남는 몇 px 은 탭바 위 빈칸 · 5판 실장 2차 2) */
.home.fit-exams .h-exams:has(> .h-ex1) :is(.h-ch, .h-list) { display: none; }
.home.fit-exams .h-exams:not(:has(> .h-ex1)) { display: none; }   /* 예정된 시험이 없으면 카드째 접는다(바쁜 날 360×640 에서 '예정된 시험 없음'이 3px 넘치던 것) */
.home.fit-exams .h-exams .fit-yes { display: flex; }
.home.fit-exams .card.h-exams:has(> .h-ex1) { padding-top: 4px; padding-bottom: 4px; }   /* 한 줄 44 = 펼친 줄(.h-er) · D-n 배지가 첫·마지막 잉크 → 카드 위·아래 16(B 체계 3) */
.h-ex1 { align-items: center; gap: 8px; height: 44px; color: var(--ink); }   /* 줄 전체가 학교 시험 일정 링크 · 배지·시험명은 펼친 줄(.h-er)과 같은 모양 */
.h-ex1 .st { flex: none; justify-content: center; min-width: 48px; }
.h-ex1 .nm { min-width: 0; font-size: var(--fs-base); line-height: 20px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (hover: hover) { .h-ex1:hover .nm { color: var(--navy-ink); } }
.home.fit-later .h-li.h-fx { display: none; }
.home.fit-later .h-li .more.fit-yes { display: flex; }
.home.fit-later .h-li > * { grid-row: 1; }   /* '외 n개'가 이름보다 앞(DOM)이라 자동 배치가 이름을 둘째 줄로 내리지 않게 */
.home.fit-later .h-li .nmw:last-child { grid-column: 3; }   /* 첫 줄에 '외 n개'가 붙으니 이름은 제 칸까지 */
.home.fit-later .h-later:not(:has(.h-dot:not(.none))) .nmw:last-child { grid-column: 2; }
.home.fit-todo .h-todo .fit-no { display: none; }
.home.fit-todo .h-todo details.fit-yes { display: contents; }
.home.fit-todo .h-todo:not(:has(.h-fold[open])) .cnt.fit-yes { display: inline; }
.home.fit-todo .h-todo:not(:has(.h-fold[open])):not(.h-closing) .h-tr.h-fx { display: none; }
@media (max-width: 360px) {
  .h-pc { padding-left: 2px; padding-right: 2px; }   /* 칸 사이는 세로선 · 좁은 폰에서 라벨 폭을 조금 더 */
}
/* PC(≥840) · 본문 여백 위아래 24 · 흰 바 64 · 2열 × 2줄 격자 = 다음 수업 | 확인할 일 · 이번 주 보드 | 다가오는 시험
   (카드 끝선이 같은 y) · 홈 높이는 한 화면 예산 632 까지 채운다 */
@media (min-width: 840px) {
  main.main-home { padding-top: 24px; padding-bottom: 24px; }
  .home { gap: 16px; min-height: min(calc(100vh - 48px), 632px); min-height: min(calc(100dvh - 48px), 632px); }
  .h-bar { height: 64px; padding: 0 12px 0 24px; }   /* 오른쪽 끝은 종(40 칸 · 아이콘 20) · 종 잉크 오른끝 = 바 끝에서 24.5(날짜 왼쪽 24.5 와 짝 · 2026-10-01 실장 지적 4 · 옛 10) */
  .h-bar h1 { font-size: var(--fs-title); line-height: 26px; font-weight: 700; }   /* 20/26(B 체계 1) */
  .h-qta { font-size: var(--fs-base); line-height: 20px; }
  .h-qta b { font-weight: 700; }
  /* 2열 × 2줄 격자(2026-09-26 비평 N1 · 열마다 따로 쌓으니 둘째 줄 제목이 계단) · 첫 줄 두 카드는 같은 높이(늘이기)
     남는 높이는 '다음 수업' 안 제목 묶음 ↔ 준비 3칸 사이가 먹는다(카드 위·아래 잉크 여백은 그대로) · 둘째 줄은 윗선만 같고 각자 내용 높이 */
  .h-grid { display: grid; grid-template-columns: minmax(0, 1fr) 352px; grid-template-areas: "next todo" "week exams"; gap: 16px; align-items: start; }
  .h-col { display: contents; }
  .h-next { grid-area: next; } .h-todo { grid-area: todo; } .h-week { grid-area: week; } .h-exams { grid-area: exams; }
  .h-next, .h-todo { align-self: stretch; }
  .h-week, .h-exams { align-self: stretch; }   /* 둘째 줄도 두 카드 아래 끝이 같게(긴 쪽 내용 높이 · 안 내용은 위 정렬 · 보드는 칸이 카드 아래까지 · 2026-09-27 실장 지적 · 옛 51 차) */
  .h-next .h-nx { margin-bottom: auto; }
  .h-next .h-nx:has(+ .h-tails) { margin-bottom: 0; }
  .h-next .h-tails { margin-top: 4px; margin-bottom: auto; }   /* 꼬리표가 이름·시각 바로 아래에 붙고 남는 높이는 그 아래가 먹는다 */
  .card.h-card { padding: 20px 24px; }   /* 위·아래 = 첫·마지막 잉크 20(B 체계 3 · 다음 수업은 꼬리표가 첫 잉크) · 옆 24 그대로 */
  .card.h-todo, .card.h-exams, .card.h-week { padding-top: 16px; }   /* 제목 글자로 시작 · 제목 잉크 위 20 */
  .h-todo .h-list { margin-top: -2px; }    /* 첫 행을 Figma 홈 프레임 위치로(2026-10-17 W202 D0 · 옛 0 은 2px 아래) · 점 유무와 무관 · 행 40 */
  .h-exams .h-list { margin-top: 2px; }    /* 제목 잉크 → D-n 배지 18(sp3 · 두 줄 행 52) */
  .h-more { height: auto; margin: 0 -4px 0 auto; }   /* PC 는 탭 타깃 규칙 밖 · 제목 줄 높이 그대로(카드 안여백 안) */
  .h-nx { gap: 16px; }
  .h-nx-t { gap: 4px; }   /* 이름 32 + 3 + 시각 22 */
  .h-nx-n { font-size: var(--fs-display); line-height: 32px; }   /* 26/32(B 체계 1) */
  .h-nx-w { font-size: var(--fs-lg); line-height: 22px; }
  .h-pc { padding: 10px var(--space-1); }
  .h-tr { height: 40px; }
  .h-er { gap: 12px; height: 52px; }
  .h-er .tx { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .h-er .dt { flex: none; }
  /* 카드 아래 여백 = 위 여백(28 · 다음 수업 29) · 격자 칸 높이가 고정(첫 줄 292 · 둘째 줄 나머지)인 넓은 화면에서는 칸 높이가 정하고,
     한 줄로 쌓이는 좁은 PC(홈 폭 < 860)에서 내용 높이대로 맞는다 */
  .card.h-todo:has(> .h-list:last-child) { padding-bottom: 8px; }     /* 행 40 · 마지막 잉크 아래 20 = 위 20(2026-09-27 B 체계 3 계측) */
  .card.h-exams:has(> .h-list:last-child) { padding-bottom: 12px; }   /* 두 줄 행 52 · 마지막 잉크 아래 20.5 · 위 20 */
  .card.h-next:has(.h-later) { padding-bottom: 12px; }                /* 행 32 · 마지막 글자 아래 20.5 ≈ 위 꼬리표 20(B 체계 3 계측) */
  .h-later { padding-top: 16px; }
  .card.h-week { padding-bottom: 20px; }                              /* 마지막 잉크 = 보드 아래 끝(칸 사이 선 · 가장 긴 오늘 칸 면) 아래 20 = 위 제목 20(2026-09-28 5판 실장 2차 5 · 옛 32 는 면이 12 내밀던 때) */
  .card.h-card:has(> .h-none:last-child) { padding-bottom: 16px; }    /* '… 없음' 한 줄 · 글자 아래 20.5 · 위 20 */
}
/* PC 인데 홈 폭이 좁으면(840–990 레일 · 사이드바를 펼친 1100 안팎) 한 줄로 쌓는다 · 보드 칸이 60 아래로 좁아지지 않게 */
@container home (max-width: 859px) {
  .h-grid { display: flex; flex-direction: column; }
  .h-col { display: contents; }
}

/* ---------- 수업 카드 ---------- */
.class-card { position: relative; background: var(--card); border-radius: var(--radius); border: 1px solid var(--line); padding: 0; overflow: hidden; display: flex; flex-direction: column; color: inherit; box-shadow: var(--shadow); transition: transform .12s, box-shadow .12s; }
.class-card .drag-h { position: absolute; top: 20px; right: 56px; padding: 2px 8px; border-radius: 6px; color: var(--ink-4); font-size: 15px; line-height: 1; cursor: grab; user-select: none; background: var(--card); border: 1px solid var(--line); opacity: 0; transition: opacity .12s; }   /* PC 마우스 올릴 때만 · 연필(오른쪽 16 · 32) 왼쪽 8 · 상자 21 의 가운데 30.5 ≈ 연필 가운데 30(모양은 그대로 · 자리만 옮김) */
.class-card:hover .drag-h { opacity: 1; }
.class-card .drag-h:active { cursor: grabbing; }
.class-card.dragging { opacity: .45; outline: 2px dashed var(--navy-400); outline-offset: 2px; }
.class-card .card-cover { position: absolute; inset: 0; z-index: 1; border-radius: var(--radius); }
.class-card .drag-h, .class-card .edit-h { z-index: 2; }
/* 연필(수업 설정) = sm 32 정사각 ghost(.btn.sm.ghost.icon · navy-50 · 테두리 없음) · 아이콘 ink-2 · 폰·PC 같게(2026-09-27 실장 지적 5)
   오른끝 = 아랫줄 글자 끝선(안여백 16) · 세로 가운데 = 수업명 첫 줄 잉크 가운데: 색 띠 7 + 안여백 13 + 줄 22/2 = 31 에서 16/22 굵은 한글 잉크는
   줄 가운데보다 0.6~0.75 위(4배 촬영 계측 · 크롬 기준선 정수 스냅) → 버튼 가운데 30 = 위 14(잉크와 차 0.25~0.38 · 글자는 옮기지 않음) */
.class-card .edit-h { position: absolute; top: 14px; right: 6.6px; color: var(--ink-2); }   /* W412 critic3 12: ⋯ 잉크 끝 = 푸터·회차 수 끝 한 선(6 → 6.6 · 점 오른쪽 여백 9.4가 4의 배수가 아님) · ⋯ 잉크 끝이 아랫줄 글자 끝선(16)에: 점 오른쪽 여백 9.4 → right 6.6 ≈ 7(2026-10-09 비평 578) */
/* 연필 자리 = 옅은 ⋯(2026-09-28 구조 5차 card5=B · 바탕·틀 없음 · ink-3 · 누름 44) */
.class-card .edit-h.btn.ghost { background: none; box-shadow: none; color: var(--ink-3); }
.class-card .edit-h svg { width: 20px; height: 20px; }
.class-card .edit-h::after { content: ""; position: absolute; inset: -6px; }
@media (hover: hover) { .class-card .edit-h.btn.ghost:hover { background: var(--navy-50); } }
/* 폰(≤839) 길게 눌러 순서 바꾸기(card5=B · app.js): 450ms 누르면 들림 scale 1.02 + shadow-lg 160ms · 다른 카드는 200ms 비켜남 · 놓으면 180ms 안착 */
.class-card { -webkit-touch-callout: none; }
.class-grid.reordering .class-card { transition: transform 200ms cubic-bezier(.2, 0, 0, 1); }
.class-grid.reordering .class-card.lifted { z-index: 5; transition: box-shadow 160ms cubic-bezier(.2, 0, 0, 1), scale 160ms cubic-bezier(.2, 0, 0, 1); scale: 1.02; box-shadow: var(--shadow-lg); }
.class-grid .class-card.settling { transition: transform 180ms cubic-bezier(.2, 0, 0, 1), scale 180ms cubic-bezier(.2, 0, 0, 1), box-shadow 180ms cubic-bezier(.2, 0, 0, 1); }
@media (prefers-reduced-motion: reduce) {
  .class-grid.reordering .class-card, .class-grid .class-card.settling { transition: none; }
  .class-grid.reordering .class-card.lifted { scale: none; transition: none; }
}
@media (hover: none) { .class-card .drag-h { display: none; } }
@media (hover: hover) { .class-card:hover { text-decoration: none; transform: translateY(-2px); box-shadow: var(--shadow-lg); } }
.class-card .top { height: 8px; }
.class-card .body { padding: 12px 16px 8px; flex: 1; }   /* 색 띠 아래 ↔ 이름 잉크 16(2026-09-27 B sp3 cls) · 아래 7(줄높이 19와 짝 · 2026-09-28 구조 5차 card5=B "월수 아래 여백 살짝 줄여도") */
.class-card .name { font-size: var(--fs-lg); line-height: 22px; font-weight: 700; letter-spacing: -0.02em; display: flex; align-items: center; gap: 8px; padding-right: 40px; }   /* 16/22(B 체계 1) · 오른쪽 40 = 연필 32 + 8(긴 이름이 연필 밑으로 가지 않게 · 320 폭 계측) */
.class-card .meta { color: var(--ink-3); font-size: var(--fs-sm); margin-top: 4px; line-height: 20px; }   /* 두 줄(학교·과목 / 요일 시간 · card5=B) · 줄높이 19 = 13px 글 반여백 3(정수 · 잉크 가운데) · 위 4 아래 7로 20 줄 두 줄과 같은 높이 */
.class-card .foot .dsl { margin: 0 .04em 0 .1em; }   /* '최근 9/28' 빗금 앞을 더 띄움(2026-09-26 대표 "9가 /와 더 붙어있는 것 같아" · 12.5px 에서 앞 +1.25 · 뒤 +0.5) · 날짜 형식은 그대로 */
.class-card .foot { display: flex; justify-content: space-between; align-items: center; padding: 10px 16px 12px; border-top: 1px solid var(--line); font-size: var(--fs-xs); color: var(--ink-3); line-height: 18px; }
.class-card .foot b { color: var(--ink); }
.class-card .live { color: var(--ok); font-weight: 700; }

/* ---------- 출결 체크 화면 (한 학생 = 한 줄: 이름 | 출결 4칸 | 과제 6칸) ---------- */
.check-head { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
/* 출석부 출결 카드: 가로 안여백 = 다른 카드(PC 20 · 폰 14 아래) · 마지막 학생 줄 아래 여백을 빼 첫 잉크(요약 띠) 위 12 = 마지막 잉크(출결 칸) 아래 12(2026-09-27 실장 지적 2) */
.card.tight:has(> .check-head) { padding: 12px 20px; }
.card.tight:has(> .check-head) > .check-list > .check-row:last-child { padding-bottom: 0; }   /* 줄 아래 여백은 출결만 5 · 과제 칸 있으면 6 이라 카드 안여백 하나로 맞춘다 */
.check-sum { display: flex; gap: 6px; flex-wrap: wrap; font-size: var(--fs-sm); align-items: center; }
/* 요약 줄 알약('전체 n명' · 과제 제목)도 .st 와 같은 한 등급(2026-09-26 크기 규칙 A) */
.check-sum span:not(.st) { display: inline-flex; align-items: center; min-height: 22px; padding: 0 8px; background: var(--navy-50); border-radius: var(--r-xs);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1; color: var(--ink-2); }
/* 출석부 출결 머리(2026-09-27 구조 4차 names=A + 구조 3차 sum B): 왼쪽 ['오늘 출결' 16/700 + 'n명' 13/600 ink-3 한 줄] 아래 6 [숫자 칩 줄]
   오른쪽 버튼 묶음은 아래 끝 = 칩 줄 아래 끝(sum3 "띠와 하단선을 맞춰") · 위 4 아래 10 · 아래 선 line-2 · 옛 요약 띠(navy-50)는 이 머리가 대신한다 */
.check-head.att-head { align-items: flex-end; justify-content: space-between; gap: 8px; padding: 4px 0 10px; margin: 0; box-shadow: inset 0 -1px 0 var(--line-2); }
.att-head .ah-l { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.att-head .ah-t { display: flex; align-items: baseline; gap: 4px; margin: 0; font-size: var(--fs-lg); font-weight: 700; line-height: 22px; color: var(--ink); letter-spacing: 0; }
.att-head .ah-t .n { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3); }
.att-head .check-sum:not(:has(.st)) { display: none; }
.att-head .check-sum .st-none { background: var(--navy-100); color: var(--ink-2); }   /* '미정 n' = 출석·지각과 같은 칩(비평 v7 6) */
.att-head .ah-ntf { display: flex; align-items: center; gap: 8px; min-height: 28px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-3); }   /* 출결 알림 상태 줄(W9 F0-1) */
.att-head .ah-ntf-t { line-height: 20px; }   /* 상태 글 = 바닥 알림 줄(.ntf-t)과 같은 19 · 글자 잉크 가운데 */
.att-head .ah-ntf[hidden],.att-head .ah-ntf .ah-ntf-go[hidden] { display: none; }
.att-head .acts { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-left: auto; }
.check-head .selbox.ic { width: 32px; padding: 0; justify-content: center; background: var(--navy-100); }   /* 전체 출결 설정 ⋯(sum2=B) = 옆 '전원 출석'(soft)과 같은 면 · 32 */
.check-head .selbox.ic svg { position: static; width: 16px; height: 16px; transform: none; }
@media (hover: hover) { .check-head .selbox.ic:hover { background: var(--navy-200); } }
/* 출결 칸은 내용 크기만큼(max-content), 남는 폭은 과제 칸(1fr)이 차지 → 조퇴 옆에 빈 여백이 생기지 않음 */
.check-row { display: grid; grid-template-columns: minmax(120px, 190px) max-content minmax(0, 1fr); gap: 6px 14px; align-items: center; padding: 6px 4px; border-bottom: 1px solid var(--line); }
.check-row:last-child { border-bottom: 0; }
.check-row .who { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* 이름 앞 번호(명단 가나다순 · 폰·PC 모두) = 이름과 같은 크기·줄(14.5/22) · 옅게(ink-4 · 500) · 폭 16 오른쪽 맞춤 · 이름과 8(2026-09-27 구조 4차 names=A) · 비례폭 숫자(비평 v7 13) */
.check-row .who .no { flex: none; width: 16px; text-align: right; font-size: var(--fs-md); font-weight: 500; line-height: 22px; color: var(--ink-4); }
.check-row .who .nm { font-weight: 700; font-size: var(--fs-md); line-height: 22px; min-width: 0; }
/* 번호 · 이름 · 꼬리표는 .who 가운데 정렬(2026-09-27 D 구조 2차 av2) · 번호·이름 같은 크기·같은 줄 22 = 같은 기준선 */
.check-row .who .at-tag { flex: none; background: var(--navy-50); color: var(--ink-3); }   /* 알릴 것 꼬리표(새 학생 · 재시험 · 지각 n회) · 한 톤 · 높이 22(.st) */
.check-row .who .nm a { color: inherit; }
.check-row .who .sub { font-size: var(--fs-2xs); color: var(--ink-3); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 170px; }
/* 학생 줄 세그먼트(출결·과제)는 보이는 높이 32 = 테두리 1 + 여백 2 + 칸 26 (2026-09-26 대표 메모: 쓸데없이 높다 · 한 화면에 학생을 더)
   누름 영역 44 는 칸(label)의 보이지 않는 ::after 로 위아래 9 씩 · 폰에서 출결·과제 두 줄 사이(4)는 뒤 줄이 우선 */
.check-row .seg { padding: 2px; }
.check-row .seg label > span { height: 26px; }
.check-row .seg label::after { content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: -8px; }
/* 머리 줄 '전체 출석' 버튼(기본 40)과 옆 선택칸은 같은 높이 40 */
.check-head select.mini { height: 40px; padding: 0 10px; border-radius: var(--r-sm); }   /* 글자 크기는 select.mini 그대로(폰 16 · iOS 확대 방지) */
.selbox { position: relative; display: inline-flex; align-items: center; height: 40px; padding: 0 32px 0 14px; border-radius: var(--r-xs); background: var(--navy-50);
  color: var(--navy-800); font-size: var(--fs-base); font-weight: 600; line-height: 1; cursor: pointer; white-space: nowrap; }   /* 보이는 칸 = ghost 기본 버튼과 같은 14/600 · 40 */
.selbox svg { position: absolute; right: 10px; width: 14px; height: 14px; transform: rotate(90deg) translateX(-2px); pointer-events: none; }
.selbox select { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: var(--fs-lg); }
.selbox:focus-within { outline: 4px solid var(--navy-700); outline-offset: 2px; }
@media (hover: hover) { .selbox:hover { background: var(--navy-100); } }
@media (max-width: 839px) { .selbox select { inset: -2px 0; height: auto; } }
/* 머리 줄 부품은 sm 32 한 높이(2026-09-26 대표 메모): '전체 출석'(.btn.sm) · '전체 출결 설정'(선택칸) 반경 8(2026-09-27 rad2) · 글자 13 · '출결만' 칩 · 과제 입력 방식 세그먼트도 32(같은 줄 부품 높이 통일)
   폰 누름 영역 44 는 보이지 않는 ::after(칩 위아래 6 · 세그 칸 9) · 선택칸은 투명 select 를 위아래 6 */
.check-head .bulk-btn { border-radius: var(--r-xs); padding: 0 10px; gap: 6px; }   /* 작은 부품 8(2026-09-27 D 구조 2차 rad2) */
/* 전원 출석 = 스위치(2026-09-26 D 모션 1) · 26×16 · 손잡이 12 · 끔 navy-200 · 켬 --ok + 손잡이 10 오른쪽 200ms · 버튼 좌우 여백 12→10 */
.sw { position: relative; flex: none; width: 26px; height: 16px; border-radius: 8px; background: var(--ink-3); transition: background-color var(--dur-2) var(--ease-standard); }   /* 꺼짐 트랙 ↔ 버튼 바탕(navy-100) 3.7:1(비평 v7 7 · navy-200 은 1.15 · navy-300~500 도 3 미만) */
.sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--chip-on); transition: transform var(--dur-2) var(--ease-standard); }
.bulk-btn[aria-checked="true"] .sw { background: var(--ok); }
.bulk-btn[aria-checked="true"] .sw::after { transform: translateX(10px); }
.check-head .selbox { height: 32px; padding-left: var(--space-3); font-size: var(--fs-sm); }
.check-head .chip { position: relative; min-height: 32px; }
.check-head .chip::after { content: ""; position: absolute; left: 0; right: 0; top: -6px; bottom: -6px; }
.check-head .seg.mode { padding: 2px; }
.check-head .seg.mode label > span { height: 26px; }
.check-head .seg.mode label::after { content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: -8px; }
@media (max-width: 839px) {
  .check-head .selbox select { inset: -6px 0; }
  .card.tight:has(> .check-head) { padding: 12px 14px; }   /* 폰 가로 14 = 다른 카드(옛 12 · 2026-09-26 비평 11) · 위 = 아래 12 */
  .check-head { row-gap: 12px; margin-bottom: 8px; }   /* 요약 띠→버튼 12 = 버튼→첫 행 출결 칸 12(옛 10 · 13) */
}
.card.tight:has(> .att-head) { padding-top: 4px; }   /* 첫 잉크(오늘 출결) 위 = 마지막 잉크 아래 12(머리 안여백 4 + 글줄 여유 3 을 뺀 값 · 옛 19 vs 12) */
/* 출석부 머리 메타: 해당 회차 시험(2026-09-26 대표 메모 '너무 촘촘') */
.page-head .ses-sub { line-height: 20px; }
.ses-ex { display: block; }
.ses-ex .ilink b { color: var(--ink-2); }   /* 시험 링크 뒤 '제출 n/n' 은 링크 색 말고 글 색(2026-09-28 5판 A13) */
/* 출석부 회차 머리(2026-09-27 구조 4차 round=B): 날짜·시각 12.5/500 ink-3(줄 16) 위 2 · 회차 20/700(줄 24) · ‹ › 한 묶음(사이 8)
   웹 = 제목 바로 옆 12 · 폰 = 제목 칸이 늘어 묶음이 오른쪽 끝(사이 8) · 버튼은 크기 규칙 A 40 · 없는 쪽은 자리만 흐리게(묶음 위치 고정) */
.ses-head { display: flex; align-items: center; gap: 12px; margin: 0 0 var(--space-2); }
.ses-t { display: flex; flex-direction: column; gap: 2px; min-width: 0; margin: 0; white-space: nowrap; }
.ses-t .d { font-size: var(--fs-xs); font-weight: 500; line-height: 16px; color: var(--ink-3); }
.ses-t .n { font-family: var(--font-head); font-size: var(--fs-title); font-weight: 700; line-height: 24px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
.ses-head .saved-ind { align-self: flex-end; height: 24px; margin-left: 0; line-height: 1; }   /* 저장됨 = 회차 글줄(24) 가운데 · 웹은 ‹ › 뒤 · 폰은 ‹ › 앞 · line-height 1 = 글자 상자를 em 으로(1.45 는 잉크 −1.3px · .card-head .saved-ind 와 같은 방식) */
.ses-arw { display: inline-flex; gap: 8px; flex: none; }
.ses-arw .btn.icon { width: 40px; height: 40px; }
.ses-arw .btn.off { opacity: .4; pointer-events: none; }
.page-head.ses-ph { margin-bottom: 12px; }
.ses-ex + .ses-exb { margin-top: 8px; }
@media (max-width: 839px) { .ses-head { gap: 8px; } .ses-t { flex: 1 1 auto; } .ses-head .saved-ind { order: 1; } .ses-arw { order: 2; } }
/* 출석부 맨 아래 회차 삭제 = 빨간 글자(2026-09-26 구조 a · 바닥 버튼 줄 없앰) · 누름 44 */
.ses-del { display: flex; margin: 2px 0 0; }
.ses-del button { display: inline-flex; align-items: center; height: 44px; padding: 0 var(--space-1); border: 0; background: none; color: var(--bad); font-size: var(--fs-sm); font-weight: 600; line-height: 1; cursor: pointer; }
/* W412 critic3 2·12: '휴강으로 표시'·'이 회차 삭제' 글자 x = 카드 내용선(PC 289 · 폰 29)
   휴강(sm 버튼): 테두리 1 + 안여백 20/14 − sm 테두리 1 − 여백 12 → PC 8 · 폰 2
   삭제(글자 버튼): 테두리 1 + 안여백 20/14 − 버튼 여백 4 → PC 17 · 폰 11 */
#ses-cancel > button { margin-left: var(--space-2); }
.ses-del button {
  margin-left: 17px; /* token-ok */
}
@media (max-width: 839px) {
  #ses-cancel > button {
    margin-left: 2px; /* token-ok */
  }
  .ses-del button {
    margin-left: 11px; /* token-ok */
  }
}
@media (hover: hover) { .ses-del button:hover { text-decoration: underline; } }
@media (max-width: 599px) { .check-row .seg.att { max-width: 248px; justify-self: end; } }   /* 폰 출결 칸 248 · 오른쪽 끝 고정 · 이름 옆을 띄움(구조 4차 names=A · 아주 긴 이름·좁은 폭에서만 줄어든다) */
/* 출결 알림 보내기 줄(2026-09-27 D 모션 4차 확정 3 · alert4=B) · 바닥 고정 바(.sticky-actions)에 글(13/19 · 500 · ink-2 · 두 줄까지 balance) + sm 버튼 32(2026-09-28 · 옛 기본 40)
   명단 전원 입력 + 안 보낸 학생이 있을 때 올라옴 260ms standard(translateY 100% → 0) · 보낸 뒤 글은 --ok(120 페이드) · 1.2초 뒤 200ms 가속 곡선으로 내려감(app.js) */
.ntf-bar { flex-wrap: nowrap; justify-content: space-between; gap: 12px; background: var(--card); }   /* 바탕 --card + 위 선 1px(.sticky-actions) · 폰·PC(2026-09-27 실장 지적 1) */
@media (min-width: 840px) { .ntf-bar { padding: 8px 20px 10px; } }   /* 글 시작 = 카드 글자 시작선 · 버튼 오른끝 = 카드 안여백선(카드 테두리 1 + 안여백 20) · 위 = 아래 10(폰과 같은 값) */
.ntf-bar[hidden] { display: none; }
.ntf-t { flex: 1 1 auto; min-width: 0; margin: 0; font-size: var(--fs-sm); line-height: 18px; font-weight: 500; color: var(--ink-2); text-wrap-style: balance; text-box: trim-end text text; }   /* 줄 17 + 끝 반 줄간격(1)만 잘라 상자 16 · 한 줄일 때 버튼 32 가운데 = (32-16)/2 = 8 정수 · 글자 잉크 가운데 = 상자 가운데(자 -1.0/-0.5 → 0 · 글자를 밀지 않고 상자 높이로 맞춤 · 두 줄이어도 끝 줄만 잘라 줄간격 17 그대로 · 2026-10-11 W65) */
.ntf-t.ok { color: var(--ok); }
.ntf-t.err { color: var(--bad); }
.sticky-actions .btn.ntf-go { flex: none; height: 31px; padding: 0 12px; font-size: var(--fs-sm); border-radius: var(--r-xs); }   /* btn.sm 한 등급(31 · 13 · 반경 8 · 바닥 바 L48 규칙의 예외) · 폰 누름 44 는 .btn.sm::after(위아래 6) · 옛 40(2026-09-28 대표 4판 '텍스트에 비해 보내기가 큼') */
.ntf-go[hidden] { display: none; }   /* 보낸 뒤 버튼 숨김(.btn 의 display 가 hidden 을 덮지 않게) */
.ntf-bar.in { animation: ntf-up 260ms var(--ease-standard) both; }
.ntf-bar.out { animation: ntf-down var(--dur-2) var(--ease-exit) both; }
@keyframes ntf-up { from { transform: translateY(100%); } }
@keyframes ntf-down { to { transform: translateY(100%); } }
/* 줄이 떠 있을 때 떠나면 바닥 시트 '보내지 않은 알림이 있습니다' [보내고 나가기(기본)] [그냥 나가기(soft)] · 바깥·Esc 는 머묾 */
.ntf-sheet { width: min(100%, 480px); max-width: 100%; margin: auto auto 0; padding: 20px 16px calc(16px + env(safe-area-inset-bottom)); border: 0;
  border-radius: var(--radius) var(--radius) 0 0; background: var(--card); color: var(--ink); box-shadow: var(--shadow-lg); }
.ntf-sheet[open] { animation: ntf-up 260ms var(--ease-standard) both; }
.ntf-sheet::backdrop { background: color-mix(in srgb, var(--navy-950) 40%, transparent); }
.ntf-sheet-t { margin: 0 0 16px; font-size: var(--fs-lg); line-height: 22px; font-weight: 700; }
.ntf-sheet-acts { display: flex; gap: 8px; }
.ntf-sheet-acts .btn { flex: 1 1 0; }
/* 저장됨 표시(2026-09-26 D 모션 5): [체크 + 출결·과제 저장됨] · 체크는 처음부터 보이며 210ms 그려지고 글자는 200ms 나타남 · 1.8초 뒤 200ms 사라짐 */
.saved-ind { display: inline-flex; align-items: center; gap: var(--space-1); margin-left: var(--space-2); vertical-align: top; font-size: var(--fs-xs); color: var(--ok); font-weight: 600; opacity: 0; transition: opacity var(--dur-2) linear; }
.saved-ind.show { opacity: 1; transition: none; }
.saved-ind svg { flex: none; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 24; }
.saved-ind.err svg { display: none; }
.card-head .saved-ind { line-height: 1; }   /* 수업 내용 카드 머리(2026-09-26 구조 a): 글자 상자를 em 으로 맞춰 잉크를 가운데로(줄높이 1.45 는 −1.3px 떠 보임) */
.saved-ind.play svg { animation: ck-draw 210ms ease-in-out both; }
.saved-ind.play .t { animation: vt-fade-in var(--dur-2) linear both; }
@keyframes ck-draw { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }

/* ---------- 성적 추이 선그래프 (학생 상세 · 학생 페이지와 같은 마크업) ---------- */
.chart-box { background: var(--navy-50); border-radius: 12px; padding: 8px 8px 6px; margin-bottom: 12px; }
.chart { width: 100%; height: auto; display: block; }
.chart .g { stroke: var(--line-2); stroke-width: 1; }
.chart .yl { font-size: 9px; fill: var(--ink-3); text-anchor: end; }
.chart .xl { font-size: 9px; fill: var(--ink-3); text-anchor: middle; }
.chart .v { font-size: 9.5px; font-weight: 700; fill: var(--navy-ink); text-anchor: middle; }
.chart .me { fill: none; stroke: var(--navy-500); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.chart .avg { fill: none; stroke: var(--ink-4); stroke-width: 1.6; stroke-dasharray: 4 3; stroke-linejoin: round; }
.chart .dot { fill: var(--card); stroke: var(--navy-500); stroke-width: 2.2; }
.legend { display: flex; gap: 12px; font-size: var(--fs-2xs); color: var(--ink-3); padding: var(--space-1) var(--space-1) 0; align-items: center; }
.legend i { display: inline-block; width: 16px; height: 0; border-top: 2px solid var(--navy-500); vertical-align: middle; margin-right: 4px; }
.legend i.avg { border-top: 2px dashed var(--ink-4); }
.legend .muted { margin-left: auto; }

/* ---------- 주차 시험 화면: 시험지·정답본 파일 행 ---------- */
.file-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.file-row:last-of-type { border-bottom: 0; }
.file-row .ttl { flex: 1 1 200px; min-width: 0; font-weight: 700; font-size: 14px; }
.file-row .ttl .hint { display: block; font-weight: 400; }
.file-row form.up { display: flex; align-items: center; gap: 6px; flex: 1 1 240px; min-width: 0; }
.file-row form.up input[type=file] { flex: 1 1 120px; min-width: 0; max-width: 100%; font-size: var(--fs-xs); }

/* ---------- 시험지 형식 빌더 ---------- */
.fmt-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 6px; }
.fmt-box { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); background: var(--navy-50); border: 1px solid var(--line); border-radius: 12px; padding: 10px var(--space-2); margin: 0 !important; text-align: center; }
.fmt-box .t { font-weight: 700; font-size: var(--fs-md); color: var(--navy-ink); }
.fmt-box input { text-align: center; font-size: var(--fs-title) !important; font-weight: 700; margin-top: 2px !important; padding: 6px !important; }

/* ---------- 클리닉 · 보강 ---------- */
.slot { padding: 12px 4px; border-bottom: 1px solid var(--line); }
.slot:last-child { border-bottom: 0; }
.slot-head { display: flex; align-items: flex-start; gap: 10px; }
.slot-head .main { flex: 1; min-width: 0; }
.slot-head .title { font-weight: 700; font-size: 15px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.slot-head .meta { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; }
.slot-head .acts { display: flex; gap: 6px; flex-shrink: 0; }
.slot-books { margin: var(--space-2) 0 0; border: 1px solid var(--line); border-radius: 10px; padding: 2px 10px; background: var(--navy-50); }
.book-row { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--line); font-size: 13.5px; }
.book-row:last-child { border-bottom: 0; }
.book-row .nm { font-weight: 700; color: var(--ink); }
.book-add { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.book-add select, .book-add input { border: 1px solid var(--line-2); border-radius: 8px; padding: var(--space-2) 10px; font-size: 13.5px; background: var(--card); color: var(--ink); }
.book-add select { flex: 0 1 160px; }
.book-add input { flex: 1 1 160px; }
select.mini, input.mini { padding: var(--space-1) var(--space-2); font-size: var(--fs-xs); border-radius: 6px; border: 1px solid var(--line-2); background: var(--card); color: var(--ink); }
.icon-btn { background: none; border: 0; cursor: pointer; color: var(--ink-4); padding: 4px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; }
@media (hover: hover) { .icon-btn:hover { background: var(--bad-bg); color: var(--bad); } }
.danger-text { color: var(--bad); }
.follow-acts { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.follow-acts form { display: flex; gap: 6px; align-items: center; }
.follow-acts select { padding: 6px 8px; font-size: 13px; border-radius: 8px; border: 1px solid var(--line-2); max-width: 210px; background: var(--card); color: var(--ink); }
/* 확인 필요 학생(2026-09-28 5판 대표 메모 · 4h): 이름은 딥네이비 · 사유 띠는 제목 줄 안(수업명 띠 오른쪽) · 체크 잉크 → 첫 글자 잉크 12 를 머리 '전체'와 모든 줄에서 같게 */
.follow-list .title a { color: var(--navy-ink); }
.card-head .pick-all { margin-left: auto; }
.pick-all .checkline { gap: 12px; }
@media (min-width: 840px) { .follow-list .item .selbox { margin-right: -6px; } }   /* PC 행 체크 판 안쪽 6 만큼 당겨 체크 잉크 → 이름 잉크도 12(폰은 판 안쪽 0) */
@media (max-width: 839px) {
  .follow-acts { justify-content: flex-start; width: 100%; }
  .follow-list .item .selbox { margin-left: -10px; padding-right: 0; background: none; }   /* 확인 필요 학생 체크 칸 판은 투명(누르는 범위만 · 머리 '전체' 줄 부품 32 와 판 높이 40 이 부딪혀 · 2026-09-28 5판 실장 2차 6) · 체크 잉크 왼끝 = 카드 안여백 선(A11) · 뒤 이름까지 12(4h) */
  .slot-head { flex-wrap: wrap; }
}
/* '전체' 체크 칸(확인 필요 학생 머리 · 2026-09-28 D0): PC 는 판 없이 그대로 · 폰(<600)은 머리 폼을 한 줄 전체로 내려 행 체크 칸과 같은 투명 판(누르는 범위 · 왼쪽 10)
   → 두 체크 잉크 x 가 카드 안여백 선에서 같다 · 누르는 범위 높이는 같은 줄 버튼과 같은 32 · 판 면은 없다(행 판 40 과 높이가 달라 보이던 것 · 5판 실장 2차 6) */
.checkline > .selbox { display: contents; }
@media (max-width: 599px) {
  .pick-all { flex: 1 1 100%; }
  .pick-all .checkline > .selbox { display: inline-flex; height: 32px; padding: 0 0 0 10px; margin-left: -10px; background: none; }
  .pick-all .checkline > .selbox input { width: 18px; height: 18px; accent-color: var(--navy-500); }
}
/* 확인 필요 학생 아래 고정 막대(.ntf-bar 와 같은 값 · 부품 전부 32): 선택 수 · 클리닉 선택칸 · 배정 */
.pick-bar .selbox { flex: 0 1 auto; min-width: 0; max-width: 210px; height: 32px; padding-left: var(--space-3); font-size: var(--fs-sm); }
.pick-bar .selbox .v { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 839px) { .pick-bar .selbox select { inset: -6px 0; } }

/* ---------- 성적표 · 인쇄 ---------- */
.print-only { display: none; }
@media print {
  @page { size: A4; margin: 12mm; }
  .sidebar, .topbar, .tabbar, .toasts, .no-print, .sticky-actions, .crumb, .page-head .acts, .tabs, .icon-btn, form .btn { display: none !important; }
  .tbl-wrap { overflow: visible; }
  main { padding: 0; max-width: none; }
  body { background: #fff; }
  .card { box-shadow: none; border: 1px solid var(--line-2); break-inside: avoid; }
  .print-only { display: block; }
  .page-break { page-break-after: always; break-after: page; }
  .banner:has(> .seps) { display: none; }   /* 시험 오류 알림 띠(base.html)는 인쇄에 넣지 않는다 */
}

/* ---------- 더보기 ---------- */
.menu-list .item svg { width: 22px; height: 22px; flex: none; color: var(--navy-600); }
/* 목록 카드 안여백 16/12(옛 14/12) · 행은 카드 끝까지 닿아 눌림 배경(폰 :active)이 카드 안쪽 가득 · 행 높이는 선 포함 44(제목 20 · 부제 18 · 마지막 행도 같음)(2026-10-01 실장 6·9) */
.card.tight.menu-list { padding: 12px 0; }
.menu-list .list .item { position: relative; min-height: 44px; padding: 12px 16px; border-bottom: 0; }
.menu-list .list .item::after { content: ""; position: absolute; left: 16px; right: 16px; bottom: 0; height: 1px; background: var(--line); }
.menu-list .list .item:last-child::after { display: none; }
.menu-list .item .title { line-height: 20px; }
.menu-list .item .title:has(.badge) { height: 20px; }   /* 개수 배지(최소 22)가 있어도 제목 줄은 20 · 배지는 위아래로 1씩 줄 밖(행 여백 안)에 걸친다 */
.menu-list .item .meta { line-height: 18px; }
.menu-list a.item:active, .menu-list button.item:active { background: var(--navy-50); border-radius: 8px; }
.menu-list .title .badge { background: var(--accent-y-lt); }   /* 게시판·클리닉 개수 = 사이드바 개수 배지와 같은 노랑 면(2026-09-28 5판 대표 메모 · 4h) · 규격은 아래 '개수 띠'
/* 새 탭 줄(구독·결제 관리) 오른쪽 바깥 링크 표시 · 상자 18(정수 · 그림이 픽셀에 붙어도 자리가 흔들리지 않게) → 잉크 14(옛 16.5) · 획 2.14 × 18/24 = 보이는 굵기 1.6 = ›(22 상자 · 획 1.75)
   잉크 오른끝 = › 잉크 오른끝(행 끝에서 약 7 · 옛 2.3 으로 4.7 튀어나옴)(2026-09-28 5판 실장 2차 7) */
.menu-list .item svg.chev.ext { width: 18px; height: 18px; margin-right: 4px; stroke-width: 2.14; }

/* ---------- 설정 묶음 목록 · 한 묶음 화면(2026-10-01 D0 · iOS 설정·토스 방식) ----------
   JS 가 #set-hub 에 .js 를 달았을 때만 목록 ↔ 한 묶음을 오간다 · 없으면 전부 펼쳐 둔다(목록은 숨김)
   목록 행은 더보기 행(.menu-list .item) 그대로 · 오른쪽 값은 ink-3 한 줄 말줄임 · 목록은 묶음 카드와 같은 격자(.grid2 첫 칸)라 폭이 같다
   묶음 머리 = 폰은 상단바 ‹ + 묶음 이름 하나 · 웹은 경로 줄 '‹ 설정 / 묶음 이름' 하나(app.js 가 이름을 넣는다) · 저장 = 묶음 카드 바로 아래 일반 버튼 */
.set-hub:not(.js) .set-list { display: none; }
.set-hub.js .set-panel { display: none; }
.set-hub.js .set-panel.on { display: block; }
.set-hub.js:not(.open) .set-form, .set-hub.js.nosave .set-form, .set-hub.js.open .set-lists { display: none; }
.set-hub.js.nobar .set-save { display: none; }   /* 저장할 칸이 없는 묶음(학생 수 · 앱·문의)은 저장 버튼도 없다 */
.set-hub.js .set-panel h3.dup { display: none; }   /* 묶음 제목과 같은 카드 제목은 한 번만 */
.set-hub .set-panel .card, .set-hub .set-panel [id] { scroll-margin-top: calc(var(--topbar-h, 0px) + env(safe-area-inset-top) + 12px); }
.set-list .list .item { flex-wrap: nowrap; }
.set-list .list .item { justify-content: flex-start; }
.set-list .list .item > .main:has(+ .set-val) { flex: 0 0 auto; }   /* 폰 .list .item > .main 의 140 바탕을 풀어 제목은 제 글자만큼 · 남는 자리는 값 */
.set-list .item .title { white-space: nowrap; }
.set-list .item .set-val { flex: 1 1 0; min-width: 0; text-align: right; font-size: var(--fs-sm); line-height: 20px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.set-list .item .set-val.pair { display: flex; justify-content: flex-end; }   /* 이름 · 과목: 좁으면 이름이 먼저 말줄임 · 과목은 끝까지 남긴다 */
.set-val.pair > .a { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.set-val.pair > .b { flex: 0 0 auto; max-width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: pre; }
.set-panel .grid2, .set-save, .set-lists { row-gap: 0; }
.set-lists > div, .set-save > div { min-width: 0; }   /* 한 칸 격자(1fr = 내용 최소폭 이상)가 줄바꿈 없는 행 때문에 좁은 폰에서 카드를 밀어내지 않게 */   /* 폰에서 두 열이 한 열로 쌓일 때 카드 사이 12(.card 아래 여백)만 */
.set-hub.js.autosave .set-save { display: none; }   /* 라디오·토글만 있는 묶음(과제 기록 · 수납 장부)은 바꾸면 바로 저장 · 저장 버튼 없음 */
/* 설정 묶음 선택 행: 행 전체가 label 이라 어디를 눌러도 선택 · 높이 44 · 설명은 이름 아래 둘째 줄에서 이름과 같은 선(체크 18 + 간격 8) · 채움은 버튼과 같은 네이비 하나 */
.set-panel .checkline { min-height: 44px; margin-bottom: 0; align-content: center; row-gap: 0; }
.set-panel .checkline input { accent-color: var(--navy-900); }
/* 라디오는 기본 부품 대신 그려서 누를 때 뜨는 사각 면(24×24)을 없앤다 · 크기 18 · 선택은 네이비 고리 + 점 · 키보드 포커스는 다른 부품과 같은 3px 고리 */
.set-panel .checkline input[type=radio] { -webkit-appearance: none; appearance: none; border: 2px solid var(--ink-3); border-radius: 50%; background: var(--card); flex: none; }
.set-panel .checkline input[type=radio]:checked { border-color: var(--navy-900); background: var(--navy-fill); box-shadow: inset 0 0 0 4px var(--card); }
.set-panel .checkline input[type=radio]:focus-visible { outline: 4px solid var(--navy-700); outline-offset: 2px; }
/* 체크박스도 라디오와 같은 방식으로 그린다: 선 1.5 ink-3 · 선택은 navy-fill 채움 + 카드색 체크 · 반경 4(꼬리표 8 이하) · 포커스 고리 같게 */
.set-panel .checkline input[type=checkbox] { -webkit-appearance: none; appearance: none; position: relative; border: 2px solid var(--ink-3); border-radius: 4px; background: var(--card); flex: none; }
.set-panel .checkline input[type=checkbox]:checked { border-color: var(--navy-900); background: var(--navy-fill); }
.set-panel .checkline input[type=checkbox]:checked::before { content: ""; position: absolute; left: 4px; top: 2px; width: 4px; height: 8px; border: solid var(--card); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.set-panel .checkline input[type=checkbox]:focus-visible { outline: 4px solid var(--navy-700); outline-offset: 2px; }
/* 설정 묶음 카드 안내는 한 부품 · 줄을 반으로 균등 분할하지 않고 카드 폭을 쓴다 */
/* 설정 카드 안내(.hint)는 body pretty 상속 · 별도 규칙 불필요 */
.set-panel .card .kbd { white-space: nowrap; }   /* 파일 이름 칩은 줄 끝에서 쪼개지지 않고 통째로 넘어간다 */
#backup-list > .sl { row-gap: var(--space-2); }   /* 세로로 쌓인 파일 칩 사이 8 */
#backup-list .kbd { font-variant-numeric: tabular-nums; }   /* 칩 안 날짜 숫자 폭을 칩마다 같게 */
.set-panel .checkline > .lab { flex: 1 1 0; min-width: 0; }   /* 긴 한 줄 설명 행: 글이 칸 옆에 붙어 여러 줄로 감긴다(칸 아래로 떨어지지 않게) */
/* 두 줄 이상 선택 행: 칸은 첫 줄 중심에(가운데 정렬 아님) · 위아래 12 */
.set-panel .checkline:has(> .lab) { align-items: flex-start; min-height: 0; padding: var(--space-3) 0; }
.set-panel .checkline:has(> .lab) > input { margin-top: 2px; }
/* 카드 마지막이 선택 행이면 첫 요소 쪽(위)과 같은 만큼만 남긴다 · 마지막 입력칸 아래 12 · 선택 행 바로 아래 딸린 안내는 행 사이보다 가깝게 붙인다 */
.set-panel .card:has(> .checkline:last-child) { padding-bottom: 8px; }
/* 맨 아래가 입력칸·버튼 줄이면 테두리 아래도 첫 글자 위와 같은 값(웹 23 · 폰 19 · 잉크 기준 실측) */
.set-panel .card:has(> .row:last-child), .set-panel .card:has(> details:last-child) { padding-bottom: 20px; }
.set-panel .card > details:last-child > label:last-child { margin-bottom: 0; }
.set-panel .checkline + p.hint { margin-top: 0; }
@media (max-width: 839px) { .set-panel .card:has(> .checkline:last-child) { padding-bottom: 2px; } .set-panel .card:has(> .row:last-child) { padding-bottom: 16px; } .set-panel .card:has(> details:last-child) { padding-bottom: 18px; } }
.set-panel[data-key="basic"] .card, .set-panel .card:has(> a[href="/settings/backup"]) { padding-bottom: 20px; }   /* 끝이 글 안내인 카드: 마지막 글 아래를 위 여백과 같게(웹 23 · 폰 19 잉크 실측) */
@media (max-width: 839px) { .set-panel[data-key="basic"] .card { padding-bottom: 16px; } .set-panel .card:has(> a[href="/settings/backup"]) { padding-bottom: 16px; } }
.set-panel .seps > .sl { --sep: 10px; }   /* 이 화면 메타 줄(· 좌우 5)과 같은 구분 폭 10 · 수업 부제 등 다른 .seps 는 그대로 */
.set-panel .seps > .sl > * { white-space: nowrap; }   /* 상태 줄 항목은 덩어리째 줄을 옮긴다 · 구분점은 .seps 가 다음 항목 앞에서 처리 */
.set-panel .checkline > .hint { flex: 1 0 100%; padding-left: 26px; }
.set-panel .checkline:has(> .hint) { padding: var(--space-2) 0; }   /* 두 줄 행(이름 19 + 설명 18)은 위아래 8 → 53 · 44 행과 간격이 같아 보이게 */
.set-panel .checkline + :not(.checkline) { margin-top: var(--space-3); }
/* 카드 첫 요소가 선택 행이면 행 높이(44)의 위 여백만큼 카드 안여백을 덜어 첫 글자·칸이 다른 카드와 같은 선에 온다(웹 18 · 폰 14) */
.set-panel .card:has(> .checkline:first-child), .set-hub.js .set-panel .card:has(> h3.dup:first-child + .checkline) { padding-top: 8px; }
@media (max-width: 839px) { .set-panel .card:has(> .checkline:first-child), .set-hub.js .set-panel .card:has(> h3.dup:first-child + .checkline) { padding-top: var(--space-1); } }
/* 펼침 표시는 선택칸과 같은 꺾쇠 하나: 연동 정보 접기 제목 ▶▼ 글자와 목록 입력칸의 기본 ▼ 단추를 걷고 같은 두 빗금으로 */
.set-panel summary { display: flex; align-items: center; gap: 8px; list-style: none; }
.set-panel summary::-webkit-details-marker { display: none; }
.set-panel summary::after { content: ""; flex: none; margin-left: auto; width: 12px; height: 6px; background-repeat: no-repeat; background-size: 6px 6px; background-position: right 6px center, right 0 center;
  background-image: linear-gradient(45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)),
    linear-gradient(-45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)); }
.set-panel details[open] > summary::after { transform: scaleY(-1); }
.set-panel input[list] { -webkit-appearance: none; appearance: none; padding-right: 32px !important; background-repeat: no-repeat !important; background-size: 6px 6px !important; background-position: right 18px center, right 12px center !important;
  background-image: linear-gradient(45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)),
    linear-gradient(-45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)) !important; }
.set-panel input[list]::-webkit-calendar-picker-indicator { display: none !important; }
@media (max-width: 839px) {   /* 폰: 상단바 → 카드 16 · 카드 → 저장 버튼 16(카드 아래 12 + 4) */
  main:has(.set-hub.open) { padding-top: var(--space-4); }
  .set-hub .set-save { margin-top: var(--space-1); }
}
.crumb .set-c { display: none; }
.crumb:has(.set-c) > a[href="/"] + .sep { display: none; }
main:has(.set-hub.open) .crumb > a[href="/"] { display: none; }
main:has(.set-hub.open) .crumb .set-c { display: inline; }
main:has(.set-hub.open) .page-head { display: none; }   /* 웹: 묶음 안에서는 큰 제목 '설정' 대신 경로 줄이 머리 */
@media (min-width: 840px) { .set-hub.js.open { margin-top: 8px; } }   /* 경로 줄 아래 16(.mtop 8 + 8) = 경로 줄만 있는 다른 화면과 같음 */
.menu-list .item.danger-text, .menu-list .item.danger-text svg { color: var(--bad); }   /* 로그아웃 줄(앱) · .list .item 의 color: inherit 를 이기려고 .menu-list 를 붙인다 */

/* ---------- 코드 블록 · 기타 ---------- */
th.wide { min-width: 220px; }
.msgbody { font-family: inherit; white-space: pre-wrap; background: var(--navy-50); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; font-size: 13.5px; max-width: 520px; line-height: 1.55; }
.tpl { border-top: 1px solid var(--line); padding-top: var(--space-3); margin-top: 12px; }
.tpl:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
.tpl-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; gap: 8px; flex-wrap: wrap; }
.stars { display: inline-flex; align-items: center; vertical-align: -0.18em; color: var(--warn); font-size: 16px; }   /* 별점 = 아이콘 세트 star(듀오톤) · 채운 별만 면 불투명(글자 ★☆ 대신 · 2026-10-13 W77 묶음 3) */
.stars svg { width: 1em; height: 1em; vertical-align: baseline; }
.stars svg.on .f { fill-opacity: 1; }
details summary { cursor: pointer; color: var(--navy-ink); font-weight: 600; }
details { border-top: 1px solid var(--line); padding: 8px 0; }
details:first-of-type { border-top: 0; }
hr { border: 0; border-top: 1px solid var(--line); margin: 16px 0; }
.code-box { display: inline-flex; align-items: center; gap: 8px; background: var(--navy-50); border: 1px dashed var(--navy-300); border-radius: 10px; padding: 0 12px; min-height: 32px; }
.code-box .mono { font-size: var(--fs-xl); font-weight: 700; color: var(--navy-ink); }
.qr svg { width: 180px; height: 180px; }
.steps { counter-reset: s; list-style: none; }
.steps li { position: relative; padding-left: 36px; margin-bottom: 12px; }
.steps li::before { counter-increment: s; content: counter(s); position: absolute; left: 0; top: 0; width: 26px; height: 26px; border-radius: 50%; background: var(--navy-fill); color: #fff; font-weight: 700; font-size: 13px; display: grid; place-items: center; }
.login-wrap { min-height: 100vh; min-height: 100dvh; display: flex; align-items: center; justify-content: center; background: var(--navy-fill); padding: 20px; }
.login-card { width: 100%; max-width: 360px; background: var(--card); border-radius: var(--r-md); padding: 30px 26px; box-shadow: var(--shadow-lg); text-align: center; }
.login-card .mark { width: 52px; height: 52px; border-radius: var(--r-md); display: block; margin: 0 auto 14px; }
/* PIN 틀림(2026-09-26 D 모션 4): 점 줄(입력칸) 320ms 좌우 8 → -5 → 3 → 0 · 채운 점 --bad → 120ms 뒤 비움(login.html) */
@keyframes pin-shake { 0% { transform: none; } 22% { transform: translateX(8px); } 48% { transform: translateX(-4px); } 74% { transform: translateX(2px); } 100% { transform: none; } }
.pin-form input.pin-shake { animation: pin-shake var(--dur-3) ease-out; }
.vform.pin-form input.pin-bad { color: var(--bad); border-color: var(--bad-line); }   /* .vform input:not():not() 의 글자색을 이기려고 .vform 을 붙인다 */
/* 첫 로그인 인사(2026-09-26 D 모션 7 · _macros.html hello_overlay): 흰 면(--card) 위 위티봇 손 흔들기 900ms + 환영 문구 · 900ms 뒤 사라짐(320ms) · 누르면 즉시 닫힘 · 강사·학생 같은 오버레이(2026-10-01 D3) */
.hello { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 24px; background: var(--card); cursor: pointer; --h: 112px; }
.hello[hidden] { display: none; }
.hello > div { display: flex; flex-direction: column; align-items: center; gap: 6px; animation: hello-in var(--dur-3) var(--ease-decel) both; }
.hello p { font-size: var(--fs-2xl); font-weight: 700; line-height: var(--lh-head); color: var(--ink); text-align: center; text-wrap-style: balance; }
.hello.out { opacity: 0; transition: opacity var(--dur-3) var(--ease-standard); }
@keyframes hello-in { from { opacity: 0; transform: translateY(8px); } }
@media (min-width: 600px) { .hello { --h: 140px; } }

/* ---------- 위티봇 모션 (D3 확정 · 2026-10-01 · 정본 design/specimens/2026-10-01/charmotion/charmotion.css) ----------
   그림은 원본 컷 층(static/char/*.webp)을 같은 크기로 겹친다 · 기본 상태가 정지 컷 · 부모에 .play 를 HTML 에 처음부터 넣으면 한 번 재생 후 멈춘다(반복 0).
   흰 테두리 컷이라 흰 면(--card) 위에만 · 한 화면 1개 · 표시 높이 --h(≤280). 진폭은 높이 %. --ax = 바닥 그림자 중심을 상자 가운데로 맞추는 축 보정 */
.cm { display: block; position: relative; height: min(var(--h, 112px), 280px); aspect-ratio: var(--ar); translate: var(--ax, 0) 0; }
.cm img { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; }
.cm .l-grp { position: absolute; inset: 0; }
.cm-wave { --ar: 287 / 260; --ax: 3.31%; }

/* wave · 손 흔들기 · 900ms · 몸 전체가 발 아래 그림자 중심을 축으로 ±2.5° 두 번 · 효과선은 두 번 깜빡임 */
.cm-wave .l-stack { transform-origin: 46.69% 86.54%; }
.play .cm-wave .l-stack { animation: cm-wave-sway 900ms both; }
.play .cm-wave .l-shadow { animation: cm-wave-shadow 900ms var(--ease-sine) both; }
.play .cm-wave .l-sparks { animation: cm-wave-sparks 900ms linear both; }
@keyframes cm-wave-sway {
  0% { transform: rotate(0); animation-timing-function: ease-out; }
  12.5% { transform: rotate(-2.5deg); animation-timing-function: var(--ease-sine); }
  37.5% { transform: rotate(2.5deg); animation-timing-function: var(--ease-sine); }
  62.5% { transform: rotate(-2.5deg); animation-timing-function: var(--ease-sine); }
  87.5% { transform: rotate(2.5deg); animation-timing-function: var(--ease-sine); }
  100% { transform: rotate(0); }
}
@keyframes cm-wave-shadow {
  0% { transform: scaleX(1); animation-timing-function: var(--ease-sine); }
  12.5%, 87.5% { transform: scaleX(.98); animation-timing-function: var(--ease-sine); }
  100% { transform: scaleX(1); }
}
@keyframes cm-wave-sparks {
  0%, 8% { opacity: 1; }
  12.5%, 17% { opacity: 0; }
  21%, 58% { opacity: 1; }
  62.5%, 67% { opacity: 0; }
  71%, 100% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .play .cm *, .play .cm { animation: none !important; }
}

/* ---------- 모바일 · 앱 화면(탭바 밴드 ~839px · 2026-09-23 D10 전에는 900px) ---------- */
@media (max-width: 839px) {
  :root { --radius: 12px; }
  /* 입력칸이 바닥 버튼줄·탭바 뒤에 숨지 않게(2026-10-10 대표 N3) · 68 = 선 1 + 위 9 + 버튼 48 + 아래 10 */
  html { scroll-padding-bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom)); }
  html:has(.sticky-actions) { scroll-padding-bottom: calc(var(--tabbar-h) + 68px + 16px + env(safe-area-inset-bottom)); }
  body { font-size: 15px; line-height: 1.46667; }   /* 15 × 1.46667 = 22px · 반여백 2 (1.45 면 21.75 라 글자가 0.9px 위로 떴다) */
  .layout { display: block; }
  .sidebar { display: none; }
  .topbar {
    display: flex; align-items: center; gap: 8px; position: sticky; top: 0; z-index: 20;
    background: var(--navy-fill); color: #fff;
    /* 노치·다이나믹 아일랜드 여백은 높이에 '더해야' 함 (안 그러면 제목·아이콘이 잘림) */
    height: calc(var(--topbar-h) + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) calc(10px + env(safe-area-inset-right)) 0 calc(10px + env(safe-area-inset-left));
  }
  .topbar .back { flex: none; width: 40px; height: 40px; display: grid; place-items: center; color: #fff; border-radius: 10px; background: none; border: 0; }   /* 제목이 길어도 ‹ 칸 40 은 줄지 않는다(위치 표시가 길 때 34~36 으로 줄던 것 · 2026-09-28) */
  .topbar .back svg { width: 22px; height: 22px; transform: translateY(-.5px); }   /* ‹ 경로는 24 격자 가운데(y 5.25–18.75) · 잉크가 제목 글자보다 낮아 아이콘만 올림(2026-09-27 D 구조 3차 ttl3 · 사양 명시 0.75 → 2026-10-12 W106b 측정으로 제목 잉크 가운데와 차 0 인 0.5) */
  .topbar:has(.ttl.path) .back svg { transform: none; }   /* 상위 이름(14px)이 ‹ 바로 옆일 때는 그 글자 잉크 가운데와 차 0 (W106b 측정) */
  .topbar .ttl { margin: 0; font-weight: 700; font-size: var(--fs-lg); line-height: 22px; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: -0.01em; }   /* h1(2026-09-27 접근성) · 기본 여백만 뺀다 */
  /* 출석부 상단바 학생 수(2026-09-27 구조 4차 count=B): 수업 이름 뒤 8 · 옅은 판(흰 12% · 20 · r6 · 좌6 우7) 안 사람 아이콘 14 + 'n명' 12/600 navy-150 · 아이콘만 살짝 올림(아래) · 이름이 길면 이름만 말줄임 */
  .topbar .ttl:has(.cnt-plate) { display: flex; align-items: center; gap: 8px; }
  .topbar .ttl .tt-n { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .cnt-plate { display: inline-flex; align-items: center; gap: 4px; flex: none; height: 20px; padding: 0 8px 0 6px; border-radius: 6px;
    background: color-mix(in srgb, var(--chip-on) 12%, transparent); color: var(--navy-150); font-size: var(--fs-xs); font-weight: 600; line-height: 1; letter-spacing: 0; }
  .cnt-plate svg { flex: none; width: 14px; height: 14px; transform: translateY(-.5px); }   /* 사양 0.75 는 시안 아이콘 경로 기준 · 지금 users 아이콘(안에서 -0.6 이동)은 0.5 가 잉크 가운데(4배 촬영: 판 가운데와 아이콘 0.00 · 글자 +0.12) */
  /* 하위 화면 위치 표시(2026-09-27 D 구조 3차 ttl3=A): '상위 › 현재' · 상위 15/500 navy-200 · › 14 navy-300 · 현재 16/700 흰색 · 사이 6
     끝 단계(2026-09-28 D3 확정 · 전 화면 공통): 길면 상위(옅은 앞 칸)가 먼저 줄고(말줄임), 상위 두 글자 + › (54)도 못 남기면 상위 묶음을 통째로 빼고 '‹ 현재'(16/700 · 그래도 길면 말줄임)
     방식: 현재를 첫 칸으로 두고(order) 오른쪽→왼쪽 배치 + 줄바꿈 · 상위 묶음이 한 줄에 못 들어가면 둘째 줄로 넘어가 높이 22 밖으로 가려진다(글 읽는 순서는 '상위 현재' 그대로) */
  .topbar .ttl.path { display: flex; flex-direction: row-reverse; flex-wrap: wrap; justify-content: flex-end; align-items: center; align-content: flex-start; gap: 0 6px; height: 22px; }
  .topbar .ttl .upw { order: 1; display: flex; align-items: center; gap: 6px; flex: 1 1 54px; min-width: 0; max-width: max-content; }   /* 줄바꿈 판단은 54(상위 두 글자 34 + 6 + › 14) · 들어가면 제 글 폭까지 늘어난다 */
  .topbar .ttl .up { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-up); font-weight: 500; color: var(--navy-200); }
  .topbar .ttl .cur { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar .ttl.path svg { flex: none; width: 14px; height: 14px; color: var(--navy-300); transform: translateY(-.75px); }   /* 작은 › 도 ‹ 와 같이(사양 명시) */
  .topbar .tacts { display: flex; gap: var(--space-1); flex: 0 0 auto; align-items: center; }
  .topbar .tacts a, .topbar .tacts button {   /* 면 흰 6% · 반경 9 · 아이콘은 선만(2026-09-27 D 구조 2차 tb2=B) */
    color: #fff; background: rgba(255,255,255,.06); border: 0; border-radius: 8px;
    display: inline-flex; align-items: center; justify-content: center; gap: 4px; position: relative;
    min-height: 32px; padding: 0 10px; font-weight: 700; font-size: 13.5px; line-height: 20px; white-space: nowrap;   /* 줄 상자 정수 20 · 물려받은 19.8 이면 글자가 0.6~0.9 뜬다(2026-09-28 게이트) */
  }
  .topbar .tacts a::after, .topbar .tacts button::after { content: ""; position: absolute; inset: -6px; }   /* 보이는 면 32 · 누르는 영역 44(2026-10-12 대표 W105 · 면이 바 53 을 꽉 채워 아래 여백이 좁아 보이던 것 · 위·아래 10.5) */
  /* 아이콘만 있는 버튼(글자 없이 aria-label만)은 폭도 탭 타깃 44px — 아이콘 크기는 그대로, 히트 영역만 (2026-09-24 계측) */
  .topbar .tacts a[aria-label], .topbar .tacts button[aria-label] { min-width: 32px; }
  /* 상단바 종은 아이콘만 — 페이지 버튼 오른쪽에 고정 (2026-09-22) */
  .topbar .tacts .bell { width: 32px; padding: 0; color: #fff; }
  .topbar .tacts .plan-badge { min-height: 22px; height: 22px; min-width: 0; padding: 0 8px; border-radius: 999px; background: var(--on-navy-track); color: var(--on-navy); font-size: var(--fs-xs); line-height: 16px; font-weight: 600; margin-right: 2px; }   /* 플랜 이름표 · 위 .tacts a 공통(44 높이·흰 6%)을 되돌린다 */
  .topbar .tacts a.plan-badge:hover { background: var(--on-navy-track); color: var(--on-navy-2); }
  main { padding: 14px max(14px, env(safe-area-inset-right)) calc(var(--tabbar-h) + var(--space-6) + env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-left)); max-width: none; }
  .page-head { margin-bottom: 12px; }   /* 머리 버튼 → 탭 · 탭 → 첫 카드 12 · 12 (2026-09-26 대표 메모 '공백이 의미 없이 넓다') */
  .tabs { margin-bottom: 12px; }
  .page-head h1 { font-size: var(--fs-title); }
  .card { padding: 14px 14px; margin-bottom: 12px; }
  .grid2, .grid3 { grid-template-columns: 1fr; }
  .stats { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .stat .num { font-size: var(--fs-2xl); }
  .form-row { grid-template-columns: 1fr; }
  /* 버튼 높이는 PC 와 같다(40·32·48) · 누름 영역 44 만 보이지 않는 ::after 로 위아래를 늘린다(기본 2 · sm·아이콘 6)
     (2026-09-26 크기 규칙 A · 전에는 폰에서 sm 44 가 기본 42 보다 커지는 역전이 있었다) */
  .btn { position: relative; }
  .btn::after { content: ""; position: absolute; left: 0; right: 0; top: -2px; bottom: -2px; }
  .btn.sm::after, .btn.icon::after { top: -6px; bottom: -6px; }
  .toast .undo button::after { content: ""; position: absolute; left: 0; right: 0; top: -8px; bottom: -8px; }   /* 되돌리기 누름 영역 44 이상 (단추 높이 실측 28.7 + 위아래 8 = 44.7) */
  /* 입력칸·선택칸 누름 영역 44 · 보이는 높이 40 그대로(2026-10-05 G0) · 칸을 감싼 label.tap 이 위아래 안여백 2 + 같은 만큼 음수 마진으로 누름 영역만 넓힌다(보이는 자리 변화 0) */
  .tap { --tap-m: -2px; --tap-p: 2px; }
  .icon-btn { padding: 8px; min-width: 36px; min-height: 36px; justify-content: center; }
  .item .selbox { padding: 10px; margin: -10px 0 -10px -6px; }
  .qcard .selbox { padding: 8px; margin: -8px; }
  .chip { min-height: 32px; position: relative; }   /* 보이는 높이는 PC 와 같은 32 · 누름 영역 44 는 ::before 로 위아래 6씩(2026-10-13 대표 W233) */
  .chip::before { content: ""; position: absolute; inset: -6px 0; }
  .chips.g8 { --cols: 4; }   /* 과목 8 · 학기 8 → 폰에서는 4칸씩 두 줄 */
  /* 보이는 탭 높이는 PC 와 같은 36(같은 방향) · 누름 영역 44 는 보이지 않는 ::before 로 위아래 4씩 늘린다 */
  .tabs a { padding: 0 14px; height: 36px; display: inline-flex; align-items: center; }
  .tabs a::before { content: ""; position: absolute; left: 0; right: 0; top: -4px; bottom: -4px; }
  /* iOS는 16px 미만 입력창에 포커스하면 화면을 확대한다 → 앱에서는 16px 고정 */
  .vform input:not([type=checkbox]):not([type=radio]), .vform select, .vform textarea, .input, select.input, textarea.input, select.mini,
  .book-add select, .book-add input, .follow-acts select, .qcard .qtop select.input, .qcard textarea.body, .qcard .ch input, .qcard .pts input,
  .grade-row .score input.note, .grade-row .score input.pts { font-size: 16px; }
  /* 바닥 고정 바는 화면 양 끝까지(본문 좌우 여백 = main 의 max(14px, 안전 영역)만큼 내민다 · 분할 밴드는 24 · 2026-09-26 대표 메모) */
  .sticky-actions { bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    margin: var(--space-3) calc(-1 * max(14px, env(safe-area-inset-right))) 0 calc(-1 * max(14px, env(safe-area-inset-left)));
    padding: 8px max(14px, env(safe-area-inset-right)) 10px max(14px, env(safe-area-inset-left)); }   /* 위 = 선 1 + 9 = 아래 10(2026-10-10 대표 N6) */
  /* 키보드가 올라온 동안(app.js .kb-open): 탭바 숨김, 고정 바는 흐름에 */
  body.kb-open .sticky-actions { position: static; background: none; padding-bottom: 0; }
  body.kb-open main { padding-bottom: 24px; }
  .toasts { top: auto; bottom: calc(var(--tabbar-h) + var(--sticky-h, 0px) + 12px + env(safe-area-inset-bottom)); left: max(14px, env(safe-area-inset-left)); right: max(14px, env(safe-area-inset-right)); max-width: none; }   /* 좌우는 본문 안여백(카드 선)과 같은 14 */
  .toast { animation-name: toastin-up; }   /* 폰은 아래에서 8px 올라온다 */
  /* 모바일: 1줄째 이름+출결 4칸, 2줄째 과제 6칸 → 한 학생 약 80px (한 화면에 7~8명) */
  .check-row { grid-template-columns: minmax(54px, max-content) 1fr; gap: 4px 8px; padding: 6px 0; }
  .check-row .who .nm { font-size: var(--fs-md); }
  .check-row .who .sub { max-width: 90px; }
  .check-row .hw-cell { grid-column: 1 / -1; }
  .seg { width: 100%; padding: 2px; }
  .seg.att { max-width: 300px; }     /* 4칸 × 최대 72px — 화면이 넓어도 토글 사이가 벌어지지 않게 */
  .seg.hw { max-width: 400px; }
  .seg.hwi { max-width: 330px; }   /* 과제 건별 3칸 — 넓은 폰에서도 토글 사이가 벌어지지 않게 */
  .seg label { flex: 1; min-width: 0; }
  .seg label > span { width: 100%; height: 40px; font-size: 13.5px; min-width: 0; padding: 0 2px; }
  .seg.hw label > span { font-size: 13px; }
  .seg > .seg-lab { padding: 0 var(--space-1) 0 4px; }
  .seg.mode { width: auto; }
  .seg.mode label { flex: 0 0 auto; }
  .seg.mode label > span { width: auto; height: 40px; padding: 0 10px; font-size: var(--fs-xs); }
  .tpick { grid-template-columns: 1fr; }
  .tpick .seg.mode label > span { height: 40px; min-width: 40px; padding: 0 8px; font-size: 13.5px; }
  .tpick .tp-h .chip { min-width: 0; min-height: 32px; }
  .tp { padding: var(--space-2) 10px; }
  /* 개강일·종강일처럼 짧은 칸 두 개는 폰에서도 좌우로 (세로 여백 절약) */
  .form-row.duo { grid-template-columns: 1fr 1fr; gap: 0 8px; }
  .hwslide { min-width: 0; }
  .hwslide input[type=range] { height: 40px; }
  th, td { padding: 8px var(--space-2); font-size: 13.5px; line-height: 20px; }   /* 13.5px 글 · 반여백 2 */
  .tabs a { padding: 0 12px; font-size: 13.5px; }
  .dist-col { width: 38px; }
  .hide-m { display: none !important; }
  /* 긴 명단에서 스크롤해도 검색 칸은 상단바 아래에 붙어 있게 (2026-09-15 C06) */
  .sticky-search { position: sticky; top: calc(var(--topbar-h) + env(safe-area-inset-top)); z-index: 5; background: var(--bg); padding: 6px 0; }
  /* 리스트 행: 제목 칸은 최소 150px. 버튼·배지·폼이 안 들어가면 아랫줄로 내려가 오른쪽 정렬 (제목이 한 글자씩 갈라지지 않게) */
  .list .item { flex-wrap: wrap; justify-content: flex-end; }
  .list .item > .main { flex: 1 1 140px; }
  .list .item > .right { margin-left: auto; }
  .list .item > .acts { flex: 0 1 auto; }
  /* 날짜 + 선택 + 버튼 한 줄 폼: 안 들어가면 버튼만 다음 줄로 */
  .inline-form { flex-wrap: wrap; }
  .inline-form .btn { flex-shrink: 0; }
  .item .meta .badge { white-space: normal; }
}
@media (min-width: 840px) { .only-m { display: none !important; } }
/* 폰(앱 밴드 ~599px) 학생 목록: 이름 줄 글자가 오른쪽 연락처 칸 위로 겹쳐 보이던 문제 (2026-09-18)
   — 학교·학년은 템플릿에서 둘째 줄(.meta)로 내리고, 링크 칸이 한 줄을 다 써서 '학습 리포트 보기'는 아랫줄로 간다.
   .main 이 .item-link 안에 있어 위 `.list .item > .main` 규칙이 닿지 않으므로 학생 목록 전용 클래스로만 고친다 */
@media (max-width: 599px) {
  .stu-list .item > .item-link { flex: 1 1 0; }
  .stu-list .item { flex-wrap: nowrap; }
  .stu-list .item .selbox { background: none; padding-right: var(--space-1); }   /* 공용 select 판(.selbox)이 체크칸에 새던 것을 걷고, 체크 잉크 왼끝 = 머리줄 체크 잉크 왼끝 */
  .stu-list .item .avatar, .stu-list .item .right, .stu-list .item .chev { display: none; }   /* 앞 자리는 체크칸 하나 · 코드·접속일은 상세에서 (HTML 은 그대로) */
  .stu-list .item .main { min-width: 0; }
  .stu-list .item .title { display: flex; align-items: center; gap: var(--space-1); flex-wrap: nowrap; height: 22px; white-space: nowrap; }   /* 이름 글자 높이 17 이 홀수라 줄 높이도 홀수 · 배지(22)가 있어도 줄은 21 이고 배지는 가운데에서 위아래로 나온다(자르지 않음) */
  .stu-list .item .title .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; line-height: normal; }
  .stu-list .item .title .nm, .stu-list .item .title .ph { align-self: baseline; }   /* 이름(17)과 연락처(13) 글자 바닥을 한 줄에(2026-10-12 · 가운데 맞춤이면 0.5 어긋남) · 배지는 그대로 가운데 */
  .stu-list .item .title .badge { flex: none; }
  .stu-list .item .title .nophone { display: inline-flex; margin-left: auto; }
  .stu-list .item .title .ph { display: inline; flex: 0 100 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; margin-left: auto; padding-left: var(--space-2); font-size: var(--fs-sm); font-weight: 400; color: var(--ink-3); font-variant-numeric: tabular-nums; }
  .stu-list .item .meta { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1); white-space: nowrap; min-width: 0; overflow: hidden; }   /* 한 줄 높이 = 수업 색띠(22) 높이 · 학교 글자와 색띠가 같은 가운데선 */
  .stu-list .item .meta .stu-sch { flex: none; line-height: normal; }
  .stu-list .item .meta .cls-tag { flex: 0 1 auto; min-width: 0; max-width: 100%; }
  .stu-list .item .meta .cls-tag .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* 행 끝 리포트 아이콘 버튼 · 퇴원 처리 버튼 끝맞춤은 파일 끝 '학생 명단 손질' 블록(≤839) */
  .stu-head .checkline { gap: var(--space-4); line-height: 20px; }
  .stu-list .item .title .ph { line-height: 20px; }   /* 체크 잉크 → '전체 선택' 글자 시작선 = 행의 체크 → 이름 시작선 */
  .stu-head .checkline input { width: 18px; height: 18px; }
}

/* ---------- 기기별 호환 (2026-09-04): 아이폰·갤럭시·아이패드·갤럭시탭·폴더블 ---------- */
/* 분할 밴드(600–839px · 태블릿 세로·폴더블 펼침): 탭바 레이아웃은 유지하되 넓이를 활용 */
@media (min-width: 600px) and (max-width: 839px) {
  main { padding-left: max(var(--space-6), env(safe-area-inset-left)); padding-right: max(var(--space-6), env(safe-area-inset-right)); }
  .toasts { left: max(24px, env(safe-area-inset-left)); right: max(24px, env(safe-area-inset-right)); }   /* 알림도 카드 선에 */
  .sticky-actions { margin: var(--space-3) calc(-1 * max(var(--space-6), env(safe-area-inset-right))) 0 calc(-1 * max(var(--space-6), env(safe-area-inset-left)));
    padding: 8px max(var(--space-6), env(safe-area-inset-right)) 10px max(var(--space-6), env(safe-area-inset-left)); }   /* 본문 여백 24 만큼 내밀어 양 끝까지 · 위 = 선 1 + 9 = 아래 10(대표 N6) */
  .grid2, .grid3 { grid-template-columns: 1fr 1fr; }
  .stats { grid-template-columns: repeat(4, 1fr); gap: 12px; }
  .form-row { grid-template-columns: 1fr 1fr; }
  .check-row { grid-template-columns: minmax(120px, 190px) max-content minmax(0, 1fr); gap: 6px 14px; padding: 6px 4px; }
  .check-row .hw-cell { grid-column: auto; }
  .card.narrow { max-width: 620px; }
  /* 출결 4칸은 폰처럼 늘리지 않고 PC처럼 고정 폭(44px+) */
  .seg { width: auto; padding: 4px; }
  .seg label { flex: 0 0 auto; }
  .seg label > span { width: auto; min-width: 44px; padding: 0 12px; font-size: 13px; }
  .seg.hw label > span { min-width: 40px; padding: 0 8px; }
}
/* 작은 폰(≤360px: 갤럭시 S·iPhone SE 계열): 과제 6칸이 한 줄에 들어가도록 */
@media (max-width: 360px) {
  .seg label > span { padding: 0 8px; min-width: 40px; }
  .seg.hw label > span { min-width: 36px; padding: 0 4px; }
  .hw-cell { max-width: 100%; overflow-x: auto; }
  .stats { gap: 8px; }
  .page-head h1 { font-size: 19px; }
  .topbar .ttl { font-size: 15.5px; }
  /* 하단 고정 버튼이 두 줄로 꺾이지 않게 */
  .sticky-actions { gap: 6px; }
  .sticky-actions .btn { padding-left: var(--space-3); padding-right: var(--space-3); }
  .sticky-actions .btn, .sticky-actions .btn.lg { padding: 0 14px; font-size: var(--fs-md); }   /* 높이는 L48 그대로(크기 규칙 A) · 폭·글자만 줄인다 */
}
/* 폰 가로 모드(높이 500 이하): 상단바·탭바를 낮춰 본문 공간 확보 */
@media (max-width: 839px) and (orientation: landscape) and (max-height: 500px) {
  :root { --topbar-h: 46px; --tabbar-h: 50px; }
}

/* ---- 문항 편집 카드 · 채점 화면 · 문제 가져오기 (2026-09-05, 과목 불문 문항 체계: mc/ox/short/blank/essay) ---- */
.fmt-grid.four { grid-template-columns: repeat(4, 1fr); }
.qedit .card { min-width: 0; }
.qcard { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px; margin-bottom: 10px; background: var(--card); }
.qcard.deleting { opacity: .45; }
.qcard .qtop { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.qcard .qno { background: var(--navy-fill); color: #fff; font-weight: 700; border-radius: 8px; min-width: 30px; height: 30px; display: grid; place-items: center; font-size: var(--fs-sm); padding: 0 8px; line-height: normal; }   /* 문항 번호 잉크 0.9px 보정 */
.qcard .qtop select.input { width: auto; margin: 0; min-height: 34px; padding: var(--space-1) var(--space-2); font-size: var(--fs-sm); }
.qcard .pts { display: flex; align-items: center; gap: 6px; margin: 0; font-size: var(--fs-sm); font-weight: 600; }
.qcard .pts input { width: 64px; margin: 0; min-height: 34px; padding: var(--space-1) var(--space-2); text-align: center; font-variant-numeric: tabular-nums; }
.qcard .del { margin: 0 0 0 auto; font-size: var(--fs-sm); color: var(--ink-3); }
.qcard .selbox { margin: 0; display: flex; align-items: center; }
.qcard .selbox input { width: 20px; height: 20px; accent-color: var(--navy-600); margin: 0; cursor: pointer; }
.qcard .qno { cursor: pointer; }
.qcard.selected { border-color: var(--navy-400); box-shadow: 0 0 0 2px var(--navy-100); }
.pts-bar { background: var(--navy-50); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 10px; }
.qcard textarea.body { margin: 0 0 var(--space-2); font-size: var(--fs-md); }
.qcard .choices { display: grid; gap: 6px; margin-bottom: 8px; }
.qcard .choices[hidden] { display: none; }
.qcard .ch { display: flex; align-items: center; gap: 8px; margin: 0; }
.qcard .ch .ci { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--navy-ink); color: var(--navy-ink); display: inline-grid; place-items: center; font-size: var(--fs-xs); font-weight: 700; flex-shrink: 0; line-height: normal; }   /* 동그라미 안 선지 번호 잉크 1.1px 보정 */
.qcard .ch input { margin: 0; min-height: 34px; padding: 4px var(--space-2); font-size: var(--fs-sm); }
.qcard .ans { display: block; margin: 0 0 6px; }
.qcard .ans input { margin-top: 4px; }
.qcard details.more { border: 0; padding: 0; margin: 0; }
.qcard details.more summary { padding: 2px 0; }
.qcard details.more label { margin: var(--space-2) 0 0; }
.qrules li { margin: 4px 0 4px 16px; }
.qno-badge { display: inline-grid; place-items: center; min-width: 26px; height: 26px; border-radius: 6px; background: var(--navy-fill); color: #fff; font-size: var(--fs-xs); font-weight: 700; padding: 0 6px; vertical-align: middle; line-height: normal; }
.card-head h3 .qbody { font-weight: 500; color: var(--ink-2); }
.grade-row { display: grid; grid-template-columns: minmax(120px, 15%) minmax(0, 1fr) minmax(200px, 25%); gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); align-items: start; }
.grade-row:last-child { border-bottom: 0; }
.grade-row .who { display: flex; align-items: center; gap: 8px; }
.grade-row .ans { white-space: pre-wrap; font-size: var(--fs-md); background: var(--navy-50); border-radius: var(--radius-sm); padding: var(--space-2) 10px; min-height: 36px; word-break: break-word; }
.grade-row.pending .ans { background: var(--warn-bg); }   /* 왼쪽 띠 대신 옅은 면 (2026-09-25) */
.grade-row.ok .ans { background: var(--ok-bg); }
.grade-row .score { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.grade-row .score input.pts { width: 72px; margin: 0; text-align: center; min-height: 34px; padding: 4px; font-variant-numeric: tabular-nums; }
.grade-row .score input.note { flex: 1 1 100%; margin: 0; min-height: 34px; padding: 4px var(--space-2); font-size: var(--fs-sm); }
@media (max-width: 839px) {   /* 폰 입력 16(iOS 확대 방지) · 위 폰 규칙 목록에 있어도 뒤에 오는 이 자리 규칙(13·14.5)에 져서 문항 유형·문제·선지·채점 메모 칸이 작았다(2026-09-28 R0 q28) */
  .qcard .qtop select.input, .qcard textarea.body, .qcard .ch input, .grade-row .score input.note { font-size: 16px; }
}
.src-tabs .chip { flex: 1; justify-content: center; }
@media (max-width: 839px) {
  .fmt-grid.four { grid-template-columns: repeat(2, 1fr); }
  .grade-row { grid-template-columns: 1fr; gap: 6px; }
  .qcard .del { margin-left: 0; }
}

/* ---- 파일 드롭 영역 (app.js가 모든 input[type=file]을 감쌈, 2026-09-05) ---- */
.dz { position: relative; border: 2px dashed var(--line-2); border-radius: var(--radius-sm); padding: 8px 12px; background: var(--navy-50); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; cursor: pointer; margin: var(--space-1) 0 var(--space-2); font-size: var(--fs-sm); color: var(--ink-2); min-height: 44px; }
.dz.over { border-color: var(--navy-400); background: var(--navy-100); }
.dz.has { border-style: solid; border-color: var(--ok); background: var(--ok-bg); }
.dz input[type=file] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; margin: 0; }
.dz .dz-ic { flex: none; width: 16px; height: 16px; color: var(--navy-600); }   /* 듀오톤 file 아이콘(옛 📎 · 2026-09-27 실장 지적 4) · 16 = 같은 줄 버튼 아이콘 · 색 = 목록 앞 아이콘 */
.dz .dz-t { flex: 1; min-width: 0; }
.dz .dz-f { flex: 1 1 100%; font-weight: 700; color: var(--ink); word-break: break-all; }
.dz .dz-f:empty { display: none; }
.file-row form.up .dz { flex: 1 1 200px; margin: 0; min-height: 40px; padding: 6px 10px; }
.inline-form .dz { flex: 1 1 200px; margin: 0; }
/* 출석부 수업 자료: 드롭존 = 입력 한 등급 40(같은 줄 '자료 올리기' 40 · 크기 규칙 A · 2026-09-27 실장 지적 4) · 폰은 전체 폭(버튼은 아랫줄) · 폰 누름 44 는 투명 선택칸을 위아래 2 */
#files .dz { flex: 1 1 200px; min-height: 40px; margin: 0; }   /* PC 는 남는 폭을 채워 '자료 올리기' 오른끝 = 과제·영상 추가 버튼 오른끝 */
#files .dz .dz-t { line-height: 20px; }   /* 13/19(B 줄높이 표) · 테두리 1.5 + 안여백 9 + 줄 19 = 40 · 글자 잉크 = 칸 가운데 */
@media (max-width: 839px) { #files .dz { flex-basis: 100%; } #files .dz input[type=file] { inset: -2px 0; height: auto; } }

/* ---- 게시판형 글쓰기 (2026-09-11 대표 지시: 공지 전용 글쓰기 화면 · 큰 본문 칸) ----
   공지 쓰기·수정(notice_form.html) + 게시판 본문 칸(.post-text.mid). 본문은 ux.js data-autogrow 로 내용만큼 늘어난다. */
.post-form { max-width: 860px; }
.post-form .post-meta { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0 18px; }
.post-form .post-meta > label:not(.checkline) { flex: 0 1 340px; min-width: 220px; }
.post-form .post-meta > .checkline { min-height: 44px; }
/* :not() 두 개는 모바일 입력칸 16px 규칙(.vform input:not(..):not(..))보다 우선하려는 것 */
.vform input.post-title:not([type=checkbox]):not([type=radio]) { font-size: 17px; font-weight: 600; min-height: 48px; padding: 12px 14px; }
.vform textarea.post-text { min-height: 420px; font-size: 15.5px; line-height: 1.75; padding: 14px 16px; resize: vertical; }
.vform textarea.post-text.mid { min-height: 260px; }
.post-count { margin: -6px 2px var(--space-3); text-align: right; font-size: var(--fs-xs); color: var(--ink-3); }
.post-acts { justify-content: flex-end; }
@media (min-width: 840px) { .post-acts.sticky-actions { position: static; background: none; border-top: 0; padding: var(--space-1) 0 0; } }
@media (max-width: 839px) {
  .post-form .post-meta > label:not(.checkline) { flex-basis: 100%; }
  .vform textarea.post-text { min-height: 55vh; min-height: 55dvh; font-size: 16px; }
  .vform textarea.post-text.mid { min-height: 40vh; min-height: 40dvh; }
  .post-acts .btn { flex: 1 1 0; }
}

/* 수업 학원명 (2026-09-27 · 홈 팝업 home/_academy.html · 수업 설정 학원 칸) · 기본 <dialog> 안에 .card · 최종 모양은 디자인 세션이 손본다 */
.aca-dlg { margin: auto; border: 0; padding: 0; background: none; width: min(460px, calc(100vw - 24px)); max-height: calc(100dvh - 24px); overflow: auto; }
.aca-dlg::backdrop { background: color-mix(in srgb, var(--navy-950) 45%, transparent); }
.aca-dlg > .card { margin: 0; }
.aca-dlg h3 { margin: 0 0 2px; }
.aca-dlg .input { margin: var(--space-3) 0 var(--space-1); }
.aca-res .item { width: 100%; min-height: 44px; background: none; border: 0; border-bottom: 1px solid var(--line); font: inherit; color: inherit; text-align: left; cursor: pointer; }
.aca-res .item:disabled { cursor: default; color: var(--ink-3); }
.aca-res .item .main { display: flex; flex-direction: column; gap: 2px; }
.aca-res .item .title, .aca-dlg .item .title, .aca-sel .chip { overflow-wrap: anywhere; }   /* 띄어쓰기 없는 긴 학원·수업 이름도 칸 안에서 줄바꿈 */
.aca-dlg label.item { cursor: pointer; }
.aca-sel { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: var(--space-3) 0 6px; }
.aca-err:empty { display: none; }
.aca-err { color: var(--bad); }
.aca-foot { justify-content: flex-end; margin-top: 10px; }

/* 모션 줄이기(2026-09-26 D 모션 1묶음): 이동·크기 없이 색·투명도만 · 같은 선택자를 이기려고 파일 맨 끝에 둔다 */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-new(root) { animation-name: vt-fade-in; }
  ::view-transition-group(tab-ink) { animation: none; }
  .seg.has-ind.ready .seg-ind { transition: background-color var(--dur-2) var(--ease-standard), opacity var(--dur-1) linear; }
  .sw, .sw::after, .h-more svg { transition: none; }
  .saved-ind.play svg { animation: none; }
  .toast { animation: toastfade .2s ease-out; }
  .pin-form input.pin-shake { animation: none; }   /* PIN 틀림: 흔들림 없이 점 색만 · 공지 줄 이동은 notices.html 이 건너뛴다 */
  .hello > div { animation-name: vt-fade-in; }
  .bell.ring .bg, .bell.ring .rays { animation: none; }   /* 알림 종: 울림 없이 상태(노랑 종 · 빛 선)만 */
  .alp[open] { animation: vt-fade-in var(--dur-1) linear both; }   /* 알림 팝업·창: 올라오지 않고 나타남 · 세부 펼침은 app.js 가 즉시 */
  .alp-tog svg { transition: none; }
  .bell.sq, .h-bar .bell { transition: none; }
  .ntf-bar.in, .ntf-sheet[open] { animation-name: vt-fade-in; }   /* 출결 알림 줄·시트: 올라오지 않고 나타남 · 내려갈 때는 사라짐 */
  .ntf-bar.out { animation-name: vt-out; }
}

/* 제목 → 첫 내용 간격(T)이 카드 위 여백(P)보다 크면 리듬이 거꾸로(design_lint 3 · 2026-10-09 gate)
   시험 상세 '학생별 결과'(폰: 제목 줄 아래 버튼 줄로 감겨 P 17) · 학생 상세 '성적 요약'(T 19 > P 17) · 값만 줄이고 글자 크기는 그대로 */
@media (max-width: 599px) { .card:has(> .card-head + .tbl-wrap) > .card-head { margin-bottom: 10px; } }
.card > .card-head:has(+ .sum) { margin-bottom: 14px; }   /* 넓은 화면 P 21 → T 21 */
@media (max-width: 839px) { .card > .card-head:has(+ .sum) { margin-bottom: 12px; } }   /* 폰·분할 P 17 → T 18 */

/* ---------- 시험 만들기 · 학생 명단(폰) 손질 (2026-10-11 대표 133 S1·S2 · 129 N3b · 접두 cx-) ---------- */
/* 접기·목록 입력칸 꺾쇠 = 선택칸(select)과 같은 두 빗금 · 세로 간격은 칸 사이 --space-3 하나 · 가로 간격은 --space-2 하나 */
.cx .cx-fold { border: 0; padding: 0; margin-bottom: var(--space-3); }
.cx .cx-fold > summary { display: flex; align-items: center; gap: var(--space-2); list-style: none; }
.cx .cx-fold[open] > summary { margin-bottom: var(--space-3); }
.cx .cx-fold > summary::-webkit-details-marker { display: none; }
.cx .cx-fold > summary::after { content: ""; flex: none; margin-left: auto; width: 12px; height: 6px; background-repeat: no-repeat; background-size: 6px 6px; background-position: right 6px center, right 0 center;
  background-image: linear-gradient(45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)),
    linear-gradient(-45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)); }
.cx .cx-fold[open] > summary::after { transform: scaleY(-1); }
.cx input[list] { -webkit-appearance: none; appearance: none; padding-right: 32px !important; background-repeat: no-repeat !important; background-size: 6px 6px !important; background-position: right 18px center, right 12px center !important;
  background-image: linear-gradient(45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)),
    linear-gradient(-45deg, transparent calc(50% - 1.25px), var(--ink-3) calc(50% - .5px), var(--ink-3) calc(50% + .5px), transparent calc(50% + 1.25px)) !important; }
.cx input[list]::-webkit-calendar-picker-indicator { display: none !important; }
.cx .cx-chips { margin-top: var(--space-2); gap: var(--space-2); }
.cx .field > .cx-chips:last-child { margin-bottom: 0; }
.cx .field > label.tap:last-child { margin-bottom: 0; padding-bottom: 0; }
.cx .form-row, .cx .fmt-grid { gap: 0 var(--space-2); }
.cx .fmt-grid { gap: var(--space-2); }
.cx .src-tabs { display: grid; grid-template-columns: 1fr; }
.cx .src-tabs .chip { justify-content: center; min-width: 0; }
@media (min-width: 600px) { .cx .src-tabs { grid-template-columns: repeat(3, 1fr); } }
.cx .checkline { margin-bottom: var(--space-3); }
.cx .dz { margin-bottom: 0; }   /* 파일 첨부 칸 아래 8 을 빼 칸 사이를 라벨 아래 12 하나로 */
.cx .cx-fold > .checkline:last-child { margin-bottom: 0; }
/* 칸 안 단위(개·분) */
.cx .uf { position: relative; display: flow-root; }
.cx .uf input { padding-right: 36px; }
.cx .uf .u { position: absolute; top: 4px; right: 12px; bottom: 0; display: flex; align-items: center; color: var(--ink-3); font-size: var(--fs-md); font-weight: 400; pointer-events: none; }
/* 폰 학생 명단 · 글 묶음 잉크 가운데 = 체크칸·리포트 버튼 가운데 (아래 4 안여백이 글 묶음을 2 올린다 · 행 높이는 위아래 8 로 70 → 68) */
@media (max-width: 599px) {
  .stu-list .item { padding-top: var(--space-2); padding-bottom: var(--space-2); }
  .stu-list .item .main { padding-bottom: var(--space-1); }
  .stu-list .item .meta .stu-sch { flex: 0 100 auto; min-width: 3em; overflow: hidden; text-overflow: ellipsis; }   /* 긴 학교 이름은 … 로 줄고 수업 색띠를 밀어내지 않는다 */
}

/* 점수·등급 분포 카드가 폭 320 에서 칸(grid2)보다 16px 넓어져 화면을 2px 넘던 것(W105) · 막대 사이만 10→4 로 좁힌다 */
@media (max-width: 340px) {
  .dist { gap: var(--space-1); }
}

/* 누적 리포트 표 추이 선 · 같은 줄 옆 칸 숫자 잉크 가운데와 차 0 (W106b 측정: PC 0.5 · 폰 1 · 표 글자가 폰에서 13.5 로 줄어 잉크 위치가 다르다) */
td > .spark { transform: translateY(.5px); }
@media (max-width: 839px) { td > .spark { transform: translateY(2px); } }
/* W102 셋째(2026-10-13 깐깐 실장 M1~M9·F2~F5): 로그인·setup·잠김은 한 카드 규격 · 기기 화면은 두 카드 같은 행 부품
   카드 32 24 · 로고 52 → 16 → 제목 28 → 4 → 부제 20 → 16 · 줄높이는 모두 정수라 카드 위치가 3배 기기 픽셀에 앉는다 · 위치는 반올림한 윗여백(가운데보다 살짝 위) */
.login-card { padding: var(--space-8) var(--space-6) var(--space-4); }
.login-card .mark { margin-bottom: var(--space-4); }
.login-card h2 { font-size: var(--fs-title); font-weight: 700; line-height: 28px; margin: 0 0 var(--space-1); }
.login-card .lc-sub { font-size: var(--fs-base); line-height: 20px; color: var(--ink-3); margin: 0 0 var(--space-4); }
.login-card .banner { justify-content: center; text-align: center; border-color: transparent; margin-bottom: var(--space-3); }   /* 띠 테두리는 면과 같은 계열(투명) · 글자는 카드 나머지처럼 가운데 */
.login-card:has(> .lc-note:last-child) { padding-bottom: calc(var(--space-4) + var(--space-3)); }   /* 마지막이 작은 안내 글이어도 카드 아래 잉크 여백 = 위 32(로그인 카드 링크 줄과 같은 규격) */
.login-card h2 + .btn.block { margin-top: var(--space-4); }
.dw-no { font-size: var(--fs-display); font-weight: 800; line-height: 32px; }   /* 기기 번호 · 줄높이 정수 */
.login-card .dw-no-note { margin: var(--space-1) 0 var(--space-4); }
.lc-links.dv-links { align-items: flex-start; margin-top: var(--space-1); }   /* 폰 번호 화면의 '다시 받기' · 잠김 화면과 같은 글자 링크 부품(왼쪽 맞춤) */
.lc-links.dv-links > * { justify-content: flex-start; }
.card.dv.ph:has(.dv-links) { padding-bottom: var(--space-1); }   /* 링크 줄 높이 44 의 아래 반(13)이 안여백을 대신한다 · 0 이면 투명한 링크 상자가 카드 끝에 닿는다 */
.login-card .vform label { margin-bottom: var(--space-3); }
input.pin-in.pin-in.pin-in { text-align: center; font-size: var(--fs-xl); margin-top: var(--space-1); letter-spacing: 0; }   /* 6자리 칸 한 부품(로그인 PIN · setup PIN · 인증번호) · 자간은 입력된 숫자에만 · .vform input 규칙(0,3,1)을 이기려고 클래스를 겹쳤다 */
input.pin-in.pin-in.pin-in:not(:placeholder-shown) { letter-spacing: 2px; }
input.pin-in.pin-in.pin-in::placeholder { font-size: var(--fs-md); letter-spacing: 0; }
.lc-links { display: flex; flex-direction: column; align-items: center; margin-top: var(--space-2); }
.lc-links > *, .lc-links form { display: flex; align-items: center; justify-content: center; min-height: 44px; font-size: var(--fs-xs); line-height: 18px; color: var(--ink-3); }
.lc-links a, .lc-links .linkbtn { padding: 0; font-size: var(--fs-xs); font-weight: 700; line-height: 18px; color: var(--navy-ink); text-decoration: underline; text-underline-offset: 2px; min-height: 44px; min-width: 44px; display: flex; align-items: center; justify-content: center; }
.lc-links p { display: block; line-height: 18px; padding: 12px 0; text-align: center; }
.lc-note { margin-top: var(--space-4); font-size: var(--fs-xs); line-height: 18px; color: var(--ink-3); }
.lc-note + .lc-note { margin-top: 0; }
.lc-note + .lc-links { margin-top: 0; }
.lc-links p a { display: inline; min-height: 0; min-width: 0; }
@supports (padding-top: round(down, 1.5px, 1px)) {
  .login-wrap { align-items: flex-start; padding-top: max(var(--space-5), round(down, calc((100dvh - 480px) / 2), 1px)); }
}
.dv .list .item { position: relative; padding: var(--space-2) 0; border-bottom: 0; }   /* 행 사이 선은 테두리가 아니라 안쪽 1px 선(::after) · 위아래 안여백 8 한 값 · 간격 리듬 I(행 사이) ≤ P(카드 끝) < S(카드 사이) */
.card.dv { margin-bottom: var(--space-8); }
.dv .list .item:not(:last-child)::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--line); }
.dv-form .btn { width: 120px; padding: 0; }   /* 두 버튼 한 폭 · 정수 폭이라 오른쪽 끝이 3배 기기 픽셀에 앉는다 */
.dv .item .title { line-height: 20px; }
.dv .item .meta { line-height: 18px; }
.card.dv { padding: var(--space-3) var(--space-4); }
.dv-form { max-width: 360px; }   /* 칸 폭 상한 · 버튼은 칸 아래 왼쪽 그대로 */
.dv-t { font-size: var(--fs-md); font-weight: 700; line-height: 20px; }
.dv-h { margin-bottom: var(--space-4); }
.card.dv.ph { padding: var(--space-3) var(--space-4) var(--space-4); }   /* 글자로 시작하는 카드는 위 12 = 글자 위 공백이 아래 16 과 같아 보인다(잉크 실측 위 4 더) */
.card.dv.ph .vform > :last-child { margin-bottom: 0; }

/* 메시지 템플릿 목록-상세(W130 · 2026-10-13 대표 ⑤): 넓은 화면은 왼쪽 목록 + 오른쪽 전체 보기, 좁은 화면은 행 아래로 펼침 */
.mt { display: block; }
.mt-det { display: none; padding: 4px 0 14px; }
.mt .tpl-head { justify-content: flex-start; }
.mt .tpl-head .acts { margin-left: auto; }
.mt-det .tpl-head > b, .mt-det .tpl-head > .badge { display: none; }   /* 폰: 행 제목·상태가 바로 위에 있어 펼친 칸은 발송·삭제만 */
.mt-item.open .mt-det { display: block; }
.mt-pane { display: none; }
.mt .list .item.mt-row { width: 100%; background: none; border: 0; border-bottom: 1px solid var(--line); font: inherit; color: inherit; text-align: left; cursor: pointer; justify-content: space-between; }
.mt .mt-item:last-child .mt-row { border-bottom: 0; }
.mt .mt-item.open .mt-row { border-bottom-color: transparent; }
.mt-meta { margin-top: var(--space-2); }
@media (hover: hover) { .mt .list .item.mt-row:hover { background: var(--navy-50); } }
@media (min-width: 1000px) {
  .mt { display: grid; grid-template-columns: minmax(240px, 300px) minmax(0, 1fr); gap: 20px; align-items: start; }
  .mt-item .mt-det, .mt-item.open .mt-det { display: none; }
  .mt-pane { display: block; position: sticky; top: 16px; border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px 16px; }
  .mt-list { margin: 0 -12px; }   /* 고른 행 배경이 카드 안쪽 여백으로 나가고 글자·승인 배지는 카드 제목·버튼과 같은 선 */
  .mt .list .item.mt-row { padding-left: 12px; padding-right: 12px; border-bottom: 0; border-radius: var(--r-xs); }
  .mt .list .item.mt-row.on { background: var(--navy-50); }   /* 고른 행·위에 올린 행 한 톤(navy-50) · 보조 글자 대비 4.5 이상 */
}
/* 알림톡 템플릿 카드 맨 아래가 접힘 요약 글줄이라 아래 여백이 위보다 큼 · 위 잉크 여백과 맞춤 */
#kakao { padding-bottom: calc(var(--space-1) * 17 / 12); }   /* 5.67 · 기기 픽셀(3배) 정수 */
@media (max-width: 839px) { #kakao { padding-bottom: calc(var(--space-1) * 2 / 12); } }   /* 0.67 */
@media (max-width: 600px) { #kakao { padding-bottom: calc(var(--space-1) * 11 / 12); } }   /* 3.67 */
/* 설정 · 요금제 / 학생 수 카드(2026-10-13 대표 W231 · D7 Figma 146:11870·146:12195) = 홈페이지 PRO 네이비 양식 · 폭은 설정 칸 · 높이는 내용만큼 */
.st-plan { background: var(--navy-fill); color: var(--card); border-radius: var(--r-md); padding: var(--space-6); }
.st-plan h3.st-pn { margin: 0; font-size: 20px; font-weight: 700; line-height: 28px; color: var(--card); }   /* 20/28 · Figma 값 */
.st-ps { margin: 0; font-size: var(--fs-md); line-height: 20px; color: var(--navy-200); }
.st-bar { height: 4px; margin-top: var(--space-4); border-radius: var(--r-pill); background: color-mix(in srgb, var(--card) 14%, transparent); overflow: hidden; }
.st-bar i { display: block; height: 100%; border-radius: inherit; background: var(--navy-200); }
.st-bar i.bad { background: var(--bad-soft); }
.st-big { margin: var(--space-4) 0 0; font-size: 23px; font-weight: 700; line-height: 30px; color: var(--card); }   /* 23/30 · Figma 값 */
.st-big small, .st-big .frac small { font-size: var(--fs-md); font-weight: 500; line-height: 20px; color: var(--navy-200); }
.st-big > small { margin-left: var(--space-2); }
.st-big > small.vat { display: inline-block; margin-left: var(--space-1); }   /* 금액 옆 '· 부가세 별도' · 포털 small.vat 와 같은 표기(W77 필수 4) */
.st-pf { margin: var(--space-5) 0 0; padding-top: var(--space-4); border-top: 1px solid color-mix(in srgb, var(--card) 16%, transparent); font-size: var(--fs-md); line-height: 20px; color: var(--navy-200); }
.st-pf + .st-pf { margin-top: var(--space-2); padding-top: 0; border-top: 0; }
.st-chk { display: flex; align-items: center; gap: var(--space-2); }
.st-chk svg { flex: none; width: 16px; height: 16px; }
.st-pb { position: relative; display: flex; align-items: center; justify-content: center; height: 40px; margin-top: var(--space-5); border-radius: var(--r-sm); background: var(--card); color: var(--navy-fill); font-size: var(--fs-md); font-weight: 600; text-decoration: none; }
.st-pb::after { content: ""; position: absolute; inset: -2px 0; }   /* 누름 44 */
@media (hover: hover) { .st-pb:hover { background: var(--navy-100); text-decoration: none; } }
/* 수업 목록 · 묶음 머리 → 첫 카드 8 · 카드 사이 12(W233 · 2026-10-13 D7 · 모든 묶음 같음) */
h2.sec:has(+ .class-grid) { margin-bottom: var(--space-2); }
.class-grid { gap: var(--space-3); align-items: start; }   /* W412 critic3 12: 짧은 카드를 옆 카드 높이로 늘리지 않음 */
/* 학생 명단 손질(W75 · 2026-10-14 대표 결정 147 D1~D4) · 폰·분할(≤839)만 · PC 그대로 */
@media (max-width: 839px) {
  .stu-list .item > .stu-rep { flex: none; width: 32px; height: 32px; padding: 0; position: relative; background: none; box-shadow: none; border: 0; border-radius: var(--r-xs); color: var(--ink-2); }   /* D1 판 없는 아이콘 버튼 · .more-btn 과 같은 값 */
  .stu-list .item > .stu-rep svg { display: block; width: 20px; height: 20px; }   /* chart 아이콘 · 강사 화면 .more-btn svg 와 같은 20 */
  .stu-list .item > .stu-rep .lbl { display: none; }
  .stu-list .item > .stu-rep::after { content: ""; position: absolute; inset: -6px; }   /* 누름 44 */
  .stu-head { padding-right: 0 !important; }
  .stu-gb { display: none; }   /* D2 가입 · 학부모가 넣음 배지는 상세에서 */
  .banner.stu-quota.ok { display: none; }   /* D3 상한 띠는 경고 · 가득일 때만 */
  .stu-chips { flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; margin-left: calc(-1 * max(14px, env(safe-area-inset-left))); margin-right: calc(-1 * max(14px, env(safe-area-inset-right)));
    padding-left: max(14px, env(safe-area-inset-left)); padding-right: max(14px, env(safe-area-inset-right)); }   /* D4 한 줄 가로 밀기 · 양 끝은 본문 여백만큼 화면 끝까지 */
  .stu-chips::-webkit-scrollbar { display: none; }
  .stu-chips .chip { flex: none; white-space: nowrap; }
  .stu-chips { scroll-snap-type: x proximity; scroll-padding-left: var(--stu-sp, 0px); }   /* W258 칩 start 정렬 · 앞 칩이 범위 칩 뒤로 통째로 */
  .stu-chips > .chip { scroll-snap-align: start; }
  .stu-chips::after { content: ""; flex: none; width: var(--stu-pad, 0px); }   /* 끝 칩도 범위 칩 옆까지 밀리게 하는 끝 여백(JS가 잰 값) */
  .stu-range { display: flex; gap: 6px; flex: none; position: sticky; left: 0; z-index: 1; padding-right: 6px; background: var(--bg); box-shadow: -14px 0 0 var(--bg); }   /* D4 범위 칩(재원생·퇴원생) 왼쪽 고정 · 수업 칩만 밀림 */
}
@media (hover: hover) and (max-width: 839px) { .stu-list .item > .stu-rep:hover { background: var(--navy-50); } }
@media (min-width: 600px) and (max-width: 839px) {
  .stu-chips { margin-left: calc(-1 * max(var(--space-6), env(safe-area-inset-left))); margin-right: calc(-1 * max(var(--space-6), env(safe-area-inset-right)));
    padding-left: max(var(--space-6), env(safe-area-inset-left)); padding-right: max(var(--space-6), env(safe-area-inset-right)); }
}
/* 수납 W185: 완납·부족·미납 세 단추 = 출결 단추(.seg)와 같은 부품·크기 · 켜진 칸 색만 상태색 */
.tu-seg input[value="완납"]:checked + span { background: var(--ok-bg); color: var(--ok); box-shadow: none; }
.tu-seg input[value="부족"]:checked + span { background: var(--warn-bg); color: var(--warn); box-shadow: none; }
.tu-seg input[value="미납"]:checked + span { background: var(--bad-bg); color: var(--bad); box-shadow: none; }
.tu-notice { margin: 14px 0; }
.tu-short { padding: 2px 4px 12px; flex-wrap: wrap; }
.tu-short[hidden] { display: none; }
.tu-sample { margin: 0; white-space: pre-wrap; word-break: keep-all; overflow-wrap: break-word; font: inherit; font-size: var(--fs-sm); color: var(--ink-2); }
.tu-block { margin: 14px 0; color: var(--bad); }
/* 학생 상세 요약 · 폰 폭에서 긴 태그 이름이 카드를 밀어 넘치던 것(W211 · 2026-10-14) */
.st-sum > .card { min-width: 0; }
.st-sum .chips .chip { max-width: 100%; white-space: normal; overflow-wrap: anywhere; text-align: left; }
.st-sum .inline-form > .tap, .st-sum .inline-form > .tap:has(> .input:only-child) { min-width: 0; flex: 1 1 100%; }   /* 칸마다 한 줄 · 새 태그 칸이 '새'만 보이게 눌리지 않게 */
@media (min-width: 840px) { .st-sum .inline-form > .tap, .st-sum .inline-form > .tap:has(> .input:only-child) { flex: 1 1 140px; } }
.st-sum td { overflow-wrap: anywhere; }
/* 태그 관리 색 고르기 · 고른 색의 안쪽 링을 그림자 대신 outline 으로(테두리+그림자 금지 패턴 · 모양은 .swatch:has(input:checked) 와 같다) */
.tg-sw .swatch:has(input:checked) { box-shadow: none; outline: 2px solid var(--bg); outline-offset: -4px; }
/* 미응시·미제출 알림 단추 · 글자 폭(숫자·띄어쓰기)이 소수라 단추 가장자리가 3배 기기 픽셀 경계에 못 앉던 것 → 가장 긴 글(세 자리 인원)보다 넓은 정수 폭으로 */
.nu-btn { min-width: 128px; }
/* 학생 상세 요약 카드 제목 14.5px 줄높이 20(줄높이 표) · 상속 값 21.27 이 아래 표·입력의 세로 위치를 소수로 밀던 것 */
.st-sum h3 { line-height: 20px; }
/* 학생 상세 태그 줄 단추 정수 폭 · 글 폭 소수가 옆 입력 칸 가장자리를 소수로 밀던 것 */
@media (min-width: 840px) { .st-sum .inline-form .btn { min-width: 128px; } }
/* 학생 상세 기본 정보 표 줄높이 20 · 상속 값이 줄 높이를 소수로 만들어 아래 태그 입력 칸 세로 위치를 밀던 것 */
.st-sum table th, .st-sum table td { line-height: 20px; }

/* 홈 주간 보드 제목 줄 = 일정(캘린더) 링크 (2026-10-13 F7 · 폰 날짜 띠 머리도 같은 부품) · 접두 h-chl 은 이 링크 전용 */
a.h-chl { position: relative; color: inherit; text-decoration: none; }
a.h-chl > svg { flex: none; width: 16px; height: 16px; margin-left: var(--space-1); color: var(--ink-4); }
a.h-chl::after { content: ""; position: absolute; inset: -9px -4px; }   /* 누름 영역 44 */
a.h-chl:focus-visible { outline: 3px solid var(--navy-700); outline-offset: 2px; border-radius: var(--r-xs); }
@media (hover: hover) { a.h-chl:hover > svg { color: var(--ink); } }
.card.h-card.h-days:has(> a.h-chl) { padding-top: 11px; }   /* 제목 글자로 시작하는 카드와 같은 위 여백 */
.h-days > a.h-chl { margin-bottom: var(--space-3); }
/* 출석부 학생 줄 '오늘 한 줄'(W220) · 접힌 한 줄 쓰기 → 펼치면 입력 한 칸 · 쓴 줄은 연필 + 첫 20자 */
.check-row .at-line { grid-column: 1 / -1; min-width: 0; position: relative; }
.check-row .at-line summary { display: flex; align-items: center; gap: 6px; min-height: 22px; list-style: none; cursor: pointer; font-size: var(--fs-2xs); font-weight: 500; color: var(--ink-3); }
.check-row .at-line summary::-webkit-details-marker { display: none; }
.check-row .at-line summary::after { content: ""; position: absolute; left: 0; right: 0; top: -9px; height: 40px; }
.check-row .at-line summary span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.check-row .at-line .input { margin-top: 6px; }

/* 학생 로그인 정보 표(lg-*): 전화번호·학교 학년·초기값 줄이 하이픈·가운뎃점에서 끊겨 한 줄에 못 들어가던 것 → 칸 안 줄바꿈 금지(가로 스크롤은 .tbl-wrap)
   수업 칸은 칸 단위로 줄을 바꾸고 칩 하나(.cls-tag)만 한 줄로 · 인쇄에서는 칸이 접히되 전화번호·초기값은 그대로 한 줄(D0) */
.lg-tbl td:not(.no-print):not(.lg-cls) { white-space: nowrap; }
.lg-tbl td.lg-cls .cls-tag { white-space: nowrap; }
@media print { .lg-tbl td:not(.no-print) { white-space: normal; } .lg-tbl td { box-shadow: none; border-bottom: 1px solid var(--line); } .lg-tbl td.lg-ph, .lg-tbl td.lg-pw .small { white-space: nowrap; } }
/* 시험 오류 알림 띠(W83): 제목·반·문항을 항목으로 나눠 항목 안은 줄바꿈 금지 · 줄이 접히면 항목 단위(D0) */
.seps > .sl .nw { white-space: nowrap; }
.banner.warn .seps a.sl { color: var(--warn); }   /* 바탕 warn-bg 위 글자는 warn(대비 5.36) */
.lg-tbl td.no-print { white-space: nowrap; }   /* 동작 칸 버튼은 줄을 바꾸지 않고 .tbl-wrap 가로 스크롤 · 폭이 좁아도 행 높이는 1440 과 같다 */
.lg-tbl td.no-print .acts { flex-wrap: nowrap !important; }
.lg-tbl td.no-print .acts > * { flex: none; }
.lg-tbl td.no-print .btn { white-space: nowrap; }   /* 템플릿 인라인 flex-wrap:wrap 을 이긴다 */
/* 행 안 칸 세로 맞춤(W285 R0): 칸 안쪽 높이 56(짝수) 가운데에 홀수 높이 부품(31)이 앉으면 0.5 어긋난다 → 이 표 안 작은 버튼만 32 · 비밀번호 칸 글줄은 줄높이 20 상자로 감싸 가운데 */
.lg-tbl { border-collapse: separate; border-spacing: 0; }   /* 합친 테두리는 칸 안쪽 상자 중심이 0.5 밀려 모든 칸이 0.5 어긋나 재진다 · 떨어진 테두리는 행 높이 57 그대로 */
.lg-tbl td { line-height: 20px; border-bottom: 0; box-shadow: inset 0 -1px 0 var(--line); }   /* 칸 아래선을 상자 밖 테두리 말고 안쪽 그림자로 → 행 높이 57(홀수)이 56 으로 짝수가 돼 칸 가운데가 정수(W363) */
.lg-tbl tr:last-child td { box-shadow: none; }
@media (min-width: 1000px) { .lg-tbl td { line-height: 21px; } }   /* 넓은 화면은 본문 글자 상자가 17(홀수) → 줄높이도 홀수 21 로 위아래 여백을 같게 */
.lg-tbl td:first-child > a { display: block; width: fit-content; line-height: normal; }   /* 이름 줄 상자를 글자 상자와 같게 → 이름+학교 두 줄 묶음이 칸 가운데 */
.lg-tbl td:first-child .hint { margin-top: 2px; }
.lg-tbl td.no-print .btn.sm { height: 32px; }
.lg-tbl td.no-print .btn.sm svg { width: 16px; height: 16px; }
.lg-tbl td.lg-pw > .small, .lg-tbl td.lg-pw > .warn { display: block; line-height: 20px; }
.lg-tbl td.lg-ph { vertical-align: top; padding-bottom: 7px; line-height: 40px; }   /* 전화번호 숫자는 잉크 높이가 홀수(9)라 칸 안쪽 가운데보다 글줄이 0.5 아래로 재진다 → 위 정렬 + 아래 여백 7(안쪽 41·가운데가 x.5) + 줄높이 40 으로 정수 값만으로 글줄 가운데를 x.5 에 맞춘다 · 소수 px 이동 없음 · 행 높이 56 그대로 (W363 2차) */
@media (min-width: 1000px) { .lg-tbl td.lg-ph { padding-bottom: 8px; line-height: 39px; } }   /* 넓은 화면은 글 상자 17(홀수)라 안쪽 40 에 줄높이 39 */
@media print { .lg-tbl td.lg-ph { vertical-align: middle; padding-bottom: 8px; line-height: 20px; } }

/* 학교 성적 반 표 입력(W82 F1) · PC 는 학생마다 한 줄, 폰은 한 명씩 */
.sc-list { display: flex; flex-direction: column; }
.sc-row { display: grid; grid-template-columns: minmax(150px, 220px) 1fr; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.sc-row:first-child { border-top: 0; }
.sc-name { display: flex; flex-direction: column; min-width: 0; }
.sc-name .small { overflow-wrap: anywhere; }
.sc-pos { display: none; }
.sc-fields { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.sc-f { display: flex; flex-direction: column; gap: 0; width: 96px; }
.sc-f input, .sc-f select { width: 100%; }
.sc-lb { display: block; font-size: var(--fs-xs); color: var(--ink-3); margin-bottom: var(--space-1); }
.sc-acts { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-3); }
.sc-m { display: none; }
@media (max-width: 839px) {
  .sc-row { display: none; grid-template-columns: 1fr; }
  .sc-row.on { display: grid; border-top: 0; }
  .sc-pos { display: inline; }
  .sc-lb { display: block; font-size: var(--fs-xs); color: var(--ink-3); margin-bottom: var(--space-1); }
  .sc-f { width: calc(50% - var(--space-1)); }
  .sc-m { display: inline-flex; }
  .sc-acts { flex-wrap: wrap; justify-content: stretch; }
  .sc-acts .btn { flex: 1; }
}
/* 학교 성적 반 표(W82 P3 고침): 입력칸 높이 40 통일(입력·선택 1px 차) · 첫 카드 위 여백 잉크 20(폰 16) · 폰 하단 단추 첫 글자 줄 맞춤 */
.sc-f input:not([type=hidden]), .sc-f select { height: 40px; box-sizing: border-box; padding-top: 0; padding-bottom: 0; line-height: normal; }
.card.sc-pick { padding-top: 17px; }
@media (max-width: 839px) {
  .card.sc-pick { padding-top: 13px; }
  .sc-acts .btn { flex: 1 1 calc(50% - var(--space-1)); justify-content: flex-start; padding-left: var(--space-4); }
  .sc-acts .btn[value="save"] { flex-basis: 100%; order: -1; }
}
/* 계정 삭제 경고(W95): 한 줄 힌트가 아니라 본문 안내라 문단으로 · 줄 사이 8 */
.ad-warn { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-4); font-size: var(--fs-sm); line-height: 20px; color: var(--ink-2); }
.lc-links .linkbtn:disabled { color: var(--ink-3); text-decoration: none; cursor: default; }   /* W126 F1 · 다시 받기 60초 · 남은 시간 글자 링크(눌림 없음) */
.lc-links .linkbtn .rt { display: inline-block; min-width: 28px; text-align: right; font-style: normal; }   /* 남은 시간 숫자 칸 정수 고정(0:59~0:00 폭 흔들림 없음 · W202 방식) */
/* W126 D0 공용 S1 · 잠김 카드 배너·링크 글자 세로 가운데(정렬 Δ -1.0/-0.5 → 0) · 사양 tests/_tmp/critic_w102d/D0사양.md */
.login-card .banner > span { line-height: 19px; padding-top: 1px; }   /* 정수 px: 칸 20 그대로(기하 Δ 0) · 글자만 1 내림 */
.lc-links .linkbtn > span { padding-top: 1px; }
/* W126 D0 공용 S2 · 링크가 마지막인 카드 아래 여백 위 32 = 아래 32 · 한 카드 안 링크 행(form 버튼·<a>) 높이 47 한 값 */
.login-card .lc-links > form, .login-card .lc-links > form .linkbtn, .login-card .lc-links > a { min-height: 47px; }
/* W412 수업 구간(중간반·기말반) · Figma 250:19179 목록 카드 · 250:19392 회차 목록 · 253:70793 공지 구간 칩 */
.class-card .periods a { position: relative; z-index: 2; display: flex; justify-content: space-between; align-items: center; gap: 12px; border-top: 1px solid var(--line); padding: 8px 16px; line-height: 20px; color: inherit; text-decoration: none; }
.class-card .periods b, .pgroups b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.class-card .periods b { font-size: 13px; font-weight: 600; color: var(--ink); }
.class-card .periods span { flex-shrink: 0; font-size: 12.5px; color: var(--ink-3); }
.ntc-pchips { margin-bottom: 16px; }
.ses-fper { gap: 18px; margin: 0 0 16px; }   /* 자료 공개 구간 칩 · 253:71111 칩 사이 18 · 아래 16 */
@media (max-width: 839px) { .ses-fper { gap: 8px; } }   /* 폰 253:71508 칩 사이 6 → 8(W412 critic3 1 · 간격 토큰) */
.pgroups { padding-bottom: 12px; }
/* W412 critic3 5·12: 구간 띠는 회색 면 대신 아래 선 · 행과 같은 x·같은 오른쪽 끝(높이 36 유지 = 35 + 선 1) */
.pg-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 12px 0 0; box-sizing: content-box; height: 35px; border-bottom: 1px solid var(--line); padding: 0 16px; color: inherit; text-decoration: none; }
.pg-head b { font-size: 13px; font-weight: 600; color: var(--ink); }
.pg-head span { flex-shrink: 0; font-size: 12.5px; color: var(--ink-3); }
.pg-row { display: flex; align-items: center; height: 39px; box-sizing: content-box; border-bottom: 1px solid var(--line); padding: 0 16px; color: inherit; text-decoration: none; }
.pg-row b { width: 104px; flex-shrink: 0; font-size: var(--fs-md); font-weight: 600; color: var(--ink); }
.pg-row .d { font-size: 13px; color: var(--ink-3); white-space: nowrap; }
/* W412 critic3 12: 공통 .st(inline-flex · 좌우 8)가 text-align 을 무시해 글자가 왼쪽에 붙었음 → 오른쪽 끝 = 구간 띠 오른쪽 끝(행 안여백선) */
.pg-row .st { margin-left: auto; width: 60px; flex-shrink: 0; text-align: right; justify-content: flex-end; padding: 0; font-size: 12.5px; color: var(--ink-3); }
.pg-row .st.on { font-weight: 600; color: var(--ink); }
.pgroups > .pg-row:last-child { border-bottom: 0; }   /* W412 critic3 12: 마지막 행 아래 선 없음 */
/* 공지 작성 구간 칩 한 줄 · 긴 수업 이름만 말줄임, 구간 이름은 늘 보임 */
#notice-period .chip { max-width: 100%; white-space: nowrap; }
#notice-period .lbl { display: inline-flex; min-width: 0; }
#notice-period .lbl .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pg-add { margin-top: 16px; }
.pg-add > summary { list-style: none; display: inline-flex; cursor: pointer; }
/* W412 critic3 2·12: '구간 추가' 아이콘 x = 카드 내용선(PC 289 · 폰 29) · 카드 테두리 1 + 안여백 20/14 − sm 테두리 1 − 여백 12 → PC 8 · 폰 2 */
.pg-add > summary { margin-left: var(--space-6); }   /* W412 critic5 · 아이콘 x = 회차 행 내용선(PC 305 · 폰 45) */
@media (max-width: 839px) { .pg-add > summary {
  margin-left: 18px; /* token-ok */
} }
.pg-add > summary::-webkit-details-marker { display: none; }
.pg-form { gap: 8px; margin-top: 8px; flex-wrap: wrap; }
@media (max-width: 839px) {
  /* Figma 252:70238 폰 회차 줄 48 · 15/700 · 날짜 12/500 */
  .pg-row { height: 47px; }
  .pg-row b { width: 57px; font-size: 15px; font-weight: 700; }
  .pg-row .d { font-size: 12px; font-weight: 500; }
}
/* W412 게이트 5차 · 회차 행 글자 높이 한 값(정수 line-height 21·22) */
.pg-row b, .pg-row .d, .pg-row .st, .pg-head b, .pg-head span { display: block; line-height: 21px; /* token-ok */ min-height: 0; }
.pg-row b { line-height: 22px; /* token-ok */ }
/* W412 게이트 6차 · 한쪽 선은 안쪽 그림자 선(.list.roster .item 선례 · 높이 그대로) · 회차 행은 기준선 맞춤(b 줄높이 = 행 안높이) */
.class-card .periods a { border-top: 0; padding-top: 9px; /* token-ok */ box-shadow: inset 0 1px 0 var(--line); }
.pg-head { box-sizing: border-box; height: 36px; border-bottom: 0; padding-bottom: 1px; /* token-ok */ box-shadow: inset 0 -1px 0 var(--line); }
.pg-row { box-sizing: border-box; height: 40px; border-bottom: 0; padding-bottom: 1px; /* token-ok */ box-shadow: inset 0 -1px 0 var(--line); align-items: baseline; }
.pg-row b { line-height: 39px; /* token-ok */ }
.pgroups > .pg-row:last-child { box-shadow: none; padding-bottom: 0; height: 39px; }
@media (max-width: 839px) {
  .pg-row { height: 48px; }
  .pg-row b { line-height: 47px; /* token-ok */ }
  .pgroups > .pg-row:last-child { height: 47px; }
}
/* W412 게이트 6차 · 구간 칩 줄이 끼어도 공지 카드 위아래 여백은 .ntc-ph + .card 와 같은 값 */
.ntc-pchips + .card { padding-top: 16px; padding-bottom: 16px; }
.ntc-pchips + .card > .card-head { margin-bottom: 6px; }
@media (max-width: 839px) { .ntc-pchips + .card { padding-top: var(--space-3); padding-bottom: var(--space-3); } }
/* W412 게이트 7차 · 회차 행 세 칸 줄높이 = 행 안높이(상자 중심 한 값) · 공지 구간 칩은 평평한 칩(점 + 이름 + 구간)으로 */
.pg-row { align-items: center; }
.pg-row .d, .pg-row .st { line-height: 39px; /* token-ok */ }
@media (max-width: 839px) { .pg-row .d, .pg-row .st { line-height: 47px; /* token-ok */ } }
#notice-period .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ntc-pchips + .card .ntc-grp[data-grp="rest"] { margin-bottom: 4px; }
.card-head form[action$="/sessions/new"] > label.chip { height: 40px; }   /* 직보 칩 = 옆 버튼·select 높이 40 */
.class-card .body .name { text-wrap-style: balance; }   /* 긴 수업 이름 마지막 줄 한 낱말 고아 방지 */
/* W412 게이트 9차 · 정수 px만 · 공지 구간 칩 padding 6/6 + 줄높이 19 · 폰 회차 행 글자 기기 픽셀 맞춤 */
#notice-period .chip { padding-top: 6px; padding-bottom: 6px; line-height: 19px; /* token-ok */ }
@media (max-width: 839px) {
  a.pg-row b { position: relative; top: 1px; }
  a.pg-row .d, a.pg-row .st { position: relative; top: 2px; /* token-ok */ }
  .pgroups > a.pg-row:last-child b { top: 0; }
}
