/* ==========================================================================
   학생·학부모 화면 공용 CSS (2026-09-19)
   base.html 을 상속하지 않는 독립 템플릿(public/*, exams/take, error)이 함께 쓴다.
   토큰·부품 값은 static/style.css(브랜드 기본층 v2, 2026-09-18)에서 그대로 옮겨 온 것 —
   여기서 새 색·새 크기를 정하지 않는다. 화면 전용 차이(폭·히어로 카드 등)만 이 파일에 둔다.
   ========================================================================== */
:root {
  color-scheme: light;
  --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;
  --navy-fill: var(--navy-900);   /* 어두운 채움면 한 톤 (style.css 와 같음 · 2026-09-23) */
  --ink: #0B1B2B; --ink-2: #3A4A5E; --ink-3: #5F6E87; --ink-4: #97A3B4;
  --line: #E4E9F0; --line-2: #CDD6E2; --bg: #F5F7FA; --card: #FFFFFF;
  --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; --bad-soft: #E3928B; --bad-line: #EFC4BF; --navy-150: #DCE4EF;
  --chip-on: #FFFFFF;
  --on-navy: #FFFFFF; --on-navy-fill: rgba(255, 255, 255, .14);   /* 네이비·색 채움 위 글자 · 그 위 옅은 면(강사 style.css 의 --on-navy 와 같은 값 · 2026-10-13 W77 묶음 4) */
  --scrim: rgba(7, 15, 36, .5);   /* 모달·메뉴 뒤 가림막 */
  --tabbar-h: 62px; --rail-w: 64px; --accent-y: #F1C249; --accent-y-lt: #FFCD37;   /* 하단 탭바(common.css) 가 쓰는 토큰 · 강사 style.css :root 와 같은 값(2026-10-12 W77) */
  --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);
  --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;
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px;
  --fs-btn-lg: 16.5px;   /* 큰 버튼 글자(2026-10-10 대표 Z5) */
  --fs-2xs: 11.5px; --r-tag: 6px;   /* 노란 개수 배지(W199) · 강사 style.css 와 같은 값 */
  --fs-xs: 12px; --fs-sm: 13px; --fs-md: 14.5px; --fs-lg: 16px; --fs-xl: 18px; --fs-2xl: 22px; --fs-3xl: 28px;
  --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;
  --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-sine: cubic-bezier(.37, 0, .63, 1);
  --ease-spring: linear(0, .25 8%, .68 16%, 1.02 27%, 1.06 35%, 1.01 47%, .985 58%, 1);
}
@media (max-width: 839px) and (orientation: landscape) and (max-height: 500px) { :root { --tabbar-h: 50px; } }   /* 폰 가로 모드 탭바 낮춤(강사 style.css 와 같은 밴드) */
@media (max-width: 839px) { :root { --radius: 12px; } }   /* 카드 반경 14 · 폰 12 (강사 style.css 와 같은 밴드) */

/* ---------- 기본 ---------- */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; touch-action: manipulation; }   /* 더블탭 확대만 막는다(핀치 확대는 유지) — 2026-09-22 대표 신고 */
body {
  font-family: var(--font); color: var(--ink); font-size: 15px; line-height: 1.5;
  font-variant-numeric: tabular-nums; -webkit-font-smoothing: antialiased; letter-spacing: 0;
  word-break: keep-all; overflow-wrap: break-word;
}
/* 줄바꿈 규칙 (2026-09-23 · style.css 와 같은 규칙): 글 전체는 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, .q .b, .qd-b, .note { text-wrap-style: balance; }   /* 제목·메타 줄만 balance · 안내 글(.empty p .banner .flash .foot .note)은 body pretty 상속 (강사 style.css 와 같은 목록 + 학생에만 있는 문제 본문·안내 칸 .q .b .qd-b .note 는 balance 유지 · 2026-10-14 W77 필수 2) */
.hint, .sub { text-wrap-style: balance; }   /* 짧은 안내 글은 pretty 가 두 줄 고아를 못 막아 balance (강사 style.css 와 같음) */
.nw, a[href^="tel:"] { white-space: nowrap; }
/* 홈 화면에 설치한 앱에서 상태바 뒤가 밝으면 시계·배터리가 안 보여 네이비 띠를 깐다 */
body::before { content: ""; position: fixed; top: 0; left: 0; right: 0; height: env(safe-area-inset-top); background: var(--navy-900); z-index: 50; }
a { color: var(--navy-600); text-decoration: none; }   /* 5판 clink(2026-09-28) */
b, strong { font-weight: 700; }
button, input, select, textarea { font-family: inherit; color: inherit; }
img { max-width: 100%; }
a, button, .chip, .tabs a, .tabs button, summary, label { -webkit-tap-highlight-color: transparent; }
button, .btn, .chip, .tabs a, .tabs button { touch-action: manipulation; user-select: none; -webkit-user-select: none; }
.btn:focus-visible, .chip:focus-visible, .tabs a:focus-visible, .tabs button:focus-visible, summary:focus-visible {
  outline: 4px solid var(--navy-700); outline-offset: 2px;
}

/* ---------- 아이콘 (듀오톤 · _icons.html) ----------
   매크로가 크기를 안 붙이므로 기본값을 글자 크기(em)로 둔다 — 안 그러면 화면 가득 커진다 */
svg { flex: none; width: 1.1em; height: 1.1em; vertical-align: -0.18em; }
.btn svg, .chip svg, .pill svg, .badge svg, .tabs svg, .st svg, .go svg { width: 1em; height: 1em; vertical-align: baseline; }
svg.i { width: 1.1em; height: 1.1em; vertical-align: -0.18em; }
/* 아이콘 선 굵기 = 옆 글자 획(2026-10-12 대표 W105 · 아이콘은 글자 굵기에 맞춘다): svg 속성 1.75 는 24칸 기준이라 아이콘 크기가 달라지면 실제 굵기가 달라진다(16 아이콘 ÷ 13 글자 = 선이 획의 0.82배).
   화면 px 로 고정(vector-effect)하고 글자 크기(em)에 비례해 정한다 · 계수 = 글자 세로획 굵기(Wanted Sans '이' ㅣ · fontTools 실측): 600 .1097 · 400 .0762
   같은 규칙이 style.css 에도 있다(강사 화면) · 검사: 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 *, .go svg *, .back svg *, .st svg *, .frow a svg * { vector-effect: non-scaling-stroke; }
.btn svg, .chip svg, .badge svg, .pill svg, .tabs a svg, .tabs button svg, .go svg, .back svg, .st svg, .frow a svg { stroke-width: calc(var(--stem-b) * 1em); }
.go { display: inline-flex; align-items: center; gap: 2px; }   /* '전체 보기 ›' 링크도 flex 가운데 · 기준선에 앉은 › 가 글자보다 2px 위로 뜨던 것(2026-10-09 묶음 9 · 대표 '아이콘이 텍스트보다 위') */
h1 svg, h2 svg, h3 svg { width: 1em; height: 1em; }
.hint svg, .small svg, .muted svg, p svg { width: 1.1em; height: 1.1em; vertical-align: -0.18em; }
.hint a svg *, .foot a svg *, .small svg *, a.go svg * { vector-effect: non-scaling-stroke; }   /* 선 굵기는 아이콘 크기와 무관하게 글자 세로획 기준(W105) */
.hint a svg, .foot a svg, a.go svg { stroke-width: calc(var(--stem-b) * 1em); }   /* 600~700 글자 곁 아이콘 선 굵기 */
.small svg { stroke-width: calc(var(--stem-r) * 1em); }
a.small { display: inline-flex; align-items: center; gap: var(--space-1); }   /* 아이콘+글자 링크는 flex 가운데 */

/* ---------- 카드 · 히어로 ---------- */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px; margin-bottom: 12px; box-shadow: var(--shadow); }
.card.tight { padding: 12px 14px; }
.card#checks .sum span { line-height: 20px; }   /* 판 높이가 소수(.25·.5)로 끝나 위·아래 가장자리가 3배 픽셀에서 0.5 어긋나던 것 · 줄 높이를 정수로 */
.card#checks .chk .d { line-height: 18px; }
.card#checks { padding: var(--space-3) 16px var(--space-4); }   /* 성적·출결 탭의 출결·과제 보드(2026-10-12 대표 W105 d): 카드 위 가장자리 → 제목 잉크 = 마지막 칸 아래 → 카드 아래 가장자리(제목 글자 위 빈 줄 4 때문에 아래 안여백이 위보다 4 큼) · 위 안여백 12 로 P 16 ≥ T 15 · 다른 카드는 그대로 */
/* 학생 화면 머리 카드 (학습 리포트 · 결과 · 오답노트) */
.head { position: relative; background: var(--navy-fill); color: var(--on-navy); border-radius: var(--radius); padding: 18px; margin-bottom: 12px; }   /* 네이비 채움 한 톤 · 반경 14 = 카드(옛 그라데이션 · 16 · 2026-09-27 규칙 정리) */
.head .brand, .head .b { font-size: var(--fs-xs); color: var(--navy-400); font-weight: 600; letter-spacing: .04em; margin-bottom: 4px; }
.head h1 { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; line-height: var(--lh-head); }
.head .sub, .head .s { color: var(--navy-200); font-size: var(--fs-sm); margin-top: 4px; }
/* 상단 바 (게시판 · 내 계정 · 영상 · 응시) */
.top { position: sticky; top: 0; z-index: 10; background: var(--navy-900); color: var(--on-navy); display: flex; align-items: center; gap: 10px;
  padding: calc(10px + env(safe-area-inset-top)) 14px 10px; }
.top .back, .top .backbtn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); flex: none;
  height: 34px; padding: 0 12px; border-radius: 8px; background: var(--on-navy-fill); color: var(--on-navy); font-size: var(--fs-sm); font-weight: 700; white-space: nowrap; }
.top .t { font-weight: 700; font-size: var(--fs-lg); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.top .s { font-size: var(--fs-xs); color: var(--navy-200); }
/* 흰 상단바(rtop5 = B · 2026-09-28 대표 선택 · 높이 53 · 뒤로 40칸 안 아이콘 22 · 제목 16/700) · 시험 결과·질문 게시판·영상·글이 한 머리(2026-10-12 W77 필수 3) */
.top.tw { background: var(--card); color: var(--ink); box-shadow: 0 1px 0 var(--line); gap: 6px; height: calc(52px + env(safe-area-inset-top)); padding: env(safe-area-inset-top) max(10px, calc(50% - 310px)) 0; }   /* PC 는 본문 640 폭에 맞춰 같은 시작선(폰 10 = 본문 14 − 4 관계 그대로) */
.top.tw .t { line-height: 1.5; }   /* 게시판 머리(body 1.55)와 결과 머리(1.5)의 제목 높이를 같게 */
.top.tw .back { width: 40px; height: 40px; padding: 0; background: transparent; color: var(--ink); }
.top.tw .back svg { width: 22px; height: 22px; transform: translateY(-.5px); }   /* 뒤로 꺾쇠 잉크 가운데 = 제목 잉크 가운데(W106b 측정 차 0) */
.top.tw.root { padding-left: max(14px, calc(50% - 306px)); }   /* 뒤로 없는 탭 뿌리 화면: 제목이 본문(카드) 시작선 14 에 선다 */
.foot { text-align: center; font-size: var(--fs-xs); color: var(--ink-3); margin-top: 18px; line-height: 1.7; }

/* ---------- 버튼 (4등급 · 고정 높이 + flex 가운데) ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; background: var(--navy-fill); color: var(--on-navy);
  border: 1px solid var(--navy-fill); border-radius: 10px; padding: 0 16px; height: 40px; font-size: 14px; font-weight: 600;
  font-family: inherit; cursor: pointer; line-height: 1; white-space: nowrap; text-decoration: none;
  box-shadow: 0 1px 2px rgba(1, 22, 43, .18); transition: background .12s, transform .08s;
  -webkit-appearance: none; appearance: none;
}
.btn:active { transform: scale(.97); }   /* 누름 0.97 · 80ms(2026-09-25 대표 모션 submit B) */
@media (hover: hover) { .btn:hover { background: var(--navy-800); border-color: var(--navy-800); text-decoration: none; } }
.btn.ghost { background: var(--navy-50); color: var(--navy-800); border-color: transparent; box-shadow: none; }
@media (hover: hover) { .btn.ghost:hover { background: var(--navy-100); } }
.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); } }
.btn.danger { background: var(--bad-bg); color: var(--bad); border-color: transparent; box-shadow: none; }
.btn.sm { height: 31px; padding: 0 12px; font-size: var(--fs-sm); border-radius: var(--r-xs); }
.btn.lg { height: 48px; padding: 0 22px; font-size: var(--fs-btn-lg); border-radius: 12px; line-height: normal; }   /* 16px 에서 줄높이 1 은 반여백 -1.5 → 잉크 0.7~0.8px 위로(style.css .btn.lg 와 같은 보정) */
.btn.block { width: 100%; }
.btn[disabled], button[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) · style.css 와 같은 값(2026-10-13 F0 사양) */
.acts { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.row2 { display: flex; gap: 8px; } .row2 > * { flex: 1; }

/* ---------- 칩 ---------- */
.chips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.chip { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 32px; padding: 0 12px;
  background: var(--card); border: 1px solid var(--line-2); border-radius: var(--r-xs); color: var(--ink-2);
  font-size: var(--fs-sm); font-weight: 500; line-height: 1; cursor: pointer; white-space: nowrap; }   /* 보이는 높이 32 · 반경 8 · 글자 500 = 강사 .chip (2026-10-14 W77 필수 1) */
.chip::before { content: ""; position: absolute; left: 0; right: 0; top: -7px; bottom: -7px; }   /* 누름 영역 44 (테두리 안쪽 30 + 위아래 7) */
.chip.on, .chip:has(input:checked) { background: var(--navy-fill); border-color: var(--navy-fill); color: var(--on-navy); font-weight: 700; }
.chip i, .chip .n { font-style: normal; font-weight: 600; opacity: .72; }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }

/* ---------- 탭 (밑줄형) ---------- */
.tabs { display: flex; gap: 2px; box-shadow: inset 0 -2px 0 var(--line); margin-bottom: 12px; overflow-x: auto; }   /* 밑줄은 안쪽 그림자(style.css .tabs 와 같은 방식) · 옛 border + 탭 margin-bottom -2px 는 탭이 칸 밖으로 2px 나가 세로 스크롤바가 생겼다 */
.tabs a, .tabs button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 44px; padding: 0 14px;
  /* 위·아래 2px 을 같이 둬야 글자가 칸 한가운데 온다 (아래만 두면 1px 위로 치우침) */
  background: none; border: 0; border-top: 2px solid transparent; border-bottom: 2px solid transparent; border-radius: 0;
  color: var(--ink-3); font-family: inherit; font-size: var(--fs-md); font-weight: 600; line-height: 1;
  white-space: nowrap; cursor: pointer; text-decoration: none; box-shadow: none;
  transition: color var(--dur-2) var(--ease-standard), border-color var(--dur-2) var(--ease-standard);
}
.tabs a.on, .tabs button.on { color: var(--navy-ink); border-bottom-color: var(--navy-ink); font-weight: 700; }

/* ---------- 배지 · 필 ---------- */
.pill { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); height: 22px; padding: 0 8px;
  border-radius: var(--r-pill); background: var(--navy-50); color: var(--ink-2);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1; white-space: nowrap; flex: none; }
@media (min-resolution: 3dppx) { .pill { padding-top: calc(2px / 3); vertical-align: calc(-1px / 3); } }   /* 폰(3배 화면)에서만 알약 글자 1/3px 내림(style.css 와 같음 · 2026-10-16 대표 W70) */
.pill.good, .pill.ok { background: var(--ok-bg); color: var(--ok); }
.pill.mid, .pill.wait { background: var(--warn-bg); color: var(--warn); }
.pill.bad, .pill.no { 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-3); }
.badge { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); height: 22px; padding: 0 8px;
  border-radius: var(--r-xs); background: var(--navy-100); color: var(--navy-ink);
  font-size: var(--fs-xs); font-weight: 700; 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); }
/* 새 글 표시 — 색 채움 위 글자라 --on-navy */
.new { display: inline-flex; align-items: center; justify-content: center; height: 16px; padding: 0 4px; border-radius: 6px;
  background: var(--bad); color: var(--on-navy); font-size: 10px; font-weight: 700; line-height: 1; vertical-align: 2px; }
.new.y { background: var(--accent-y-lt); color: var(--ink); }   /* 영상 목록 행: 하단 탭바 개수 배지(.cnt)와 같은 노랑 체계(2026-10-12 W77 필수 5) */
.cnt { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 16px; min-width: 16px; padding: 0 4px; border-radius: 6px;   /* token-ok */
  background: var(--navy-100); color: var(--ink); font-size: 11.5px; font-weight: 700; line-height: 12px;   /* token-ok */ font-variant-numeric: tabular-nums; }   /* 개수 띠 한 규격(2026-10-12 대표 W105 e · style.css .badge.cnt 와 같음) */

/* ---------- 안내 띠 · flash ---------- */
.flash, .banner { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: var(--r-sm); margin-bottom: 12px;
  font-size: var(--fs-md); font-weight: 600; background: var(--navy-50); color: var(--ink-2); }
.flash.ok, .banner.ok { background: var(--ok-bg); color: var(--ok); }
.flash.err, .banner.err { background: var(--bad-bg); color: var(--bad); }
.flash.warn, .banner.warn { background: var(--warn-bg); color: var(--warn); }
.flash.info, .banner.info { background: var(--info-bg); color: var(--info); }

/* ---------- 입력 ---------- */
.input { display: block; width: 100%; height: 40px; padding: 0 12px; border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--card); color: var(--ink); font-size: 16px; font-family: inherit; font-weight: 500;
  -webkit-appearance: none; appearance: none; transition: border-color .12s, box-shadow .12s; }
textarea.input { height: auto; min-height: 40px; padding: 8px 12px; }   /* 입력 40(크기 규칙 A) · 여러 줄 칸은 한 줄 높이가 40 */
/* 입력칸·선택칸 누름 영역 44 · 보이는 높이 40 그대로 · 칸을 감싼 label.tap 이 위아래 안여백 2 + 같은 만큼 음수 마진으로 누름 영역만 넓힌다(강사 style.css 와 같은 규칙) */
label.tap { display: block; margin: var(--tap-m, 0px) 0; padding: var(--tap-p, 0px) 0; }
@media (max-width: 839px) { .tap { --tap-m: -2px; --tap-p: 2px; } }
textarea.input { line-height: 1.6; resize: vertical; }
.input:focus { outline: none; border-color: var(--navy-700); box-shadow: none; }
/* 선택칸(select) 한 부품 · 강사 화면 style.css 와 같은 규칙(2026-09-28 R0 q29) · WebKit 기본 회색 단추 대신 면 + 오른쪽 ⌄(토큰 색 두 빗금) */
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;
}
.err-line { color: var(--bad); font-size: var(--fs-xs); font-weight: 600; margin: var(--space-2) 0; }
label:has(> .err-line:not([hidden])) { margin-bottom: 0; }   /* 오류가 보이는 칸은 라벨 아래 간격 대신 오류 줄 아래 8 하나 · 바로 뒤 버튼의 윗 여백도 걷는다(옛 10 · 14) */
label:has(> .err-line:not([hidden])) + .btn { margin-top: 0; }
[aria-invalid="true"] { border-color: var(--bad-line); }
.ck { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--ink-3); margin: 0 var(--space-3) 6px 0; cursor: pointer; }
.ck input { width: 18px; height: 18px; accent-color: var(--navy-600); margin: 0; }

/* ---------- 통계 칸 ---------- */
.kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 10px; }
.kpi { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: var(--navy-50); border-radius: var(--r-sm); padding: 8px 6px; min-height: 52px; text-align: center; }
.kpi .v { font-size: var(--fs-lg); font-weight: 700; color: var(--navy-ink); line-height: 1.15; }
.kpi .v small { font-size: 11px; font-weight: 600; color: var(--ink-3); }
.kpi .l { font-size: 11px; line-height: 1.35; color: var(--ink-3); }
/* 큰 숫자 + 작은 '/ 전체'(2026-09-28 대표 채택 '9 / 10' · 매크로 _macros.html frac · style.css 와 같은 두 줄) */
.frac { display: inline-flex; align-items: baseline; }
.frac small { margin-left: 4px; }
.st .nb, .badge .nb, .pill .nb, .chip .nb, .btn .nb, .tabs a .nb { top: 0; }   /* 높이 고정 부품 안은 내림 해제(2026-10-10 대표 Z1) */
.nb { position: relative; top: .07em; top: round(calc(var(--nb-u, 1em) * .07), 1px); }   /* 숫자+한글 아래선(2026-10-09 · static/nb.js · style.css 와 같은 한 줄) */

/* ---------- 목록 행 ---------- */
.list { display: flex; flex-direction: column; }
.list .item { display: flex; align-items: center; gap: 10px; padding: 12px 4px; border-bottom: 1px solid var(--line); color: inherit; flex-wrap: wrap; }
.list .item:last-child { border-bottom: 0; }
.list .item .main { flex: 1 1 140px; min-width: 0; }
.list .item .title { font-weight: 700; font-size: var(--fs-md); }
.list .item .meta { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; }
/* 학생 화면 목록 행 (성적·게시글·영상) */
.xrow { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--line); color: inherit; text-decoration: none; flex-wrap: wrap; }
.xrow:last-child { border-bottom: 0; }
.xrow .main { flex: 1 1 140px; min-width: 0; color: inherit; text-decoration: none; }
.xrow .t { font-weight: 700; font-size: var(--fs-md); }
.xrow .m { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; }
.seps { display: block; overflow-x: clip; }
.seps > .sl { --sep: 12px; display: flex; flex-wrap: wrap; align-items: center; margin-left: calc(-1 * var(--sep)); }
.seps > .sl > * { margin-left: var(--sep); }   /* '·' 는 항목 앞 여백 안에 · 항목 상자는 글자에서 시작(카드 왼쪽 시작선 · style.css 와 같음 · 2026-10-10 w30) */
.seps > .sl > *::before { content: "·"; display: inline-block; width: var(--sep); margin-left: calc(-1 * var(--sep)); text-align: center; }
.xrow .pills { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.xrow .go { display: inline-flex; align-items: center; justify-content: center; gap: 2px; color: var(--navy-700);
  font-size: var(--fs-sm); font-weight: 700; line-height: 1; white-space: nowrap; text-decoration: none; }

/* ---------- 접이식 ---------- */
details { border-top: 1px solid var(--line); padding: 8px 0; }
details:first-of-type { border-top: 0; }
summary { cursor: pointer; font-weight: 700; color: var(--navy-ink); }
/* 공지 접이식 머리(2026-10-12 대표 W105 c 원문 '세모 기호와 제목 사이 간격을 아주 조금만 넓혀보자'): 기본 세모(▶▼)는 그대로 두고 제목만 4 띄운다 */
.vitem > summary > :first-child { margin-left: var(--space-1); }

/* ---------- 표 ---------- */
table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
th, td { padding: 8px 6px; border-bottom: 1px solid var(--line); text-align: left; }
th { background: var(--navy-50); font-size: var(--fs-xs); color: var(--ink-2); white-space: nowrap; }
tr:last-child td { border-bottom: 0; }

/* ---------- 진행 막대 · 글자 ---------- */
.bar { position: relative; background: var(--navy-50); border-radius: 6px; height: 18px; min-width: 90px; overflow: hidden; }
.bar .fill, .bar .f { height: 100%; background: var(--navy-500); border-radius: 6px; }
.bar .fill.bad, .bar .f.bad { background: var(--bad-soft); }
.bar .fill.ok, .bar .f.ok { background: var(--ok-soft); }
.bar span { position: absolute; left: 6px; top: 0; font-size: var(--fs-xs); font-weight: 700; line-height: 18px; }
.muted { color: var(--ink-3); } .small { font-size: var(--fs-sm); }
.pt-u { margin-left: .1em; }   /* 점수 숫자와 뒤 '점' 사이 .1em · 줄 끝에서 갈리지 않게 앞에 붙임 글자(2026-09-28 5판 대표 결정) */
.pt-u::before { content: "\2060"; }
.stars { display: inline-flex; align-items: center; vertical-align: -0.18em; color: var(--warn); }   /* 별점 = 아이콘 세트 star(듀오톤) · 채운 별만 면 불투명(글자 ★☆ 대신 · 2026-10-13 W77 묶음 3) */
.stars svg { width: 1em; height: 1em; vertical-align: baseline; }
.stars svg.on .f { fill-opacity: 1; }
.empty { text-align: center; padding: 24px 10px; color: var(--ink-3); font-size: var(--fs-md); }
.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) */

/* ---------- 위티봇 모션 (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; margin: 0 auto; 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%; }
.cm-cheer { --ar: 265 / 271; --ax: 2.15%; }
.cm-rest { --ar: 277 / 271; --ax: calc(3.5% + 3.5px); }   /* 폰 104px 에서 화면 재측정으로 맞춘 값(정답 잉크 x 153.0~251.0 · 실장 지적 +3.5px · 2026-10-01) · 600px 이상은 아래 */
.cm-oops { --ar: 270 / 271; --ax: 4.44%; }

/* 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; }
}

/* cheer · 기뻐 뛰기 · 800ms · 두 번(첫 점프 2.2% · 둘째 1.3%) 뛰고 효과선이 켜진다 */
.cm-cheer .l-body { transform-origin: 46.98% 92.62%; }
.play .cm-cheer .l-body { animation: cm-cheer-body 800ms both; }
.play .cm-cheer .l-shadow { animation: cm-cheer-shadow 800ms var(--ease-standard) both; }
.play .cm-cheer .l-sparks { animation: cm-cheer-sparks 800ms linear both; }
@keyframes cm-cheer-body {
  0% { transform: translateY(0) scaleY(1); animation-timing-function: var(--ease-standard); }
  10% { transform: translateY(0) scaleY(.96); animation-timing-function: var(--ease-spring); }
  25% { transform: translateY(-2.2%) scaleY(1); animation-timing-function: var(--ease-exit); }
  40% { transform: translateY(0) scaleY(1); animation-timing-function: var(--ease-spring); }
  50.63% { transform: translateY(-1.3%) scaleY(1); animation-timing-function: var(--ease-exit); }
  61.25%, 100% { transform: translateY(0) scaleY(1); }
}
@keyframes cm-cheer-shadow {
  0%, 10% { transform: scaleX(1); opacity: 1; }
  25% { transform: scaleX(.96); opacity: .85; }
  40% { transform: scaleX(1); opacity: 1; }
  50.63% { transform: scaleX(.96); opacity: .85; }
  61.25%, 100% { transform: scaleX(1); opacity: 1; }
}
@keyframes cm-cheer-sparks {
  0%, 61.25% { opacity: 0; }
  80%, 100% { opacity: 1; }
}

/* rest · 쉬는 중 · 3.2초 동안 숨 한 번(높이 2% 떴다 내려옴) 뒤 정지 */
.play .cm-rest .l-body { animation: cm-rest 3.2s var(--ease-sine) both; }
.play .cm-rest .l-shadow { animation: cm-rest-shadow 3.2s var(--ease-sine) both; }
@keyframes cm-rest {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-2%); }
}
@keyframes cm-rest-shadow {
  0%, 100% { transform: scaleX(1); opacity: 1; }
  50% { transform: scaleX(.98); opacity: .85; }
}
/* oops · 404 · 움직이지 않는다(정지 컷) */

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

/* 첫 로그인 인사(강사 화면 style.css 와 같은 오버레이 · _macros.html hello_overlay) */
.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; } }

/* 쓰는 자리(학생·공용 화면) · 크기 --h 는 폰 → 600px 이상에서 키운다 · 여백은 잉크(그림·글자) 기준으로 위·아래를 같게 맞춘 값(컷의 투명 여백만큼 calc 로 뺀다) */
.done { --h: 112px; padding: 28px 16px 28px; }   /* 제출 완료 · 카드 위 잉크 = 아래 잉크(±0.2) · 캐릭터 → 제목 24 · 제목 → 본문 8~12 */
.done h2 { display: block; margin: var(--space-3) 0 0; font-size: var(--fs-xl); line-height: 1.3; text-align: center; }
.done p { margin: 2px 0 0; }
.empty.rest { --h: 104px; padding: 26px 10px 46px; }   /* 게시판 글 없음 · 안내문 ↔ 그림 = 문구 ↔ 카드 아래 */
.empty.rest .cm { margin-bottom: 6px; }
@media (min-width: 600px) { .done { --h: 140px; padding-bottom: 28px; } .empty.rest { --h: 120px; padding: 22px 10px 48px; } .done h2 { margin-top: 10px; } .cm-rest { --ax: 2.9%; } }

/* ---------- 모션 · 인쇄 ---------- */
@media (prefers-reduced-motion: reduce) {
  .btn:active { transform: none; }
  .btn, .chip, .tabs a, .tabs button { transition: none; }
  * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}
@media print {
  body::before, .top, .tabbar, .no-print { display: none !important; }
  body { background: var(--card); }
  .card { box-shadow: none; border: 1px solid var(--line-2); break-inside: avoid; }
}
/* 로그인 카드: 제목·부제 줄높이가 23.75·19.5 소수라 로그인 버튼이 y=.25 에 앉아 글자가 0.5px 위로 → 정수 줄높이로(버튼 높이·크기는 그대로) */
.card:has(form[action="/p/login"]) h1 { line-height: 24px; }
.card:has(form[action="/p/login"]) .sub { line-height: 20px; }
/* 학교 성적 카드(학생 리포트·학부모 화면 · W82 P3): 내신·모의고사 묶음 · 표 · 선그래프(같은 과목 3건부터) */
.sg-k { margin: var(--space-3) 0 var(--space-1); font-size: var(--fs-md); font-weight: 700; color: var(--navy-ink); }
.sg h2 + .sg-k { margin-top: var(--space-1); }
.sg-note { margin: var(--space-1) 0 var(--space-2); font-size: var(--fs-sm); color: var(--ink-3); }
.sg-m { display: flex; flex-wrap: wrap; gap: 0 var(--space-2); font-size: var(--fs-xs); }
.sg-m span { white-space: nowrap; }
.sg-chart { background: var(--navy-50); border-radius: var(--r-md); padding: var(--space-2) var(--space-2) var(--space-1); margin-bottom: var(--space-2); }
.sg-chart svg { width: 100%; height: auto; display: block; font-family: inherit; }
.sg-chart .g { stroke: var(--line-2); stroke-width: 1; }
.sg-chart .yl { font-size: var(--fs-xs); fill: var(--ink-3); text-anchor: end; }
.sg-chart .xl { font-size: var(--fs-xs); fill: var(--ink-3); text-anchor: middle; }
.sg-chart .v { font-size: var(--fs-xs); font-weight: 700; fill: var(--navy-ink); text-anchor: middle; paint-order: stroke; stroke: var(--navy-50); stroke-width: 4px; stroke-linejoin: round; }
.sg-chart .me { fill: none; stroke: var(--navy-700); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.sg-chart .dot { fill: var(--card); stroke: var(--navy-700); stroke-width: 2.2; }
.sg-lg { padding: var(--space-1) var(--space-1) 0; font-size: var(--fs-xs); color: var(--ink-3); }
